]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++/modules: Keep entity mapping info across duplicate_decls [PR99241]
authorNathaniel Shead <nathanieloshead@gmail.com>
Mon, 8 Jul 2024 04:35:58 +0000 (14:35 +1000)
committerNathaniel Shead <nathanieloshead@gmail.com>
Thu, 11 Jul 2024 11:05:29 +0000 (21:05 +1000)
When duplicate_decls finds a match with an existing imported
declaration, it clears DECL_LANG_SPECIFIC of the olddecl and replaces it
with the contents of newdecl; this clears DECL_MODULE_ENTITY_P causing
an ICE if the same declaration is imported again later.

This fixes the issue by ensuring that the flag is transferred to newdecl
before clearing so that it ends up on olddecl again.

For future-proofing we also do the same with DECL_MODULE_KEYED_DECLS_P,
though because we don't yet support textual redefinition merging we
can't yet test this works as intended.  I don't expect it's possible for
a new declaration already to have extra keyed decls mismatching that of
the old declaration though, so I don't do anything with 'keyed_map' at
this time.

PR c++/99241

gcc/cp/ChangeLog:

* decl.cc (duplicate_decls): Merge module entity information.

gcc/testsuite/ChangeLog:

* g++.dg/modules/pr99241_a.H: New test.
* g++.dg/modules/pr99241_b.H: New test.
* g++.dg/modules/pr99241_c.C: New test.

Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
gcc/cp/decl.cc
gcc/testsuite/g++.dg/modules/pr99241_a.H [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/pr99241_b.H [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/pr99241_c.C [new file with mode: 0644]

index d4c65a199329b3fa3f6981db2ae6bf1343430ee5..edf4c155bf77e5c1b733dd1ea5ef1ca1d2fff974 100644 (file)
@@ -3139,6 +3139,16 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
   if (TREE_CODE (newdecl) == FIELD_DECL)
     DECL_PACKED (olddecl) = DECL_PACKED (newdecl);
 
+  /* Merge module entity mapping information.  */
+  if (DECL_LANG_SPECIFIC (olddecl)
+      && (DECL_MODULE_ENTITY_P (olddecl)
+         || DECL_MODULE_KEYED_DECLS_P (olddecl)))
+    {
+      retrofit_lang_decl (newdecl);
+      DECL_MODULE_ENTITY_P (newdecl) = DECL_MODULE_ENTITY_P (olddecl);
+      DECL_MODULE_KEYED_DECLS_P (newdecl) = DECL_MODULE_KEYED_DECLS_P (olddecl);
+    }
+
   /* The DECL_LANG_SPECIFIC information in OLDDECL will be replaced
      with that from NEWDECL below.  */
   if (DECL_LANG_SPECIFIC (olddecl))
diff --git a/gcc/testsuite/g++.dg/modules/pr99241_a.H b/gcc/testsuite/g++.dg/modules/pr99241_a.H
new file mode 100644 (file)
index 0000000..c7031f0
--- /dev/null
@@ -0,0 +1,3 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+void terminate();
diff --git a/gcc/testsuite/g++.dg/modules/pr99241_b.H b/gcc/testsuite/g++.dg/modules/pr99241_b.H
new file mode 100644 (file)
index 0000000..c7031f0
--- /dev/null
@@ -0,0 +1,3 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+void terminate();
diff --git a/gcc/testsuite/g++.dg/modules/pr99241_c.C b/gcc/testsuite/g++.dg/modules/pr99241_c.C
new file mode 100644 (file)
index 0000000..7f2b1bb
--- /dev/null
@@ -0,0 +1,5 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy" }
+
+import "pr99241_a.H";
+void terminate();
+import "pr99241_b.H";