https://gcc.gnu.org/g:8b9a294a484ed50ee36cb435dc089a78df385f5c
commit r16-8488-g8b9a294a484ed50ee36cb435dc089a78df385f5c Author: Nathaniel Shead <[email protected]> Date: Thu Mar 19 23:58:30 2026 +1100 c++/modules: Allow exporting usings of internal GMF entities with pedwarn [PR124268] 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. 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]> Reviewed-by: Patrick Palka <[email protected]> Reviewed-by: Jason Merrill <[email protected]> Diff: --- 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(-) diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 1757bd58f772..e5547f7d029f 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -14531,7 +14531,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"); @@ -14972,7 +14972,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. */ @@ -15998,6 +15999,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 c0f48b5496dc..2127cf999370 100644 --- a/gcc/cp/name-lookup.cc +++ b/gcc/cp/name-lookup.cc @@ -5496,18 +5496,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 4b208344398d..b01787d29fc8 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -4898,7 +4898,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 000000000000..ac4994372cae --- /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 000000000000..e6b2f1d48c3e --- /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-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; +}
