]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++/modules: Import purview using-directives in the same module [PR122279]
authorNathaniel Shead <nathanieloshead@gmail.com>
Wed, 15 Oct 2025 07:13:38 +0000 (18:13 +1100)
committerNathaniel Shead <nathanieloshead@gmail.com>
Sat, 18 Oct 2025 13:53:31 +0000 (00:53 +1100)
[namespace.qual] p1 says that a namespace nominated by a using-directive
is searched if the using-directive precedes that point.

[basic.lookup.general] p2 says that a declaration in a different TU
within a module purview is visible if either the declaration is
exported, or the other TU is part of the same module as the point of
lookup.  This patch implements the second half of that.

PR c++/122279

gcc/cp/ChangeLog:

* module.cc (depset::hash::add_namespace_entities): Seed any
purview using-decls.
(module_state::write_using_directives): Stream if the udir was
exported or not.
(module_state::read_using_directives): Add the using-directive
if it's either exported or part of this module.

gcc/testsuite/ChangeLog:

* g++.dg/modules/namespace-13_b.C: Adjust expected results.
* g++.dg/modules/namespace-13_c.C: Test non-exported
using-directive is not used.
* g++.dg/modules/namespace-14_a.C: New test.
* g++.dg/modules/namespace-14_b.C: New test.
* g++.dg/modules/namespace-14_c.C: New test.
* g++.dg/modules/namespace-14_d.C: New test.

Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
Reviewed-by: Patrick Palka <ppalka@redhat.com>
Reviewed-by: Jason Merrill <jason@redhat.com>
gcc/cp/module.cc
gcc/testsuite/g++.dg/modules/namespace-13_b.C
gcc/testsuite/g++.dg/modules/namespace-13_c.C
gcc/testsuite/g++.dg/modules/namespace-14_a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/namespace-14_b.C [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/namespace-14_c.C [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/namespace-14_d.C [new file with mode: 0644]

index bdc7e6af874898814cddf47c7160d095908512b0..ed0d69cead45cf073aa76d6c76a9b87352f1bdd2 100644 (file)
@@ -14761,10 +14761,11 @@ depset::hash::add_namespace_entities (tree ns, bitmap partitions)
 
   /* Seed any using-directives so that we emit the relevant namespaces.  */
   for (tree udir : NAMESPACE_LEVEL (ns)->using_directives)
-    if (TREE_CODE (udir) == USING_DECL && DECL_MODULE_EXPORT_P (udir))
+    if (TREE_CODE (udir) == USING_DECL && DECL_MODULE_PURVIEW_P (udir))
       {
        make_dependency (USING_DECL_DECLS (udir), depset::EK_NAMESPACE);
-       count++;
+       if (DECL_MODULE_EXPORT_P (udir))
+         count++;
       }
 
   if (count)
@@ -17397,14 +17398,16 @@ module_state::write_using_directives (elf_out *to, depset::hash &table,
       tree parent = parent_dep->get_entity ();
       for (auto udir : NAMESPACE_LEVEL (parent)->using_directives)
        {
-         if (TREE_CODE (udir) != USING_DECL || !DECL_MODULE_EXPORT_P (udir))
+         if (TREE_CODE (udir) != USING_DECL || !DECL_MODULE_PURVIEW_P (udir))
            continue;
+         bool exported = DECL_MODULE_EXPORT_P (udir);
          tree target = USING_DECL_DECLS (udir);
          depset *target_dep = table.find_dependency (target);
          gcc_checking_assert (target_dep);
 
          dump () && dump ("Writing using-directive in %N for %N",
                           parent, target);
+         sec.u (exported);
          write_namespace (sec, parent_dep);
          write_namespace (sec, target_dep);
          ++num;
@@ -17441,13 +17444,15 @@ module_state::read_using_directives (unsigned num)
 
   for (unsigned ix = 0; ix != num; ++ix)
     {
+      bool exported = sec.u ();
       tree parent = read_namespace (sec);
       tree target = read_namespace (sec);
       if (sec.get_overrun ())
        break;
 
       dump () && dump ("Read using-directive in %N for %N", parent, target);
-      add_using_namespace (parent, target);
+      if (exported || is_module () || is_partition ())
+       add_using_namespace (parent, target);
     }
 
   dump.outdent ();
index 1b309617814ae5182a38b7d1139837d45c174a64..4c2a7d9d12c77ec92bb4fa666d37917c9f20ad48 100644 (file)
@@ -6,6 +6,7 @@ module;
 
 namespace gmf::blah {}
 namespace gmf::other {}
+using namespace gmf::other;  // not emitted
 
 export module b;
 export import a;
@@ -21,7 +22,7 @@ namespace c {
   using namespace a;
 }
 
-// { dg-final { scan-lang-dump {Using-directives 3} module } }
+// { dg-final { scan-lang-dump {Using-directives 4} module } }
 
 // { dg-final { scan-lang-dump {Writing using-directive in '::b' for '::a'} module } }
 // { dg-final { scan-lang-dump {Writing using-directive in '::b' for '::gmf::blah'} module } }
@@ -30,3 +31,4 @@ namespace c {
 
 // { dg-final { scan-lang-dump {Writing namespace:[0-9]* '::gmf::blah', public} module } }
 // { dg-final { scan-lang-dump-not {Writing namespace:[0-9]* '::gmf::other'} module } }
+// { dg-final { scan-lang-dump-not {Writing using-directive in '::' for '::gmf::other'} module } }
index d04ef37cdbf52ae7255a0e38698e45844ecf8096..51f4dfc47a23289b145a6f2dcdf1cb28756b64ec 100644 (file)
@@ -15,3 +15,6 @@ static_assert(b::f() == 42);
 static_assert(b::g() == 123);
 static_assert(c::other::h() == 99);
 static_assert(y::i() == 5);
+
+// unexported 'using namespace a'; should not be visible in 'c'
+int result = c::f();  // { dg-error "'f' is not a member of 'c'" }
diff --git a/gcc/testsuite/g++.dg/modules/namespace-14_a.C b/gcc/testsuite/g++.dg/modules/namespace-14_a.C
new file mode 100644 (file)
index 0000000..c26964e
--- /dev/null
@@ -0,0 +1,11 @@
+// PR c++/122279
+// { dg-additional-options "-fmodules" }
+// { dg-module-cmi M:part }
+
+module M:part;
+namespace foo {
+  void go();
+}
+namespace bar {
+  using namespace foo;
+}
diff --git a/gcc/testsuite/g++.dg/modules/namespace-14_b.C b/gcc/testsuite/g++.dg/modules/namespace-14_b.C
new file mode 100644 (file)
index 0000000..987c768
--- /dev/null
@@ -0,0 +1,12 @@
+// PR c++/122279
+// { dg-additional-options "-fmodules" }
+// { dg-module-cmi M }
+
+export module M;
+import :part;
+namespace qux {
+  using namespace bar;
+}
+void test1() {
+  bar::go();
+}
diff --git a/gcc/testsuite/g++.dg/modules/namespace-14_c.C b/gcc/testsuite/g++.dg/modules/namespace-14_c.C
new file mode 100644 (file)
index 0000000..0896609
--- /dev/null
@@ -0,0 +1,7 @@
+// PR c++/122279
+// { dg-additional-options "-fmodules" }
+
+module M;
+void test2() {
+  qux::go();
+}
diff --git a/gcc/testsuite/g++.dg/modules/namespace-14_d.C b/gcc/testsuite/g++.dg/modules/namespace-14_d.C
new file mode 100644 (file)
index 0000000..e5a55ed
--- /dev/null
@@ -0,0 +1,10 @@
+// PR c++/122279
+// { dg-additional-options "-fmodules" }
+// { dg-module-cmi M:other_part }
+
+module M:other_part;
+import :part;
+
+void test3() {
+  bar::go();
+}