c++: Fix ICE on nonsense requires-clause.

Here we were swallowing all the syntax errors by parsing tentatively, and
returning error_mark_node without ever actually giving an error.  Fixed by
using save_tokens/rollback_tokens instead.

	PR c++/92517
	* parser.c (cp_parser_constraint_primary_expression): Do the main
	parse non-tentatively.
This commit is contained in:
Jason Merrill 2020-02-06 16:14:19 -05:00
parent 3c7a03bc36
commit 82aee6dd61
3 changed files with 22 additions and 10 deletions

View File

@ -1,3 +1,9 @@
2020-02-06 Jason Merrill <jason@redhat.com>
PR c++/92517
* parser.c (cp_parser_constraint_primary_expression): Do the main
parse non-tentatively.
2020-02-06 Marek Polacek <polacek@redhat.com>
PR c++/93597 - ICE with lambda in operator function.

View File

@ -27478,7 +27478,7 @@ cp_parser_constraint_primary_expression (cp_parser *parser, bool lambda_p)
return e;
}
cp_parser_parse_tentatively (parser);
cp_lexer_save_tokens (parser->lexer);
cp_id_kind idk;
location_t loc = input_location;
cp_expr expr = cp_parser_primary_expression (parser,
@ -27494,19 +27494,16 @@ cp_parser_constraint_primary_expression (cp_parser *parser, bool lambda_p)
/* The primary-expression could be part of an unenclosed non-logical
compound expression. */
pce = cp_parser_constraint_requires_parens (parser, lambda_p);
if (pce != pce_ok)
cp_parser_simulate_error (parser);
else
expr = finish_constraint_primary_expr (expr);
}
if (cp_parser_parse_definitely (parser))
return expr;
if (expr == error_mark_node)
return error_mark_node;
if (pce == pce_ok)
{
cp_lexer_commit_tokens (parser->lexer);
return finish_constraint_primary_expr (expr);
}
/* Retry the parse at a lower precedence. If that succeeds, diagnose the
error, but return the expression as if it were valid. */
gcc_assert (pce != pce_ok);
cp_lexer_rollback_tokens (parser->lexer);
cp_parser_parse_tentatively (parser);
if (pce == pce_maybe_operator)
expr = cp_parser_assignment_expression (parser, NULL, false, false);

View File

@ -0,0 +1,9 @@
// PR c++/92517
// { dg-do compile { target concepts } }
template <typename T>
concept C = true;
template<int I>
requires C decltype<I> // { dg-error "" }
void f() {}