10#include "clang/AST/ASTContext.h"
11#include "clang/ASTMatchers/ASTMatchFinder.h"
18 Finder->addMatcher(callExpr(callee(functionDecl(hasName(
"::dispatch_async"))),
20 hasArgument(1, blockExpr().bind(
"arg-block"))),
22 Finder->addMatcher(callExpr(callee(functionDecl(hasName(
"::dispatch_after"))),
24 hasArgument(2, blockExpr().bind(
"arg-block"))),
29 const auto *MatchedEscapingBlock =
30 Result.Nodes.getNodeAs<BlockExpr>(
"arg-block");
31 const BlockDecl *EscapingBlockDecl = MatchedEscapingBlock->getBlockDecl();
32 for (
const BlockDecl::Capture &CapturedVar : EscapingBlockDecl->captures()) {
33 const VarDecl *Var = CapturedVar.getVariable();
34 if (Var && Var->hasAttr<NoEscapeAttr>()) {
37 diag(MatchedEscapingBlock->getBeginLoc(),
38 "pointer %0 with attribute 'noescape' is captured by an "
39 "asynchronously-executed block")
41 diag(Var->getBeginLoc(),
"the 'noescape' attribute is declared here.",
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.