]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: add lk_module
authorMarek Polacek <polacek@redhat.com>
Tue, 20 Jan 2026 21:16:33 +0000 (16:16 -0500)
committerMarek Polacek <polacek@redhat.com>
Thu, 23 Apr 2026 15:35:07 +0000 (11:35 -0400)
During Reflection review it came up that we don't have lk_module.
Instead, we're checking lk_external && DECL_MODULE_ATTACH_P &&
!DECL_MODULE_EXPORT_P.  This patch adds lk_module which allows further
cleanups.

I'm not sure the cp_parser_template_argument change is required.

gcc/cp/ChangeLog:

* cp-tree.h (enum linkage_kind): Add lk_module.
* module.cc (check_module_decl_linkage): Use DECL_EXTERNAL_LINKAGE_P.
* name-lookup.cc (check_can_export_using_decl): Don't check for
attachment.
* parser.cc (cp_parser_template_argument): Check that linkage isn't
lk_module.
* reflect.cc (eval_has_module_linkage): Check lk_module.
(eval_has_external_linkage): Use DECL_EXTERNAL_LINKAGE_P.
* tree.cc (decl_linkage): Return lk_module if appropriate.

Reviewed-by: Jason Merrill <jason@redhat.com>
gcc/cp/cp-tree.h
gcc/cp/module.cc
gcc/cp/name-lookup.cc
gcc/cp/parser.cc
gcc/cp/reflect.cc
gcc/cp/tree.cc

index 8a4ac4600590de452afb9990611f27c335a95927..3d1f6f99aad9363687d694830968070013954c6b 100644 (file)
@@ -6124,12 +6124,16 @@ enum special_function_kind {
         translation unit.
 
       -- When a name has no linkage, the entity it denotes cannot be
-        referred to by names from other scopes.  */
+        referred to by names from other scopes.
+
+      -- When the declaration of the name is attached to a named module
+        and is not exported, the name has module linkage.  */
 
 enum linkage_kind {
   lk_none,                     /* No linkage.  */
   lk_internal,                 /* Internal linkage.  */
-  lk_external                  /* External linkage.  */
+  lk_external,                 /* External linkage.  */
+  lk_module                    /* Module linkage.  */
 };
 
 enum duration_kind {
index a7245aae46a1201281b32bbbfa3869958d77f20b..896058d96d91928de460bdd7d60eb09d358b7982 100644 (file)
@@ -22139,7 +22139,7 @@ check_module_decl_linkage (tree decl)
       && decl_defined_p (decl)
       && !(DECL_LANG_SPECIFIC (decl)
           && DECL_TEMPLATE_INSTANTIATION (decl))
-      && decl_linkage (decl) == lk_external)
+      && DECL_EXTERNAL_LINKAGE_P (decl))
     error_at (DECL_SOURCE_LOCATION (decl),
              "external linkage definition of %qD in header module must "
              "be declared %<inline%>", decl);
index 2127cf9993706978fa84c1afe48bd66404f57356..568e615918c5ae4aa4e033fa2a7da29cf758fedd 100644 (file)
@@ -5488,12 +5488,8 @@ check_can_export_using_decl (tree binding)
     not_tmpl = TYPE_NAME (DECL_CONTEXT (not_tmpl));
 
   /* If the using decl is exported, the things it refers to must
-     have external linkage.  decl_linkage returns lk_external for
-     module linkage so also check for attachment.  */
-  if (linkage != lk_external
-      || (DECL_LANG_SPECIFIC (not_tmpl)
-         && DECL_MODULE_ATTACH_P (not_tmpl)
-         && !DECL_MODULE_EXPORT_P (not_tmpl)))
+     have external linkage.  */
+  if (linkage != lk_external)
     {
       auto_diagnostic_group d;
       bool diag = true;
index 3ec85e8416d8962035af5bc23233958d5bd6e8df..d07dc01650f610144370cac998add7394cd55288 100644 (file)
@@ -21993,6 +21993,7 @@ cp_parser_template_argument (cp_parser* parser)
                {
                  linkage_kind linkage = decl_linkage (probe);
                  if (linkage != lk_external
+                     && linkage != lk_module
                      && (cxx_dialect < cxx11 || linkage != lk_internal))
                    cp_parser_simulate_error (parser);
                }
index b36c4be427360190a74f97782b3fe578a49f28f6..09e99b5ef83b822fe7180cfcd8ff52444d07896b 100644 (file)
@@ -2031,10 +2031,7 @@ eval_has_module_linkage (tree r, reflect_kind kind)
       if (!r)
        return boolean_false_node;
     }
-  if (decl_linkage (r) == lk_external
-      && DECL_LANG_SPECIFIC (r)
-      && DECL_MODULE_ATTACH_P (r)
-      && !DECL_MODULE_EXPORT_P (r))
+  if (decl_linkage (r) == lk_module)
     return boolean_true_node;
   else
     return boolean_false_node;
@@ -2061,10 +2058,7 @@ eval_has_external_linkage (tree r, reflect_kind kind)
       if (!r)
        return boolean_false_node;
     }
-  if (decl_linkage (r) == lk_external
-      && !(DECL_LANG_SPECIFIC (r)
-          && DECL_MODULE_ATTACH_P (r)
-          && !DECL_MODULE_EXPORT_P (r)))
+  if (DECL_EXTERNAL_LINKAGE_P (r))
     return boolean_true_node;
   else
     return boolean_false_node;
index c57587dbeee81b318faf56e418bec1f5c3ffb41b..d3e202e8b04833ad8e1917ac711e6d965f6f6e20 100644 (file)
@@ -6653,6 +6653,18 @@ decl_linkage (tree decl)
   if (cxx_dialect >= cxx11 && decl_internal_context_p (decl))
     return lk_internal;
 
+  /* Helper to decide if T is lk_module or lk_external.  */
+  auto external_or_module = [] (tree t)
+    {
+      if (t
+         && DECL_LANG_SPECIFIC (t)
+         && DECL_MODULE_ATTACH_P (t)
+         && !DECL_MODULE_EXPORT_P (t))
+       return lk_module;
+
+      return lk_external;
+    };
+
   /* Templates don't properly propagate TREE_PUBLIC, consider the
      template result instead.  Any template that isn't a variable
      or function must be external linkage by this point.  */
@@ -6660,17 +6672,17 @@ decl_linkage (tree decl)
     {
       decl = DECL_TEMPLATE_RESULT (decl);
       if (!decl || !VAR_OR_FUNCTION_DECL_P (decl))
-       return lk_external;
+       return external_or_module (decl);
     }
 
   /* Things that are TREE_PUBLIC have external linkage.  */
   if (TREE_PUBLIC (decl))
-    return lk_external;
+    return external_or_module (decl);
 
   /* All types have external linkage in C++98, since anonymous namespaces
      didn't explicitly confer internal linkage.  */
   if (TREE_CODE (decl) == TYPE_DECL && cxx_dialect < cxx11)
-    return lk_external;
+    return external_or_module (decl);
 
   /* Variables or function decls not marked as TREE_PUBLIC might still
      be external linkage, such as for template instantiations on targets
@@ -6678,7 +6690,7 @@ decl_linkage (tree decl)
      or compiler-generated entities; in such cases, decls really meant to
      have internal linkage will have DECL_THIS_STATIC set.  */
   if (VAR_OR_FUNCTION_DECL_P (decl) && !DECL_THIS_STATIC (decl))
-    return lk_external;
+    return external_or_module (decl);
 
   /* Everything else has internal linkage.  */
   return lk_internal;