]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Allow exporting a typedef redeclaration [PR102341]
authorNathaniel Shead <nathanieloshead@gmail.com>
Mon, 13 Nov 2023 05:48:36 +0000 (16:48 +1100)
committerNathaniel Shead <nathanieloshead@gmail.com>
Sat, 25 Nov 2023 01:44:17 +0000 (12:44 +1100)
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>
gcc/cp/decl.cc
gcc/testsuite/g++.dg/modules/export-1.C
gcc/testsuite/g++.dg/modules/export-2_a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/export-2_b.C [new file with mode: 0644]

index ed1401591fa2f5ecff09382e607a92ef3db35191..e269f689c1c8cf7f7128d4b62f710fe4aacef665 100644 (file)
@@ -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))
index 3f93814d270bd29106a253afd76bcd60129e89f2..598814370eca9f71e510919af72f85209ec463c2 100644 (file)
@@ -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 (file)
index 0000000..9a201bf
--- /dev/null
@@ -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 (file)
index 0000000..456aa8d
--- /dev/null
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import aliases;
+
+x a = 123;
+y b = 12.45;
+T c = T{};