@@ -136,7 +136,19 @@ class UncountedLocalVarsChecker
136
136
bool shouldVisitImplicitCode () const { return false ; }
137
137
138
138
bool VisitVarDecl (VarDecl *V) {
139
- Checker->visitVarDecl (V);
139
+ auto *Init = V->getInit ();
140
+ if (Init && V->isLocalVarDecl ())
141
+ Checker->visitVarDecl (V, Init);
142
+ return true ;
143
+ }
144
+
145
+ bool VisitBinaryOperator (const BinaryOperator *BO) {
146
+ if (BO->isAssignmentOp ()) {
147
+ if (auto *VarRef = dyn_cast<DeclRefExpr>(BO->getLHS ())) {
148
+ if (auto *V = dyn_cast<VarDecl>(VarRef->getDecl ()))
149
+ Checker->visitVarDecl (V, BO->getRHS ());
150
+ }
151
+ }
140
152
return true ;
141
153
}
142
154
@@ -175,7 +187,7 @@ class UncountedLocalVarsChecker
175
187
visitor.TraverseDecl (const_cast <TranslationUnitDecl *>(TUD));
176
188
}
177
189
178
- void visitVarDecl (const VarDecl *V) const {
190
+ void visitVarDecl (const VarDecl *V, const Expr *Value ) const {
179
191
if (shouldSkipVarDecl (V))
180
192
return ;
181
193
@@ -185,12 +197,8 @@ class UncountedLocalVarsChecker
185
197
186
198
std::optional<bool > IsUncountedPtr = isUncountedPtr (ArgType);
187
199
if (IsUncountedPtr && *IsUncountedPtr) {
188
- const Expr *const InitExpr = V->getInit ();
189
- if (!InitExpr)
190
- return ; // FIXME: later on we might warn on uninitialized vars too
191
-
192
200
if (tryToFindPtrOrigin (
193
- InitExpr , /* StopAtFirstRefCountedObj=*/ false ,
201
+ Value , /* StopAtFirstRefCountedObj=*/ false ,
194
202
[&](const clang::Expr *InitArgOrigin, bool IsSafe) {
195
203
if (!InitArgOrigin)
196
204
return true ;
@@ -233,34 +241,46 @@ class UncountedLocalVarsChecker
233
241
}))
234
242
return ;
235
243
236
- reportBug (V);
244
+ reportBug (V, Value );
237
245
}
238
246
}
239
247
240
248
bool shouldSkipVarDecl (const VarDecl *V) const {
241
249
assert (V);
242
- if (!V->isLocalVarDecl ())
243
- return true ;
244
-
245
- if (BR->getSourceManager ().isInSystemHeader (V->getLocation ()))
246
- return true ;
247
-
248
- return false ;
250
+ return BR->getSourceManager ().isInSystemHeader (V->getLocation ());
249
251
}
250
252
251
- void reportBug (const VarDecl *V) const {
253
+ void reportBug (const VarDecl *V, const Expr *Value ) const {
252
254
assert (V);
253
255
SmallString<100 > Buf;
254
256
llvm::raw_svector_ostream Os (Buf);
255
257
256
- Os << " Local variable " ;
257
- printQuotedQualifiedName (Os, V);
258
- Os << " is uncounted and unsafe." ;
259
-
260
- PathDiagnosticLocation BSLoc (V->getLocation (), BR->getSourceManager ());
261
- auto Report = std::make_unique<BasicBugReport>(Bug, Os.str (), BSLoc);
262
- Report->addRange (V->getSourceRange ());
263
- BR->emitReport (std::move (Report));
258
+ if (dyn_cast<ParmVarDecl>(V)) {
259
+ Os << " Assignment to an uncounted parameter " ;
260
+ printQuotedQualifiedName (Os, V);
261
+ Os << " is unsafe." ;
262
+
263
+ PathDiagnosticLocation BSLoc (Value->getExprLoc (), BR->getSourceManager ());
264
+ auto Report = std::make_unique<BasicBugReport>(Bug, Os.str (), BSLoc);
265
+ Report->addRange (Value->getSourceRange ());
266
+ BR->emitReport (std::move (Report));
267
+ } else {
268
+ if (V->hasLocalStorage ())
269
+ Os << " Local variable " ;
270
+ else if (V->isStaticLocal ())
271
+ Os << " Static local variable " ;
272
+ else if (V->hasGlobalStorage ())
273
+ Os << " Global variable " ;
274
+ else
275
+ Os << " Variable " ;
276
+ printQuotedQualifiedName (Os, V);
277
+ Os << " is uncounted and unsafe." ;
278
+
279
+ PathDiagnosticLocation BSLoc (V->getLocation (), BR->getSourceManager ());
280
+ auto Report = std::make_unique<BasicBugReport>(Bug, Os.str (), BSLoc);
281
+ Report->addRange (V->getSourceRange ());
282
+ BR->emitReport (std::move (Report));
283
+ }
264
284
}
265
285
};
266
286
} // namespace
0 commit comments