diff mbox series

[2/1] c++/modules: Allow exporting a typedef redeclaration

Message ID 6551bdb9.170a0220.9dd60.6ce4@mx.google.com
State New
Headers show
Series c++/modules: check mismatching exports for class tags [PR98885] | expand

Commit Message

Nathaniel Shead Nov. 13, 2023, 6:09 a.m. UTC
I happened to be browsing the standard a bit later and noticed that we
incorrectly reject the example given below.

Bootstrapped on x86_64-pc-linux-gnu; regtesting ongoing but modules.exp
completed with no errors.

-- >8 --

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.

Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
---
 gcc/cp/decl.cc                          | 5 ++++-
 gcc/testsuite/g++.dg/modules/export-1.C | 6 +++++-
 2 files changed, 9 insertions(+), 2 deletions(-)

Comments

Nathan Sidwell Nov. 23, 2023, 4:45 p.m. UTC | #1
On 11/13/23 01:09, Nathaniel Shead wrote:
> I happened to be browsing the standard a bit later and noticed that we
> incorrectly reject the example given below.
> 
> Bootstrapped on x86_64-pc-linux-gnu; regtesting ongoing but modules.exp
> completed with no errors.
> 
> -- >8 --
> 
> 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:

ok.  Could you put a reference to [module.interface]/p6 in the comment though?

nathan

> 
>    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.
> 
> Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
> ---
>   gcc/cp/decl.cc                          | 5 ++++-
>   gcc/testsuite/g++.dg/modules/export-1.C | 6 +++++-
>   2 files changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
> index bde9bd79d58..5e175d3e835 100644
> --- a/gcc/cp/decl.cc
> +++ b/gcc/cp/decl.cc
> @@ -2231,7 +2231,10 @@ 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 can be exported later.  */
> +	  && 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 3f93814d270..598814370ec 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 mbox series

Patch

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index bde9bd79d58..5e175d3e835 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -2231,7 +2231,10 @@  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 can be exported later.  */
+	  && 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 3f93814d270..598814370ec 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" }