aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2019-12-11 11:51:14 -0500
committerJason Merrill <jason@gcc.gnu.org>2019-12-11 11:51:14 -0500
commit7ae01728007dcfcdec117706191adeb922cf7b76 (patch)
treec7f78a1d65960375235d14476bfb315fee35b9af
parent0e5def817a5142dd3eeb91ce4acf9ea22a43ad94 (diff)
downloadgcc-7ae01728007dcfcdec117706191adeb922cf7b76.zip
gcc-7ae01728007dcfcdec117706191adeb922cf7b76.tar.gz
gcc-7ae01728007dcfcdec117706191adeb922cf7b76.tar.bz2
PR c++/92105 - decltype(decltype) error cascade.
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. * parser.c (cp_parser_decltype_expr): Don't tentative_firewall here. (cp_parser_decltype): Do it here. Remember a non-tentative error. From-SVN: r279237
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/parser.c32
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype-err1.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype10.C2
4 files changed, 35 insertions, 10 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index e371a40..7051a42 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,9 @@
2019-12-11 Jason Merrill <jason@redhat.com>
+ PR c++/92105 - decltype(decltype) error cascade.
+ * parser.c (cp_parser_decltype_expr): Don't tentative_firewall here.
+ (cp_parser_decltype): Do it here. Remember a non-tentative error.
+
PR c++/57082 - new X{} and private destructor.
* init.c (build_new_1): Also pass tf_no_cleanup to
build_special_member_call.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index bf6d291..16d1359 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 0000000..302cb64
--- /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 846d0bf..fe72472 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" }