clang: lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
20
22namespace ento {
23namespace mpi {
24
27 if (!FuncClassifier->isNonBlockingType(PreCallEvent.getCalleeIdentifier())) {
28 return;
29 }
32 if (!MR)
33 return;
34 const ElementRegion *const ER = dyn_cast(MR);
35
36
37 if (!isa(MR) || (ER && !isa(ER->getSuperRegion())))
38 return;
39
42
43
45 ExplodedNode *ErrorNode = Ctx.generateNonFatalErrorNode();
47 Ctx.getBugReporter());
48 Ctx.addTransition(ErrorNode->getState(), ErrorNode);
49 }
50
51 else {
53 Ctx.addTransition(State);
54 }
55}
56
60 return;
61 const MemRegion *const MR = topRegionUsedByWait(PreCallEvent);
62 if (!MR)
63 return;
64 const ElementRegion *const ER = dyn_cast(MR);
65
66
67 if (!isa(MR) || (ER && !isa(ER->getSuperRegion())))
68 return;
69
71 allRegionsUsedByWait(ReqRegions, MR, PreCallEvent, Ctx);
72 if (ReqRegions.empty())
73 return;
74
78
79
80 for (const auto &ReqRegion : ReqRegions) {
83 if (!Req) {
84 if (!ErrorNode) {
85 ErrorNode = Ctx.generateNonFatalErrorNode(State, &Tag);
86 State = ErrorNode->getState();
87 }
88
90 Ctx.getBugReporter());
91 }
92 }
93
94 if (!ErrorNode) {
95 Ctx.addTransition(State);
96 } else {
97 Ctx.addTransition(State, ErrorNode);
98 }
99}
100
104 const auto &Requests = State->get<RequestMap>();
105 if (Requests.isEmpty())
106 return;
107
110
111 auto ReqMap = State->get<RequestMap>();
112 for (const auto &Req : ReqMap) {
115
116 if (!ErrorNode) {
117 ErrorNode = Ctx.generateNonFatalErrorNode(State, &Tag);
118 State = ErrorNode->getState();
119 }
121 Ctx.getBugReporter());
122 }
123 State = State->remove<RequestMap>(Req.first);
124 }
125 }
126
127
128 if (!ErrorNode) {
129 Ctx.addTransition(State);
130 } else {
131 Ctx.addTransition(State, ErrorNode);
132 }
133}
134
135const MemRegion *MPIChecker::topRegionUsedByWait(const CallEvent &CE) const {
136
141 } else {
142 return (const MemRegion *)nullptr;
143 }
144}
145
146void MPIChecker::allRegionsUsedByWait(
148 const MemRegion *const MR, const CallEvent &CE, CheckerContext &Ctx) const {
149
151
152 if (FuncClassifier->isMPI_Waitall(CE.getCalleeIdentifier())) {
153 const SubRegion *SuperRegion{nullptr};
154 if (const ElementRegion *const ER = MR->getAs()) {
155 SuperRegion = cast(ER->getSuperRegion());
156 }
157
158
159 if (!SuperRegion) {
160 ReqRegions.push_back(MR);
161 return;
162 }
163
165 Ctx.getState(), SuperRegion, Ctx.getSValBuilder(),
166 CE.getArgExpr(1)->getType()->getPointeeType());
167 const llvm::APSInt &ArrSize =
168 ElementCount.castAsnonloc::ConcreteInt().getValue();
169
170 for (size_t i = 0; i < ArrSize; ++i) {
171 const NonLoc Idx = Ctx.getSValBuilder().makeArrayIndex(i);
172
173 const ElementRegion *const ER = RegionManager.getElementRegion(
174 CE.getArgExpr(1)->getType()->getPointeeType(), Idx, SuperRegion,
175 Ctx.getASTContext());
176
177 ReqRegions.push_back(ER->getAs());
178 }
179 } else if (FuncClassifier->isMPI_Wait(CE.getCalleeIdentifier())) {
180 ReqRegions.push_back(MR);
181 }
182}
183
184}
185}
186}
187
188
189void clang::ento::registerMPIChecker(CheckerManager &MGR) {
191}
192
193bool clang::ento::shouldRegisterMPIChecker(const CheckerManager &mgr) {
194 return true;
195}
This file defines the main class of MPI-Checker which serves as an entry point.
Represents an abstract call to a function or method along a particular path.
const IdentifierInfo * getCalleeIdentifier() const
Returns the name of the callee, if its name is a simple identifier.
virtual SVal getArgSVal(unsigned Index) const
Returns the value of a given argument at the time of the call.
virtual unsigned getNumArgs() const =0
Returns the number of arguments (explicit and implicit).
Tag that can use a checker name as a message provider (see SimpleProgramPointTag).
ElementRegion is used to represent both array elements and casts.
const ProgramStateRef & getState() const
MemRegion - The root abstract class for all memory regions.
virtual MemRegionManager & getMemRegionManager() const =0
const MemRegion * getAsRegion() const
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getSuperRegion() const
A class responsible for cleaning up unused symbols.
bool isLiveRegion(const MemRegion *region)
void reportMissingWait(const Request &Req, const MemRegion *const RequestRegion, const ExplodedNode *const ExplNode, BugReporter &BReporter) const
Report a missing wait for a nonblocking call.
void reportDoubleNonblocking(const CallEvent &MPICallEvent, const Request &Req, const MemRegion *const RequestRegion, const ExplodedNode *const ExplNode, BugReporter &BReporter) const
Report duplicate request use by nonblocking calls without intermediate wait.
void reportUnmatchedWait(const CallEvent &CE, const MemRegion *const RequestRegion, const ExplodedNode *const ExplNode, BugReporter &BReporter) const
Report a wait on a request that has not been used at all before.
void checkMissingWaits(clang::ento::SymbolReaper &SymReaper, clang::ento::CheckerContext &Ctx) const
Check if a nonblocking call is not matched by a wait.
void checkDoubleNonblocking(const clang::ento::CallEvent &PreCallEvent, clang::ento::CheckerContext &Ctx) const
Checks if a request is used by nonblocking calls multiple times in sequence without intermediate wait...
void checkUnmatchedWaits(const clang::ento::CallEvent &PreCallEvent, clang::ento::CheckerContext &Ctx) const
Checks if the request used by the wait function was not used at all before.
DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State, const MemRegion *MR, SValBuilder &SVB, QualType Ty)
The JSON file list parser is used to communicate input to InstallAPI.