On 1/21/26 8:48 PM, Marek Polacek wrote:
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

OK for next stage 1.

-- >8 --
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.
---
  gcc/cp/cp-tree.h      |  8 ++++++--
  gcc/cp/module.cc      |  2 +-
  gcc/cp/name-lookup.cc |  8 ++------
  gcc/cp/parser.cc      |  1 +
  gcc/cp/reflect.cc     | 10 ++--------
  gcc/cp/tree.cc        | 20 ++++++++++++++++----
  6 files changed, 28 insertions(+), 21 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index cef8a8e5c19..790cc0573b5 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6043,12 +6043,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 {
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index c786519c1c0..ef49c0a4555 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -22022,7 +22022,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);
diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index 1b3713dc40e..c4456b8c34f 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -5349,12 +5349,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;
        error ("exporting %q#D that does not have external linkage",
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 393c8b2ec44..4a69e711951 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -21853,6 +21853,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);
                }
diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc
index eae70f86eac..c633a5406ae 100644
--- a/gcc/cp/reflect.cc
+++ b/gcc/cp/reflect.cc
@@ -1927,10 +1927,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;
@@ -1957,10 +1954,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;
diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index ab9d0d532f5..1201d995e5d 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -6484,6 +6484,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.  */
@@ -6491,17 +6503,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
@@ -6509,7 +6521,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;

base-commit: 6b79f1a5b8b62ce711d590a7f3e6ecb40b465464

Reply via email to