On 11/21/25 11:39 AM, Jakub Jelinek wrote:
Hi!
The following testcase ICEs, because the constexpr ctor in C++14
or later doesn't contain any member initializers and so the
massage_constexpr_body -> build_constexpr_constructor_member_initializers
-> build_data_member_initialization member initialization discovery
looks at the ctor body instead. And while it has various
cases where it punts, including COMPONENT_REF with a VAR_DECL as first
operand on lhs of INIT_EXPR, here there is COMPONENT_REF with
several COMPONENT_REFs and VAR_DECL only inside the innermost.
The following patch makes sure we punt on those as well, instead of
blindly assuming it is anonymous union member initializer or asserting
it is a vtable store.
An alternative to this would be some flag on the INIT_EXPRs created
by perform_member_init and let build_data_member_initialization inspect
only INIT_EXPRs with that flag set.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
OK.
2025-11-21 Jakub Jelinek <[email protected]>
PR c++/121445
* constexpr.cc (build_data_member_initialization): Just return
false if member is COMPONENT_REF of COMPONENT_REF with
VAR_P get_base_address.
* g++.dg/cpp1y/constexpr-121445.C: New test.
--- gcc/cp/constexpr.cc.jj 2025-11-14 11:00:14.357583931 +0100
+++ gcc/cp/constexpr.cc 2025-11-20 13:34:39.637321699 +0100
@@ -477,6 +477,9 @@ build_data_member_initialization (tree t
if (TREE_CODE (aggr) != COMPONENT_REF)
/* Normal member initialization. */
member = TREE_OPERAND (member, 1);
+ else if (VAR_P (get_base_address (aggr)))
+ /* Initializing a local variable, don't add anything. */
+ return true;
else if (ANON_AGGR_TYPE_P (TREE_TYPE (aggr)))
/* Initializing a member of an anonymous union. */
return build_anon_member_initialization (member, init, vec);
--- gcc/testsuite/g++.dg/cpp1y/constexpr-121445.C.jj 2025-11-20
13:40:02.779804563 +0100
+++ gcc/testsuite/g++.dg/cpp1y/constexpr-121445.C 2025-11-20
13:41:35.352511923 +0100
@@ -0,0 +1,19 @@
+// PR c++/121445
+// { dg-do compile { target c++14 } }
+
+struct D {
+ const char *d;
+ const char *foo () { return ""; }; // { dg-message "declared here"
"" { target c++20_down } }
+ constexpr D () : d (foo ()) {} // { dg-error "call to non-'constexpr'
function 'const char\\\* D::foo\\\(\\\)'" "" { target c++20_down } }
+ constexpr D &operator= (const char *) { return *this; }
+};
+struct S {
+ constexpr S ()
+ {
+ struct A { D a; };
+ struct B { A b; };
+ struct C { B c; };
+ C d {};
+ d.c.b.a = "";
+ }
+};
Jakub