diff options
author | Nathaniel Shead <nathanieloshead@gmail.com> | 2025-01-19 15:26:03 +1100 |
---|---|---|
committer | Nathaniel Shead <nathanieloshead@gmail.com> | 2025-01-21 09:35:15 +1100 |
commit | 2fcb0c079530b019586e5693f057d2eb72855e70 (patch) | |
tree | e4ead205e00e072cdb01e15e808af219166104bb /gcc | |
parent | 5c0e1879ea639dc527d3928af877d3df985e3f13 (diff) | |
download | gcc-2fcb0c079530b019586e5693f057d2eb72855e70.zip gcc-2fcb0c079530b019586e5693f057d2eb72855e70.tar.gz gcc-2fcb0c079530b019586e5693f057d2eb72855e70.tar.bz2 |
c++/modules: Check linkage of structured binding decls
When looking at PR c++/118513 I noticed that we don't currently check
the linkage of structured binding declarations in modules. This patch
adds those checks, and corrects decl_linkage to properly recognise
structured binding declarations as potentially having linkage.
gcc/cp/ChangeLog:
* parser.cc (cp_parser_decomposition_declaration): Check linkage
of structured bindings in modules.
* tree.cc (decl_linkage): Structured bindings don't necessarily
have no linkage.
gcc/testsuite/ChangeLog:
* g++.dg/modules/export-6.C: Add structured binding tests.
* g++.dg/modules/hdr-2.H: Likewise.
Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/parser.cc | 1 | ||||
-rw-r--r-- | gcc/cp/tree.cc | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/modules/export-6.C | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/modules/hdr-2.H | 9 |
4 files changed, 18 insertions, 0 deletions
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index ff58a8e..a8ac8af 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -16728,6 +16728,7 @@ cp_parser_decomposition_declaration (cp_parser *parser, cp_finish_decl (decl, initializer, non_constant_p, NULL_TREE, (is_direct_init ? LOOKUP_NORMAL : LOOKUP_IMPLICIT), &decomp); + check_module_decl_linkage (decl); } } else if (decl != error_mark_node) diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc index ed01ca4..3658186 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -6003,6 +6003,8 @@ decl_linkage (tree decl) { if (TREE_CODE (decl) == TYPE_DECL && !TYPE_ANON_P (TREE_TYPE (decl))) /* This entity has a typedef name for linkage purposes. */; + else if (DECL_DECOMPOSITION_P (decl) && DECL_DECOMP_IS_BASE (decl)) + /* Namespace-scope structured bindings can have linkage. */; else if (TREE_CODE (decl) == NAMESPACE_DECL && cxx_dialect >= cxx11) /* An anonymous namespace has internal linkage since C++11. */ return lk_internal; diff --git a/gcc/testsuite/g++.dg/modules/export-6.C b/gcc/testsuite/g++.dg/modules/export-6.C index c59944a..460cdf0 100644 --- a/gcc/testsuite/g++.dg/modules/export-6.C +++ b/gcc/testsuite/g++.dg/modules/export-6.C @@ -3,6 +3,7 @@ export module bad; namespace global {} +struct S { int x; }; export static int x = 123; // { dg-error "internal linkage" } export static void f(); // { dg-error "internal linkage" } @@ -10,12 +11,17 @@ export static void g() {} // { dg-error "internal linkage" } export template <typename T> static void t(); // { dg-error "internal linkage" } export template <typename T> static void u() {} // { dg-error "internal linkage" } +#if __cplusplus >= 202002L +export static auto [d] = S{}; // { dg-error "internal linkage" "" { target c++20 } } +#endif + namespace { export int y = 456; // { dg-error "internal linkage" } export void h(); // { dg-error "internal linkage" } export void i() {} // { dg-error "internal linkage" } export template <typename T> void v(); // { dg-error "internal linkage" } export template <typename T> void w() {} // { dg-error "internal linkage" } + export auto [e] = S{}; // { dg-error "internal linkage" } export namespace ns {} // { dg-error "internal linkage" } export namespace alias = global; // { dg-error "internal linkage" } diff --git a/gcc/testsuite/g++.dg/modules/hdr-2.H b/gcc/testsuite/g++.dg/modules/hdr-2.H index 097546d..834c682 100644 --- a/gcc/testsuite/g++.dg/modules/hdr-2.H +++ b/gcc/testsuite/g++.dg/modules/hdr-2.H @@ -3,8 +3,11 @@ // external linkage variables or functions in header units must // not have non-inline definitions +struct S { int x; }; + int x_err; // { dg-error "external linkage definition" } int y_err = 123; // { dg-error "external linkage definition" } +auto [d_err] = S{}; // { dg-error "external linkage definition" } void f_err() {} // { dg-error "external linkage definition" } struct Err { @@ -59,6 +62,7 @@ struct Inl { // Internal linkage decls are OK static int x_internal; static int y_internal = 123; +namespace { auto [d_internal] = S{}; } static void f_internal() {} namespace { @@ -81,6 +85,11 @@ inline void f_static() { thread_local int x_thread_local; thread_local int y_thread_local = 123; +#if __cplusplus >= 202002L + static auto [d_static] = S{}; + thread_local auto [d_thread_local] = S{}; +#endif + x_static = y_static; x_thread_local = y_thread_local; } |