From acb2970c3bdf4cfd81954278d28f53adcffab99c Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 11 Jun 2015 11:45:01 -0400 Subject: [PATCH] re PR c++/66450 ([C++11][constexpr] Issues when delegating implicit copy constructor in constexpr function) PR c++/66450 * constexpr.c (cxx_eval_store_expression): Avoid messing up outer ctx->ctor. From-SVN: r224381 --- gcc/cp/ChangeLog | 6 ++++++ gcc/cp/constexpr.c | 18 ++++++++++++++---- .../g++.dg/cpp0x/constexpr-fwctor1.C | 19 +++++++++++++++++++ 3 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-fwctor1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a3dd1db9157..b6fdc107f6e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2015-06-11 Jason Merrill + + PR c++/66450 + * constexpr.c (cxx_eval_store_expression): Avoid messing up outer + ctx->ctor. + 2015-06-10 Jason Merrill PR c++/66289 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 8fa2eb3ac61..af6b39ecaf5 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -2671,11 +2671,13 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, } release_tree_vector (refs); - if ((AGGREGATE_TYPE_P (TREE_TYPE (t)) || VECTOR_TYPE_P (TREE_TYPE (t)))) + if (AGGREGATE_TYPE_P (type) || VECTOR_TYPE_P (type)) { /* Create a new CONSTRUCTOR in case evaluation of the initializer wants to modify it. */ - *valp = new_ctx.ctor = build_constructor (TREE_TYPE (t), NULL); + new_ctx.ctor = build_constructor (type, NULL); + if (*valp == NULL_TREE) + *valp = new_ctx.ctor; CONSTRUCTOR_NO_IMPLICIT_ZERO (new_ctx.ctor) = true; new_ctx.object = target; } @@ -2683,8 +2685,16 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, init = cxx_eval_constant_expression (&new_ctx, init, false, non_constant_p, overflow_p); if (target == object) - /* The hash table might have moved since the get earlier. */ - ctx->values->put (object, init); + { + /* 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 just replace + its contents. */ + CONSTRUCTOR_ELTS (*valp) = CONSTRUCTOR_ELTS (init); + else + *valp = init; + } else *valp = init; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-fwctor1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-fwctor1.C new file mode 100644 index 00000000000..d25c9c7c625 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-fwctor1.C @@ -0,0 +1,19 @@ +// PR c++/66450 +// { dg-do compile { target c++11 } } + +struct foo { + constexpr foo(int a); + constexpr foo(int a, int b, int c): a{a}, b{b}, c{c} {} + + int a, b, c; +}; + +constexpr foo make_foo(int a) { return foo{a, a+1, a+2}; } +constexpr foo::foo(int a): foo{make_foo(a)} {} + +int main() { + constexpr const foo f{3}; + static_assert(f.a == 3, ""); + static_assert(f.b == 4, ""); + static_assert(f.c == 5, ""); +} -- 2.30.2