]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++/modules+reflection: fix merging typedef struct { } A [PR124582]
authorPatrick Palka <ppalka@redhat.com>
Wed, 29 Apr 2026 12:48:31 +0000 (08:48 -0400)
committerPatrick Palka <ppalka@redhat.com>
Wed, 29 Apr 2026 12:48:31 +0000 (08:48 -0400)
r16-7903 changed the representation of typedefs to an unnamed type, such
as typedef struct { } A, so that we preserve both the unnamed and typedef
TYPE_DECL rather than replacing the unnamed decl.  This patch teaches
modules declaration merging to handle the new representation when streaming
in the unnamed decl, working around the fact that the unnamed decl isn't
visible to name lookup but still has the same DECL_NAME as the typedef decl.

PR c++/124582
PR c++/123810

gcc/cp/ChangeLog:

* module.cc (check_mergeable_decl) <case TYPE_DECL>: Handle
merging a typedef to an unnamed type with the -freflection
representation.

gcc/testsuite/ChangeLog:

* g++.dg/modules/anon-4.h: New test.
* g++.dg/modules/anon-4_a.H: New test.
* g++.dg/modules/anon-4_b.C: New test.

Reviewed-by: Jason Merrill <jason@redhat.com>
gcc/cp/module.cc
gcc/testsuite/g++.dg/modules/anon-4.h [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/anon-4_a.H [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/anon-4_b.C [new file with mode: 0644]

index bd4b919133bc576dd7fafd0cea09c9ea570d48b6..f2649f76bd79526dbe89a43bc6ce15a62074469e 100644 (file)
@@ -12159,6 +12159,20 @@ check_mergeable_decl (merge_kind mk, tree decl, tree ovl, merge_key const &key)
                           == key.ret))
                found = match;
            }
+         /* With -freflection, typedef struct { } A is now represented the same
+            as typedef struct A_ { } A except the TYPE_DECL for A_ is invisible
+            to name lookup, so we won't be able to find and match it directly.
+            But we will find the in-TU A (m_inner), through which we can obtain
+            the in-TU A_ when d_inner is the streamed-in A_.  */
+         else if (flag_reflection
+                  && TYPE_DECL_WAS_UNNAMED (d_inner)
+                  && DECL_ORIGINAL_TYPE (m_inner))
+           {
+             tree orig = TYPE_NAME (DECL_ORIGINAL_TYPE (m_inner));
+             if (TYPE_DECL_WAS_UNNAMED (orig)
+                 && DECL_NAME (orig) == DECL_NAME (d_inner))
+               found = orig;
+           }
          break;
 
        default:
diff --git a/gcc/testsuite/g++.dg/modules/anon-4.h b/gcc/testsuite/g++.dg/modules/anon-4.h
new file mode 100644 (file)
index 0000000..480fcd8
--- /dev/null
@@ -0,0 +1,3 @@
+typedef struct { } A;
+struct B { typedef struct { } C; };
+template<class T> struct D { typedef struct { } E; };
diff --git a/gcc/testsuite/g++.dg/modules/anon-4_a.H b/gcc/testsuite/g++.dg/modules/anon-4_a.H
new file mode 100644 (file)
index 0000000..56a1851
--- /dev/null
@@ -0,0 +1,6 @@
+// PR c++/124582
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-fmodule-header -freflection" }
+// { dg-module-cmi {} }
+
+#include "anon-4.h"
diff --git a/gcc/testsuite/g++.dg/modules/anon-4_b.C b/gcc/testsuite/g++.dg/modules/anon-4_b.C
new file mode 100644 (file)
index 0000000..c71a308
--- /dev/null
@@ -0,0 +1,6 @@
+// PR c++/124582
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-fmodules -fno-module-lazy -freflection" }
+
+#include "anon-4.h"
+import "anon-4_a.H";