aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2020-03-28 08:57:11 -0400
committerPatrick Palka <ppalka@redhat.com>2020-03-28 08:57:11 -0400
commit7981c06ae92548bd66f07121db1802eb6aec73ed (patch)
treec5c9ddcf1dd284be44597236b30a683b91ba4ddd
parenta7ea3d2ced786c4544fa625f34f515d89ed074fe (diff)
downloadgcc-7981c06ae92548bd66f07121db1802eb6aec73ed.zip
gcc-7981c06ae92548bd66f07121db1802eb6aec73ed.tar.gz
gcc-7981c06ae92548bd66f07121db1802eb6aec73ed.tar.bz2
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.
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/parser.c17
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/g++.dg/concepts/diagnostic8.C6
4 files changed, 29 insertions, 1 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a197c7d..e7c248a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,9 @@
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
* constraint.cc (tsubst_compound_requirement): Always suppress errors
from type_deducible_p and expression_convertible_p, as they're not
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index bf7387d..fc3c297 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -27704,7 +27704,22 @@ cp_parser_requires_clause_opt (cp_parser *parser, bool lambda_p)
}
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)
return cp_parser_requires_clause_expression (parser, lambda_p);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8c8eee0..3422550 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,8 @@
2020-03-28 Patrick Palka <ppalka@redhat.com>
+ PR c++/94306
+ * g++.dg/concepts/diagnostic8.C: New test.
+
PR c++/94252
* g++.dg/concepts/diagnostic7.C: New test.
* g++.dg/concepts/pr94252.C: New test.
diff --git a/gcc/testsuite/g++.dg/concepts/diagnostic8.C b/gcc/testsuite/g++.dg/concepts/diagnostic8.C
new file mode 100644
index 0000000..70d7e4a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/diagnostic8.C
@@ -0,0 +1,6 @@
+// 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 }