[PATCH] c++: Fix mangling of aggregates containing std::meta::info [PR126922]
Jakub Jelinek <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <aoVaaoO-LVX1trek@tucnak> |
Hi!
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).
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
2026-08-19 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.
--- gcc/cp/mangle.cc.jj 2026-08-18 17:49:06.122775263 +0200
+++ gcc/cp/mangle.cc 2026-08-18 20:34:38.984625917 +0200
@@ -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);
}
}
--- gcc/cp/tree.cc.jj 2026-08-18 20:15:37.371873189 +0200
+++ gcc/cp/tree.cc 2026-08-18 20:39:28.758837710 +0200
@@ -5328,6 +5328,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 null_reflection_p (t);
if (TREE_CODE (t) == CONSTRUCTOR)
{
if (COMPOUND_LITERAL_P (t)
--- gcc/testsuite/g++.dg/reflect/mangle10.C.jj 2026-08-18 20:42:48.583226296 +0200
+++ gcc/testsuite/g++.dg/reflect/mangle10.C 2026-08-18 20:42:31.088454926 +0200
@@ -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" } }
Jakub