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

Reply via email to