diff options
author | Nathaniel Shead <nathanieloshead@gmail.com> | 2024-09-04 01:18:19 +1000 |
---|---|---|
committer | Nathaniel Shead <nathanieloshead@gmail.com> | 2024-09-27 13:49:23 +1000 |
commit | d0762e93ce1ed046e1dd9477ebe0ad941c298677 (patch) | |
tree | 4397cb7dafd5705ee82b30f6ded4c347394f3ace /gcc/cp | |
parent | ad08ef098a8c8bb9c148d0a32e91456fdf58ffc1 (diff) | |
download | gcc-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.cc | 57 |
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; } |