154178fc6SNoah Watkins //===--- AvoidCapturingLambdaCoroutinesCheck.cpp - clang-tidy -------------===// 254178fc6SNoah Watkins // 354178fc6SNoah Watkins // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 454178fc6SNoah Watkins // See https://llvm.org/LICENSE.txt for license information. 554178fc6SNoah Watkins // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 654178fc6SNoah Watkins // 754178fc6SNoah Watkins //===----------------------------------------------------------------------===// 854178fc6SNoah Watkins 954178fc6SNoah Watkins #include "AvoidCapturingLambdaCoroutinesCheck.h" 1054178fc6SNoah Watkins #include "clang/AST/ASTContext.h" 1154178fc6SNoah Watkins #include "clang/ASTMatchers/ASTMatchFinder.h" 1254178fc6SNoah Watkins 1354178fc6SNoah Watkins using namespace clang::ast_matchers; 1454178fc6SNoah Watkins 15*17d403f6SPiotr Zegar namespace clang::tidy::cppcoreguidelines { 16*17d403f6SPiotr Zegar 17*17d403f6SPiotr Zegar namespace { AST_MATCHER(LambdaExpr,hasCoroutineBody)18*17d403f6SPiotr ZegarAST_MATCHER(LambdaExpr, hasCoroutineBody) { 19*17d403f6SPiotr Zegar const Stmt *Body = Node.getBody(); 20*17d403f6SPiotr Zegar return Body != nullptr && CoroutineBodyStmt::classof(Body); 21*17d403f6SPiotr Zegar } 22*17d403f6SPiotr Zegar AST_MATCHER(LambdaExpr,hasCaptures)23*17d403f6SPiotr ZegarAST_MATCHER(LambdaExpr, hasCaptures) { return Node.capture_size() != 0U; } 24*17d403f6SPiotr Zegar } // namespace 2554178fc6SNoah Watkins registerMatchers(MatchFinder * Finder)2654178fc6SNoah Watkinsvoid AvoidCapturingLambdaCoroutinesCheck::registerMatchers( 2754178fc6SNoah Watkins MatchFinder *Finder) { 28*17d403f6SPiotr Zegar Finder->addMatcher( 29*17d403f6SPiotr Zegar lambdaExpr(hasCaptures(), hasCoroutineBody()).bind("lambda"), this); 30*17d403f6SPiotr Zegar } 31*17d403f6SPiotr Zegar isLanguageVersionSupported(const LangOptions & LangOpts) const32*17d403f6SPiotr Zegarbool AvoidCapturingLambdaCoroutinesCheck::isLanguageVersionSupported( 33*17d403f6SPiotr Zegar const LangOptions &LangOpts) const { 34*17d403f6SPiotr Zegar return LangOpts.CPlusPlus20; 3554178fc6SNoah Watkins } 3654178fc6SNoah Watkins check(const MatchFinder::MatchResult & Result)3754178fc6SNoah Watkinsvoid AvoidCapturingLambdaCoroutinesCheck::check( 3854178fc6SNoah Watkins const MatchFinder::MatchResult &Result) { 39*17d403f6SPiotr Zegar const auto *MatchedLambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda"); 40*17d403f6SPiotr Zegar diag(MatchedLambda->getExprLoc(), 41*17d403f6SPiotr Zegar "coroutine lambda may cause use-after-free, avoid captures or ensure " 42*17d403f6SPiotr Zegar "lambda closure object has guaranteed lifetime"); 4354178fc6SNoah Watkins } 4454178fc6SNoah Watkins 45*17d403f6SPiotr Zegar } // namespace clang::tidy::cppcoreguidelines 46