diff mbox series

c++: Duplicate namespace bindings [PR 99245]

Message ID 03f18890-38d7-ae04-a66f-817203ffc70d@acm.org
State New
Headers show
Series c++: Duplicate namespace bindings [PR 99245] | expand

Commit Message

Nathan Sidwell March 5, 2021, 8:53 p.m. UTC
Header units can declare the same entity, and this can lead to one of 
them containing a (non-using) binding to an import.  If one gets the 
cluster ordering just right, an assert will trigger.  Relax that assert.

         PR c++/99245
         gcc/cp/
         * module.cc (module_state::write_cluster): Relax binding assert.
         gcc/testsuite/
         * g++.dg/modules/pr99245_a.H: New.
         * g++.dg/modules/pr99245_b.H: New.
diff mbox series

Patch

diff --git c/gcc/cp/module.cc w/gcc/cp/module.cc
index 31bbf9776dd..48862dd9bbc 100644
--- c/gcc/cp/module.cc
+++ w/gcc/cp/module.cc
@@ -14496,20 +14496,25 @@  module_state::write_cluster (elf_out *to, depset *scc[], unsigned size,
 	  gcc_unreachable ();
 
 	case depset::EK_BINDING:
-	  dump (dumper::CLUSTER)
-	    && dump ("[%u]=%s %P", ix, b->entity_kind_name (),
-		     b->get_entity (), b->get_name ());
-	  for (unsigned jx = b->deps.length (); jx--;)
-	    {
-	      depset *dep = b->deps[jx];
-	      if (jx)
-		gcc_checking_assert (dep->get_entity_kind () == depset::EK_USING
-				     || TREE_VISITED (dep->get_entity ()));
-	      else
-		gcc_checking_assert (dep->get_entity_kind ()
-				     == depset::EK_NAMESPACE
-				     && dep->get_entity () == b->get_entity ());
-	    }
+	  {
+	    dump (dumper::CLUSTER)
+	      && dump ("[%u]=%s %P", ix, b->entity_kind_name (),
+		       b->get_entity (), b->get_name ());
+	    depset *ns_dep = b->deps[0];
+	    gcc_checking_assert (ns_dep->get_entity_kind ()
+				 == depset::EK_NAMESPACE
+				 && ns_dep->get_entity () == b->get_entity ());
+	    for (unsigned jx = b->deps.length (); --jx;)
+	      {
+		depset *dep = b->deps[jx];
+		// We could be declaring something that is also a
+		// (merged) import
+		gcc_checking_assert (dep->is_import ()
+				     || TREE_VISITED (dep->get_entity ())
+				     || (dep->get_entity_kind ()
+					 == depset::EK_USING));
+	      }
+	  }
 	  break;
 
 	case depset::EK_DECL:
diff --git c/gcc/testsuite/g++.dg/modules/pr99245_a.H w/gcc/testsuite/g++.dg/modules/pr99245_a.H
new file mode 100644
index 00000000000..94c6bf11995
--- /dev/null
+++ w/gcc/testsuite/g++.dg/modules/pr99245_a.H
@@ -0,0 +1,5 @@ 
+// PR 99245 ICE writing out user of type_info
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+namespace std { class type_info {}; }
diff --git c/gcc/testsuite/g++.dg/modules/pr99245_b.H w/gcc/testsuite/g++.dg/modules/pr99245_b.H
new file mode 100644
index 00000000000..548c2720ef5
--- /dev/null
+++ w/gcc/testsuite/g++.dg/modules/pr99245_b.H
@@ -0,0 +1,9 @@ 
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+namespace std { class type_info; }
+
+import "pr99245_a.H";
+
+namespace std {
+  const type_info* __cxa_exception_type () noexcept;
+}