]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: bogus error with nested lambdas [PR117602]
authorMarek Polacek <polacek@redhat.com>
Fri, 15 Nov 2024 04:47:46 +0000 (23:47 -0500)
committerMarek Polacek <polacek@redhat.com>
Thu, 23 Jan 2025 22:13:08 +0000 (17:13 -0500)
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 <jason@redhat.com>
gcc/cp/cp-tree.h
gcc/cp/lambda.cc
gcc/cp/parser.cc
gcc/testsuite/g++.dg/cpp2a/lambda-uneval21.C [new file with mode: 0644]

index 0eb3e8531c58ee15e0f74585017ee2d40306e09c..5e8aefc12893cb8ea87ef781e63a42225de95d30 100644 (file)
@@ -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);
index acb7208fd18555cc5c988bca2564d97ee5815796..5593636eaf8edc9b5ac8efda8c964c0214e383a9 100644 (file)
@@ -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));
index 24322817f3ed4ed2c3b32e965cf18f8c4d5d415d..03010089c3c625a0f625c83e0dc7ce8901c19a1f 100644 (file)
@@ -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 (file)
index 0000000..d3ea3ac
--- /dev/null
@@ -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([&]() {})) {})) {})) {})){};
+
+  [=]() {
+    [&]() { };
+  };
+}