diff mbox series

c++: Clear is_unbraced_* when parsing declaration_seq_opt [PR114917]

Message ID 66332254.620a0220.c0abb.0c82@mx.google.com
State New
Headers show
Series c++: Clear is_unbraced_* when parsing declaration_seq_opt [PR114917] | expand

Commit Message

Nathaniel Shead May 2, 2024, 5:19 a.m. UTC
Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?

-- >8 --

Currently we incorrectly retain "in_unbraced_linkage_specification_p"
and "in_unbraced_export_declaration_p" when parsing a (braced)
declaration-seq.  This patch ensures that we clear these flags before
parsing the toplevel declarations.

Strictly speaking we don't need to save and restore the flags around the
parsing because there's currently no way to provide new declarations
within the unbraced context after the closing brace, but this patch does
it anyway in case this ever changes and for consistency with other
places where these flags are adjusted.

	PR c++/114917

gcc/cp/ChangeLog:

	* parser.cc (cp_parser_declaration_seq_opt): Clear
	parser->in_unbraced_* flags when parsing toplevel declarations.

gcc/testsuite/ChangeLog:

	* g++.dg/modules/export-5_a.C: New test.
	* g++.dg/modules/export-5_b.C: New test.
	* g++.dg/parse/linkage4.C: New test.

Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
---
 gcc/cp/parser.cc                          | 15 +++++++++++++++
 gcc/testsuite/g++.dg/modules/export-5_a.C | 17 +++++++++++++++++
 gcc/testsuite/g++.dg/modules/export-5_b.C | 13 +++++++++++++
 gcc/testsuite/g++.dg/parse/linkage4.C     | 11 +++++++++++
 4 files changed, 56 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/modules/export-5_a.C
 create mode 100644 gcc/testsuite/g++.dg/modules/export-5_b.C
 create mode 100644 gcc/testsuite/g++.dg/parse/linkage4.C

Comments

Jason Merrill May 2, 2024, 1:45 p.m. UTC | #1
On 5/2/24 01:19, Nathaniel Shead wrote:
> Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?

OK.

> -- >8 --
> 
> Currently we incorrectly retain "in_unbraced_linkage_specification_p"
> and "in_unbraced_export_declaration_p" when parsing a (braced)
> declaration-seq.  This patch ensures that we clear these flags before
> parsing the toplevel declarations.
> 
> Strictly speaking we don't need to save and restore the flags around the
> parsing because there's currently no way to provide new declarations
> within the unbraced context after the closing brace, but this patch does
> it anyway in case this ever changes and for consistency with other
> places where these flags are adjusted.
> 
> 	PR c++/114917
> 
> gcc/cp/ChangeLog:
> 
> 	* parser.cc (cp_parser_declaration_seq_opt): Clear
> 	parser->in_unbraced_* flags when parsing toplevel declarations.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/modules/export-5_a.C: New test.
> 	* g++.dg/modules/export-5_b.C: New test.
> 	* g++.dg/parse/linkage4.C: New test.
> 
> Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
> ---
>   gcc/cp/parser.cc                          | 15 +++++++++++++++
>   gcc/testsuite/g++.dg/modules/export-5_a.C | 17 +++++++++++++++++
>   gcc/testsuite/g++.dg/modules/export-5_b.C | 13 +++++++++++++
>   gcc/testsuite/g++.dg/parse/linkage4.C     | 11 +++++++++++
>   4 files changed, 56 insertions(+)
>   create mode 100644 gcc/testsuite/g++.dg/modules/export-5_a.C
>   create mode 100644 gcc/testsuite/g++.dg/modules/export-5_b.C
>   create mode 100644 gcc/testsuite/g++.dg/parse/linkage4.C
> 
> diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> index a2bc6f69000..9a39ed27b23 100644
> --- a/gcc/cp/parser.cc
> +++ b/gcc/cp/parser.cc
> @@ -15341,6 +15341,16 @@ cp_parser_module_export (cp_parser *parser)
>   static void
>   cp_parser_declaration_seq_opt (cp_parser* parser)
>   {
> +  bool saved_in_unbraced_linkage_specification_p
> +    = parser->in_unbraced_linkage_specification_p;
> +  bool saved_in_unbraced_export_declaration_p
> +    = parser->in_unbraced_export_declaration_p;
> +
> +  /* We're not in an unbraced linkage-specification
> +     or export-declaration anymore.  */
> +  parser->in_unbraced_linkage_specification_p = false;
> +  parser->in_unbraced_export_declaration_p = false;
> +
>     while (true)
>       {
>         cp_token *token = cp_lexer_peek_token (parser->lexer);
> @@ -15351,6 +15361,11 @@ cp_parser_declaration_seq_opt (cp_parser* parser)
>         else
>   	cp_parser_toplevel_declaration (parser);
>       }
> +
> +  parser->in_unbraced_linkage_specification_p
> +    = saved_in_unbraced_linkage_specification_p;
> +  parser->in_unbraced_export_declaration_p
> +    = saved_in_unbraced_export_declaration_p;
>   }
>   
>   /* Parse a declaration.  The distinction between name-declaration
> diff --git a/gcc/testsuite/g++.dg/modules/export-5_a.C b/gcc/testsuite/g++.dg/modules/export-5_a.C
> new file mode 100644
> index 00000000000..a325591ca8e
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/modules/export-5_a.C
> @@ -0,0 +1,17 @@
> +// PR c++/114917
> +// { dg-additional-options "-fmodules-ts" }
> +// { dg-module-cmi M }
> +
> +export module M;
> +
> +export namespace ns {
> +  template <typename T> struct S {};
> +  template <typename T> struct S<T*> { using a = int; };
> +  template <> struct S<int*> { using b = int; };
> +  template struct S<int>;
> +};
> +
> +export extern "C++" namespace ns {
> +  template <typename T> void foo() {}
> +  template <> void foo<int>() {}
> +}
> diff --git a/gcc/testsuite/g++.dg/modules/export-5_b.C b/gcc/testsuite/g++.dg/modules/export-5_b.C
> new file mode 100644
> index 00000000000..cb10e37c7fc
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/modules/export-5_b.C
> @@ -0,0 +1,13 @@
> +// PR c++/114917
> +// { dg-additional-options "-fmodules-ts" }
> +
> +import M;
> +
> +int main() {
> +  ns::S<double*>::a x{};
> +  ns::S<int*>::b y{};
> +  ns::S<int> z{};
> +
> +  ns::foo<double>();
> +  ns::foo<int>();
> +}
> diff --git a/gcc/testsuite/g++.dg/parse/linkage4.C b/gcc/testsuite/g++.dg/parse/linkage4.C
> new file mode 100644
> index 00000000000..10fcc77e9d5
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/parse/linkage4.C
> @@ -0,0 +1,11 @@
> +// PR c++/114917
> +// { dg-do compile }
> +
> +extern "C++" namespace ns {
> +  struct Incomplete;
> +  Incomplete foo;  // { dg-error "incomplete type" }
> +}
> +
> +extern "C" extern "C" {
> +  static int bar;  // { dg-bogus "invalid" }
> +}
diff mbox series

Patch

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index a2bc6f69000..9a39ed27b23 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -15341,6 +15341,16 @@  cp_parser_module_export (cp_parser *parser)
 static void
 cp_parser_declaration_seq_opt (cp_parser* parser)
 {
+  bool saved_in_unbraced_linkage_specification_p
+    = parser->in_unbraced_linkage_specification_p;
+  bool saved_in_unbraced_export_declaration_p
+    = parser->in_unbraced_export_declaration_p;
+
+  /* We're not in an unbraced linkage-specification
+     or export-declaration anymore.  */
+  parser->in_unbraced_linkage_specification_p = false;
+  parser->in_unbraced_export_declaration_p = false;
+
   while (true)
     {
       cp_token *token = cp_lexer_peek_token (parser->lexer);
@@ -15351,6 +15361,11 @@  cp_parser_declaration_seq_opt (cp_parser* parser)
       else
 	cp_parser_toplevel_declaration (parser);
     }
