@@ -135,7 +135,19 @@ class UncountedLocalVarsChecker
135135 bool shouldVisitImplicitCode () const { return false ; }
136136
137137 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+ }
139151 return true ;
140152 }
141153
@@ -174,7 +186,7 @@ class UncountedLocalVarsChecker
174186 visitor.TraverseDecl (const_cast <TranslationUnitDecl *>(TUD));
175187 }
176188
177- void visitVarDecl (const VarDecl *V) const {
189+ void visitVarDecl (const VarDecl *V, const Expr *Value ) const {
178190 if (shouldSkipVarDecl (V))
179191 return ;
180192
@@ -184,12 +196,8 @@ class UncountedLocalVarsChecker
184196
185197 std::optional<bool > IsUncountedPtr = isUncountedPtr (ArgType);
186198 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-
191199 if (tryToFindPtrOrigin (
192- InitExpr , /* StopAtFirstRefCountedObj=*/ false ,
200+ Value , /* StopAtFirstRefCountedObj=*/ false ,
193201 [&](const clang::Expr *InitArgOrigin, bool IsSafe) {
194202 if (!InitArgOrigin)
195203 return true ;
@@ -232,34 +240,46 @@ class UncountedLocalVarsChecker
232240 }))
233241 return ;
234242
235- reportBug (V);
243+ reportBug (V, Value );
236244 }
237245 }
238246
239247 bool shouldSkipVarDecl (const VarDecl *V) const {
240248 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 ());
248250 }
249251
250- void reportBug (const VarDecl *V) const {
252+ void reportBug (const VarDecl *V, const Expr *Value ) const {
251253 assert (V);
252254 SmallString<100 > Buf;
253255 llvm::raw_svector_ostream Os (Buf);
254256
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+ }
263283 }
264284};
265285} // namespace
0 commit comments