* [PATCH] c++: generic lambda as default template argument [PR88313]
@ 2024-07-29 15:38 Patrick Palka
2024-07-29 19:29 ` Jason Merrill
0 siblings, 1 reply; 2+ messages in thread
From: Patrick Palka @ 2024-07-29 15:38 UTC (permalink / raw)
To: gcc-patches; +Cc: jason, Patrick Palka
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this
look OK for trunk and perhaps 14.3? It should only make a differenc
for C++20 code where lambdas are permitted as template arguments.
-- >8 --
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 this happens by way of 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.
---
gcc/cp/parser.cc | 34 +++++++++++++----------
gcc/testsuite/g++.dg/cpp2a/lambda-targ6.C | 11 ++++++++
2 files changed, 31 insertions(+), 14 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-targ6.C
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index f79736c17ac..f5336eae74a 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -2600,7 +2600,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
@@ -11889,7 +11889,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. */
@@ -24097,7 +24097,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=*/false);
const location_t parens_end
= cp_lexer_peek_token (parser->lexer)->location;
@@ -25444,13 +25445,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;
@@ -25459,15 +25464,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);
@@ -31743,7 +31748,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 00000000000..6dbcbf40970
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ6.C
@@ -0,0 +1,11 @@
+// PR c++/88313
+// { dg-do compile { target c++20 } }
+
+template<int N = [](auto x) { return x; }(42)>
+constexpr int f() { return N; }
+
+template<class T = decltype([](auto x) { return x; })>
+constexpr int g(T t = {}) { return t(42); }
+
+static_assert(f() == 42);
+static_assert(g() == 42);
--
2.46.0.rc2
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] c++: generic lambda as default template argument [PR88313]
2024-07-29 15:38 [PATCH] c++: generic lambda as default template argument [PR88313] Patrick Palka
@ 2024-07-29 19:29 ` Jason Merrill
0 siblings, 0 replies; 2+ messages in thread
From: Jason Merrill @ 2024-07-29 19:29 UTC (permalink / raw)
To: Patrick Palka, gcc-patches
On 7/29/24 11:38 AM, Patrick Palka wrote:
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this
> look OK for trunk and perhaps 14.3? It should only make a differenc
> for C++20 code where lambdas are permitted as template arguments.
OK for both.
> -- >8 --
>
> 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 this happens by way of 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.
> ---
> gcc/cp/parser.cc | 34 +++++++++++++----------
> gcc/testsuite/g++.dg/cpp2a/lambda-targ6.C | 11 ++++++++
> 2 files changed, 31 insertions(+), 14 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-targ6.C
>
> diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> index f79736c17ac..f5336eae74a 100644
> --- a/gcc/cp/parser.cc
> +++ b/gcc/cp/parser.cc
> @@ -2600,7 +2600,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
> @@ -11889,7 +11889,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. */
> @@ -24097,7 +24097,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=*/false);
> const location_t parens_end
> = cp_lexer_peek_token (parser->lexer)->location;
>
> @@ -25444,13 +25445,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;
> @@ -25459,15 +25464,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);
> @@ -31743,7 +31748,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 00000000000..6dbcbf40970
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ6.C
> @@ -0,0 +1,11 @@
> +// PR c++/88313
> +// { dg-do compile { target c++20 } }
> +
> +template<int N = [](auto x) { return x; }(42)>
> +constexpr int f() { return N; }
> +
> +template<class T = decltype([](auto x) { return x; })>
> +constexpr int g(T t = {}) { return t(42); }
> +
> +static_assert(f() == 42);
> +static_assert(g() == 42);
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2024-07-29 19:29 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-07-29 15:38 [PATCH] c++: generic lambda as default template argument [PR88313] Patrick Palka
2024-07-29 19:29 ` Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).