This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: C++ PATCH for c++/69995 (wrong value with C++14 constexpr)
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches List <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 1 Mar 2016 21:05:55 -0500
- Subject: Re: C++ PATCH for c++/69995 (wrong value with C++14 constexpr)
- Authentication-results: sourceware.org; auth=none
- References: <56D454CD dot 7020309 at redhat dot com>
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());