https://gcc.gnu.org/g:6d8a0e8b2cfb5c8997b378f230a4ccdbfacaee4d
commit r15-7169-g6d8a0e8b2cfb5c8997b378f230a4ccdbfacaee4d Author: Marek Polacek <pola...@redhat.com> Date: Thu Nov 14 23:47:46 2024 -0500 c++: bogus error with nested lambdas [PR117602] The error here should also check that we aren't nested in another lambda; in it, at_function_scope_p() will be false. PR c++/117602 gcc/cp/ChangeLog: * cp-tree.h (current_nonlambda_scope): Add a default argument. * lambda.cc (current_nonlambda_scope): New bool parameter. Use it. * parser.cc (cp_parser_lambda_introducer): Use current_nonlambda_scope to check if the lambda is non-local. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/lambda-uneval21.C: New test. Reviewed-by: Jason Merrill <ja...@redhat.com> Diff: --- gcc/cp/cp-tree.h | 2 +- gcc/cp/lambda.cc | 8 ++++--- gcc/cp/parser.cc | 3 ++- gcc/testsuite/g++.dg/cpp2a/lambda-uneval21.C | 32 ++++++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 0eb3e8531c58..5e8aefc12893 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -8097,7 +8097,7 @@ extern void maybe_generic_this_capture (tree, tree); extern tree maybe_resolve_dummy (tree, bool); extern tree current_nonlambda_function (void); extern tree nonlambda_method_basetype (void); -extern tree current_nonlambda_scope (void); +extern tree current_nonlambda_scope (bool = false); extern tree current_lambda_expr (void); extern bool generic_lambda_fn_p (tree); extern tree do_dependent_capture (tree, bool = false); diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc index acb7208fd185..5593636eaf8e 100644 --- a/gcc/cp/lambda.cc +++ b/gcc/cp/lambda.cc @@ -1045,15 +1045,17 @@ nonlambda_method_basetype (void) } } -/* Like current_scope, but looking through lambdas. */ +/* Like current_scope, but looking through lambdas. If ONLY_SKIP_CLOSURES_P, + only look through closure types. */ tree -current_nonlambda_scope (void) +current_nonlambda_scope (bool only_skip_closures_p/*=false*/) { tree scope = current_scope (); for (;;) { - if (TREE_CODE (scope) == FUNCTION_DECL + if (!only_skip_closures_p + && TREE_CODE (scope) == FUNCTION_DECL && LAMBDA_FUNCTION_P (scope)) { scope = CP_TYPE_CONTEXT (DECL_CONTEXT (scope)); diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 24322817f3ed..03010089c3c6 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -11877,7 +11877,8 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) cp_lexer_consume_token (parser->lexer); first = false; - if (!(at_function_scope_p () || parsing_nsdmi ())) + tree scope = current_nonlambda_scope (/*only_skip_closures_p=*/true); + if (TREE_CODE (scope) != FUNCTION_DECL && !parsing_nsdmi ()) error ("non-local lambda expression cannot have a capture-default"); } diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-uneval21.C b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval21.C new file mode 100644 index 000000000000..d3ea3acf52d4 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-uneval21.C @@ -0,0 +1,32 @@ +// PR c++/117602 +// { dg-do compile { target c++20 } } + +auto x1 = [](decltype([&]{})){}; // { dg-error "non-local lambda" } + +auto x2 = [&]() { // { dg-error "non-local lambda" } + [&]() { }; +}; + +auto x3 = []() { + [&]() { }; +}; + +auto x4 = []() { + []() { }; +}; + +auto x5 = [&]() { // { dg-error "non-local lambda" } + []() { }; +}; + +void +g () +{ + [&](decltype([&](decltype([=](decltype([&](decltype([&]() {})) {})) {})) {})){}; + [&](decltype([&](decltype([&](decltype([&](decltype([&]() {})) {})) {})) {})){}; + [=](decltype([=](decltype([=](decltype([=](decltype([&]() {})) {})) {})) {})){}; + + [=]() { + [&]() { }; + }; +}