diff mbox series

c++: Avoid "infinite parsing" because of cp_parser_decltype [PR114858]

Message ID 01020191ffe7d291-0ceb3852-2428-49cc-97c5-7c6e8072ec43-000000@eu-west-1.amazonses.com
State New
Headers show
Series c++: Avoid "infinite parsing" because of cp_parser_decltype [PR114858] | expand

Commit Message

Simon Martin Sept. 17, 2024, 12:14 p.m. UTC
The invalid test case in this PR highlights a bad interaction between
the tentative_firewall and error recovery in cp_parser_decltype: the
firewall makes cp_parser_skip_to_closing_parenthesis a no-op, and the
parser does not make any progress, running "forever".

This patch calls cp_parser_commit_to_tentative_parse before initiating
error recovery.

Successfully tested on x86_64-pc-linux-gnu.

	PR c++/114858

gcc/cp/ChangeLog:

	* parser.cc (cp_parser_decltype): Commit tentative parse before
	initiating error recovery.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp0x/decltype10.C: Adjust test expectation.
	* g++.dg/cpp2a/pr114858.C: New test.
---
 gcc/cp/parser.cc                        |  3 +++
 gcc/testsuite/g++.dg/cpp0x/decltype10.C |  2 ++
 gcc/testsuite/g++.dg/cpp2a/pr114858.C   | 25 +++++++++++++++++++++++++
 3 files changed, 30 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/pr114858.C
diff mbox series

Patch

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 4dd9474cf60..3a7c5ffe4c8 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -17508,6 +17508,9 @@  cp_parser_decltype (cp_parser *parser)
   /* Parse to the closing `)'.  */
   if (expr == error_mark_node || !parens.require_close (parser))
     {
+      /* Commit to the tentative_firewall so we actually skip to the closing
+	 parenthesis.  */
+      cp_parser_commit_to_tentative_parse (parser);
       cp_parser_skip_to_closing_parenthesis (parser, true, false,
 					     /*consume_paren=*/true);
       expr = error_mark_node;
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype10.C b/gcc/testsuite/g++.dg/cpp0x/decltype10.C
index fe7247269f5..bd606e325d4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype10.C
@@ -7,3 +7,5 @@  template<int> struct A
 };
 
 template<int N> int A<N>::i(decltype (A::i;	// { dg-error "expected" }
+
+// { dg-excess-errors "" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/pr114858.C b/gcc/testsuite/g++.dg/cpp2a/pr114858.C
new file mode 100644
index 00000000000..6ffde4c3a2c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/pr114858.C
@@ -0,0 +1,25 @@ 
+// PR c++/114858
+// { dg-do compile { target c++20 } }
+// { dg-timeout 2 }
+
+template <class F> void g(F);
+template <class... A>
+auto h(A &&... a) -> decltype(
+  decltype(g< // { dg-error "expected primary-expression" }
+  decltype(g<decltype(g<decltype(g<decltype(g<decltype(g<
+  decltype(g<decltype(g<decltype(g<decltype(g<decltype(g<decltype(g<
+  decltype(g<decltype(g<decltype(g<decltype(g<decltype(g<decltype(g<
+  decltype(g<decltype(g<decltype(g<decltype(g<decltype(g<decltype(g<
+  decltype(g<decltype(g<decltype(g<decltype(g<decltype(g<decltype(g<
+  decltype(g<decltype(g<
+  decltype()>)(a)...)
+{
+  h([] {});
+}
+
+int main() { 
+  h(); 
+  return 0; 
+}
+
+// { dg-excess-errors "" }