https://gcc.gnu.org/g:4bcfaaed25b1b8ecc81f6a28d9ca76f00870dedf
commit r15-3980-g4bcfaaed25b1b8ecc81f6a28d9ca76f00870dedf Author: Marek Polacek <pola...@redhat.com> Date: Wed Sep 18 15:44:31 2024 -0400 c++: concept in default argument [PR109859] 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 <ja...@redhat.com> Diff: --- 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(-) diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index f50534f5f395..0944827d777b 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 000000000000..6fe82f91e434 --- /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 000000000000..3685b0ef880b --- /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<>; }