We don't unshare CONSTRUCTORs as often during constexpr evaluation, so we need to unshare them here.
Many thanks to bin cheng for the analysis and initial patch. Tested x86_64-pc-linux-gnu, applying to trunk. * constexpr.c (cxx_eval_outermost_constant_expr): Don't assume CONSTRUCTORs are already unshared. --- gcc/cp/constexpr.c | 6 ++--- .../g++.dg/cpp0x/constexpr-array22.C | 27 +++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-array22.C diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 9306a7dce4a..3ca3b9ecd65 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -6347,10 +6347,10 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, if (!non_constant_p && overflow_p) non_constant_p = true; - /* Unshare the result unless it's a CONSTRUCTOR in which case it's already - unshared. */ + /* Unshare the result. */ bool should_unshare = true; - if (r == t || TREE_CODE (r) == CONSTRUCTOR) + if (r == t || (TREE_CODE (t) == TARGET_EXPR + && TARGET_EXPR_INITIAL (t) == r)) should_unshare = false; if (non_constant_p && !allow_non_constant) diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array22.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array22.C new file mode 100644 index 00000000000..80e24e2d697 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array22.C @@ -0,0 +1,27 @@ +// PR c++/93143 +// { dg-do run { target c++11 } } + +struct A { char a[2]; }; + +static constexpr A foo () { return A{1}; } + +void bar () +{ + A a = foo (); + if (a.a[0] != 1) + __builtin_abort(); +} + +void foobar () +{ + A x[] = { foo (), foo () }; + A a = foo (); + if (a.a[0] != 1) + __builtin_abort(); +} + +int main() +{ + bar(); + foobar(); +} base-commit: c9f70c28f33768726b227eb188575882cd40ed52 -- 2.18.1