On Wed, Oct 15, 2025 at 12:29:47PM -0400, Patrick Palka wrote:
> 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.
> 

Thanks for the review!  I think 'c' and 'u' should be equally space
efficient in this case (both will be a single byte), but 'c' is less
complex and so would probably be the better choice regardless.

Another approach would be to partition the using-directives and emit
e.g. all exported before all non-exported, and then perhaps allow
importers to skip reading the non-exported directives entirely unless
they know they'll need them.  I'm not sure there's much benefit to this
though, so I didn't bother; maybe can revisit at some point.

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