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? 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
