dotnwat created this revision. Herald added subscribers: carlosgalvezp, ChuanqiXu, kbarton, xazax.hun, nemanjai. Herald added a project: All. dotnwat requested review of this revision. Herald added a project: clang-tools-extra. Herald added a subscriber: cfe-commits.
Signed-off-by: Noah Watkins <n...@redpanda.com> Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D137514 Files: clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidCapturingLambdaCoroutinesCheck.cpp clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidCapturingLambdaCoroutinesCheck.h clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp clang-tools-extra/docs/ReleaseNotes.rst clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-avoid-capturing-lambda-coroutines.rst clang-tools-extra/docs/clang-tidy/checks/list.rst clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-avoid-capturing-lambda-coroutines.cpp
Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-avoid-capturing-lambda-coroutines.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-avoid-capturing-lambda-coroutines.cpp @@ -0,0 +1,35 @@ +// RUN: %check_clang_tidy -std=c++20-or-later %s cppcoreguidelines-avoid-capturing-lambda-coroutines %t -- -- \ +// RUN: -isystem %S/readability/Inputs/identifier-naming/system + +#include <coroutines.h> + +void Caught() { + int v; + + [&] () -> task { int y = v; co_return; }; + // CHECK-MESSAGES: [[@LINE-1]]:5: warning: found capturing coroutine lambda [cppcoreguidelines-avoid-capturing-lambda-coroutines] + [=] () -> task { int y = v; co_return; }; + // CHECK-MESSAGES: [[@LINE-1]]:5: warning: found capturing coroutine lambda [cppcoreguidelines-avoid-capturing-lambda-coroutines] + [v] () -> task { co_return; }; + // CHECK-MESSAGES: [[@LINE-1]]:5: warning: found capturing coroutine lambda [cppcoreguidelines-avoid-capturing-lambda-coroutines] + [&v] () -> task { co_return; }; + // CHECK-MESSAGES: [[@LINE-1]]:5: warning: found capturing coroutine lambda [cppcoreguidelines-avoid-capturing-lambda-coroutines] + [y=v] () -> task { co_return; }; + // CHECK-MESSAGES: [[@LINE-1]]:5: warning: found capturing coroutine lambda [cppcoreguidelines-avoid-capturing-lambda-coroutines] + [y{v}] () -> task { co_return; }; + // CHECK-MESSAGES: [[@LINE-1]]:5: warning: found capturing coroutine lambda [cppcoreguidelines-avoid-capturing-lambda-coroutines] +} + +struct S { + void m() { + [this] () -> task { co_return; }; + // CHECK-MESSAGES: [[@LINE-1]]:9: warning: found capturing coroutine lambda [cppcoreguidelines-avoid-capturing-lambda-coroutines] + } +}; + +void Safe() { + int v; + [] () -> task { co_return; }; + [&] () -> task { co_return; }; + [=] () -> task { co_return; }; +} Index: clang-tools-extra/docs/clang-tidy/checks/list.rst =================================================================== --- clang-tools-extra/docs/clang-tidy/checks/list.rst +++ clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -177,6 +177,7 @@ `clang-analyzer-valist.Unterminated <clang-analyzer/valist.Unterminated.html>`_, `concurrency-mt-unsafe <concurrency/mt-unsafe.html>`_, `concurrency-thread-canceltype-asynchronous <concurrency/thread-canceltype-asynchronous.html>`_, + `cppcoreguidelines-avoid-capturing-lambda-coroutines <cppcoreguidelines-avoid-capturing-lambda-coroutines.html>`_, "Yes" `cppcoreguidelines-avoid-const-or-ref-data-members <cppcoreguidelines/avoid-const-or-ref-data-members.html>`_, `cppcoreguidelines-avoid-do-while <cppcoreguidelines/avoid-do-while.html>`_, `cppcoreguidelines-avoid-goto <cppcoreguidelines/avoid-goto.html>`_, Index: clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-avoid-capturing-lambda-coroutines.rst =================================================================== --- /dev/null +++ clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-avoid-capturing-lambda-coroutines.rst @@ -0,0 +1,31 @@ +.. title:: clang-tidy - cppcoreguidelines-avoid-capturing-lambda-coroutines + +cppcoreguidelines-avoid-capturing-lambda-coroutines +=================================================== + +Warns if a capturing lambda is a coroutine. For example: + +.. code-block:: c++ + + int c; + + [c] () -> task { co_return; }; + [&] () -> task { int y = c; co_return; }; + [=] () -> task { int y = c; co_return; }; + + struct s { + void m() { + [this] () -> task { co_return; }; + } + }; + +All of the cases above will trigger the warning. However, implicit captures +do not trigger the warning unless the body of the lambda uses the capture. +For example, the following do not trigger the warning. + +.. code-block:: c++ + + int c; + + [&] () -> task { co_return; }; + [=] () -> task { co_return; }; Index: clang-tools-extra/docs/ReleaseNotes.rst =================================================================== --- clang-tools-extra/docs/ReleaseNotes.rst +++ clang-tools-extra/docs/ReleaseNotes.rst @@ -115,6 +115,13 @@ Warns when using ``do-while`` loops. +- New :doc:`cppcoreguidelines-avoid-capturing-lambda-coroutines + <clang-tidy/checks/cppcoreguidelines-avoid-capturing-lambda-coroutines>` check. + + Adds check for cpp core guideline: "CP.51: Do not use capturing lambdas that + are coroutines." + + New check aliases ^^^^^^^^^^^^^^^^^ Index: clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp =================================================================== --- clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp +++ clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp @@ -14,6 +14,7 @@ #include "../modernize/AvoidCArraysCheck.h" #include "../modernize/UseOverrideCheck.h" #include "../readability/MagicNumbersCheck.h" +#include "AvoidCapturingLambdaCoroutinesCheck.h" #include "AvoidConstOrRefDataMembersCheck.h" #include "AvoidDoWhileCheck.h" #include "AvoidGotoCheck.h" @@ -47,6 +48,8 @@ class CppCoreGuidelinesModule : public ClangTidyModule { public: void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { + CheckFactories.registerCheck<AvoidCapturingLambdaCoroutinesCheck>( + "cppcoreguidelines-avoid-capturing-lambda-coroutines"); CheckFactories.registerCheck<modernize::AvoidCArraysCheck>( "cppcoreguidelines-avoid-c-arrays"); CheckFactories.registerCheck<AvoidConstOrRefDataMembersCheck>( Index: clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt =================================================================== --- clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt +++ clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt @@ -4,6 +4,7 @@ ) add_clang_library(clangTidyCppCoreGuidelinesModule + AvoidCapturingLambdaCoroutinesCheck.cpp AvoidConstOrRefDataMembersCheck.cpp AvoidDoWhileCheck.cpp AvoidGotoCheck.cpp Index: clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidCapturingLambdaCoroutinesCheck.h =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidCapturingLambdaCoroutinesCheck.h @@ -0,0 +1,36 @@ +//===--- AvoidCapturingLambdaCoroutinesCheck.h - clang-tidy -----*- C++ -*-===// +// +// 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_CPPCOREGUIDELINES_AVOIDCAPTURINGLAMBDACOROUTINESCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_AVOIDCAPTURINGLAMBDACOROUTINESCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang { +namespace tidy { +namespace cppcoreguidelines { + +/// The normal usage of captures in lambdas are problematic when the lambda is a +/// coroutine because the captures are destroyed after the first suspension +/// point. Using the captures after this point is a use-after-free issue. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-avoid-capturing-lambda-coroutines.html +class AvoidCapturingLambdaCoroutinesCheck : public ClangTidyCheck { +public: + AvoidCapturingLambdaCoroutinesCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace cppcoreguidelines +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_AVOIDCAPTURINGLAMBDACOROUTINESCHECK_H Index: clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidCapturingLambdaCoroutinesCheck.cpp =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidCapturingLambdaCoroutinesCheck.cpp @@ -0,0 +1,45 @@ +//===--- AvoidCapturingLambdaCoroutinesCheck.cpp - clang-tidy -------------===// +// +// 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 "AvoidCapturingLambdaCoroutinesCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace cppcoreguidelines { + +void AvoidCapturingLambdaCoroutinesCheck::registerMatchers( + MatchFinder *Finder) { + Finder->addMatcher(lambdaExpr().bind("lambda"), this); +} + +void AvoidCapturingLambdaCoroutinesCheck::check( + const MatchFinder::MatchResult &Result) { + const auto *Lambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda"); + if (!Lambda) { + return; + } + + const auto *Body = dyn_cast<CoroutineBodyStmt>(Lambda->getBody()); + if (!Body) { + return; + } + + if (Lambda->captures().empty()) { + return; + } + + diag(Lambda->getBeginLoc(), "found capturing coroutine lambda"); +} + +} // namespace cppcoreguidelines +} // namespace tidy +} // namespace clang
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits