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