clang: lib/StaticAnalyzer/Core/BugSuppression.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
12#include "llvm/Support/FormatVariadic.h"
13#include "llvm/Support/TimeProfiler.h"
14
15using namespace clang;
16using namespace ento;
17
18namespace {
19
21
22inline bool hasSuppression(const Decl *D) {
23
24
25 if (const auto *Suppression = D->getAttr())
26 return !Suppression->isGSL() &&
27 (Suppression->diagnosticIdentifiers().empty());
28 return false;
29}
31
32
33 return llvm::any_of(S->getAttrs(), [](const Attr *A) {
34 const auto *Suppression = dyn_cast(A);
35 return Suppression && !Suppression->isGSL() &&
36 (Suppression->diagnosticIdentifiers().empty());
37 });
38}
39
40template inline SourceRange getRange(const NodeType *Node) {
41 return Node->getSourceRange();
42}
44
45
46
47
48
49
50
51
53}
54
57
58
59
60
61
62
63
64 return .isBeforeInTranslationUnit(RHS, LHS);
65}
66
69
70
71
72
73
74
75
76
79}
80
82public:
83 static void initialize(const Decl *D, Ranges &ToInit) {
84 CacheInitializer(ToInit).TraverseDecl(const_cast<Decl *>(D));
85 }
86
87 bool VisitDecl(Decl *D) override {
88
89
90
91
92 return VisitAttributedNode(D);
93 }
94
95 bool VisitAttributedStmt(AttributedStmt *AS) override {
96
97
98
99 return VisitAttributedNode(AS);
100 }
101
102private:
103 template bool VisitAttributedNode(NodeType *Node) {
104 if (hasSuppression(Node)) {
105
106
107
109 }
110
111 return true;
112 }
113
114 void addRange(SourceRange R) {
116 Result.push_back(R);
117 }
118 }
119
120 CacheInitializer(Ranges &R) : Result(R) {
121 ShouldVisitTemplateInstantiations = true;
122 ShouldWalkTypesOfTypeLocs = false;
123 ShouldVisitImplicitCode = false;
124 ShouldVisitLambdaBody = true;
125 }
126 Ranges &Result;
127};
128
129std::string timeScopeName(const Decl *DeclWithIssue) {
130 if (!llvm::timeTraceProfilerEnabled())
131 return "";
132 return llvm::formatv(
133 "BugSuppression::isSuppressed init suppressions cache for {0}",
135 .str();
136}
137
138llvm::TimeTraceMetadata getDeclTimeTraceMetadata(const Decl *DeclWithIssue) {
139 assert(DeclWithIssue);
140 assert(llvm::timeTraceProfilerEnabled());
141 std::string Name = "";
142 if (const auto *ND = dyn_cast(DeclWithIssue)) {
143 Name = ND->getNameAsString();
144 }
146 auto Line = SM.getPresumedLineNumber(DeclWithIssue->getBeginLoc());
147 auto Fname = SM.getFilename(DeclWithIssue->getBeginLoc());
148 return llvm::TimeTraceMetadata{std::move(Name), Fname.str(),
149 static_cast<int>(Line)};
150}
151
152}
153
154
155
156
157
158
163
164 return isSuppressed(Location, DeclWithIssue, {}) ||
165 isSuppressed(UniqueingLocation, DeclWithIssue, {});
166}
167
169 const Decl *DeclWithIssue,
171 if (!Location.isValid())
172 return false;
173
174 if (!DeclWithIssue) {
175
176
177
178
180 } else {
181
182
183
184 while (true) {
185
186
187 const Decl *Parent =
190 break;
191
192 DeclWithIssue = Parent;
193 }
194 }
195
196
197
198
199
200
201
202
203
204
205
206 auto InsertionResult = CachedSuppressionLocations.insert(
207 std::make_pair(DeclWithIssue, CachedRanges{}));
208 Ranges &SuppressionRanges = InsertionResult.first->second;
209 if (InsertionResult.second) {
210 llvm::TimeTraceScope TimeScope(
211 timeScopeName(DeclWithIssue),
212 [DeclWithIssue]() { return getDeclTimeTraceMetadata(DeclWithIssue); });
213
214 CacheInitializer::initialize(DeclWithIssue, SuppressionRanges);
215 }
216
217 SourceRange BugRange = Location.asRange();
219
220 return llvm::any_of(SuppressionRanges,
222 return fullyContains(Suppression, BugRange, SM);
223 });
224}
static CharSourceRange getRange(const CharSourceRange &EditRange, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeMacroExpansion)
SourceManager & getSourceManager()
Attr - This represents one attribute.
Represents an attribute applied to a statement.
ArrayRef< const Attr * > getAttrs() const
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
const char * getDeclKindName() const
SourceLocation getBeginLoc() const LLVM_READONLY
TranslationUnitDecl * getTranslationUnitDecl()
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
Encodes a location in the source.
This class handles loading and caching of source files into memory.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
This class provides an interface through which checkers can create individual bug reports.
virtual PathDiagnosticLocation getUniqueingLocation() const =0
Get the location on which the report should be uniqued.
virtual PathDiagnosticLocation getLocation() const =0
The primary location of the bug report that points at the undesirable behavior in the code.
virtual const Decl * getDeclWithIssue() const =0
The smallest declaration that contains the bug location.
llvm::ArrayRef< llvm::StringRef > DiagnosticIdentifierList
bool isSuppressed(const BugReport &)
Return true if the given bug report was explicitly suppressed by the user.
Definition BugSuppression.cpp:159
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
void initialize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor