aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorNathaniel Shead <nathanieloshead@gmail.com>2024-09-04 01:18:19 +1000
committerNathaniel Shead <nathanieloshead@gmail.com>2024-09-27 13:49:23 +1000
commitd0762e93ce1ed046e1dd9477ebe0ad941c298677 (patch)
tree4397cb7dafd5705ee82b30f6ded4c347394f3ace /gcc/cp
parentad08ef098a8c8bb9c148d0a32e91456fdf58ffc1 (diff)
downloadgcc-d0762e93ce1ed046e1dd9477ebe0ad941c298677.zip
gcc-d0762e93ce1ed046e1dd9477ebe0ad941c298677.tar.gz
gcc-d0762e93ce1ed046e1dd9477ebe0ad941c298677.tar.bz2
c++/modules: Fix linkage checks for exported using-decls
This fixes some inconsistencies with what kinds of linkage various entities are assumed to have. This also fixes handling of exported using-decls binding to GM entities and type aliases to better align with the standard's requirements. gcc/cp/ChangeLog: * name-lookup.cc (check_can_export_using_decl): Handle internal linkage GM entities (but ignore in header units); use linkage of entity ultimately referred to by aliases. gcc/testsuite/ChangeLog: * g++.dg/modules/using-10.C: Add tests for no-linkage, fix expected linkage of aliases. * g++.dg/modules/using-12.C: Likewise. * g++.dg/modules/using-27.C: New test. * g++.dg/modules/using-28_a.C: New test. * g++.dg/modules/using-28_b.C: New test. * g++.dg/modules/using-29.H: New test. Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com> Reviewed-by: Jason Merrill <jason@redhat.com>
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/name-lookup.cc57
1 files changed, 33 insertions, 24 deletions
diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index c0f89f9..eb365b2 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -5206,38 +5206,47 @@ pushdecl_outermost_localscope (tree x)
static bool
check_can_export_using_decl (tree binding)
{
- tree decl = STRIP_TEMPLATE (binding);
-
- /* Linkage is determined by the owner of an enumerator. */
- if (TREE_CODE (decl) == CONST_DECL)
- decl = TYPE_NAME (DECL_CONTEXT (decl));
+ /* Declarations in header units are always OK. */
+ if (header_module_p ())
+ return true;
- /* If the using decl is exported, the things it refers
- to must also be exported (or not have module attachment). */
- if (!DECL_MODULE_EXPORT_P (decl)
- && (DECL_LANG_SPECIFIC (decl)
- && DECL_MODULE_ATTACH_P (decl)))
+ /* We want the linkage of the underlying entity, so strip typedefs.
+ If the underlying entity is a builtin type then we're OK. */
+ tree entity = binding;
+ if (TREE_CODE (entity) == TYPE_DECL)
{
- bool internal_p = !TREE_PUBLIC (decl);
+ entity = TYPE_MAIN_DECL (TREE_TYPE (entity));
+ if (!entity)
+ return true;
+ }
- /* A template in an anonymous namespace doesn't constrain TREE_PUBLIC
- until it's instantiated, so double-check its context. */
- if (!internal_p && TREE_CODE (binding) == TEMPLATE_DECL)
- internal_p = decl_internal_context_p (decl);
+ linkage_kind linkage = decl_linkage (entity);
+ tree not_tmpl = STRIP_TEMPLATE (entity);
+ /* Attachment is determined by the owner of an enumerator. */
+ if (TREE_CODE (not_tmpl) == CONST_DECL)
+ 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)))
+ {
auto_diagnostic_group d;
error ("exporting %q#D that does not have external linkage",
binding);
- if (TREE_CODE (decl) == TYPE_DECL && !DECL_IMPLICIT_TYPEDEF_P (decl))
- /* An un-exported explicit type alias has no linkage. */
- inform (DECL_SOURCE_LOCATION (binding),
- "%q#D declared here with no linkage", binding);
- else if (internal_p)
- inform (DECL_SOURCE_LOCATION (binding),
- "%q#D declared here with internal 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);
else
- inform (DECL_SOURCE_LOCATION (binding),
- "%q#D declared here with module linkage", binding);
+ inform (DECL_SOURCE_LOCATION (entity),
+ "%q#D declared here with module linkage", entity);
return false;
}