11 #include "clang/AST/ASTContext.h" 12 #include "clang/ASTMatchers/ASTMatchFinder.h" 13 #include "clang/StaticAnalyzer/Checkers/MPIFunctionClassifier.h" 14 #include "clang/Tooling/FixIt.h" 22 void BufferDerefCheck::registerMatchers(MatchFinder *Finder) {
23 Finder->addMatcher(callExpr().bind(
"CE"),
this);
26 void BufferDerefCheck::check(
const MatchFinder::MatchResult &Result) {
27 static ento::mpi::MPIFunctionClassifier FuncClassifier(*Result.Context);
28 const auto *CE = Result.Nodes.getNodeAs<CallExpr>(
"CE");
29 if (!CE->getDirectCallee())
32 const IdentifierInfo *Identifier = CE->getDirectCallee()->getIdentifier();
33 if (!Identifier || !FuncClassifier.isMPIType(Identifier))
37 SmallVector<const Type *, 1> BufferTypes;
38 SmallVector<const Expr *, 1> BufferExprs;
42 auto addBuffer = [&CE, &Result, &BufferTypes,
43 &BufferExprs](
const size_t BufferIdx) {
45 if (CE->getArg(BufferIdx)->isNullPointerConstant(
46 *Result.Context, Expr::NPC_ValueDependentIsNull) ||
47 tooling::fixit::getText(*CE->getArg(BufferIdx), *Result.Context) ==
51 const Expr *ArgExpr = CE->getArg(BufferIdx);
54 const Type *ArgType = ArgExpr->IgnoreImpCasts()->getType().getTypePtr();
57 BufferExprs.push_back(ArgExpr);
58 BufferTypes.push_back(ArgType);
64 if (FuncClassifier.isPointToPointType(Identifier)) {
66 }
else if (FuncClassifier.isCollectiveType(Identifier)) {
67 if (FuncClassifier.isReduceType(Identifier)) {
70 }
else if (FuncClassifier.isScatterType(Identifier) ||
71 FuncClassifier.isGatherType(Identifier) ||
72 FuncClassifier.isAlltoallType(Identifier)) {
75 }
else if (FuncClassifier.isBcastType(Identifier)) {
80 checkBuffers(BufferTypes, BufferExprs);
83 void BufferDerefCheck::checkBuffers(ArrayRef<const Type *> BufferTypes,
84 ArrayRef<const Expr *> BufferExprs) {
85 for (
size_t i = 0; i < BufferTypes.size(); ++i) {
86 unsigned IndirectionCount = 0;
87 const Type *BufferType = BufferTypes[i];
88 llvm::SmallVector<IndirectionType, 1> Indirections;
92 if (BufferType->isPointerType()) {
93 BufferType = BufferType->getPointeeType().getTypePtr();
94 Indirections.push_back(IndirectionType::Pointer);
95 }
else if (BufferType->isArrayType()) {
96 BufferType = BufferType->getArrayElementTypeNoTypeQual();
97 Indirections.push_back(IndirectionType::Array);
104 if (IndirectionCount > 1) {
107 if (IndirectionCount == 2 &&
108 Indirections[0] == IndirectionType::Pointer &&
109 Indirections[1] == IndirectionType::Array)
113 std::string IndirectionDesc;
114 for (
auto It = Indirections.rbegin(); It != Indirections.rend(); ++It) {
115 if (!IndirectionDesc.empty())
116 IndirectionDesc +=
"->";
117 if (*It == IndirectionType::Pointer) {
118 IndirectionDesc +=
"pointer";
120 IndirectionDesc +=
"array";
124 const auto Loc = BufferExprs[i]->getSourceRange().getBegin();
125 diag(
Loc,
"buffer is insufficiently dereferenced: %0") << IndirectionDesc;
SourceLocation Loc
'#' location in the include directive
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//