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