clang 8.0.0

MPIChecker.cpp
Go to the documentation of this file.
1 //===-- MPIChecker.cpp - Checker Entry Point Class --------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// This file defines the main class of MPI-Checker which serves as an entry
12 /// point. It is created once for each translation unit analysed.
13 /// The checker defines path-sensitive checks, to verify correct usage of the
14 /// MPI API.
15 ///
16 //===----------------------------------------------------------------------===//
17
18 #include "MPIChecker.h"
19 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
20
21 namespace clang {
22 namespace ento {
23 namespace mpi {
24
25 void MPIChecker::checkDoubleNonblocking(const CallEvent &PreCallEvent,
26 CheckerContext &Ctx) const {
27 if (!FuncClassifier->isNonBlockingType(PreCallEvent.getCalleeIdentifier())) {
28 return;
29 }
30 const MemRegion *const MR =
31 PreCallEvent.getArgSVal(PreCallEvent.getNumArgs() - 1).getAsRegion();
32 if (!MR)
33 return;
34 const ElementRegion *const ER = dyn_cast<ElementRegion>(MR);
35
36 // The region must be typed, in order to reason about it.
37 if (!isa<TypedRegion>(MR) || (ER && !isa<TypedRegion>(ER->getSuperRegion())))
38 return;
39
40 ProgramStateRef State = Ctx.getState();
41 const Request *const Req = State->get<RequestMap>(MR);
42
43 // double nonblocking detected
44 if (Req && Req->CurrentState == Request::State::Nonblocking) {
45 ExplodedNode *ErrorNode = Ctx.generateNonFatalErrorNode();
46 BReporter.reportDoubleNonblocking(PreCallEvent, *Req, MR, ErrorNode,
47 Ctx.getBugReporter());
48 Ctx.addTransition(ErrorNode->getState(), ErrorNode);
49 }
50 // no error
51 else {
52 State = State->set<RequestMap>(MR, Request::State::Nonblocking);
53 Ctx.addTransition(State);
54 }
55 }
56
57 void MPIChecker::checkUnmatchedWaits(const CallEvent &PreCallEvent,
58 CheckerContext &Ctx) const {
59 if (!FuncClassifier->isWaitType(PreCallEvent.getCalleeIdentifier()))
60 return;
61 const MemRegion *const MR = topRegionUsedByWait(PreCallEvent);
62 if (!MR)
63 return;
64 const ElementRegion *const ER = dyn_cast<ElementRegion>(MR);
65
66 // The region must be typed, in order to reason about it.
67 if (!isa<TypedRegion>(MR) || (ER && !isa<TypedRegion>(ER->getSuperRegion())))
68 return;
69
70 llvm::SmallVector<const MemRegion *, 2> ReqRegions;
71 allRegionsUsedByWait(ReqRegions, MR, PreCallEvent, Ctx);
72 if (ReqRegions.empty())
73 return;
74
75 ProgramStateRef State = Ctx.getState();
76 static CheckerProgramPointTag Tag("MPI-Checker", "UnmatchedWait");
77 ExplodedNode *ErrorNode{nullptr};
78
79 // Check all request regions used by the wait function.
80 for (const auto &ReqRegion : ReqRegions) {
81 const Request *const Req = State->get<RequestMap>(ReqRegion);
82 State = State->set<RequestMap>(ReqRegion, Request::State::Wait);
83 if (!Req) {
84 if (!ErrorNode) {
85 ErrorNode = Ctx.generateNonFatalErrorNode(State, &Tag);
86 State = ErrorNode->getState();
87 }
88 // A wait has no matching nonblocking call.
89 BReporter.reportUnmatchedWait(PreCallEvent, ReqRegion, ErrorNode,
90 Ctx.getBugReporter());
91 }
92 }
93
94 if (!ErrorNode) {
95 Ctx.addTransition(State);
96 } else {
97 Ctx.addTransition(State, ErrorNode);
98 }
99 }
100
101 void MPIChecker::checkMissingWaits(SymbolReaper &SymReaper,
102 CheckerContext &Ctx) const {
103 ProgramStateRef State = Ctx.getState();
104 const auto &Requests = State->get<RequestMap>();
105 if (Requests.isEmpty())
106 return;
107
108 static CheckerProgramPointTag Tag("MPI-Checker", "MissingWait");
109 ExplodedNode *ErrorNode{nullptr};
110
111 auto ReqMap = State->get<RequestMap>();
112 for (const auto &Req : ReqMap) {
113 if (!SymReaper.isLiveRegion(Req.first)) {
114 if (Req.second.CurrentState == Request::State::Nonblocking) {
115
116 if (!ErrorNode) {
117 ErrorNode = Ctx.generateNonFatalErrorNode(State, &Tag);
118 State = ErrorNode->getState();
119 }
120 BReporter.reportMissingWait(Req.second, Req.first, ErrorNode,
121 Ctx.getBugReporter());
122 }
123 State = State->remove<RequestMap>(Req.first);
124 }
125 }
126
127 // Transition to update the state regarding removed requests.
128 if (!ErrorNode) {
129 Ctx.addTransition(State);
130 } else {
131 Ctx.addTransition(State, ErrorNode);
132 }
133 }
134
135 const MemRegion *MPIChecker::topRegionUsedByWait(const CallEvent &CE) const {
136
137 if (FuncClassifier->isMPI_Wait(CE.getCalleeIdentifier())) {
138 return CE.getArgSVal(0).getAsRegion();
139 } else if (FuncClassifier->isMPI_Waitall(CE.getCalleeIdentifier())) {
140 return CE.getArgSVal(1).getAsRegion();
141 } else {
142 return (const MemRegion *)nullptr;
143 }
144 }
145
146 void MPIChecker::allRegionsUsedByWait(
147 llvm::SmallVector<const MemRegion *, 2> &ReqRegions,
148 const MemRegion *const MR, const CallEvent &CE, CheckerContext &Ctx) const {
149
150 MemRegionManager *const RegionManager = MR->getMemRegionManager();
151
152 if (FuncClassifier->isMPI_Waitall(CE.getCalleeIdentifier())) {
153 const SubRegion *SuperRegion{nullptr};
154 if (const ElementRegion *const ER = MR->getAs<ElementRegion>()) {
155 SuperRegion = cast<SubRegion>(ER->getSuperRegion());
156 }
157
158 // A single request is passed to MPI_Waitall.
159 if (!SuperRegion) {
160 ReqRegions.push_back(MR);
161 return;
162 }
163
164 const auto &Size = Ctx.getStoreManager().getSizeInElements(
165 Ctx.getState(), SuperRegion,
166 CE.getArgExpr(1)->getType()->getPointeeType());
167 const llvm::APSInt &ArrSize = Size.getAs<nonloc::ConcreteInt>()->getValue();
168
169 for (size_t i = 0; i < ArrSize; ++i) {
170 const NonLoc Idx = Ctx.getSValBuilder().makeArrayIndex(i);
171
172 const ElementRegion *const ER = RegionManager->getElementRegion(
173 CE.getArgExpr(1)->getType()->getPointeeType(), Idx, SuperRegion,
174 Ctx.getASTContext());
175
176 ReqRegions.push_back(ER->getAs<MemRegion>());
177 }
178 } else if (FuncClassifier->isMPI_Wait(CE.getCalleeIdentifier())) {
179 ReqRegions.push_back(MR);
180 }
181 }
182
183 } // end of namespace: mpi
184 } // end of namespace: ento
185 } // end of namespace: clang
186
187 // Registers the checker for static analysis.
188 void clang::ento::registerMPIChecker(CheckerManager &MGR) {
189 MGR.registerChecker<clang::ento::mpi::MPIChecker>();
190 }
ento
clang::ento::StoreManager::getSizeInElements
virtual DefinedOrUnknownSVal getSizeInElements(ProgramStateRef state, const MemRegion *region, QualType EleTy)
Definition: Store.h:154
clang::ento::mpi::RequestMap
Definition: MPITypes.h:49
clang::ento::MemRegion
MemRegion - The root abstract class for all memory regions.
Definition: MemRegion.h:95
clang::Type::getPointeeType
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
Definition: Type.cpp:505
clang::ento::CheckerContext::addTransition
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
Definition: CheckerContext.h:165
clang::ento::ExplodedNode::getState
const ProgramStateRef & getState() const
Definition: ExplodedGraph.h:164
clang::ento::nonloc::ConcreteInt
Value representing integer constant.
Definition: SVals.h:377
clang::ento::SValBuilder::makeArrayIndex
NonLoc makeArrayIndex(uint64_t idx)
Definition: SValBuilder.h:273
clang::ento::mpi::MPIChecker::checkDoubleNonblocking
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...
Definition: MPIChecker.cpp:25
clang::ento::CheckerManager
Definition: CheckerManager.h:117
clang::ento::SubRegion::getSuperRegion
const MemRegion * getSuperRegion() const
Definition: MemRegion.h:448
clang::ento::mpi::MPIBugReporter::reportDoubleNonblocking
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.
Definition: MPIBugReporter.cpp:24
State
LineState State
Definition: UnwrappedLineFormatter.cpp:877
clang::ento::CallEvent::getArgExpr
virtual const Expr * getArgExpr(unsigned Index) const
Returns the expression associated with a given argument.
Definition: CallEvent.h:305
clang::ento::ExplodedNode
Definition: ExplodedGraph.h:66
clang::ento::CheckerContext::getBugReporter
BugReporter & getBugReporter()
Definition: CheckerContext.h:103
clang::ento::mpi::MPIChecker
Definition: MPIChecker.h:31
clang::ento::mpi::MPIBugReporter::reportUnmatchedWait
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.
Definition: MPIBugReporter.cpp:70
clang::ento::CheckerContext
Definition: CheckerContext.h:24
clang::ento::SymbolReaper::isLiveRegion
bool isLiveRegion(const MemRegion *region)
Definition: SymbolManager.cpp:428
clang::ento::mpi::MPIBugReporter::reportMissingWait
void reportMissingWait(const Request &Req, const MemRegion *const RequestRegion, const ExplodedNode *const ExplNode, BugReporter &BReporter) const
Report a missing wait for a nonblocking call.
Definition: MPIBugReporter.cpp:50
clang::ento::MemRegion::getAs
const RegionTy * getAs() const
Definition: MemRegion.h:1231
clang::ento::mpi::Request::CurrentState
const State CurrentState
Definition: MPITypes.h:42
MPIChecker.h
This file defines the main class of MPI-Checker which serves as an entry point.
clang::ento::CallEvent::getCalleeIdentifier
const IdentifierInfo * getCalleeIdentifier() const
Returns the name of the callee, if its name is a simple identifier.
Definition: CallEvent.h:365
getValue
static SVal getValue(SVal val, SValBuilder &svalBuilder)
Definition: ArrayBoundCheckerV2.cpp:276
clang::Expr::getType
QualType getType() const
Definition: Expr.h:128
clang::ento::mpi::Request
Definition: MPITypes.h:28
clang::ento::NonLoc
Definition: SVals.h:296
clang::ento::CheckerContext::generateNonFatalErrorNode
ExplodedNode * generateNonFatalErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
Definition: CheckerContext.h:212
BuiltinCheckerRegistration.h
clang::ento::SVal::getAs
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
Definition: SVals.h:112
clang::ento::MemRegionManager
Definition: MemRegion.h:1242
llvm::IntrusiveRefCntPtr
Definition: LLVM.h:45
clang::ento::CheckerContext::getStoreManager
StoreManager & getStoreManager()
Definition: CheckerContext.h:64
clang::ento::CheckerManager::registerChecker
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
Definition: CheckerManager.h:154
clang::ento::SVal::getAsRegion
const MemRegion * getAsRegion() const
Definition: SVals.cpp:151
llvm::SmallVector
Definition: LLVM.h:36
clang::ento::SymbolReaper
A class responsible for cleaning up unused symbols.
Definition: SymbolManager.h:549
clang
Dataflow Directional Tag Classes.
Definition: CFGReachabilityAnalysis.h:22
clang::ento::CheckerContext::getASTContext
ASTContext & getASTContext()
Definition: CheckerContext.h:84
clang::ento::MemRegionManager::getElementRegion
const ElementRegion * getElementRegion(QualType elementType, NonLoc Idx, const SubRegion *superRegion, ASTContext &Ctx)
getElementRegion - Retrieve the memory region associated with the associated element type...
Definition: MemRegion.cpp:988
clang::ento::CallEvent
Represents an abstract call to a function or method along a particular path.
Definition: CallEvent.h:171
clang::ento::MemRegion::getMemRegionManager
virtual MemRegionManager * getMemRegionManager() const =0
clang::ento::SubRegion
SubRegion - A region that subsets another larger region.
Definition: MemRegion.h:436
clang::ento::CheckerContext::getState
const ProgramStateRef & getState() const
Definition: CheckerContext.h:72
clang::ento::CallEvent::getNumArgs
virtual unsigned getNumArgs() const =0
Returns the number of arguments (explicit and implicit).
clang::ento::CheckerContext::getSValBuilder
SValBuilder & getSValBuilder()
Definition: CheckerContext.h:111
clang::ento::ElementRegion
ElementRegion is used to represent both array elements and casts.
Definition: MemRegion.h:1086
clang::ento::mpi::MPIChecker::checkUnmatchedWaits
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.
Definition: MPIChecker.cpp:57
clang::ento::CallEvent::getArgSVal
virtual SVal getArgSVal(unsigned Index) const
Returns the value of a given argument at the time of the call.
Definition: CallEvent.cpp:401
clang::ento::CheckerProgramPointTag
Tag that can use a checker name as a message provider (see SimpleProgramPointTag).
Definition: Checker.h:509
clang::ento::mpi::MPIChecker::checkMissingWaits
void checkMissingWaits(clang::ento::SymbolReaper &SymReaper, clang::ento::CheckerContext &Ctx) const
Check if a nonblocking call is not matched by a wait.
Definition: MPIChecker.cpp:101