On 1/23/25 11:45 AM, Marek Polacek wrote:
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?

OK.

-- >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

Reply via email to