https://gcc.gnu.org/g:cafd139767627981b675daff29933edcdd210230

commit r16-9754-gcafd139767627981b675daff29933edcdd210230
Author: Jakub Jelinek <[email protected]>
Date:   Mon Aug 31 09:38:43 2026 +0200

    c++: Fix mangling of aggregates containing std::meta::info [PR126922]
    
    We ICE during mangling on the following testcase.
    There are two problems on it.
    One is the use of build_zero_cst for skipped members when
    using designated initializers.  build_zero_cst is a gcc/tree.cc
    function, so it doesn't know about META_TYPE and how to create a zero
    constant for it.
    We could call probably build_zero_init instead, but it does significantly
    more work and apparently (from what I've been playing with e.g. using
    pointer-to-data-member types etc.) it isn't needed except for the reflection
    case, so this patch just calls get_null_reflection () for reflections
    and keeps using build_zero_cst for everything else.
    Another problem is that we mangle
    A { .a = {}, .b = {} }
    vs.
    A { .a = {} }
    differently, although both have the same value.  If a and b fields have
    pointer-to-data-member type instead (or int), the zero initialized members
    are skipped from the tl value list, and this patch changes zero_init_expr_p
    so that it handles null reflections the same way (before P4101 mangling
    is probably the only way to observe whether null reflection is all zeros or
    not).
    
    2026-08-31  Jakub Jelinek  <[email protected]>
    
            PR c++/126922
            * mangle.cc (write_expression): For CONSTRUCTOR skipped
            member of std::meta::info type, call write_expression on
            get_null_reflection rather than build_zero_cst.
            * tree.cc (zero_init_expr_p): If type is std::meta::info,
            return true iff t is null reflection.
    
            * g++.dg/reflect/mangle10.C: New test.
    
    Reviewed-by: Jason Merrill <[email protected]>
    (cherry picked from commit 7c459132de478dbede44e323e195073e8d2bca55)

Diff:
---
 gcc/cp/mangle.cc                        | 10 ++++++++--
 gcc/cp/tree.cc                          |  2 ++
 gcc/testsuite/g++.dg/reflect/mangle10.C | 26 ++++++++++++++++++++++++++
 3 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index 3d0da42939e7..1779b28349fd 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -3888,8 +3888,14 @@ write_expression (tree expr)
                                if (field == ce->index)
                                  break;
                                if (abi_check (21))
-                                 write_expression (build_zero_cst
-                                                   (TREE_TYPE (field)));
+                                 {
+                                   tree type = TREE_TYPE (field), expr;
+                                   if (REFLECTION_TYPE_P (type))
+                                     expr = get_null_reflection ();
+                                   else
+                                     expr = build_zero_cst (type);
+                                   write_expression (expr);
+                                 }
                                field = DECL_CHAIN (field);
                              }
                          }
diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 084dfd70f6bd..ffc347ff15ef 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -5301,6 +5301,8 @@ zero_init_expr_p (tree t)
     return false;
   if (TYPE_PTRMEM_P (type))
     return null_member_pointer_value_p (t);
+  if (REFLECTION_TYPE_P (type))
+    return REFLECT_EXPR_P (t) && REFLECT_EXPR_HANDLE (t) == unknown_type_node;
   if (TREE_CODE (t) == CONSTRUCTOR)
     {
       if (COMPOUND_LITERAL_P (t)
diff --git a/gcc/testsuite/g++.dg/reflect/mangle10.C 
b/gcc/testsuite/g++.dg/reflect/mangle10.C
new file mode 100644
index 000000000000..84751e3fe8f2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/mangle10.C
@@ -0,0 +1,26 @@
+// PR c++/126922
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection -O0 -fno-short-enums" }
+
+struct A { decltype (^^::) a, b; };
+struct B { A c; };
+
+template <int N, auto C>
+[[gnu::noipa]] void
+foo ()
+{
+}
+
+int
+main ()
+{
+  foo <1, A { .a = {}, .b = {} }> ();
+  foo <2, A { .a = {} }> ();
+  foo <3, A { .b = {} }> ();
+  foo <4, B { .c = {} }> ();
+}
+
+// { dg-final { scan-assembler "_Z3fooILi1ETnDaXtl1AEEEvv" } }
+// { dg-final { scan-assembler "_Z3fooILi2ETnDaXtl1AEEEvv" } }
+// { dg-final { scan-assembler "_Z3fooILi3ETnDaXtl1AEEEvv" } }
+// { dg-final { scan-assembler "_Z3fooILi4ETnDaXtl1BEEEvv" } }

Reply via email to