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