Bootstrapped and regtested on x86_64-pc-linux-gnu. OK for trunk?
I added an invalid test case because without the cleanup on
cp_parser_lambda_declarator_opt, we correctly accept the valid testcase
but we get an ICE for the invalid one.
I can't tell if skipping abort_fully_implicit_template during tentative
parsing is always correct or not, but it didn't cause any regressions.
This seemed like the best place to put it from the options I tried that
worked.
Also I noticed that g++.dg/cpp2a/consteval37.C:
```
constexpr int f (auto i)
requires requires { id (i) } // { dg-error "expected" }
{
return i;
}
```
has poor error messages, and it seems related to this error handling
path (my patch didn't change the errors for it). Tried getting it to
give better diagnostics as well but didn't improve much for it.
and it leaks a bit of internal information with `auto:1` showing up:
```
/home/riogu/gcc-dev/source4/gcc/testsuite/g++.dg/cpp2a/consteval37.C:6:15:
error: constraints on a non-templated function
6 | constexpr int f (auto i)
| ^
/home/riogu/gcc-dev/source4/gcc/testsuite/g++.dg/cpp2a/consteval37.C:6:23:
error: ‘i’ has incomplete type
6 | constexpr int f (auto i)
| ~~~~~^
/home/riogu/gcc-dev/source4/gcc/testsuite/g++.dg/cpp2a/consteval37.C:7:30:
error: invalid use of template type parameter ‘auto:1’
7 | requires requires { id (i) } // { dg-error "expected" }
| ^
/home/riogu/gcc-dev/source4/gcc/testsuite/g++.dg/cpp2a/consteval37.C: In
function ‘constexpr int f(auto:1)’:
```
It is invalid code but fwiw it might be worth looking into recovering
better from this example.
-- >8 --
When parsing a lambda with a trailing requires-clause, calling
cp_parser_requires_clause_opt confused generic lambda parsing when
implicit template parameters were involved.
After failing to parse a type-requirement during tentative parsing and
hitting error recovery code in cp_parser_skip_to_end_of_statement that
aborted the current implicit template, attemping to finish the lambda
declaration caused ICEs.
Fix this by not aborting the current implicit template during tentative
parsing and adding cleanup for fully_implicit_function_template_p.
PR c++/123080
gcc/cp/ChangeLog:
* parser.cc (cp_parser_skip_to_end_of_statement): Don't abort
implicit templates during tentative parsing.
(cp_parser_lambda_declarator_opt): Add cleanup for
fully_implicit_function_template_p before parsing
trailing_requires_clause.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/lambda-requires6.C: New test.
* g++.dg/cpp2a/lambda-requires6a.C: New test.
Signed-off-by: Egas Ribeiro <[email protected]>
---
gcc/cp/parser.cc | 5 ++++-
gcc/testsuite/g++.dg/cpp2a/lambda-requires6.C | 5 +++++
gcc/testsuite/g++.dg/cpp2a/lambda-requires6a.C | 3 +++
3 files changed, 12 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-requires6.C
create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-requires6a.C
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 26da789f821..c70cf59c0b2 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -4288,7 +4288,8 @@ cp_parser_skip_to_end_of_statement (cp_parser* parser)
unsigned nesting_depth = 0;
/* Unwind generic function template scope if necessary. */
- if (parser->fully_implicit_function_template_p)
+ if (parser->fully_implicit_function_template_p
+ && !cp_parser_parsing_tentatively (parser))
abort_fully_implicit_template (parser);
while (true)
@@ -12748,6 +12749,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser,
tree lambda_expr,
if (has_param_list)
{
+ auto cleanup
+ = make_temp_override (parser->fully_implicit_function_template_p);
/* Parse optional trailing requires clause. */
trailing_requires_clause = cp_parser_requires_clause_opt (parser, false);
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-requires6.C
b/gcc/testsuite/g++.dg/cpp2a/lambda-requires6.C
new file mode 100644
index 00000000000..eada6779ac3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-requires6.C
@@ -0,0 +1,5 @@
+// PR c++/123080
+// { dg-do compile { target c++20 } }
+template<typename T> struct type_identity { using type = T; };
+auto f = [](auto x) requires requires { typename
type_identity<decltype(x)>::type(0); } {};
+int main() { f(0); }
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-requires6a.C
b/gcc/testsuite/g++.dg/cpp2a/lambda-requires6a.C
new file mode 100644
index 00000000000..54e72345c9a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-requires6a.C
@@ -0,0 +1,3 @@
+// PR c++/123080
+// { dg-do compile { target c++20 } }
+auto f = [](auto x) requires requires { // { dg-error "expected | invalid
member template | constraints" }
--
2.52.0