Commit 7ae01728 by Jason Merrill Committed by Jason Merrill

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
parent 0e5def81
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.
......
......@@ -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 ();
// 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 }
......@@ -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" }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment