diff mbox series

[C++] PR c++/92105 - decltype(decltype) error cascade.

Message ID 20191211165042.24890-1-jason@redhat.com
State New
Headers show
Series [C++] PR c++/92105 - decltype(decltype) error cascade. | expand

Commit Message

Jason Merrill Dec. 11, 2019, 4:50 p.m. UTC
The primary change here is to do the CPP_DECLTYPE replacement even when we
get an error, so we don't keep trying and giving the same parse error each
time.  We also commit to the tentative firewall parse more often, leading to
better diagnostics.

Tested x86_64-pc-linux-gnu, applying to trunk.

	* parser.c (cp_parser_decltype_expr): Don't tentative_firewall here.
	(cp_parser_decltype): Do it here.  Remember a non-tentative error.
---
 gcc/cp/parser.c                            | 32 ++++++++++++++++------
 gcc/testsuite/g++.dg/cpp0x/decltype-err1.C |  7 +++++
 gcc/testsuite/g++.dg/cpp0x/decltype10.C    |  2 +-
 3 files changed, 31 insertions(+), 10 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/decltype-err1.C


base-commit: 945f2b19497eff52ef44923d291bf0fdba043299
diff mbox series

Patch

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index bf6d291ba9d..16d1359c47d 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -14637,11 +14637,6 @@  cp_parser_decltype_expr (cp_parser *parser,
   cp_token *id_expr_start_token;
   tree expr;
 
-  /* Since we're going to preserve any side-effects from this parse, set up a
-     firewall to protect our callers from cp_parser_commit_to_tentative_parse
-     in the expression.  */
-  tentative_firewall firewall (parser);
-
   /* First, try parsing an id-expression.  */
   id_expr_start_token = cp_lexer_peek_token (parser->lexer);
   cp_parser_parse_tentatively (parser);
@@ -14733,9 +14728,6 @@  cp_parser_decltype_expr (cp_parser *parser,
          expression.  */
       cp_parser_abort_tentative_parse (parser);
 
-      /* Commit to the tentative_firewall so we get syntax errors.  */
-      cp_parser_commit_to_tentative_parse (parser);
-
       /* Parse a full expression.  */
       expr = cp_parser_expression (parser, /*pidk=*/NULL, /*cast_p=*/false,
 				   /*decltype_p=*/true);
@@ -14773,6 +14765,17 @@  cp_parser_decltype (cp_parser *parser)
   if (!parens.require_open (parser))
     return error_mark_node;
 
+  /* Since we're going to preserve any side-effects from this parse, set up a
+     firewall to protect our callers from cp_parser_commit_to_tentative_parse
+     in the expression.  */
+  tentative_firewall firewall (parser);
+
+  /* If in_declarator_p, a reparse as an expression might succeed (60361).
+     Otherwise, commit now for better diagnostics.  */
+  if (cp_parser_uncommitted_to_tentative_parse_p (parser)
+      && !parser->in_declarator_p)
+    cp_parser_commit_to_topmost_tentative_parse (parser);
+
   push_deferring_access_checks (dk_deferred);
 
   tree expr = NULL_TREE;
@@ -14833,10 +14836,16 @@  cp_parser_decltype (cp_parser *parser)
     }
 
   /* Parse to the closing `)'.  */
-  if (!parens.require_close (parser))
+  if (expr == error_mark_node || !parens.require_close (parser))
     {
       cp_parser_skip_to_closing_parenthesis (parser, true, false,
 					     /*consume_paren=*/true);
+      expr = error_mark_node;
+    }
+
+  /* If we got a parse error while tentative, bail out now.  */
+  if (cp_parser_error_occurred (parser))
+    {
       pop_deferring_access_checks ();
       return error_mark_node;
     }
@@ -14859,6 +14868,11 @@  cp_parser_decltype (cp_parser *parser)
   start_token->u.tree_check_value->value = expr;
   start_token->u.tree_check_value->checks = get_deferred_access_checks ();
   start_token->keyword = RID_MAX;
+
+  location_t loc = start_token->location;
+  loc = make_location (loc, loc, parser->lexer);
+  start_token->location = loc;
+
   cp_lexer_purge_tokens_after (parser->lexer, start_token);
 
   pop_to_parent_deferring_access_checks ();
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-err1.C b/gcc/testsuite/g++.dg/cpp0x/decltype-err1.C
new file mode 100644
index 00000000000..302cb64aafc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype-err1.C
@@ -0,0 +1,7 @@ 
+// PR c++/92105
+// { dg-do compile { target c++11 } }
+
+// Test that we get exactly one "expected" error.
+
+decltype(decltype) x = 42;	// { dg-bogus "expected.*expected" }
+// { dg-error "expected" "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype10.C b/gcc/testsuite/g++.dg/cpp0x/decltype10.C
index 846d0bf57cf..fe7247269f5 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype10.C
@@ -6,4 +6,4 @@  template<int> struct A
   static int i;
 };
 
-template<int N> int A<N>::i(decltype (A::i;	// { dg-error "expected primary-expression before" }
+template<int N> int A<N>::i(decltype (A::i;	// { dg-error "expected" }