On Wed, 15 Oct 2025, Nathaniel Shead wrote:

> Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?
> 
> -- >8 --
> 
> [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 <[email protected]>
> ---
>  gcc/cp/module.cc                              | 13 +++++++++----
>  gcc/testsuite/g++.dg/modules/namespace-13_b.C |  4 +++-
>  gcc/testsuite/g++.dg/modules/namespace-13_c.C |  3 +++
>  gcc/testsuite/g++.dg/modules/namespace-14_a.C | 11 +++++++++++
>  gcc/testsuite/g++.dg/modules/namespace-14_b.C | 12 ++++++++++++
>  gcc/testsuite/g++.dg/modules/namespace-14_c.C |  7 +++++++
>  gcc/testsuite/g++.dg/modules/namespace-14_d.C | 10 ++++++++++
>  7 files changed, 55 insertions(+), 5 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/modules/namespace-14_a.C
>  create mode 100644 gcc/testsuite/g++.dg/modules/namespace-14_b.C
>  create mode 100644 gcc/testsuite/g++.dg/modules/namespace-14_c.C
>  create mode 100644 gcc/testsuite/g++.dg/modules/namespace-14_d.C
> 
> diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
> index bdc7e6af874..ed0d69cead4 100644
> --- a/gcc/cp/module.cc
> +++ b/gcc/cp/module.cc
> @@ -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);

Perhaps c instead of u? Would be slightly more space efficient.

LGTM besides that, but deferring to Jason for proper review.

>         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 ();
> diff --git a/gcc/testsuite/g++.dg/modules/namespace-13_b.C 
> b/gcc/testsuite/g++.dg/modules/namespace-13_b.C
> index 1b309617814..4c2a7d9d12c 100644
> --- a/gcc/testsuite/g++.dg/modules/namespace-13_b.C
> +++ b/gcc/testsuite/g++.dg/modules/namespace-13_b.C
> @@ -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 } }
> diff --git a/gcc/testsuite/g++.dg/modules/namespace-13_c.C 
> b/gcc/testsuite/g++.dg/modules/namespace-13_c.C
> index d04ef37cdbf..51f4dfc47a2 100644
> --- a/gcc/testsuite/g++.dg/modules/namespace-13_c.C
> +++ b/gcc/testsuite/g++.dg/modules/namespace-13_c.C
> @@ -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
> index 00000000000..c26964e2538
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/modules/namespace-14_a.C
> @@ -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
> index 00000000000..987c76883b1
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/modules/namespace-14_b.C
> @@ -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
> index 00000000000..08966091525
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/modules/namespace-14_c.C
> @@ -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
> index 00000000000..e5a55ed9524
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/modules/namespace-14_d.C
> @@ -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();
> +}
> -- 
> 2.51.0
> 
> 

Reply via email to