re PR c++/67364 ("accessing uninitialized member" error in constexpr context)
authorJason Merrill <jason@redhat.com>
Sun, 6 Mar 2016 06:47:22 +0000 (01:47 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Sun, 6 Mar 2016 06:47:22 +0000 (01:47 -0500)
PR c++/67364
* constexpr.c (cxx_eval_store_expression): Replace
CONSTRUCTOR_ELTS in nested CONSTRUCTORs, too.

From-SVN: r234013

gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/testsuite/g++.dg/cpp0x/constexpr-aggr3.C [new file with mode: 0644]

index 0ef1ac744addbcd85988c029fd8a08ab9ca098d6..a803ec984863f18a01acf4fee12ee4cc4daf0f70 100644 (file)
@@ -1,3 +1,9 @@
+2016-03-05  Jason Merrill  <jason@redhat.com>
+
+       PR c++/67364
+       * constexpr.c (cxx_eval_store_expression): Replace
+       CONSTRUCTOR_ELTS in nested CONSTRUCTORs, too.
+
 2016-03-05  Patrick Palka  <ppalka@gcc.gnu.org>
 
        PR c++/66786
index c9f9c47472f0e8bbdb050048b051fbbf021d5f67..f23e7c91755f0b0fe630d5db9039871dd4e0b69b 100644 (file)
@@ -2939,39 +2939,34 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
   /* Don't share a CONSTRUCTOR that might be changed later.  */
   init = unshare_expr (init);
   if (target == object)
+    /* The hash table might have moved since the get earlier.  */
+    valp = ctx->values->get (object);
+
+  if (TREE_CODE (init) == CONSTRUCTOR)
     {
-      /* The hash table might have moved since the get earlier.  */
-      valp = ctx->values->get (object);
-      if (TREE_CODE (init) == CONSTRUCTOR)
-       {
-         /* An outer ctx->ctor might be pointing to *valp, so replace
-            its contents.  */
-         CONSTRUCTOR_ELTS (*valp) = CONSTRUCTOR_ELTS (init);
-         TREE_CONSTANT (*valp) = TREE_CONSTANT (init);
-         TREE_SIDE_EFFECTS (*valp) = TREE_SIDE_EFFECTS (init);
-       }
-      else
-       *valp = init;
+      /* An outer ctx->ctor might be pointing to *valp, so replace
+        its contents.  */
+      CONSTRUCTOR_ELTS (*valp) = CONSTRUCTOR_ELTS (init);
+      TREE_CONSTANT (*valp) = TREE_CONSTANT (init);
+      TREE_SIDE_EFFECTS (*valp) = TREE_SIDE_EFFECTS (init);
     }
   else
-    {
-      *valp = init;
-
-      /* Update TREE_CONSTANT and TREE_SIDE_EFFECTS on enclosing
-        CONSTRUCTORs.  */
-      tree elt;
-      unsigned i;
-      bool c = TREE_CONSTANT (init);
-      bool s = TREE_SIDE_EFFECTS (init);
-      if (!c || s)
-       FOR_EACH_VEC_SAFE_ELT (ctors, i, elt)
-         {
-           if (!c)
-             TREE_CONSTANT (elt) = false;
-           if (s)
-             TREE_SIDE_EFFECTS (elt) = true;
-         }
-    }
+    *valp = init;
+
+  /* Update TREE_CONSTANT and TREE_SIDE_EFFECTS on enclosing
+     CONSTRUCTORs, if any.  */
+  tree elt;
+  unsigned i;
+  bool c = TREE_CONSTANT (init);
+  bool s = TREE_SIDE_EFFECTS (init);
+  if (!c || s)
+    FOR_EACH_VEC_SAFE_ELT (ctors, i, elt)
+      {
+       if (!c)
+         TREE_CONSTANT (elt) = false;
+       if (s)
+         TREE_SIDE_EFFECTS (elt) = true;
+      }
   release_tree_vector (ctors);
 
   if (*non_constant_p)
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-aggr3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-aggr3.C
new file mode 100644 (file)
index 0000000..547dec4
--- /dev/null
@@ -0,0 +1,30 @@
+// PR c++/67364
+// { dg-do compile { target c++11 } }
+
+template <typename Xn>
+struct tuple {
+  Xn storage_;
+
+  constexpr tuple(Xn const& xn)
+    : storage_(xn)
+  { }
+
+  template <typename ...dummy>
+  constexpr tuple(tuple const& other)
+    : storage_(other.storage_)
+  { }
+
+  template <typename ...dummy>
+  constexpr tuple(tuple& other)
+    : tuple(const_cast<tuple const&>(other))
+  { }
+};
+
+template <typename T>
+struct wrapper { T value; };
+
+template <typename T>
+constexpr wrapper<T> wrap(T t) { return {t}; }
+
+constexpr wrapper<tuple<int>> t = wrap(tuple<int>{2});
+static_assert(t.value.storage_ == 2, "");