From 7f0e23e931064d8e8758e01d95bfb89b8fa32e6e Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 1 Mar 2016 21:32:38 -0500 Subject: [PATCH] re PR c++/69995 ([C++14] Invalid result when evaluating constexpr function) PR c++/69995 * constexpr.c (cxx_eval_call_expression): Unshare arg. (cxx_eval_constant_expression) [DECL_EXPR]: Unshare init. [TARGET_EXPR]: Unshare init. From-SVN: r233877 --- gcc/cp/ChangeLog | 7 ++++++ gcc/cp/constexpr.c | 5 ++++ gcc/testsuite/g++.dg/cpp1y/constexpr-copy2.C | 24 ++++++++++++++++++ gcc/testsuite/g++.dg/cpp1y/constexpr-copy3.C | 26 ++++++++++++++++++++ 4 files changed, 62 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-copy2.C create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-copy3.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 04e14268459..3a24cc9392b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2016-03-01 Jason Merrill + + PR c++/69995 + * constexpr.c (cxx_eval_call_expression): Unshare arg. + (cxx_eval_constant_expression) [DECL_EXPR]: Unshare init. + [TARGET_EXPR]: Unshare init. + 2016-03-01 Patrick Palka PR c++/68948 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 5e359404c8d..a21997ab97a 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 00000000000..6707975f0ab --- /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 00000000000..cce4b54df7f --- /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());