Message ID | Zvrjxpem2Xt025jZ@redhat.com |
---|---|
State | New |
Headers | show |
Series | [v3] c++: concept in default argument [PR109859] | expand |
On 9/30/24 1:45 PM, Marek Polacek wrote: > On Mon, Sep 30, 2024 at 10:53:04AM -0400, Jason Merrill wrote: >> On 9/27/24 5:30 PM, Marek Polacek wrote: >>> On Fri, Sep 27, 2024 at 04:57:58PM -0400, Jason Merrill wrote: >>>> On 9/18/24 5:06 PM, Marek Polacek wrote: >>>>> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? >>>>> >>>>> -- >8 -- >>>>> 1) We're hitting the assert in cp_parser_placeholder_type_specifier. >>>>> It says that if it turns out to be false, we should do error() instead. >>>>> Do so, then. >>>>> >>>>> 2) lambda-targ8.C should compile fine, though. The problem was that >>>>> local_variables_forbidden_p wasn't cleared when we're about to parse >>>>> the optional template-parameter-list for a lambda in a default argument. >>>>> >>>>> PR c++/109859 >>>>> >>>>> gcc/cp/ChangeLog: >>>>> >>>>> * parser.cc (cp_parser_lambda_declarator_opt): Temporarily clear >>>>> local_variables_forbidden_p. >>>>> (cp_parser_placeholder_type_specifier): Turn an assert into an error. >>>>> >>>>> gcc/testsuite/ChangeLog: >>>>> >>>>> * g++.dg/cpp2a/concepts-defarg3.C: New test. >>>>> * g++.dg/cpp2a/lambda-targ8.C: New test. >>>>> --- >>>>> gcc/cp/parser.cc | 9 +++++++-- >>>>> gcc/testsuite/g++.dg/cpp2a/concepts-defarg3.C | 8 ++++++++ >>>>> gcc/testsuite/g++.dg/cpp2a/lambda-targ8.C | 10 ++++++++++ >>>>> 3 files changed, 25 insertions(+), 2 deletions(-) >>>>> create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-defarg3.C >>>>> create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-targ8.C >>>>> >>>>> diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc >>>>> index 4dd9474cf60..bdc4fef243a 100644 >>>>> --- a/gcc/cp/parser.cc >>>>> +++ b/gcc/cp/parser.cc >>>>> @@ -11891,6 +11891,11 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) >>>>> "lambda templates are only available with " >>>>> "%<-std=c++20%> or %<-std=gnu++20%>"); >>>>> + /* Even though the whole lambda may be a default argument, its >>>>> + template-parameter-list is a context where it's OK to create >>>>> + new parameters. */ >>>>> + auto lvf = make_temp_override (parser->local_variables_forbidden_p, 0u); >>>>> + >>>>> cp_lexer_consume_token (parser->lexer); >>>>> template_param_list = cp_parser_template_parameter_list (parser); >>>>> @@ -20978,8 +20983,8 @@ cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc, >>>>> /* In a default argument we may not be creating new parameters. */ >>>>> if (parser->local_variables_forbidden_p & LOCAL_VARS_FORBIDDEN) >>>>> { >>>>> - /* If this assert turns out to be false, do error() instead. */ >>>>> - gcc_assert (tentative); >>>>> + if (!tentative) >>>>> + error_at (loc, "local variables may not appear in this context"); >>>> >>>> There's no local variable in the new testcase, the error should talk about a >>>> concept-name. >>> >>> Ah sure. So like this? >>> >>> Tested dg.exp. >>> >>> -- >8 -- >>> 1) We're hitting the assert in cp_parser_placeholder_type_specifier. >>> It says that if it turns out to be false, we should do error() instead. >>> Do so, then. >>> >>> 2) lambda-targ8.C should compile fine, though. The problem was that >>> local_variables_forbidden_p wasn't cleared when we're about to parse >>> the optional template-parameter-list for a lambda in a default argument. >>> >>> PR c++/109859 >>> >>> gcc/cp/ChangeLog: >>> >>> * parser.cc (cp_parser_lambda_declarator_opt): Temporarily clear >>> local_variables_forbidden_p. >>> (cp_parser_placeholder_type_specifier): Turn an assert into an error. >>> >>> gcc/testsuite/ChangeLog: >>> >>> * g++.dg/cpp2a/concepts-defarg3.C: New test. >>> * g++.dg/cpp2a/lambda-targ8.C: New test. >>> --- >>> gcc/cp/parser.cc | 9 +++++++-- >>> gcc/testsuite/g++.dg/cpp2a/concepts-defarg3.C | 8 ++++++++ >>> gcc/testsuite/g++.dg/cpp2a/lambda-targ8.C | 10 ++++++++++ >>> 3 files changed, 25 insertions(+), 2 deletions(-) >>> create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-defarg3.C >>> create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-targ8.C >>> >>> diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc >>> index f50534f5f39..a92e6a29ba6 100644 >>> --- a/gcc/cp/parser.cc >>> +++ b/gcc/cp/parser.cc >>> @@ -11891,6 +11891,11 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) >>> "lambda templates are only available with " >>> "%<-std=c++20%> or %<-std=gnu++20%>"); >>> + /* Even though the whole lambda may be a default argument, its >>> + template-parameter-list is a context where it's OK to create >>> + new parameters. */ >>> + auto lvf = make_temp_override (parser->local_variables_forbidden_p, 0u); >>> + >>> cp_lexer_consume_token (parser->lexer); >>> template_param_list = cp_parser_template_parameter_list (parser); >>> @@ -20989,8 +20994,8 @@ cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc, >>> /* In a default argument we may not be creating new parameters. */ >>> if (parser->local_variables_forbidden_p & LOCAL_VARS_FORBIDDEN) >>> { >>> - /* If this assert turns out to be false, do error() instead. */ >>> - gcc_assert (tentative); >>> + if (!tentative) >>> + error_at (loc, "concept-name may not appear in this context"); >> >> Hmm, actually I expect it can appear in a concept-id. > > Aha. I just followed the commentary. Yeah, sorry. >> What if we fall >> through to the next case instead of erroring/returning at this point? > > Then for concepts-defarg3.C we emit: > > concepts-defarg3.C:7:19: error: expected 'auto' or 'decltype(auto)' after 'C' > 7 | template <class = C> // { dg-error "may not appear in this context" } > | ^ > concepts-defarg3.C:7:19: error: invalid use of ‘auto’ in default template argument I guess a more helpful diagnostic would be to go back to v2 and make the error the more vague "invalid use of concept-name %qD". OK that way, thanks. > The first error is fine, the second...not so much. We created the > auto at the end of cp_parser_placeholder_type_specifier in > make_constrained_auto. I could fix it by adding a flag and returning early > but maybe it can stay as-is. The fall through after "expected auto" is > deliberate... > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? > > -- >8 -- > 1) We're hitting the assert in cp_parser_placeholder_type_specifier. > Rather than turning that assert into an error, we can fall through > to the next block to get an error. > > 2) lambda-targ8.C should compile fine, though. The problem was that > local_variables_forbidden_p wasn't cleared when we're about to parse > the optional template-parameter-list for a lambda in a default argument. > > PR c++/109859 > > gcc/cp/ChangeLog: > > * parser.cc (cp_parser_lambda_declarator_opt): Temporarily clear > local_variables_forbidden_p. > (cp_parser_placeholder_type_specifier): Remove an assert; fall > through to the next condition instead. > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp2a/concepts-defarg3.C: New test. > * g++.dg/cpp2a/lambda-targ8.C: New test. > --- > gcc/cp/parser.cc | 20 +++++++++---------- > gcc/testsuite/g++.dg/cpp2a/concepts-defarg3.C | 8 ++++++++ > gcc/testsuite/g++.dg/cpp2a/lambda-targ8.C | 10 ++++++++++ > 3 files changed, 27 insertions(+), 11 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-defarg3.C > create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-targ8.C > > diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc > index f50534f5f39..54c59363da1 100644 > --- a/gcc/cp/parser.cc > +++ b/gcc/cp/parser.cc > @@ -11891,6 +11891,11 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) > "lambda templates are only available with " > "%<-std=c++20%> or %<-std=gnu++20%>"); > > + /* Even though the whole lambda may be a default argument, its > + template-parameter-list is a context where it's OK to create > + new parameters. */ > + auto lvf = make_temp_override (parser->local_variables_forbidden_p, 0u); > + > cp_lexer_consume_token (parser->lexer); > > template_param_list = cp_parser_template_parameter_list (parser); > @@ -20984,17 +20989,10 @@ cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc, > > /* In a template parameter list, a type-parameter can be introduced > by type-constraints alone. */ > - if (processing_template_parmlist && !placeholder) > - { > - /* In a default argument we may not be creating new parameters. */ > - if (parser->local_variables_forbidden_p & LOCAL_VARS_FORBIDDEN) > - { > - /* If this assert turns out to be false, do error() instead. */ > - gcc_assert (tentative); > - return error_mark_node; > - } > - return build_constrained_parameter (con, proto, args); > - } > + if (processing_template_parmlist > + && !placeholder > + && (parser->local_variables_forbidden_p & LOCAL_VARS_FORBIDDEN) == 0) > + return build_constrained_parameter (con, proto, args); > > /* Diagnose issues placeholder issues. */ > if (!parser->in_result_type_constraint_p && !placeholder) > diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-defarg3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-defarg3.C > new file mode 100644 > index 00000000000..aaf3edf77e6 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-defarg3.C > @@ -0,0 +1,8 @@ > +// PR c++/109859 > +// { dg-do compile { target c++20 } } > + > +template<class> > +concept C = true; > + > +template <class = C> // { dg-error "expected|invalid" } > +int f(); > diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ8.C b/gcc/testsuite/g++.dg/cpp2a/lambda-targ8.C > new file mode 100644 > index 00000000000..3685b0ef880 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ8.C > @@ -0,0 +1,10 @@ > +// PR c++/109859 > +// { dg-do compile { target c++20 } } > + > +template<typename> > +concept A = true; > + > +template<auto = []<A a> {}> > +int x; > + > +void g() { (void) x<>; } > > base-commit: 9c14f9a9c19957d9a45a7df97701bad475c80eea
On Mon, Sep 30, 2024 at 03:02:39PM -0400, Jason Merrill wrote: > On 9/30/24 1:45 PM, Marek Polacek wrote: > > On Mon, Sep 30, 2024 at 10:53:04AM -0400, Jason Merrill wrote: > > > On 9/27/24 5:30 PM, Marek Polacek wrote: > > > > On Fri, Sep 27, 2024 at 04:57:58PM -0400, Jason Merrill wrote: > > > > > On 9/18/24 5:06 PM, Marek Polacek wrote: > > > > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? > > > > > > > > > > > > -- >8 -- > > > > > > 1) We're hitting the assert in cp_parser_placeholder_type_specifier. > > > > > > It says that if it turns out to be false, we should do error() instead. > > > > > > Do so, then. > > > > > > > > > > > > 2) lambda-targ8.C should compile fine, though. The problem was that > > > > > > local_variables_forbidden_p wasn't cleared when we're about to parse > > > > > > the optional template-parameter-list for a lambda in a default argument. > > > > > > > > > > > > PR c++/109859 > > > > > > > > > > > > gcc/cp/ChangeLog: > > > > > > > > > > > > * parser.cc (cp_parser_lambda_declarator_opt): Temporarily clear > > > > > > local_variables_forbidden_p. > > > > > > (cp_parser_placeholder_type_specifier): Turn an assert into an error. > > > > > > > > > > > > gcc/testsuite/ChangeLog: > > > > > > > > > > > > * g++.dg/cpp2a/concepts-defarg3.C: New test. > > > > > > * g++.dg/cpp2a/lambda-targ8.C: New test. > > > > > > --- > > > > > > gcc/cp/parser.cc | 9 +++++++-- > > > > > > gcc/testsuite/g++.dg/cpp2a/concepts-defarg3.C | 8 ++++++++ > > > > > > gcc/testsuite/g++.dg/cpp2a/lambda-targ8.C | 10 ++++++++++ > > > > > > 3 files changed, 25 insertions(+), 2 deletions(-) > > > > > > create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-defarg3.C > > > > > > create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-targ8.C > > > > > > > > > > > > diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc > > > > > > index 4dd9474cf60..bdc4fef243a 100644 > > > > > > --- a/gcc/cp/parser.cc > > > > > > +++ b/gcc/cp/parser.cc > > > > > > @@ -11891,6 +11891,11 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) > > > > > > "lambda templates are only available with " > > > > > > "%<-std=c++20%> or %<-std=gnu++20%>"); > > > > > > + /* Even though the whole lambda may be a default argument, its > > > > > > + template-parameter-list is a context where it's OK to create > > > > > > + new parameters. */ > > > > > > + auto lvf = make_temp_override (parser->local_variables_forbidden_p, 0u); > > > > > > + > > > > > > cp_lexer_consume_token (parser->lexer); > > > > > > template_param_list = cp_parser_template_parameter_list (parser); > > > > > > @@ -20978,8 +20983,8 @@ cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc, > > > > > > /* In a default argument we may not be creating new parameters. */ > > > > > > if (parser->local_variables_forbidden_p & LOCAL_VARS_FORBIDDEN) > > > > > > { > > > > > > - /* If this assert turns out to be false, do error() instead. */ > > > > > > - gcc_assert (tentative); > > > > > > + if (!tentative) > > > > > > + error_at (loc, "local variables may not appear in this context"); > > > > > > > > > > There's no local variable in the new testcase, the error should talk about a > > > > > concept-name. > > > > > > > > Ah sure. So like this? > > > > > > > > Tested dg.exp. > > > > > > > > -- >8 -- > > > > 1) We're hitting the assert in cp_parser_placeholder_type_specifier. > > > > It says that if it turns out to be false, we should do error() instead. > > > > Do so, then. > > > > > > > > 2) lambda-targ8.C should compile fine, though. The problem was that > > > > local_variables_forbidden_p wasn't cleared when we're about to parse > > > > the optional template-parameter-list for a lambda in a default argument. > > > > > > > > PR c++/109859 > > > > > > > > gcc/cp/ChangeLog: > > > > > > > > * parser.cc (cp_parser_lambda_declarator_opt): Temporarily clear > > > > local_variables_forbidden_p. > > > > (cp_parser_placeholder_type_specifier): Turn an assert into an error. > > > > > > > > gcc/testsuite/ChangeLog: > > > > > > > > * g++.dg/cpp2a/concepts-defarg3.C: New test. > > > > * g++.dg/cpp2a/lambda-targ8.C: New test. > > > > --- > > > > gcc/cp/parser.cc | 9 +++++++-- > > > > gcc/testsuite/g++.dg/cpp2a/concepts-defarg3.C | 8 ++++++++ > > > > gcc/testsuite/g++.dg/cpp2a/lambda-targ8.C | 10 ++++++++++ > > > > 3 files changed, 25 insertions(+), 2 deletions(-) > > > > create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-defarg3.C > > > > create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-targ8.C > > > > > > > > diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc > > > > index f50534f5f39..a92e6a29ba6 100644 > > > > --- a/gcc/cp/parser.cc > > > > +++ b/gcc/cp/parser.cc > > > > @@ -11891,6 +11891,11 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) > > > > "lambda templates are only available with " > > > > "%<-std=c++20%> or %<-std=gnu++20%>"); > > > > + /* Even though the whole lambda may be a default argument, its > > > > + template-parameter-list is a context where it's OK to create > > > > + new parameters. */ > > > > + auto lvf = make_temp_override (parser->local_variables_forbidden_p, 0u); > > > > + > > > > cp_lexer_consume_token (parser->lexer); > > > > template_param_list = cp_parser_template_parameter_list (parser); > > > > @@ -20989,8 +20994,8 @@ cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc, > > > > /* In a default argument we may not be creating new parameters. */ > > > > if (parser->local_variables_forbidden_p & LOCAL_VARS_FORBIDDEN) > > > > { > > > > - /* If this assert turns out to be false, do error() instead. */ > > > > - gcc_assert (tentative); > > > > + if (!tentative) > > > > + error_at (loc, "concept-name may not appear in this context"); > > > > > > Hmm, actually I expect it can appear in a concept-id. > > > > Aha. I just followed the commentary. > > Yeah, sorry. > > > > What if we fall > > > through to the next case instead of erroring/returning at this point? > > > > Then for concepts-defarg3.C we emit: > > > > concepts-defarg3.C:7:19: error: expected 'auto' or 'decltype(auto)' after 'C' > > 7 | template <class = C> // { dg-error "may not appear in this context" } > > | ^ > > concepts-defarg3.C:7:19: error: invalid use of ‘auto’ in default template argument > > I guess a more helpful diagnostic would be to go back to v2 and make the > error the more vague "invalid use of concept-name %qD". OK that way, > thanks. Thanks. Here's what I'm pushing: -- >8 -- 1) We're hitting the assert in cp_parser_placeholder_type_specifier. It says that if it turns out to be false, we should do error() instead. Do so, then. 2) lambda-targ8.C should compile fine, though. The problem was that local_variables_forbidden_p wasn't cleared when we're about to parse the optional template-parameter-list for a lambda in a default argument. PR c++/109859 gcc/cp/ChangeLog: * parser.cc (cp_parser_lambda_declarator_opt): Temporarily clear local_variables_forbidden_p. (cp_parser_placeholder_type_specifier): Turn an assert into an error. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-defarg3.C: New test. * g++.dg/cpp2a/lambda-targ8.C: New test. Reviewed-by: Jason Merrill <jason@redhat.com> --- gcc/cp/parser.cc | 9 +++++++-- gcc/testsuite/g++.dg/cpp2a/concepts-defarg3.C | 8 ++++++++ gcc/testsuite/g++.dg/cpp2a/lambda-targ8.C | 10 ++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-defarg3.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-targ8.C diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index f50534f5f39..0944827d777 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -11891,6 +11891,11 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) "lambda templates are only available with " "%<-std=c++20%> or %<-std=gnu++20%>"); + /* Even though the whole lambda may be a default argument, its + template-parameter-list is a context where it's OK to create + new parameters. */ + auto lvf = make_temp_override (parser->local_variables_forbidden_p, 0u); + cp_lexer_consume_token (parser->lexer); template_param_list = cp_parser_template_parameter_list (parser); @@ -20989,8 +20994,8 @@ cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc, /* In a default argument we may not be creating new parameters. */ if (parser->local_variables_forbidden_p & LOCAL_VARS_FORBIDDEN) { - /* If this assert turns out to be false, do error() instead. */ - gcc_assert (tentative); + if (!tentative) + error_at (loc, "invalid use of concept-name %qD", con); return error_mark_node; } return build_constrained_parameter (con, proto, args); diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-defarg3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-defarg3.C new file mode 100644 index 00000000000..6fe82f91e43 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-defarg3.C @@ -0,0 +1,8 @@ +// PR c++/109859 +// { dg-do compile { target c++20 } } + +template<class> +concept C = true; + +template <class = C> // { dg-error "invalid use of concept-name .C." } +int f(); diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ8.C b/gcc/testsuite/g++.dg/cpp2a/lambda-targ8.C new file mode 100644 index 00000000000..3685b0ef880 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ8.C @@ -0,0 +1,10 @@ +// PR c++/109859 +// { dg-do compile { target c++20 } } + +template<typename> +concept A = true; + +template<auto = []<A a> {}> +int x; + +void g() { (void) x<>; } base-commit: 65073a5b90c00a1c47efae8a67b9c754e2287ee0
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index f50534f5f39..54c59363da1 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -11891,6 +11891,11 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) "lambda templates are only available with " "%<-std=c++20%> or %<-std=gnu++20%>"); + /* Even though the whole lambda may be a default argument, its + template-parameter-list is a context where it's OK to create + new parameters. */ + auto lvf = make_temp_override (parser->local_variables_forbidden_p, 0u); + cp_lexer_consume_token (parser->lexer); template_param_list = cp_parser_template_parameter_list (parser); @@ -20984,17 +20989,10 @@ cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc, /* In a template parameter list, a type-parameter can be introduced by type-constraints alone. */ - if (processing_template_parmlist && !placeholder) - { - /* In a default argument we may not be creating new parameters. */ - if (parser->local_variables_forbidden_p & LOCAL_VARS_FORBIDDEN) - { - /* If this assert turns out to be false, do error() instead. */ - gcc_assert (tentative); - return error_mark_node; - } - return build_constrained_parameter (con, proto, args); - } + if (processing_template_parmlist + && !placeholder + && (parser->local_variables_forbidden_p & LOCAL_VARS_FORBIDDEN) == 0) + return build_constrained_parameter (con, proto, args); /* Diagnose issues placeholder issues. */ if (!parser->in_result_type_constraint_p && !placeholder) diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-defarg3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-defarg3.C new file mode 100644 index 00000000000..aaf3edf77e6 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-defarg3.C @@ -0,0 +1,8 @@ +// PR c++/109859 +// { dg-do compile { target c++20 } } + +template<class> +concept C = true; + +template <class = C> // { dg-error "expected|invalid" } +int f(); diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ8.C b/gcc/testsuite/g++.dg/cpp2a/lambda-targ8.C new file mode 100644 index 00000000000..3685b0ef880 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ8.C @@ -0,0 +1,10 @@ +// PR c++/109859 +// { dg-do compile { target c++20 } } + +template<typename> +concept A = true; + +template<auto = []<A a> {}> +int x; + +void g() { (void) x<>; }