https://gcc.gnu.org/g:549bfeaa0bd2641ed99f1525caf3d54e2126396a

commit r16-6432-g549bfeaa0bd2641ed99f1525caf3d54e2126396a
Author: Egas Ribeiro <[email protected]>
Date:   Thu Dec 25 12:33:47 2025 +0000

    c++: Fix ICE with requires-expression in lambda requires-clause [PR123080]
    
    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]>
    Reviewed-by: Jason Merrill <[email protected]>

Diff:
---
 gcc/cp/parser.cc                               | 6 +++++-
 gcc/testsuite/g++.dg/cpp2a/lambda-requires6.C  | 5 +++++
 gcc/testsuite/g++.dg/cpp2a/lambda-requires6a.C | 3 +++
 3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 26da789f8218..9ec3b21ab7f7 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,9 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, 
tree lambda_expr,
 
   if (has_param_list)
     {
+      /* Avoid ICE on lambda-requires6a.C.  */
+      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 000000000000..eada6779ac3a
--- /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 000000000000..54e72345c9a7
--- /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" }

Reply via email to