diff options
author | Jason Merrill <jason@redhat.com> | 2025-01-28 13:11:50 -0500 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2025-01-28 17:19:02 -0500 |
commit | c3b0b98b3ba57840ab2cfbc9d44d001c1e9167bf (patch) | |
tree | e25adef3450b177922fb415e9d97db857fcbb13d /gcc | |
parent | d0f230adf0e888d9218a123ac620c9a5b3020c2d (diff) | |
download | gcc-c3b0b98b3ba57840ab2cfbc9d44d001c1e9167bf.zip gcc-c3b0b98b3ba57840ab2cfbc9d44d001c1e9167bf.tar.gz gcc-c3b0b98b3ba57840ab2cfbc9d44d001c1e9167bf.tar.bz2 |
c++: constexpr VEC_INIT_EXPR [PR118285]
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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/constexpr.cc | 9 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/initlist-opt7.C | 41 |
2 files changed, 49 insertions, 1 deletions
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index 94a4680..58bed6f 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 0000000..f55ef5b --- /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 (), ""); |