diff options
author | Nathaniel Shead <nathanieloshead@gmail.com> | 2023-11-13 16:48:36 +1100 |
---|---|---|
committer | Nathaniel Shead <nathanieloshead@gmail.com> | 2023-11-25 12:44:17 +1100 |
commit | 9dd8be6fc2debc4fbd0950386d4e98878af27a45 (patch) | |
tree | 73c796cfdef8fced6012cba8ab5fa9da5c139f9b | |
parent | 77cf1dba78b25f2e57bdbcffd6499a288772e700 (diff) | |
download | gcc-9dd8be6fc2debc4fbd0950386d4e98878af27a45.zip gcc-9dd8be6fc2debc4fbd0950386d4e98878af27a45.tar.gz gcc-9dd8be6fc2debc4fbd0950386d4e98878af27a45.tar.bz2 |
c++: Allow exporting a typedef redeclaration [PR102341]
A typedef doesn't create a new entity, and thus should be allowed to be
exported even if it has been previously declared un-exported. See the
example in [module.interface] p6:
export module M;
struct S { int n; };
typedef S S;
export typedef S S; // OK, does not redeclare an entity
PR c++/102341
gcc/cp/ChangeLog:
* decl.cc (duplicate_decls): Allow exporting a redeclaration of
a typedef.
gcc/testsuite/ChangeLog:
* g++.dg/modules/export-1.C: Adjust test.
* g++.dg/modules/export-2_a.C: New test.
* g++.dg/modules/export-2_b.C: New test.
Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
-rw-r--r-- | gcc/cp/decl.cc | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/modules/export-1.C | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/modules/export-2_a.C | 14 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/modules/export-2_b.C | 7 |
4 files changed, 31 insertions, 2 deletions
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index ed14015..e269f68 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -2231,7 +2231,11 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) } tree not_tmpl = STRIP_TEMPLATE (olddecl); - if (DECL_LANG_SPECIFIC (not_tmpl) && DECL_MODULE_ATTACH_P (not_tmpl)) + if (DECL_LANG_SPECIFIC (not_tmpl) + && DECL_MODULE_ATTACH_P (not_tmpl) + /* Typedefs are not entities and so are OK to be redeclared + as exported: see [module.interface]/p6. */ + && TREE_CODE (olddecl) != TYPE_DECL) { if (DECL_MODULE_EXPORT_P (STRIP_TEMPLATE (newdecl)) && !DECL_MODULE_EXPORT_P (not_tmpl)) diff --git a/gcc/testsuite/g++.dg/modules/export-1.C b/gcc/testsuite/g++.dg/modules/export-1.C index 3f93814..5988143 100644 --- a/gcc/testsuite/g++.dg/modules/export-1.C +++ b/gcc/testsuite/g++.dg/modules/export-1.C @@ -9,8 +9,12 @@ export int x (); // { dg-error "conflicting exporting for declaration" } int y; export extern int y; // { dg-error "conflicting exporting for declaration" } +// A typedef is not an entity so the following is OK; see [module.interface] example 4 typedef int z; -export typedef int z; // { dg-error "conflicting exporting for declaration" } +export typedef int z; // { dg-bogus "conflicting exporting for declaration" } + +template <typename T> using w = T; +export template <typename T> using w = T; // { dg-error "conflicting exporting for declaration" } template <typename T> int f (T); export template <typename T> int f (T); // { dg-error "conflicting exporting for declaration" } diff --git a/gcc/testsuite/g++.dg/modules/export-2_a.C b/gcc/testsuite/g++.dg/modules/export-2_a.C new file mode 100644 index 0000000..9a201bf --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/export-2_a.C @@ -0,0 +1,14 @@ +// { dg-additional-options "-fmodules-ts" } +// { dg-module-cmi aliases } + +export module aliases; + +typedef int x; +export typedef int x; + +using y = double; +export using y = double; + +struct S {}; +using T = S; +export using T = S; diff --git a/gcc/testsuite/g++.dg/modules/export-2_b.C b/gcc/testsuite/g++.dg/modules/export-2_b.C new file mode 100644 index 0000000..456aa8d --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/export-2_b.C @@ -0,0 +1,7 @@ +// { dg-additional-options "-fmodules-ts" } + +import aliases; + +x a = 123; +y b = 12.45; +T c = T{}; |