On Tue, Jan 21, 2025 at 05:09:32PM -0500, Jason Merrill wrote: > On 1/16/25 5:42 PM, Marek Polacek wrote: > > On Wed, Jan 15, 2025 at 04:18:36PM -0500, Jason Merrill wrote: > > > On 1/15/25 12:55 PM, Marek Polacek wrote: > > > > On Wed, Jan 15, 2025 at 09:39:41AM -0500, Jason Merrill wrote: > > > > > On 11/15/24 9:08 AM, Marek Polacek wrote: > > > > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? > > > > > > > > > > > > -- >8 -- > > > > > > 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: > > > > > > > > > > > > * parser.cc (cp_parser_lambda_introducer): Check if we're in a > > > > > > lambda > > > > > > before emitting the error about a non-local lambda with > > > > > > a capture-default. > > > > > > > > > > > > gcc/testsuite/ChangeLog: > > > > > > > > > > > > * g++.dg/cpp2a/lambda-uneval19.C: New test. > > > > > > --- > > > > > > gcc/cp/parser.cc | 5 ++++- > > > > > > gcc/testsuite/g++.dg/cpp2a/lambda-uneval19.C | 14 ++++++++++++++ > > > > > > 2 files changed, 18 insertions(+), 1 deletion(-) > > > > > > create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-uneval19.C > > > > > > > > > > > > diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc > > > > > > index 07b12224615..dc79ff42a3b 100644 > > > > > > --- a/gcc/cp/parser.cc > > > > > > +++ b/gcc/cp/parser.cc > > > > > > @@ -11611,7 +11611,10 @@ 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 ())) > > > > > > + if (!(at_function_scope_p () > > > > > > + || parsing_nsdmi () > > > > > > + || (current_class_type > > > > > > + && LAMBDA_TYPE_P (current_class_type)))) > > > > > > > > > > How about using current_nonlambda_scope () instead of > > > > > at_function_scope_p > > > > > ()? > > > > > > > > I think I remember not using that because current_nonlambda_scope() will > > > > give us a namespace_decl :: for non-local stuff so it won't be null. Do > > > > you still prefer that (checking the result of current_nonlambda_scope()) > > > > to what I did in my patch? > > > > > > I think so, your change looks to be true for lambdas outside function > > > scope > > > as well. > > > > I think it works correctly for both > > > > auto x = [&]() { // error > > [&]() { }; > > }; > > auto x2 = []() { > > [&]() { }; > > }; > > > > but current_nonlambda_scope () will return '::' for the nested lambdas too. > > Am I missing something? > > Ah, good point. But it doesn't work correctly for an adjustment to the PR > testcase; with your patch the following is wrongly accepted: > > auto x = [](decltype([&]{})){};
You're right. > Perhaps current_scope should look through closure types, so > at_function_scope_p gives the right answer? I've tried but then other code breaks because it doesn't expect current_scope to behave like that. So how about this one? It seems very safe. Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? -- >8 -- 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. --- 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(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-uneval21.C diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 0eb3e8531c5..5e8aefc1289 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 acb7208fd18..5593636eaf8 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 24322817f3e..03010089c3c 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 00000000000..d3ea3acf52d --- /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([&]() {})) {})) {})) {})){}; + + [=]() { + [&]() { }; + }; +} base-commit: 0bb3223097e5ced4f9a13d18c6c65f2a9496437e -- 2.48.1