]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++/modules: Allow exporting usings of internal GMF entities with pedwarn [PR124268]
authorNathaniel Shead <nathanieloshead@gmail.com>
Thu, 19 Mar 2026 12:58:30 +0000 (23:58 +1100)
committerNathaniel Shead <nathanieloshead@gmail.com>
Mon, 6 Apr 2026 21:50:35 +0000 (07:50 +1000)
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 <nathanieloshead@gmail.com>
Reviewed-by: Patrick Palka <ppalka@redhat.com>
Reviewed-by: Jason Merrill <jason@redhat.com>
gcc/cp/module.cc
gcc/cp/name-lookup.cc
gcc/doc/invoke.texi
gcc/testsuite/g++.dg/modules/using-34_a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/using-34_b.C [new file with mode: 0644]

index 1757bd58f772fb416a67173e98c80e41efc3f77b..e5547f7d029fd5a1e23a5b6527c20096f50ea01f 100644 (file)
@@ -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);
index c0f48b5496dc9b1709cc3876b33183522a6dcb29..2127cf9993706978fa84c1afe48bd66404f57356 100644 (file)
@@ -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;
index 4b208344398d08b520faa656bce067a1e9702269..b01787d29fc835ab9713f612762839fdeab46c62 100644 (file)
@@ -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 (file)
index 0000000..ac49943
--- /dev/null
@@ -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 (file)
index 0000000..e6b2f1d
--- /dev/null
@@ -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;
+}