[clang-tools-extra] [clang-tidy] Add concurrency-lambda-coroutine-capture check (PR #182916)
Willem Kaufmann via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 23 11:00:58 PST 2026
https://github.com/WillemKauf created https://github.com/llvm/llvm-project/pull/182916
Adds a new check which finds lambda coroutines that capture variables without using the C++23 "deducing this" explicit object parameter, which can cause use-after-free when the lambda is destroyed while the coroutine is still suspended ([the "lambda coroutine fiasco"](https://github.com/scylladb/seastar/blob/master/doc/lambda-coroutine-fiasco.md)).
There is an existing clang-tidy check based on the [CP.53](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#rcoro-reference-parameters), `cppcoreguidelines-avoid-capturing-lambda-coroutines`. This check warns on all lambda coroutines with captures, including C++23 lambdas that use explicit object parameters (deducing this) which are safefrom the lifetime issue. Since we now have a way of avoiding this problem in C++23 and up (along with the added `clang-tidy` check), we can suppress the warning when the lambda uses `this auto`, and cross-reference the two related checks in their documentation.
>From 3bbe094077a65b3e78c44a38ce473b1dcc5b0510 Mon Sep 17 00:00:00 2001
From: Willem Kaufmann <willem.kaufmann at gmail.com>
Date: Mon, 23 Feb 2026 13:53:00 -0500
Subject: [PATCH 1/2] [clang-tidy] Add `concurrency-lambda-coroutine-capture
check`
Adds a new check which finds lambda coroutines that capture variables
without using the C++23 "deducing this" explicit object parameter,
which can cause use-after-free when the lambda is destroyed while
the coroutine is still suspended (the "lambda coroutine fiasco") [1].
The check provides fix-it hints to insert `this auto` as the first
parameter, which moves captures into the coroutine frame and
decouples their lifetime from the lambda object.
[1]: https://github.com/scylladb/seastar/blob/master/doc/lambda-coroutine-fiasco.md
---
.../clang-tidy/concurrency/CMakeLists.txt | 1 +
.../concurrency/ConcurrencyTidyModule.cpp | 4 +
.../LambdaCoroutineCaptureCheck.cpp | 72 ++++++++++
.../concurrency/LambdaCoroutineCaptureCheck.h | 41 ++++++
clang-tools-extra/docs/ReleaseNotes.rst | 8 ++
.../concurrency/lambda-coroutine-capture.rst | 58 ++++++++
.../docs/clang-tidy/checks/list.rst | 1 +
.../concurrency/lambda-coroutine-capture.cpp | 132 ++++++++++++++++++
8 files changed, 317 insertions(+)
create mode 100644 clang-tools-extra/clang-tidy/concurrency/LambdaCoroutineCaptureCheck.cpp
create mode 100644 clang-tools-extra/clang-tidy/concurrency/LambdaCoroutineCaptureCheck.h
create mode 100644 clang-tools-extra/docs/clang-tidy/checks/concurrency/lambda-coroutine-capture.rst
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/concurrency/lambda-coroutine-capture.cpp
diff --git a/clang-tools-extra/clang-tidy/concurrency/CMakeLists.txt b/clang-tools-extra/clang-tidy/concurrency/CMakeLists.txt
index 91c6cedabcc80..ffd871bb1059c 100644
--- a/clang-tools-extra/clang-tidy/concurrency/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/concurrency/CMakeLists.txt
@@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS
add_clang_library(clangTidyConcurrencyModule STATIC
ConcurrencyTidyModule.cpp
+ LambdaCoroutineCaptureCheck.cpp
MtUnsafeCheck.cpp
ThreadCanceltypeAsynchronousCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/concurrency/ConcurrencyTidyModule.cpp b/clang-tools-extra/clang-tidy/concurrency/ConcurrencyTidyModule.cpp
index 0d02a3d9b6e2b..9626a438a07b0 100644
--- a/clang-tools-extra/clang-tidy/concurrency/ConcurrencyTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/concurrency/ConcurrencyTidyModule.cpp
@@ -8,6 +8,8 @@
#include "../ClangTidy.h"
#include "../ClangTidyModule.h"
+#include "../ClangTidyModuleRegistry.h"
+#include "LambdaCoroutineCaptureCheck.h"
#include "MtUnsafeCheck.h"
#include "ThreadCanceltypeAsynchronousCheck.h"
@@ -18,6 +20,8 @@ namespace {
class ConcurrencyModule : public ClangTidyModule {
public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+ CheckFactories.registerCheck<LambdaCoroutineCaptureCheck>(
+ "concurrency-lambda-coroutine-capture");
CheckFactories.registerCheck<concurrency::MtUnsafeCheck>(
"concurrency-mt-unsafe");
CheckFactories.registerCheck<ThreadCanceltypeAsynchronousCheck>(
diff --git a/clang-tools-extra/clang-tidy/concurrency/LambdaCoroutineCaptureCheck.cpp b/clang-tools-extra/clang-tidy/concurrency/LambdaCoroutineCaptureCheck.cpp
new file mode 100644
index 0000000000000..dedb41066c618
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/concurrency/LambdaCoroutineCaptureCheck.cpp
@@ -0,0 +1,72 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "LambdaCoroutineCaptureCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::concurrency {
+
+namespace {
+
+AST_MATCHER(LambdaExpr, hasCoroutineBody) {
+ const Stmt *Body = Node.getBody();
+ return Body != nullptr && isa<CoroutineBodyStmt>(Body);
+}
+
+AST_MATCHER(LambdaExpr, capturesWithoutDeducingThis) {
+ if (Node.capture_size() == 0U)
+ return false;
+ const auto *Call = Node.getCallOperator();
+ return !Call->isExplicitObjectMemberFunction();
+}
+
+} // namespace
+
+void LambdaCoroutineCaptureCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(
+ lambdaExpr(hasCoroutineBody(), capturesWithoutDeducingThis())
+ .bind("lambda"),
+ this);
+}
+
+void LambdaCoroutineCaptureCheck::check(
+ const MatchFinder::MatchResult &Result) {
+ const auto *MatchedLambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda");
+ auto *Call = MatchedLambda->getCallOperator();
+ bool HasExplicitParams = MatchedLambda->hasExplicitParameters();
+
+ auto DiagBuilder =
+ diag(MatchedLambda->getExprLoc(),
+ "lambda coroutine with captures may cause use-after-free; use "
+ "'this auto' as the first parameter to move captures into the "
+ "coroutine frame");
+
+ if (HasExplicitParams) {
+ bool HasParams = !Call->param_empty();
+ if (HasParams) {
+ const ParmVarDecl *FirstParam = Call->parameters().front();
+ DiagBuilder << FixItHint::CreateInsertion(FirstParam->getBeginLoc(),
+ "this auto, ");
+ } else {
+ // Empty parens `()` — insert `this auto` before the closing paren.
+ DiagBuilder << FixItHint::CreateInsertion(
+ Call->getFunctionTypeLoc().getRParenLoc(), "this auto");
+ }
+ } else {
+ // No explicit parameter list — insert `(this auto)` after the
+ // capture list closing `]`.
+ auto IntroRange = MatchedLambda->getIntroducerRange();
+ DiagBuilder << FixItHint::CreateInsertion(
+ IntroRange.getEnd().getLocWithOffset(1), "(this auto)");
+ }
+}
+
+} // namespace clang::tidy::concurrency
diff --git a/clang-tools-extra/clang-tidy/concurrency/LambdaCoroutineCaptureCheck.h b/clang-tools-extra/clang-tidy/concurrency/LambdaCoroutineCaptureCheck.h
new file mode 100644
index 0000000000000..aaf51b5b4fefc
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/concurrency/LambdaCoroutineCaptureCheck.h
@@ -0,0 +1,41 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CONCURRENCY_LAMBDACOROUTINECAPTURECHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CONCURRENCY_LAMBDACOROUTINECAPTURECHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::concurrency {
+
+/// Finds lambda coroutines that capture variables without using the C++23
+/// "deducing this" syntax, which can lead to use-after-free bugs.
+///
+/// When a lambda coroutine is passed to APIs that store the lambda temporarily
+/// (e.g. ``seastar::future::then()``), the lambda object may be destroyed while
+/// the coroutine is still suspended. Captures reference the lambda's storage,
+/// so accessing them after the lambda is destroyed causes undefined behavior.
+/// The C++23 explicit object parameter (``this auto``) moves captures into the
+/// coroutine frame, decoupling their lifetime from the lambda object.
+///
+/// For the user-facing documentation see:
+/// https://clang.llvm.org/extra/clang-tidy/checks/concurrency/lambda-coroutine-capture.html
+class LambdaCoroutineCaptureCheck : public ClangTidyCheck {
+public:
+ LambdaCoroutineCaptureCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+ bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+ return LangOpts.CPlusPlus23;
+ }
+};
+
+} // namespace clang::tidy::concurrency
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CONCURRENCY_LAMBDACOROUTINECAPTURECHECK_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 64c8fbbe2f07a..b9d6dd8456b19 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -117,6 +117,14 @@ New checks
Finds ``llvm::TypeSwitch::Case`` calls with redundant explicit template
arguments that can be inferred from the lambda parameter type.
+- New :doc:`concurrency-lambda-coroutine-capture
+ <clang-tidy/checks/concurrency/lambda-coroutine-capture>` check.
+
+ Finds lambda coroutines that capture variables without using the C++23
+ "deducing this" (explicit object parameter) syntax, which can lead to
+ use-after-free bugs when the lambda object is destroyed while the coroutine
+ is still suspended.
+
- New :doc:`llvm-use-vector-utils
<clang-tidy/checks/llvm/use-vector-utils>` check.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/concurrency/lambda-coroutine-capture.rst b/clang-tools-extra/docs/clang-tidy/checks/concurrency/lambda-coroutine-capture.rst
new file mode 100644
index 0000000000000..836c02e9bb974
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/concurrency/lambda-coroutine-capture.rst
@@ -0,0 +1,58 @@
+.. title:: clang-tidy - concurrency-lambda-coroutine-capture
+
+concurrency-lambda-coroutine-capture
+====================================
+
+Finds lambda coroutines that capture variables without using the C++23
+"deducing this" (explicit object parameter) syntax, which can lead to
+use-after-free bugs.
+
+When a lambda coroutine is passed to APIs that store the lambda temporarily
+(e.g. continuation-passing style like ``future::then()``), the lambda object
+may be destroyed while the coroutine is still suspended. Since captures
+reference the lambda's storage, accessing them after destruction causes
+undefined behavior. This is known as the
+`lambda coroutine fiasco <https://github.com/scylladb/seastar/blob/master/doc/lambda-coroutine-fiasco.md>`_.
+
+The C++23 explicit object parameter (``this auto``) solves this by moving
+captures directly into the coroutine frame, decoupling their lifetime from
+the lambda object.
+
+Example
+-------
+
+Before:
+
+.. code-block:: c++
+
+ auto handler = [&data](int x) -> task {
+ co_await process(data, x); // 'data' may be dangling
+ };
+
+After:
+
+.. code-block:: c++
+
+ auto handler = [&data](this auto, int x) -> task {
+ co_await process(data, x); // captures live in the coroutine frame
+ };
+
+The check handles three lambda forms:
+
+- Lambdas with explicit parameters: inserts ``this auto, `` before the first
+ parameter.
+- Lambdas with empty parentheses: inserts ``this auto`` inside the
+ parentheses.
+- Lambdas without a parameter list: inserts ``(this auto)`` after the capture
+ list.
+
+Options
+-------
+
+This check has no configurable options.
+
+This check requires C++23 or later (``-std=c++23``). For pre-C++23 code, see
+:doc:`cppcoreguidelines-avoid-capturing-lambda-coroutines
+<../cppcoreguidelines/avoid-capturing-lambda-coroutines>` which flags the same
+problem but recommends avoiding captures entirely rather than using deducing
+this.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index c475870ed7b31..815093f2f55fa 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -183,6 +183,7 @@ Clang-Tidy Checks
:doc:`bugprone-use-after-move <bugprone/use-after-move>`,
:doc:`bugprone-virtual-near-miss <bugprone/virtual-near-miss>`, "Yes"
:doc:`cert-err33-c <cert/err33-c>`,
+ :doc:`concurrency-lambda-coroutine-capture <concurrency/lambda-coroutine-capture>`, "Yes"
:doc:`concurrency-mt-unsafe <concurrency/mt-unsafe>`,
:doc:`concurrency-thread-canceltype-asynchronous <concurrency/thread-canceltype-asynchronous>`,
:doc:`cppcoreguidelines-avoid-capturing-lambda-coroutines <cppcoreguidelines/avoid-capturing-lambda-coroutines>`,
diff --git a/clang-tools-extra/test/clang-tidy/checkers/concurrency/lambda-coroutine-capture.cpp b/clang-tools-extra/test/clang-tidy/checkers/concurrency/lambda-coroutine-capture.cpp
new file mode 100644
index 0000000000000..0d2e1b6c4ec28
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/concurrency/lambda-coroutine-capture.cpp
@@ -0,0 +1,132 @@
+// RUN: %check_clang_tidy -std=c++23 %s concurrency-lambda-coroutine-capture %t
+
+// Minimal coroutine support types.
+namespace std {
+
+template <typename R, typename...> struct coroutine_traits {
+ using promise_type = typename R::promise_type;
+};
+
+template <typename Promise = void> struct coroutine_handle;
+
+template <> struct coroutine_handle<void> {
+ static coroutine_handle from_address(void *);
+ coroutine_handle() = default;
+ coroutine_handle(decltype(nullptr)) {}
+};
+
+template <typename Promise> struct coroutine_handle : coroutine_handle<> {
+ static coroutine_handle from_address(void *);
+};
+
+struct suspend_never {
+ bool await_ready() noexcept { return true; }
+ void await_suspend(coroutine_handle<>) noexcept {}
+ void await_resume() noexcept {}
+};
+
+} // namespace std
+
+struct task {
+ struct promise_type {
+ task get_return_object() { return {}; }
+ std::suspend_never initial_suspend() { return {}; }
+ std::suspend_never final_suspend() noexcept { return {}; }
+ void return_void() {}
+ void unhandled_exception() {}
+ };
+};
+
+template <typename F> void invoke(F &&f) {}
+
+// --- Cases that SHOULD trigger the warning ---
+
+void test_capture_no_parens() {
+ int x = 42;
+ invoke([&x] -> task {
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: lambda coroutine with captures may cause use-after-free; use 'this auto' as the first parameter to move captures into the coroutine frame [concurrency-lambda-coroutine-capture]
+ // CHECK-FIXES: {{^}} invoke([&x](this auto) -> task {{{$}}
+ co_return;
+ });
+}
+
+void test_capture_empty_parens() {
+ int x = 42;
+ invoke([&x]() -> task {
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: lambda coroutine with captures may cause use-after-free
+ // CHECK-FIXES: {{^}} invoke([&x](this auto) -> task {{{$}}
+ co_return;
+ });
+}
+
+void test_capture_with_params() {
+ int x = 42;
+ invoke([&x](int a) -> task {
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: lambda coroutine with captures may cause use-after-free
+ // CHECK-FIXES: {{^}} invoke([&x](this auto, int a) -> task {{{$}}
+ co_return;
+ });
+}
+
+void test_capture_with_multiple_params() {
+ int x = 42;
+ invoke([&x](int a, int b) -> task {
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: lambda coroutine with captures may cause use-after-free
+ // CHECK-FIXES: {{^}} invoke([&x](this auto, int a, int b) -> task {{{$}}
+ co_return;
+ });
+}
+
+void test_capture_by_value() {
+ int x = 42;
+ invoke([x]() -> task {
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: lambda coroutine with captures may cause use-after-free
+ // CHECK-FIXES: {{^}} invoke([x](this auto) -> task {{{$}}
+ co_return;
+ });
+}
+
+void test_default_capture_ref() {
+ int x = 42;
+ invoke([&]() -> task {
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: lambda coroutine with captures may cause use-after-free
+ // CHECK-FIXES: {{^}} invoke([&](this auto) -> task {{{$}}
+ (void)x;
+ co_return;
+ });
+}
+
+void test_default_capture_copy() {
+ int x = 42;
+ invoke([=]() -> task {
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: lambda coroutine with captures may cause use-after-free
+ // CHECK-FIXES: {{^}} invoke([=](this auto) -> task {{{$}}
+ (void)x;
+ co_return;
+ });
+}
+
+// --- Cases that should NOT trigger the warning ---
+
+void test_no_captures_no_coroutine() {
+ invoke([]() { return; });
+}
+
+void test_no_captures_coroutine() {
+ invoke([]() -> task { co_return; });
+}
+
+void test_deducing_this_coroutine() {
+ int x = 42;
+ invoke([&x](this auto) -> task { co_return; });
+}
+
+void test_deducing_this_with_params() {
+ int x = 42;
+ invoke([&x](this auto, int a) -> task { co_return; });
+}
+
+void test_captures_not_coroutine() {
+ int x = 42;
+ invoke([&x]() { (void)x; });
+}
>From 638b66eeb3020d888e944838db5e74b8c2720698 Mon Sep 17 00:00:00 2001
From: Willem Kaufmann <willem.kaufmann at gmail.com>
Date: Mon, 23 Feb 2026 13:53:22 -0500
Subject: [PATCH 2/2] [clang-tidy] Suppress `avoid-capturing-lambda-coroutines`
for `deducing this`
The `cppcoreguidelines-avoid-capturing-lambda-coroutines` check warns
on all lambda coroutines with captures, including C++23 lambdas
that use explicit object parameters (deducing this) which are safe
from the lifetime issue. Suppress the warning when the lambda uses
`this auto`, and cross-reference the two related checks in their
documentation.
---
.../AvoidCapturingLambdaCoroutinesCheck.cpp | 9 ++++++++-
.../avoid-capturing-lambda-coroutines.rst | 7 +++++++
.../avoid-capturing-lambda-coroutines.cpp | 6 ++++++
3 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidCapturingLambdaCoroutinesCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidCapturingLambdaCoroutinesCheck.cpp
index 618554663ab91..a6c969c6feb9e 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidCapturingLambdaCoroutinesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidCapturingLambdaCoroutinesCheck.cpp
@@ -21,12 +21,19 @@ AST_MATCHER(LambdaExpr, hasCoroutineBody) {
}
AST_MATCHER(LambdaExpr, hasCaptures) { return Node.capture_size() != 0U; }
+
+AST_MATCHER(LambdaExpr, hasDeducingThis) {
+ return Node.getCallOperator()->isExplicitObjectMemberFunction();
+}
} // namespace
void AvoidCapturingLambdaCoroutinesCheck::registerMatchers(
MatchFinder *Finder) {
Finder->addMatcher(
- lambdaExpr(hasCaptures(), hasCoroutineBody()).bind("lambda"), this);
+ lambdaExpr(hasCaptures(), hasCoroutineBody(),
+ unless(hasDeducingThis()))
+ .bind("lambda"),
+ this);
}
bool AvoidCapturingLambdaCoroutinesCheck::isLanguageVersionSupported(
diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-capturing-lambda-coroutines.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-capturing-lambda-coroutines.rst
index 58bfc35c557dc..c617a7715f6d1 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-capturing-lambda-coroutines.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-capturing-lambda-coroutines.rst
@@ -52,3 +52,10 @@ captures or ensuring the lambda closure object has a guaranteed lifetime.
Following these guidelines can help ensure the safe and reliable use of
coroutine lambdas in C++ code.
+
+In C++23, the "deducing this" (explicit object parameter) syntax provides a
+solution to this problem by moving captures into the coroutine frame. Lambda
+coroutines using ``this auto`` as their first parameter are not flagged by
+this check. See :doc:`concurrency-lambda-coroutine-capture
+<../concurrency/lambda-coroutine-capture>` for a check that can automatically
+apply this fix.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-capturing-lambda-coroutines.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-capturing-lambda-coroutines.cpp
index 6670f4a5420be..3e83fbefba7cf 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-capturing-lambda-coroutines.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-capturing-lambda-coroutines.cpp
@@ -33,4 +33,10 @@ void Safe() {
[=] () -> task { co_return; };
[&v]{++v;}();
+
+#if __cplusplus >= 202302L
+ // Lambda coroutines using C++23 deducing this are safe.
+ [&v] (this auto) -> task { co_return; };
+ [v] (this auto, int x) -> task { co_return; };
+#endif
}
More information about the cfe-commits
mailing list