10#include "clang/AST/ASTContext.h"
11#include "clang/ASTMatchers/ASTMatchFinder.h"
12#include "clang/Tooling/FixIt.h"
19 Finder->addMatcher(callExpr().bind(
"CE"),
this);
23 const auto *
CE = Result.Nodes.getNodeAs<CallExpr>(
"CE");
24 if (!
CE->getDirectCallee())
28 FuncClassifier.emplace(*Result.Context);
30 const IdentifierInfo *Identifier =
CE->getDirectCallee()->getIdentifier();
31 if (!Identifier || !FuncClassifier->isMPIType(Identifier))
35 SmallVector<const Type *, 1> BufferTypes;
36 SmallVector<const Expr *, 1> BufferExprs;
40 auto AddBuffer = [&
CE, &Result, &BufferTypes,
41 &BufferExprs](
const size_t BufferIdx) {
43 if (
CE->getArg(BufferIdx)->isNullPointerConstant(
44 *Result.Context, Expr::NPC_ValueDependentIsNull) ||
45 tooling::fixit::getText(*
CE->getArg(BufferIdx), *Result.Context) ==
49 const Expr *ArgExpr =
CE->getArg(BufferIdx);
52 const Type *ArgType = ArgExpr->IgnoreImpCasts()->getType().getTypePtr();
55 BufferExprs.push_back(ArgExpr);
56 BufferTypes.push_back(ArgType);
62 if (FuncClassifier->isPointToPointType(Identifier)) {
64 }
else if (FuncClassifier->isCollectiveType(Identifier)) {
65 if (FuncClassifier->isReduceType(Identifier)) {
68 }
else if (FuncClassifier->isScatterType(Identifier) ||
69 FuncClassifier->isGatherType(Identifier) ||
70 FuncClassifier->isAlltoallType(Identifier)) {
73 }
else if (FuncClassifier->isBcastType(Identifier)) {
78 checkBuffers(BufferTypes, BufferExprs);
81void BufferDerefCheck::checkBuffers(ArrayRef<const Type *> BufferTypes,
82 ArrayRef<const Expr *> BufferExprs) {
83 for (
size_t I = 0; I < BufferTypes.size(); ++I) {
84 unsigned IndirectionCount = 0;
85 const Type *BufferType = BufferTypes[I];
86 llvm::SmallVector<IndirectionType, 1> Indirections;
90 if (BufferType->isPointerType()) {
91 BufferType = BufferType->getPointeeType().getTypePtr();
92 Indirections.push_back(IndirectionType::Pointer);
93 }
else if (BufferType->isArrayType()) {
94 BufferType = BufferType->getArrayElementTypeNoTypeQual();
95 Indirections.push_back(IndirectionType::Array);
102 if (IndirectionCount > 1) {
105 if (IndirectionCount == 2 &&
106 Indirections[0] == IndirectionType::Pointer &&
107 Indirections[1] == IndirectionType::Array)
111 std::string IndirectionDesc;
112 for (
auto It = Indirections.rbegin(); It != Indirections.rend(); ++It) {
113 if (!IndirectionDesc.empty())
114 IndirectionDesc +=
"->";
115 if (*It == IndirectionType::Pointer) {
116 IndirectionDesc +=
"pointer";
118 IndirectionDesc +=
"array";
122 const auto Loc = BufferExprs[I]->getSourceRange().getBegin();
123 diag(
Loc,
"buffer is insufficiently dereferenced: %0") << IndirectionDesc;
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 onEndOfTranslationUnit() override
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.