Commit 7981c06a by Patrick Palka

c++: Diagnose when "requires" is used instead of "requires requires" [PR94306]

This adds support to detect and recover from the case where an opening brace
immediately follows the start of a requires-clause.  So rather than emitting the
error

  error: expected primary-expression before '{' token

followed by a slew of irrevelant errors, we now assume the user had intended to
write "requires requires {" and diagnose and recover accordingly.

gcc/cp/ChangeLog:

	PR c++/94306
	* parser.c (cp_parser_requires_clause_opt): Diagnose and recover from
	"requires {" when "requires requires {" was probably intended.

gcc/testsuite/ChangeLog:

	PR c++/94306
	* g++.dg/concepts/diagnostic8.C: New test.
parent a7ea3d2c
2020-03-28 Patrick Palka <ppalka@redhat.com> 2020-03-28 Patrick Palka <ppalka@redhat.com>
PR c++/94306
* parser.c (cp_parser_requires_clause_opt): Diagnose and recover from
"requires {" when "requires requires {" was probably intended.
PR c++/94252 PR c++/94252
* constraint.cc (tsubst_compound_requirement): Always suppress errors * constraint.cc (tsubst_compound_requirement): Always suppress errors
from type_deducible_p and expression_convertible_p, as they're not from type_deducible_p and expression_convertible_p, as they're not
......
...@@ -27704,7 +27704,22 @@ cp_parser_requires_clause_opt (cp_parser *parser, bool lambda_p) ...@@ -27704,7 +27704,22 @@ cp_parser_requires_clause_opt (cp_parser *parser, bool lambda_p)
} }
return NULL_TREE; return NULL_TREE;
} }
cp_lexer_consume_token (parser->lexer);
cp_token *tok2 = cp_lexer_peek_nth_token (parser->lexer, 2);
if (tok2->type == CPP_OPEN_BRACE)
{
/* An opening brace following the start of a requires-clause is
ill-formed; the user likely forgot the second `requires' that
would start a requires-expression. */
gcc_rich_location richloc (tok2->location);
richloc.add_fixit_insert_after (tok->location, " requires");
error_at (&richloc, "missing additional %<requires%> to start "
"a requires-expression");
/* Don't consume the `requires', so that it's reused as the start of a
requires-expression. */
}
else
cp_lexer_consume_token (parser->lexer);
if (!flag_concepts_ts) if (!flag_concepts_ts)
return cp_parser_requires_clause_expression (parser, lambda_p); return cp_parser_requires_clause_expression (parser, lambda_p);
2020-03-28 Patrick Palka <ppalka@redhat.com> 2020-03-28 Patrick Palka <ppalka@redhat.com>
PR c++/94306
* g++.dg/concepts/diagnostic8.C: New test.
PR c++/94252 PR c++/94252
* g++.dg/concepts/diagnostic7.C: New test. * g++.dg/concepts/diagnostic7.C: New test.
* g++.dg/concepts/pr94252.C: New test. * g++.dg/concepts/pr94252.C: New test.
......
// PR c++/94306
// { dg-do compile { target c++2a } }
template<typename T> struct S { };
template<typename T> requires { typename T::type; } struct S<T> { };
// { dg-error "missing additional .requires." "" { target *-*-* } .-1 }
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