1818#include " clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
1919#include " clang/StaticAnalyzer/Core/BugReporter/BugType.h"
2020#include " clang/StaticAnalyzer/Core/Checker.h"
21+ #include " llvm/ADT/DenseSet.h"
22+ #include " llvm/Support/SaveAndRestore.h"
2123#include < optional>
2224
2325using namespace clang ;
@@ -44,7 +46,11 @@ class UncountedCallArgsChecker
4446 // visit template instantiations or lambda classes. We
4547 // want to visit those, so we make our own RecursiveASTVisitor.
4648 struct LocalVisitor : public RecursiveASTVisitor <LocalVisitor> {
49+ using Base = RecursiveASTVisitor<LocalVisitor>;
50+
4751 const UncountedCallArgsChecker *Checker;
52+ Decl *DeclWithIssue{nullptr };
53+
4854 explicit LocalVisitor (const UncountedCallArgsChecker *Checker)
4955 : Checker(Checker) {
5056 assert (Checker);
@@ -56,12 +62,18 @@ class UncountedCallArgsChecker
5662 bool TraverseClassTemplateDecl (ClassTemplateDecl *Decl) {
5763 if (isRefType (safeGetName (Decl)))
5864 return true ;
59- return RecursiveASTVisitor<LocalVisitor>::TraverseClassTemplateDecl (
60- Decl);
65+ return Base::TraverseClassTemplateDecl (Decl);
66+ }
67+
68+ bool TraverseDecl (Decl *D) {
69+ llvm::SaveAndRestore SavedDecl (DeclWithIssue);
70+ if (D && (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)))
71+ DeclWithIssue = D;
72+ return Base::TraverseDecl (D);
6173 }
6274
6375 bool VisitCallExpr (const CallExpr *CE) {
64- Checker->visitCallExpr (CE);
76+ Checker->visitCallExpr (CE, DeclWithIssue );
6577 return true ;
6678 }
6779 };
@@ -70,7 +82,7 @@ class UncountedCallArgsChecker
7082 visitor.TraverseDecl (const_cast <TranslationUnitDecl *>(TUD));
7183 }
7284
73- void visitCallExpr (const CallExpr *CE) const {
85+ void visitCallExpr (const CallExpr *CE, const Decl *D ) const {
7486 if (shouldSkipCall (CE))
7587 return ;
7688
@@ -89,7 +101,7 @@ class UncountedCallArgsChecker
89101 QualType ArgType = MemberCallExpr->getObjectType ().getCanonicalType ();
90102 std::optional<bool > IsUncounted = isUncounted (ArgType);
91103 if (IsUncounted && *IsUncounted && !isPtrOriginSafe (E))
92- reportBugOnThis (E);
104+ reportBugOnThis (E, D );
93105 }
94106
95107 for (auto P = F->param_begin ();
@@ -120,7 +132,7 @@ class UncountedCallArgsChecker
120132 if (isPtrOriginSafe (Arg))
121133 continue ;
122134
123- reportBug (Arg, *P);
135+ reportBug (Arg, *P, D );
124136 }
125137 }
126138 }
@@ -241,7 +253,8 @@ class UncountedCallArgsChecker
241253 ClsName.ends_with (" String" ));
242254 }
243255
244- void reportBug (const Expr *CallArg, const ParmVarDecl *Param) const {
256+ void reportBug (const Expr *CallArg, const ParmVarDecl *Param,
257+ const Decl *DeclWithIssue) const {
245258 assert (CallArg);
246259
247260 SmallString<100 > Buf;
@@ -262,10 +275,11 @@ class UncountedCallArgsChecker
262275 PathDiagnosticLocation BSLoc (SrcLocToReport, BR->getSourceManager ());
263276 auto Report = std::make_unique<BasicBugReport>(Bug, Os.str (), BSLoc);
264277 Report->addRange (CallArg->getSourceRange ());
278+ Report->setDeclWithIssue (DeclWithIssue);
265279 BR->emitReport (std::move (Report));
266280 }
267281
268- void reportBugOnThis (const Expr *CallArg) const {
282+ void reportBugOnThis (const Expr *CallArg, const Decl *DeclWithIssue ) const {
269283 assert (CallArg);
270284
271285 const SourceLocation SrcLocToReport = CallArg->getSourceRange ().getBegin ();
@@ -275,6 +289,7 @@ class UncountedCallArgsChecker
275289 Bug, " Call argument for 'this' parameter is uncounted and unsafe." ,
276290 BSLoc);
277291 Report->addRange (CallArg->getSourceRange ());
292+ Report->setDeclWithIssue (DeclWithIssue);
278293 BR->emitReport (std::move (Report));
279294 }
280295};
0 commit comments