48 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "NoEscapeCheck.h"10#include "clang/AST/ASTContext.h"11#include "clang/ASTMatchers/ASTMatchFinder.h"12 13using namespace clang::ast_matchers;14 15namespace clang::tidy::bugprone {16 17void NoEscapeCheck::registerMatchers(MatchFinder *Finder) {18 Finder->addMatcher(callExpr(callee(functionDecl(hasName("::dispatch_async"))),19 argumentCountIs(2),20 hasArgument(1, blockExpr().bind("arg-block"))),21 this);22 Finder->addMatcher(callExpr(callee(functionDecl(hasName("::dispatch_after"))),23 argumentCountIs(3),24 hasArgument(2, blockExpr().bind("arg-block"))),25 this);26}27 28void NoEscapeCheck::check(const MatchFinder::MatchResult &Result) {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>()) {35 // FIXME: Add a method to get the location of the use of a CapturedVar so36 // that we can diagnose the use of the pointer instead of the block.37 diag(MatchedEscapingBlock->getBeginLoc(),38 "pointer %0 with attribute 'noescape' is captured by an "39 "asynchronously-executed block")40 << Var;41 diag(Var->getBeginLoc(), "the 'noescape' attribute is declared here.",42 DiagnosticIDs::Note);43 }44 }45}46 47} // namespace clang::tidy::bugprone48