https://gcc.gnu.org/g:81db6857686c2d7932949afb948419a575bc0b3f

commit r14-10548-g81db6857686c2d7932949afb948419a575bc0b3f
Author: Patrick Palka <ppa...@redhat.com>
Date:   Mon Jul 29 16:37:19 2024 -0400

    c++: generic lambda in default template argument [PR88313]
    
    Here we're rejecting the generic lambda inside the default template
    argument ultimately because auto_is_implicit_function_template_parm_p
    doesn't get set during parsing of the lambda's parameter list, due
    to the !processing_template_parmlist restriction.  But when parsing a
    lambda parameter list we should always set that flag regardless of where
    the lambda appears.  This patch makes sure of this via a local lambda_p
    flag.
    
            PR c++/88313
    
    gcc/cp/ChangeLog:
    
            * parser.cc (cp_parser_lambda_declarator_opt): Pass
            lambda_p=true to cp_parser_parameter_declaration_clause.
            (cp_parser_direct_declarator): Pass lambda_p=false to
            to cp_parser_parameter_declaration_clause.
            (cp_parser_parameter_declaration_clause): Add bool lambda_p
            parameter.  Consider lambda_p instead of current_class_type
            when setting parser->auto_is_implicit_function_template_parm_p.
            Don't consider processing_template_parmlist.
            (cp_parser_requirement_parameter_list): Pass lambda_p=false
            to cp_parser_parameter_declaration_clause.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp2a/lambda-targ6.C: New test.
    
    Reviewed-by: Jason Merrill <ja...@redhat.com>
    (cherry picked from commit 72a7ab891ae0061841c4eb641ef6ab7719bf0369)

Diff:
---
 gcc/cp/parser.cc                          | 34 ++++++++++++++++++-------------
 gcc/testsuite/g++.dg/cpp2a/lambda-targ6.C | 15 ++++++++++++++
 2 files changed, 35 insertions(+), 14 deletions(-)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 7e81c1010c45..00cf128522a7 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -2598,7 +2598,7 @@ static tree cp_parser_type_id_1
 static void cp_parser_type_specifier_seq
   (cp_parser *, cp_parser_flags, bool, bool, cp_decl_specifier_seq *);
 static tree cp_parser_parameter_declaration_clause
-  (cp_parser *, cp_parser_flags);
+  (cp_parser *, cp_parser_flags, bool);
 static tree cp_parser_parameter_declaration_list
   (cp_parser *, cp_parser_flags, auto_vec<tree> *);
 static cp_parameter_declarator *cp_parser_parameter_declaration
@@ -11867,7 +11867,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, 
tree lambda_expr)
       /* Parse parameters.  */
       param_list
        = cp_parser_parameter_declaration_clause
-           (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL);
+           (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL, /*lambda_p=*/true);
 
       /* Default arguments shall not be specified in the
         parameter-declaration-clause of a lambda-declarator.  */
@@ -23903,7 +23903,8 @@ cp_parser_direct_declarator (cp_parser* parser,
 
              /* Parse the parameter-declaration-clause.  */
              params
-               = cp_parser_parameter_declaration_clause (parser, flags);
+               = cp_parser_parameter_declaration_clause (parser, flags,
+                                                         /*lambda_p=*/false);
              const location_t parens_end
                = cp_lexer_peek_token (parser->lexer)->location;
 
@@ -25252,13 +25253,17 @@ function_being_declared_is_template_p (cp_parser* 
parser)
 
    The parser flags FLAGS is used to control type-specifier parsing.
 
+   LAMBDA_P is true if this is the parameter-declaration-clause of
+   a lambda-declarator.
+
    Returns a representation for the parameter declarations.  A return
    value of NULL indicates a parameter-declaration-clause consisting
    only of an ellipsis.  */
 
 static tree
 cp_parser_parameter_declaration_clause (cp_parser* parser,
-                                       cp_parser_flags flags)
+                                       cp_parser_flags flags,
+                                       bool lambda_p)
 {
   tree parameters;
   cp_token *token;
@@ -25267,15 +25272,15 @@ cp_parser_parameter_declaration_clause (cp_parser* 
parser,
   auto cleanup = make_temp_override
     (parser->auto_is_implicit_function_template_parm_p);
 
-  if (!processing_specialization
-      && !processing_template_parmlist
-      && !processing_explicit_instantiation
-      /* default_arg_ok_p tracks whether this is a parameter-clause for an
-         actual function or a random abstract declarator.  */
-      && parser->default_arg_ok_p)
-    if (!current_function_decl
-       || (current_class_type && LAMBDA_TYPE_P (current_class_type)))
-      parser->auto_is_implicit_function_template_parm_p = true;
+  if (lambda_p
+      || (!processing_specialization
+         && !processing_template_parmlist
+         && !processing_explicit_instantiation
+         /* default_arg_ok_p tracks whether this is a parameter-clause for an
+            actual function or a random abstract declarator.  */
+         && parser->default_arg_ok_p
+         && !current_function_decl))
+    parser->auto_is_implicit_function_template_parm_p = true;
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -31472,7 +31477,8 @@ cp_parser_requirement_parameter_list (cp_parser *parser)
     return error_mark_node;
 
   tree parms = (cp_parser_parameter_declaration_clause
-               (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL));
+               (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
+                /*lambda_p=*/false));
 
   if (!parens.require_close (parser))
     return error_mark_node;
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ6.C 
b/gcc/testsuite/g++.dg/cpp2a/lambda-targ6.C
new file mode 100644
index 000000000000..51728a040e25
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ6.C
@@ -0,0 +1,15 @@
+// PR c++/88313
+// { dg-do compile { target c++20 } }
+
+template<int N = [](auto x) { return x; }(42)>
+constexpr int f() { return N; }
+
+template<auto F = [](auto x) { return x; }>
+constexpr auto g() { return F; }
+
+template<class T = decltype([](auto x) { return x; })>
+constexpr int h(T t = {}) { return t(42); }
+
+static_assert(f() == 42);
+static_assert(g()(42) == 42);
+static_assert(h() == 42);

Reply via email to