+
+  parser->in_unbraced_linkage_specification_p
+    = saved_in_unbraced_linkage_specification_p;
+  parser->in_unbraced_export_declaration_p
+    = saved_in_unbraced_export_declaration_p;
 }
 
 /* Parse a declaration.  The distinction between name-declaration
diff --git a/gcc/testsuite/g++.dg/modules/export-5_a.C b/gcc/testsuite/g++.dg/modules/export-5_a.C
new file mode 100644
index 00000000000..a325591ca8e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/export-5_a.C
@@ -0,0 +1,17 @@ 
+// PR c++/114917
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi M }
+
+export module M;
+
+export namespace ns {
+  template <typename T> struct S {};
+  template <typename T> struct S<T*> { using a = int; };
+  template <> struct S<int*> { using b = int; };
+  template struct S<int>;
+};
+
+export extern "C++" namespace ns {
+  template <typename T> void foo() {}
+  template <> void foo<int>() {}
+}
diff --git a/gcc/testsuite/g++.dg/modules/export-5_b.C b/gcc/testsuite/g++.dg/modules/export-5_b.C
new file mode 100644
index 00000000000..cb10e37c7fc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/export-5_b.C
@@ -0,0 +1,13 @@ 
+// PR c++/114917
+// { dg-additional-options "-fmodules-ts" }
+
+import M;
+
+int main() {
+  ns::S<double*>::a x{};
+  ns::S<int*>::b y{};
+  ns::S<int> z{};
+
+  ns::foo<double>();
+  ns::foo<int>();
+}
diff --git a/gcc/testsuite/g++.dg/parse/linkage4.C b/gcc/testsuite/g++.dg/parse/linkage4.C
new file mode 100644
index 00000000000..10fcc77e9d5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/linkage4.C
@@ -0,0 +1,11 @@ 
+// PR c++/114917
+// { dg-do compile }
+
+extern "C++" namespace ns {
+  struct Incomplete;
+  Incomplete foo;  // { dg-error "incomplete type" }
+}
+
+extern "C" extern "C" {
+  static int bar;  // { dg-bogus "invalid" }
+}