17
17
#include " clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h"
18
18
#include " clang/StaticAnalyzer/Core/Checker.h"
19
19
#include " clang/StaticAnalyzer/Core/CheckerManager.h"
20
+ #include " clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
20
21
#include " clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
21
22
#include " clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
22
23
#include " llvm/ADT/STLExtras.h"
@@ -41,8 +42,7 @@ enum class OpenVariant {
41
42
namespace {
42
43
43
44
class UnixAPIMisuseChecker
44
- : public Checker<check::PreStmt<CallExpr>,
45
- check::ASTDecl<TranslationUnitDecl>> {
45
+ : public Checker<check::PreCall, check::ASTDecl<TranslationUnitDecl>> {
46
46
const BugType BT_open{this , " Improper use of 'open'" , categories::UnixAPI};
47
47
const BugType BT_pthreadOnce{this , " Improper use of 'pthread_once'" ,
48
48
categories::UnixAPI};
@@ -52,14 +52,14 @@ class UnixAPIMisuseChecker
52
52
void checkASTDecl (const TranslationUnitDecl *TU, AnalysisManager &Mgr,
53
53
BugReporter &BR) const ;
54
54
55
- void checkPreStmt (const CallExpr *CE , CheckerContext &C) const ;
55
+ void checkPreCall (const CallEvent &Call , CheckerContext &C) const ;
56
56
57
- void CheckOpen (CheckerContext &C, const CallExpr *CE ) const ;
58
- void CheckOpenAt (CheckerContext &C, const CallExpr *CE ) const ;
59
- void CheckPthreadOnce (CheckerContext &C, const CallExpr *CE ) const ;
57
+ void CheckOpen (CheckerContext &C, const CallEvent &Call ) const ;
58
+ void CheckOpenAt (CheckerContext &C, const CallEvent &Call ) const ;
59
+ void CheckPthreadOnce (CheckerContext &C, const CallEvent &Call ) const ;
60
60
61
- void CheckOpenVariant (CheckerContext &C,
62
- const CallExpr *CE, OpenVariant Variant) const ;
61
+ void CheckOpenVariant (CheckerContext &C, const CallEvent &Call,
62
+ OpenVariant Variant) const ;
63
63
64
64
void ReportOpenBug (CheckerContext &C, ProgramStateRef State, const char *Msg,
65
65
SourceRange SR) const ;
@@ -113,9 +113,9 @@ void UnixAPIMisuseChecker::checkASTDecl(const TranslationUnitDecl *TU,
113
113
// "open" (man 2 open)
114
114
// ===----------------------------------------------------------------------===/
115
115
116
- void UnixAPIMisuseChecker::checkPreStmt (const CallExpr *CE ,
116
+ void UnixAPIMisuseChecker::checkPreCall (const CallEvent &Call ,
117
117
CheckerContext &C) const {
118
- const FunctionDecl *FD = C. getCalleeDecl (CE );
118
+ const FunctionDecl *FD = dyn_cast_if_present<FunctionDecl>(Call. getDecl () );
119
119
if (!FD || FD->getKind () != Decl::Function)
120
120
return ;
121
121
@@ -130,13 +130,13 @@ void UnixAPIMisuseChecker::checkPreStmt(const CallExpr *CE,
130
130
return ;
131
131
132
132
if (FName == " open" )
133
- CheckOpen (C, CE );
133
+ CheckOpen (C, Call );
134
134
135
135
else if (FName == " openat" )
136
- CheckOpenAt (C, CE );
136
+ CheckOpenAt (C, Call );
137
137
138
138
else if (FName == " pthread_once" )
139
- CheckPthreadOnce (C, CE );
139
+ CheckPthreadOnce (C, Call );
140
140
}
141
141
void UnixAPIMisuseChecker::ReportOpenBug (CheckerContext &C,
142
142
ProgramStateRef State,
@@ -152,17 +152,17 @@ void UnixAPIMisuseChecker::ReportOpenBug(CheckerContext &C,
152
152
}
153
153
154
154
void UnixAPIMisuseChecker::CheckOpen (CheckerContext &C,
155
- const CallExpr *CE ) const {
156
- CheckOpenVariant (C, CE , OpenVariant::Open);
155
+ const CallEvent &Call ) const {
156
+ CheckOpenVariant (C, Call , OpenVariant::Open);
157
157
}
158
158
159
159
void UnixAPIMisuseChecker::CheckOpenAt (CheckerContext &C,
160
- const CallExpr *CE ) const {
161
- CheckOpenVariant (C, CE , OpenVariant::OpenAt);
160
+ const CallEvent &Call ) const {
161
+ CheckOpenVariant (C, Call , OpenVariant::OpenAt);
162
162
}
163
163
164
164
void UnixAPIMisuseChecker::CheckOpenVariant (CheckerContext &C,
165
- const CallExpr *CE ,
165
+ const CallEvent &Call ,
166
166
OpenVariant Variant) const {
167
167
// The index of the argument taking the flags open flags (O_RDONLY,
168
168
// O_WRONLY, O_CREAT, etc.),
@@ -191,11 +191,11 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C,
191
191
192
192
ProgramStateRef state = C.getState ();
193
193
194
- if (CE-> getNumArgs () < MinArgCount) {
194
+ if (Call. getNumArgs () < MinArgCount) {
195
195
// The frontend should issue a warning for this case. Just return.
196
196
return ;
197
- } else if (CE-> getNumArgs () == MaxArgCount) {
198
- const Expr *Arg = CE-> getArg (CreateModeArgIndex);
197
+ } else if (Call. getNumArgs () == MaxArgCount) {
198
+ const Expr *Arg = Call. getArgExpr (CreateModeArgIndex);
199
199
QualType QT = Arg->getType ();
200
200
if (!QT->isIntegerType ()) {
201
201
SmallString<256 > SBuf;
@@ -209,15 +209,15 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C,
209
209
Arg->getSourceRange ());
210
210
return ;
211
211
}
212
- } else if (CE-> getNumArgs () > MaxArgCount) {
212
+ } else if (Call. getNumArgs () > MaxArgCount) {
213
213
SmallString<256 > SBuf;
214
214
llvm::raw_svector_ostream OS (SBuf);
215
215
OS << " Call to '" << VariantName << " ' with more than " << MaxArgCount
216
216
<< " arguments" ;
217
217
218
218
ReportOpenBug (C, state,
219
219
SBuf.c_str (),
220
- CE-> getArg (MaxArgCount)->getSourceRange ());
220
+ Call. getArgExpr (MaxArgCount)->getSourceRange ());
221
221
return ;
222
222
}
223
223
@@ -226,8 +226,8 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C,
226
226
}
227
227
228
228
// Now check if oflags has O_CREAT set.
229
- const Expr *oflagsEx = CE-> getArg (FlagsArgIndex);
230
- const SVal V = C. getSVal (oflagsEx );
229
+ const Expr *oflagsEx = Call. getArgExpr (FlagsArgIndex);
230
+ const SVal V = Call. getArgSVal (FlagsArgIndex );
231
231
if (!isa<NonLoc>(V)) {
232
232
// The case where 'V' can be a location can only be due to a bad header,
233
233
// so in this case bail out.
@@ -253,7 +253,7 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C,
253
253
if (!(trueState && !falseState))
254
254
return ;
255
255
256
- if (CE-> getNumArgs () < MaxArgCount) {
256
+ if (Call. getNumArgs () < MaxArgCount) {
257
257
SmallString<256 > SBuf;
258
258
llvm::raw_svector_ostream OS (SBuf);
259
259
OS << " Call to '" << VariantName << " ' requires a "
@@ -271,18 +271,18 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C,
271
271
// ===----------------------------------------------------------------------===//
272
272
273
273
void UnixAPIMisuseChecker::CheckPthreadOnce (CheckerContext &C,
274
- const CallExpr *CE ) const {
274
+ const CallEvent &Call ) const {
275
275
276
276
// This is similar to 'CheckDispatchOnce' in the MacOSXAPIChecker.
277
277
// They can possibly be refactored.
278
278
279
- if (CE-> getNumArgs () < 1 )
279
+ if (Call. getNumArgs () < 1 )
280
280
return ;
281
281
282
282
// Check if the first argument is stack allocated. If so, issue a warning
283
283
// because that's likely to be bad news.
284
284
ProgramStateRef state = C.getState ();
285
- const MemRegion *R = C. getSVal (CE-> getArg ( 0 ) ).getAsRegion ();
285
+ const MemRegion *R = Call. getArgSVal ( 0 ).getAsRegion ();
286
286
if (!R || !isa<StackSpaceRegion>(R->getMemorySpace ()))
287
287
return ;
288
288
@@ -304,7 +304,7 @@ void UnixAPIMisuseChecker::CheckPthreadOnce(CheckerContext &C,
304
304
305
305
auto report =
306
306
std::make_unique<PathSensitiveBugReport>(BT_pthreadOnce, os.str (), N);
307
- report->addRange (CE-> getArg (0 )->getSourceRange ());
307
+ report->addRange (Call. getArgExpr (0 )->getSourceRange ());
308
308
C.emitReport (std::move (report));
309
309
}
310
310
0 commit comments