aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathaniel Shead <nathanieloshead@gmail.com>2023-11-13 16:48:36 +1100
committerNathaniel Shead <nathanieloshead@gmail.com>2023-11-25 12:44:17 +1100
commit9dd8be6fc2debc4fbd0950386d4e98878af27a45 (patch)
tree73c796cfdef8fced6012cba8ab5fa9da5c139f9b
parent77cf1dba78b25f2e57bdbcffd6499a288772e700 (diff)
downloadgcc-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.cc6
-rw-r--r--gcc/testsuite/g++.dg/modules/export-1.C6
-rw-r--r--gcc/testsuite/g++.dg/modules/export-2_a.C14
-rw-r--r--gcc/testsuite/g++.dg/modules/export-2_b.C7
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{};