Tested x86_64-pc-linux-gnu, applying to trunk. -- 8< --
cxx_eval_vec_init_1 was doing the wrong thing for an array of self-referential class type; just evaluating the TARGET_EXPR initializer creates a new object that refers to the TARGET_EXPR_SLOT, if we want it to refer properly to the initialization target we need to provide it. PR c++/118285 gcc/cp/ChangeLog: * constexpr.cc (cxx_eval_vec_init_1): Build INIT_EXPR for initializing a class. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/initlist-opt7.C: New test. --- gcc/cp/constexpr.cc | 9 ++++- gcc/testsuite/g++.dg/cpp0x/initlist-opt7.C | 41 ++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/initlist-opt7.C diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index 94a468056f9..58bed6f8965 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -5624,7 +5624,11 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init, if (init == void_node) /* Trivial default-init, don't do anything to the CONSTRUCTOR. */ return ctx->ctor; - eltinit = cxx_eval_constant_expression (&new_ctx, init, lval, + eltinit = init; + if (CLASS_TYPE_P (elttype) && new_ctx.object) + /* Clarify what object is being initialized (118285). */ + eltinit = build2 (INIT_EXPR, elttype, new_ctx.object, eltinit); + eltinit = cxx_eval_constant_expression (&new_ctx, eltinit, lval, non_constant_p, overflow_p); reuse = i == 0; } @@ -5637,6 +5641,9 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init, eltinit = (perform_implicit_conversion_flags (elttype, eltinit, complain, LOOKUP_IMPLICIT|LOOKUP_NO_NARROWING)); + if (CLASS_TYPE_P (elttype) && new_ctx.object) + /* Clarify what object is being initialized (118285). */ + eltinit = build2 (INIT_EXPR, elttype, new_ctx.object, eltinit); eltinit = cxx_eval_constant_expression (&new_ctx, eltinit, lval, non_constant_p, overflow_p); } diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-opt7.C b/gcc/testsuite/g++.dg/cpp0x/initlist-opt7.C new file mode 100644 index 00000000000..f55ef5b77c5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-opt7.C @@ -0,0 +1,41 @@ +// PR c++/118285 +// { dg-do compile { target c++20 } } + +#include <initializer_list> + +struct A { + char *a; + union { char b[8]; long c; }; + constexpr A (const char *x) : a(b) + { + for (int i = 0; i < 8; ++i) + b[i] = 0; + } + constexpr ~A () + { + if (!foo ()) + bar (c); + } + constexpr bool foo () + { + char *x = a; + if (x == b) + return true; + return false; + } + constexpr void bar (long) {} +}; + +constexpr void +baz (std::initializer_list<A>) +{ +} + +constexpr bool +qux () +{ + baz ({""}); + return true; +} + +static_assert (qux (), ""); base-commit: d0f230adf0e888d9218a123ac620c9a5b3020c2d -- 2.48.0