On Fri, 20 Mar 2026, Nathaniel Shead wrote: > Bootstrapped and regtested (so far just modules.exp) on > x86_64-pc-linux-gnu. Does this seem like a reasonable change to make? > > -- >8 -- > > As discussed in libstdc++/124268, the std module relies on exporting > using-declarations for various entities, but on some targets the > relevant declarations have internal linkage. > > Given we already support exposures of such internal linkage entities for > migration purposes, it seems reasonable to allow the same for > using-declarations.
Agreed. This is OK by me, thanks a lot! > > PR libstdc++/124268 > > gcc/ChangeLog: > > * doc/invoke.texi: Note that -Wexpose-global-module-tu-local > also applies to 'export using' declarations. > > gcc/cp/ChangeLog: > > * module.cc (instantiating_tu_local_entity): Use pedwarn instead > of warning. > (depset::hash::add_binding_entity): Don't skip exported > using-decls as TU-local entities. > (depset::hash::finalize_dependencies): Don't attempt to complain > again about using-decls referencing TU-local entities. > * name-lookup.cc (check_can_export_using_decl): Demote the error > to a warning for using-decls of GMF vars or functions. > > gcc/testsuite/ChangeLog: > > * g++.dg/modules/using-34_a.C: New test. > * g++.dg/modules/using-34_b.C: New test. > > Signed-off-by: Nathaniel Shead <[email protected]> > --- > gcc/cp/module.cc | 10 ++++- > gcc/cp/name-lookup.cc | 46 +++++++++++++++++------ > gcc/doc/invoke.texi | 3 +- > gcc/testsuite/g++.dg/modules/using-34_a.C | 15 ++++++++ > gcc/testsuite/g++.dg/modules/using-34_b.C | 22 +++++++++++ > 5 files changed, 82 insertions(+), 14 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/modules/using-34_a.C > create mode 100644 gcc/testsuite/g++.dg/modules/using-34_b.C > > diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc > index 83d24a3267d..8ee15f41aeb 100644 > --- a/gcc/cp/module.cc > +++ b/gcc/cp/module.cc > @@ -14494,7 +14494,7 @@ instantiating_tu_local_entity (tree decl) > return false; > > auto_diagnostic_group d; > - warning (OPT_Wexpose_global_module_tu_local, > + pedwarn (input_location, OPT_Wexpose_global_module_tu_local, > "instantiation exposes TU-local entity %qD", decl); > inform (DECL_SOURCE_LOCATION (decl), "declared here"); > > @@ -14934,7 +14934,8 @@ depset::hash::add_binding_entity (tree decl, > WMB_Flags flags, void *data_) > return false; > > bool internal_decl = false; > - if (!header_module_p () && is_tu_local_entity (decl)) > + if (!header_module_p () && is_tu_local_entity (decl) > + && !((flags & WMB_Using) && (flags & WMB_Export))) > { > /* A TU-local entity. For ADL we still need to create bindings > for internal-linkage functions attached to a named module. */ > @@ -15960,6 +15961,11 @@ depset::hash::finalize_dependencies () > if (dep->is_tu_local ()) > continue; > > + /* We already complained about usings of non-external entities in > + check_can_export_using_decl, don't do it again here. */ > + if (dep->get_entity_kind () == EK_USING) > + continue; > + > if (dep->is_exposure ()) > { > bool explained = diagnose_bad_internal_ref (dep); > diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc > index 13aafab4e68..5a642e48851 100644 > --- a/gcc/cp/name-lookup.cc > +++ b/gcc/cp/name-lookup.cc > @@ -5480,18 +5480,42 @@ check_can_export_using_decl (tree binding) > && !DECL_MODULE_EXPORT_P (not_tmpl))) > { > auto_diagnostic_group d; > - error ("exporting %q#D that does not have external linkage", > - binding); > - if (linkage == lk_none) > - inform (DECL_SOURCE_LOCATION (entity), > - "%q#D declared here with no linkage", entity); > - else if (linkage == lk_internal) > - inform (DECL_SOURCE_LOCATION (entity), > - "%q#D declared here with internal linkage", entity); > + bool diag = true; > + > + /* As an extension, we'll allow exposing internal entities from > + the GMF, to aid in migration to modules. For now, we only > + support this for functions and variables; see also > + depset::is_tu_local. */ > + bool relaxed = (VAR_OR_FUNCTION_DECL_P (not_tmpl) > + && !(DECL_LANG_SPECIFIC (not_tmpl) > + && DECL_MODULE_PURVIEW_P (not_tmpl))); > + if (relaxed) > + { > + gcc_checking_assert (linkage != lk_external); > + diag = (warning_enabled_at (DECL_SOURCE_LOCATION (entity), > + OPT_Wexpose_global_module_tu_local) > + && pedwarn (input_location, > + OPT_Wexpose_global_module_tu_local, > + "exporting %q#D that does not have " > + "external linkage", binding)); > + } > else > - inform (DECL_SOURCE_LOCATION (entity), > - "%q#D declared here with module linkage", entity); > - return false; > + error ("exporting %q#D that does not have external linkage", binding); > + > + if (diag) > + { > + if (linkage == lk_none) > + inform (DECL_SOURCE_LOCATION (entity), > + "%q#D declared here with no linkage", entity); > + else if (linkage == lk_internal) > + inform (DECL_SOURCE_LOCATION (entity), > + "%q#D declared here with internal linkage", entity); > + else > + inform (DECL_SOURCE_LOCATION (entity), > + "%q#D declared here with module linkage", entity); > + } > + > + return relaxed; > } > > return true; > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi > index 00f470a0d5d..f1d1769ef07 100644 > --- a/gcc/doc/invoke.texi > +++ b/gcc/doc/invoke.texi > @@ -4895,7 +4895,8 @@ As an extension, GCC allows exposures of internal > variables and functions that > were declared in the global module fragment. This warning indicates when > such > an invalid exposure has occurred, and can be silenced using diagnostic > pragmas > either at the site of the exposure, or at the point of declaration of the > -internal declaration. > +internal declaration. This also applies to @code{export using} declarations > +naming such entities. > > When combined with @option{-Wtemplate-names-tu-local}, GCC will also warn > about > non-exposure references to TU-local entities in template bodies. Such > templates > diff --git a/gcc/testsuite/g++.dg/modules/using-34_a.C > b/gcc/testsuite/g++.dg/modules/using-34_a.C > new file mode 100644 > index 00000000000..ac4994372ca > --- /dev/null > +++ b/gcc/testsuite/g++.dg/modules/using-34_a.C > @@ -0,0 +1,15 @@ > +// PR libstdc++/124268 > +// { dg-additional-options "-fmodules -Wno-global-module > -Wno-error=expose-global-module-tu-local" } > +// { dg-module-cmi M } > + > +module; > + > +static void f() {} // { dg-message "declared here with internal linkage" } > +static int x; // { dg-message "declared here with internal linkage" } > + > +export module M; > + > +namespace ns { > + export using ::f; // { dg-warning "does not have external linkage" } > + export using ::x; // { dg-warning "does not have external linkage" } > +} > diff --git a/gcc/testsuite/g++.dg/modules/using-34_b.C > b/gcc/testsuite/g++.dg/modules/using-34_b.C > new file mode 100644 > index 00000000000..bb829832ebc > --- /dev/null > +++ b/gcc/testsuite/g++.dg/modules/using-34_b.C > @@ -0,0 +1,22 @@ > +// PR libstdc++/124268 > +// { dg-additional-options "-fmodules -Wno-global-module > -Wno-error=expose-global-module-tu-local" } > +// { dg-module-cmi !K } > + > +module; > + > +// Non vars/functions cannot escape, even when relaxed. > +namespace { struct Internal; }; // { dg-message "declared here with > internal linkage" } > +struct {} none; // { dg-message "declared here with no > linkage" } > +using NoneType = decltype(none); > + > +export module K; > +import M; > + > +export using ::Internal; // { dg-error "does not have external linkage" } > +export using ::NoneType; // { dg-error "does not have external linkage" } > + > +// OK > +int test() { > + ns::f(); > + return ns::x; > +} > -- > 2.51.0 > >
