[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.