c++: Seed imported bindings [PR 99039]
authorNathan Sidwell <nathan@acm.org>
Fri, 12 Feb 2021 16:43:09 +0000 (08:43 -0800)
committerNathan Sidwell <nathan@acm.org>
Fri, 12 Feb 2021 21:50:03 +0000 (13:50 -0800)
As mentioned in 99040's fix, we can get inter-module using decls.  If the
using decl is the only reference to an import, we'll have failed to
seed our imports leading to an assertion failure.  The fix is
straight-forwards, check binding contents when seeding imports.

gcc/cp/
* module.cc (module_state::write_cluster): Check bindings for
imported using-decls.
gcc/testsuite/
* g++.dg/modules/pr99039_a.C: New.
* g++.dg/modules/pr99039_b.C: New.

gcc/cp/module.cc
gcc/testsuite/g++.dg/modules/pr99039_a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/pr99039_b.C [new file with mode: 0644]

index 37ccddc74a578586d550aacf455dddf5d91072e0..520494f2543a3d8884df5e90e55fe0bd208a2e78 100644 (file)
@@ -3108,7 +3108,8 @@ private:
   unsigned section;
 #if CHECKING_P
   int importedness;            /* Checker that imports not occurring
-                                  inappropriately.  */
+                                  inappropriately.  +ve imports ok,
+                                  -ve imports not ok.  */
 #endif
 
 public:
@@ -14632,13 +14633,36 @@ module_state::write_cluster (elf_out *to, depset *scc[], unsigned size,
        {
          depset *dep = b->deps[jx];
 
-         if (!dep->is_binding ()
-             && dep->is_import () && !TREE_VISITED (dep->get_entity ()))
+         if (dep->is_binding ())
            {
-             tree import = dep->get_entity ();
+             /* A cross-module using decl could be here.  */
+             for (unsigned ix = dep->deps.length (); --ix;)
+               {
+                 depset *bind = dep->deps[ix];
+                 if (bind->get_entity_kind () == depset::EK_USING
+                     && bind->deps[1]->is_import ())
+                   {
+                     tree import = bind->deps[1]->get_entity ();
+                     if (!TREE_VISITED (import))
+                       {
+                         sec.tree_node (import);
+                         dump (dumper::CLUSTER)
+                           && dump ("Seeded import %N", import);
+                       }
+                   }
+               }
+             /* Also check the namespace itself.  */
+             dep = dep->deps[0];
+           }
 
-             sec.tree_node (import);
-             dump (dumper::CLUSTER) && dump ("Seeded import %N", import);
+         if (dep->is_import ())
+           {
+             tree import = dep->get_entity ();
+             if (!TREE_VISITED (import))
+               {
+                 sec.tree_node (import);
+                 dump (dumper::CLUSTER) && dump ("Seeded import %N", import);
+               }
            }
        }
     }
diff --git a/gcc/testsuite/g++.dg/modules/pr99039_a.C b/gcc/testsuite/g++.dg/modules/pr99039_a.C
new file mode 100644 (file)
index 0000000..56041e9
--- /dev/null
@@ -0,0 +1,9 @@
+// PR c++/99039
+// { dg-additional-options -fmodules-ts }
+export  module  format;
+// { dg-module-cmi format }
+
+export namespace NS
+{
+void Format ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/pr99039_b.C b/gcc/testsuite/g++.dg/modules/pr99039_b.C
new file mode 100644 (file)
index 0000000..6fb76f5
--- /dev/null
@@ -0,0 +1,9 @@
+// { dg-additional-options -fmodules-ts }
+export  module  hello;
+// { dg-module-cmi hello }
+import  format;
+
+export namespace NS
+{
+using NS::Format;
+}