18
18
#include " clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
19
19
#include " clang/StaticAnalyzer/Core/BugReporter/BugType.h"
20
20
#include " clang/StaticAnalyzer/Core/Checker.h"
21
+ #include " llvm/ADT/DenseSet.h"
22
+ #include " llvm/Support/SaveAndRestore.h"
21
23
#include < optional>
22
24
23
25
using namespace clang ;
@@ -44,7 +46,11 @@ class UncountedCallArgsChecker
44
46
// visit template instantiations or lambda classes. We
45
47
// want to visit those, so we make our own RecursiveASTVisitor.
46
48
struct LocalVisitor : public RecursiveASTVisitor <LocalVisitor> {
49
+ using Base = RecursiveASTVisitor<LocalVisitor>;
50
+
47
51
const UncountedCallArgsChecker *Checker;
52
+ Decl *DeclWithIssue{nullptr };
53
+
48
54
explicit LocalVisitor (const UncountedCallArgsChecker *Checker)
49
55
: Checker(Checker) {
50
56
assert (Checker);
@@ -56,12 +62,18 @@ class UncountedCallArgsChecker
56
62
bool TraverseClassTemplateDecl (ClassTemplateDecl *Decl) {
57
63
if (isRefType (safeGetName (Decl)))
58
64
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);
61
73
}
62
74
63
75
bool VisitCallExpr (const CallExpr *CE) {
64
- Checker->visitCallExpr (CE);
76
+ Checker->visitCallExpr (CE, DeclWithIssue );
65
77
return true ;
66
78
}
67
79
};
@@ -70,7 +82,7 @@ class UncountedCallArgsChecker
70
82
visitor.TraverseDecl (const_cast <TranslationUnitDecl *>(TUD));
71
83
}
72
84
73
- void visitCallExpr (const CallExpr *CE) const {
85
+ void visitCallExpr (const CallExpr *CE, const Decl *D ) const {
74
86
if (shouldSkipCall (CE))
75
87
return ;
76
88
@@ -89,7 +101,7 @@ class UncountedCallArgsChecker
89
101
QualType ArgType = MemberCallExpr->getObjectType ().getCanonicalType ();
90
102
std::optional<bool > IsUncounted = isUncounted (ArgType);
91
103
if (IsUncounted && *IsUncounted && !isPtrOriginSafe (E))
92
- reportBugOnThis (E);
104
+ reportBugOnThis (E, D );
93
105
}
94
106
95
107
for (auto P = F->param_begin ();
@@ -120,7 +132,7 @@ class UncountedCallArgsChecker
120
132
if (isPtrOriginSafe (Arg))
121
133
continue ;
122
134
123
- reportBug (Arg, *P);
135
+ reportBug (Arg, *P, D );
124
136
}
125
137
}
126
138
}
@@ -241,7 +253,8 @@ class UncountedCallArgsChecker
241
253
ClsName.ends_with (" String" ));
242
254
}
243
255
244
- void reportBug (const Expr *CallArg, const ParmVarDecl *Param) const {
256
+ void reportBug (const Expr *CallArg, const ParmVarDecl *Param,
257
+ const Decl *DeclWithIssue) const {
245
258
assert (CallArg);
246
259
247
260
SmallString<100 > Buf;
@@ -262,10 +275,11 @@ class UncountedCallArgsChecker
262
275
PathDiagnosticLocation BSLoc (SrcLocToReport, BR->getSourceManager ());
263
276
auto Report = std::make_unique<BasicBugReport>(Bug, Os.str (), BSLoc);
264
277
Report->addRange (CallArg->getSourceRange ());
278
+ Report->setDeclWithIssue (DeclWithIssue);
265
279
BR->emitReport (std::move (Report));
266
280
}
267
281
268
- void reportBugOnThis (const Expr *CallArg) const {
282
+ void reportBugOnThis (const Expr *CallArg, const Decl *DeclWithIssue ) const {
269
283
assert (CallArg);
270
284
271
285
const SourceLocation SrcLocToReport = CallArg->getSourceRange ().getBegin ();
@@ -275,6 +289,7 @@ class UncountedCallArgsChecker
275
289
Bug, " Call argument for 'this' parameter is uncounted and unsafe." ,
276
290
BSLoc);
277
291
Report->addRange (CallArg->getSourceRange ());
292
+ Report->setDeclWithIssue (DeclWithIssue);
278
293
BR->emitReport (std::move (Report));
279
294
}
280
295
};
0 commit comments