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.