diff mbox

C++ PATCH for another c++/67364 testcase (constexpr wrong evaluation)

Message ID 56DBD255.60404@redhat.com
State New
Headers show

Commit Message

Jason Merrill March 6, 2016, 6:46 a.m. UTC
Lewis reported another testcase which hits the "accessing uninitialized 
member" error, and can lead to wrong values.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox

Patch

commit 1bfb2997968d18b337cbd144a698b7be3bf6b28e
Author: Jason Merrill <jason@redhat.com>
Date:   Sat Mar 5 14:44:31 2016 -0500

    	PR c++/67364
    	* constexpr.c (cxx_eval_store_expression): Replace
    	CONSTRUCTOR_ELTS in nested CONSTRUCTORs, too.

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index c9f9c47..f23e7c9 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -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;
+    *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;
-	  }
-    }
+  /* 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
index 0000000..547dec4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-aggr3.C
@@ -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, "");