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
>
>