This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: C++ PATCH for c++/69995 (wrong value with C++14 constexpr)


On 02/29/2016 09:25 AM, Jason Merrill wrote:
The bug here was that we were sharing the CONSTRUCTOR between the value
of 'a' and the elements of 'result', so changing 'a' also changed the
value of result[0].  Oops.

And there were a few other places with the same problem.

Tested x86_64-pc-linux-gnu, applying to trunk and 5.



commit 0b712dc1cf26859a8ae01eac4ea60005c82e95eb
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Mar 1 01:28:41 2016 -0500

    	PR c++/69995
    
    	* constexpr.c (cxx_eval_call_expression): Unshare arg.
    	(cxx_eval_constant_expression) [DECL_EXPR]: Unshare init.
    	[TARGET_EXPR]: Unshare init.

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 5e35940..a21997a 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -1365,6 +1365,8 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
 	      tree oparm = TREE_PURPOSE (bound);
 	      tree arg = TREE_VALUE (bound);
 	      gcc_assert (DECL_NAME (remapped) == DECL_NAME (oparm));
+	      /* Don't share a CONSTRUCTOR that might be changed.  */
+	      arg = unshare_expr (arg);
 	      ctx->values->put (remapped, arg);
 	      bound = TREE_CHAIN (bound);
 	      remapped = DECL_CHAIN (remapped);
@@ -3366,6 +3368,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
 	    init = cxx_eval_constant_expression (ctx, init,
 						 false,
 						 non_constant_p, overflow_p);
+	    /* Don't share a CONSTRUCTOR that might be changed.  */
+	    init = unshare_expr (init);
 	    ctx->values->put (r, init);
 	  }
 	else if (ctx == &new_ctx)
@@ -3410,6 +3414,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
       if (lval)
 	{
 	  tree slot = TARGET_EXPR_SLOT (t);
+	  r = unshare_expr (r);
 	  ctx->values->put (slot, r);
 	  return slot;
 	}
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-copy2.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-copy2.C
new file mode 100644
index 0000000..6707975
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-copy2.C
@@ -0,0 +1,24 @@
+// PR c++/69995
+// { dg-do compile { target c++14 } }
+
+struct A
+{
+  int i;
+};
+
+constexpr int f(A a)
+{
+  ++a.i;
+  return a.i;
+}
+
+constexpr bool g()
+{
+  A a = { 42 };
+  if (f(a) != 43) return false;
+  if (a.i != 42) return false;
+  return true;
+}
+
+#define SA(X) static_assert((X),#X)
+SA(g());
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-copy3.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-copy3.C
new file mode 100644
index 0000000..cce4b54
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-copy3.C
@@ -0,0 +1,26 @@
+// PR c++/69995
+// { dg-do compile { target c++14 } }
+
+struct A
+{
+  int i;
+};
+
+constexpr int f(A a)
+{
+  ++a.i;
+  return a.i;
+}
+
+constexpr bool g()
+{
+  A a = { 42 };
+  A b = a;
+  ++b.i;
+  if (b.i != 43) return false;
+  if (a.i != 42) return false;
+  return true;
+}
+
+#define SA(X) static_assert((X),#X)
+SA(g());

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]