Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >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
-- 
2.52.0

Reply via email to