clang: include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
15#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
16
29#include "llvm/ADT/ArrayRef.h"
30#include "llvm/ADT/FoldingSet.h"
31#include "llvm/ADT/ImmutableSet.h"
32#include "llvm/ADT/SmallSet.h"
33#include "llvm/ADT/SmallVector.h"
34#include "llvm/ADT/StringMap.h"
35#include "llvm/ADT/StringRef.h"
36#include "llvm/ADT/ilist.h"
37#include "llvm/ADT/ilist_node.h"
38#include "llvm/ADT/iterator_range.h"
39#include
40#include
41#include
42#include
43#include
44#include
45
47
48class AnalyzerOptions;
49class ASTContext;
51class LocationContext;
52class SourceManager;
53class Stmt;
54
55namespace ento {
56
57class BugType;
58class CheckerBase;
59class ExplodedGraph;
60class ExplodedNode;
61class ExprEngine;
62class MemRegion;
63
64
65
66
67
68
69
71 llvm::DenseMap<PathDiagnosticConsumer *, std::unique_ptr>;
72
73
74
75
76
78public:
80
81
83};
84
85
86
87
88
89
90
92private:
94 std::string Msg;
95
96public:
99
100
101
103
104
105
107
109 return Msg;
110 }
111
113 return Msg;
114 }
115};
116
117
118
120public:
122
123protected:
126
131
135
137 : BugReport(kind, bt, "", desc) {}
138
143
144public:
146
148
150
151
152
153
154
155
156
158
159
160
161
162
167 }
168
169
170
171
172
174
175
176
177
179
180
181
182
183
184
185
186
187
188
190
191
192
193
194
196
197
198
199
200
203 auto P = std::make_shared(Pos, Msg);
204
205 for (const auto &R : Ranges)
206 P->addRange(R);
207
208 Notes.push_back(std::move(P));
209 }
210
213 }
214
215
216
217
218
219
220
221
223 assert((R.isValid() || Ranges.empty()) && "Invalid range can only be used "
224 "to specify that the report does not have a range.");
226 }
227
228
231 }
232
233
234
235
236
237
238
239
242 }
243
245
246
247
248 virtual void Profile(llvm::FoldingSetNodeID& hash) const = 0;
249};
250
253 const Decl *DeclWithIssue = nullptr;
254
255public:
258
261 }
262
264 assert(Location.isValid());
265 return Location;
266 }
267
269 return DeclWithIssue;
270 }
271
274 }
275
278 }
279
280
281
283 DeclWithIssue = declWithIssue;
284 }
285
286 void Profile(llvm::FoldingSetNodeID& hash) const override;
287};
288
290public:
293 using visitor_range = llvm::iterator_range<visitor_iterator>;
294
295protected:
296
297
299
300
301
303
304
305
306
307
308
309
310
312
313
314
315
316
317
318 llvm::DenseMap<const MemRegion *, bugreporter::TrackingKind>
320
321
322
324
325
326
328
329
331
332
333
334
336
337
338
339
340
342
343
344
345
346
347
349
350
352
353
354
357
359
360
361
362
363
364
365 std::map<PathDiagnosticPieceRef, std::unique_ptr>
367
368public:
372
376 {},
377 nullptr) {}
378
379
380
381
382
383
384
385
389 const Decl *DeclToUnique)
391 DeclToUnique) {}
392
396 const Decl *DeclToUnique);
397
400 }
401
403
404
405
407
408
410
411
414 }
415
416
419 }
420
422
424
426
427
428
429
432
434
435
436
437
441
443
444
445
446
450
455
456 std::optionalbugreporter::TrackingKind
458
459 std::optionalbugreporter::TrackingKind
461
463
464
465
466
467
470 }
471
472
473
474
475
476
477
478
479
480
483 }
484
485
486
487
488 void Profile(llvm::FoldingSetNodeID &hash) const override;
489
490
491
492
493
494
495 void addVisitor(std::unique_ptr visitor);
496
497 template <class VisitorType, class... Args>
500 std::make_unique(std::forward(ConstructorArgs)...));
501 }
502
503
504
506
507
511
512
513
514
517 }
518
520 std::unique_ptr StackHint) {
521 StackHints[Piece] = std::move(StackHint);
522 }
523
526 }
527
528
529
530 std::string
535 return I->second->getMessage(N);
536 return "";
537 }
538};
539
540
541
542
543
546
547
549
550 void AddReport(std::unique_ptr &&R) {
551 Reports.push_back(std::move(R));
552 }
553
554public:
556
558
559 void Profile(llvm::FoldingSetNodeID& ID) const {
560 assert(!Reports.empty());
561 Reports.front()->Profile(ID);
562 }
563};
564
565
566
567
568
570public:
572
578};
579
580
581
582
583
584
586private:
588
589
590 const Decl *AnalysisEntryPoint = nullptr;
591
592
594
595
596 llvm::FoldingSet EQClasses;
597
598
599 std::vector<BugReportEquivClass *> EQClassesVector;
600
601
603
604public:
607
608
610
612 return D.getPathDiagnosticConsumers();
613 }
614
615
618 return EQClasses;
619 }
620
622
624
626
628
629
631
633 assert(EntryPoint);
634 AnalysisEntryPoint = EntryPoint;
635 }
636
637
638
639
640
641
642 virtual void emitReport(std::unique_ptr R);
643
645 StringRef BugName, StringRef BugCategory,
649
650 void EmitBasicReport(const Decl *DeclWithIssue, CheckerNameRef CheckerName,
651 StringRef BugName, StringRef BugCategory,
652 StringRef BugStr, PathDiagnosticLocation Loc,
653 ArrayRef Ranges = {},
654 ArrayRef Fixits = {});
655
656private:
657 llvm::StringMap<std::unique_ptr> StrBugTypes;
658
659
660
661 BugType *getBugTypeForName(CheckerNameRef CheckerName, StringRef name,
662 StringRef category);
663
664 virtual BugReport *
665 findReportInEquivalenceClass(BugReportEquivClass &eqClass,
666 SmallVectorImpl<BugReport *> &bugReports) {
667 return eqClass.getReports()[0].get();
668 }
669
670protected:
671
672 virtual std::unique_ptr
674 ArrayRef<PathDiagnosticConsumer *> consumers,
675 ArrayRef<BugReport *> bugReports);
676};
677
678
681
682 BugReport *findReportInEquivalenceClass(
685
686
687 std::unique_ptr
688 generateDiagnosticForConsumerMap(BugReport *exampleReport,
691public:
694
695
696
698
699
700
702
703
704
705
706
707
711
712 void emitReport(std::unique_ptr R) override;
713};
714
715
718
719 virtual void anchor();
720
721public:
723
725
728
731 }
732
735 }
736
739 }
740
743 }
744};
745
746
747
748
749
750
751
752
753
755public:
757
758
760 std::vector<std::unique_ptr> Tags;
761
762 public:
763 template <class DataTagType, class... Args>
764 const DataTagType *make(Args &&... ConstructorArgs) {
765
766
767 Tags.emplace_back(
768 new DataTagType(std::forward(ConstructorArgs)...));
769 return static_cast<DataTagType *>(Tags.back().get());
770 }
771 };
772
773protected:
775};
776
777
778
780public:
783
784private:
785 static int Kind;
786
788 const bool IsPrunable;
789
791 : DataTag(&Kind), Cb(std::move(Cb)), IsPrunable(IsPrunable) {}
792
793public:
795 return T->getTagKind() == &Kind;
796 }
797
800 std::string Msg = Cb(BRC, R);
801 if (Msg.empty())
802 return std::nullopt;
803
804 return std::move(Msg);
805 }
806
808
809
810
811 return "Note Tag";
812 }
813
815
818};
819
820}
821
822}
823
824#endif
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines the clang::Preprocessor interface.
Defines the clang::SourceLocation class and associated facilities.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Stores options for the analyzer from the command line.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Decl - This represents one declaration (or definition), e.g.
This represents one expression.
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
ProgramPoints can be "tagged" as representing points specific to a given analysis entity.
This class handles loading and caching of source files into memory.
A trivial tuple used to represent a source range.
Stmt - This represents one statement.
BasicBugReport(const BugType &bt, StringRef desc, PathDiagnosticLocation l)
PathDiagnosticLocation getLocation() const override
The primary location of the bug report that points at the undesirable behavior in the code.
const Decl * getDeclWithIssue() const override
The smallest declaration that contains the bug location.
PathDiagnosticLocation getUniqueingLocation() const override
Get the location on which the report should be uniqued.
void Profile(llvm::FoldingSetNodeID &hash) const override
Reports are uniqued to ensure that we do not emit multiple diagnostics for each bug.
static bool classof(const BugReport *R)
const Decl * getUniqueingDecl() const override
Get the declaration that corresponds to (usually contains) the uniqueing location.
void setDeclWithIssue(const Decl *declWithIssue)
Specifically set the Decl where an issue occurred.
ArrayRef< std::unique_ptr< BugReport > > getReports() const
BugReportEquivClass(std::unique_ptr< BugReport > R)
void Profile(llvm::FoldingSetNodeID &ID) const
This class provides an interface through which checkers can create individual bug reports.
llvm::ArrayRef< FixItHint > getFixits() const
void addRange(SourceRange R)
Add a range to a bug report.
SmallVector< SourceRange, 4 > Ranges
std::string ShortDescription
void addNote(StringRef Msg, const PathDiagnosticLocation &Pos, ArrayRef< SourceRange > Ranges={})
Add new item to the list of additional notes that need to be attached to this report.
virtual PathDiagnosticLocation getUniqueingLocation() const =0
Get the location on which the report should be uniqued.
virtual ~BugReport()=default
virtual PathDiagnosticLocation getLocation() const =0
The primary location of the bug report that points at the undesirable behavior in the code.
virtual const Decl * getUniqueingDecl() const =0
Get the declaration that corresponds to (usually contains) the uniqueing location.
SmallVector< std::shared_ptr< PathDiagnosticNotePiece >, 4 > Notes
SmallVector< FixItHint, 4 > Fixits
ArrayRef< std::shared_ptr< PathDiagnosticNotePiece > > getNotes()
BugReport(Kind kind, const BugType &bt, StringRef desc)
void addFixItHint(const FixItHint &F)
Add a fix-it hint to the bug report.
StringRef getDescription() const
A verbose warning message that is appropriate for displaying next to the source code that introduces ...
virtual void Profile(llvm::FoldingSetNodeID &hash) const =0
Reports are uniqued to ensure that we do not emit multiple diagnostics for each bug.
const BugType & getBugType() const
StringRef getShortDescription(bool UseFallback=true) const
A short general warning message that is appropriate for displaying in the list of all reported bugs.
virtual ArrayRef< SourceRange > getRanges() const
Get the SourceRanges associated with the report.
virtual const Decl * getDeclWithIssue() const =0
The smallest declaration that contains the bug location.
BugReport(Kind K, const BugType &BT, StringRef ShortDescription, StringRef Description)
ASTContext & getASTContext() const
BugReporterContext(PathSensitiveBugReporter &br)
ProgramStateManager & getStateManager() const
const SourceManager & getSourceManager() const
PathSensitiveBugReporter & getBugReporter()
virtual ~BugReporterContext()=default
const PathSensitiveBugReporter & getBugReporter() const
const AnalyzerOptions & getAnalyzerOptions() const
virtual ASTContext & getASTContext()=0
virtual ~BugReporterData()=default
virtual AnalyzerOptions & getAnalyzerOptions()=0
virtual SourceManager & getSourceManager()=0
virtual Preprocessor & getPreprocessor()=0
virtual ArrayRef< PathDiagnosticConsumer * > getPathDiagnosticConsumers()=0
BugReporter is a utility class for generating PathDiagnostics for analysis.
virtual std::unique_ptr< DiagnosticForConsumerMapTy > generateDiagnosticForConsumerMap(BugReport *exampleReport, ArrayRef< PathDiagnosticConsumer * > consumers, ArrayRef< BugReport * > bugReports)
Generate the diagnostics for the given bug report.
Preprocessor & getPreprocessor()
void FlushReports()
Generate and flush diagnostics for all bug reports.
const SourceManager & getSourceManager()
const Decl * getAnalysisEntryPoint() const
Get the top-level entry point for the issue to be reported.
llvm::iterator_range< EQClasses_iterator > equivalenceClasses()
ASTContext & getContext()
const AnalyzerOptions & getAnalyzerOptions()
void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker, StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, ArrayRef< SourceRange > Ranges={}, ArrayRef< FixItHint > Fixits={})
virtual void emitReport(std::unique_ptr< BugReport > R)
Add the given report to the set of reports tracked by BugReporter.
llvm::FoldingSet< BugReportEquivClass >::iterator EQClasses_iterator
Iterator over the set of BugReports tracked by the BugReporter.
ArrayRef< PathDiagnosticConsumer * > getPathDiagnosticConsumers()
void setAnalysisEntryPoint(const Decl *EntryPoint)
const DataTagType * make(Args &&... ConstructorArgs)
The tag that carries some information with it.
StringRef getTagDescription() const override
MemRegion - The root abstract class for all memory regions.
The tag upon which the TagVisitor reacts.
std::function< std::string(BugReporterContext &, PathSensitiveBugReport &)> Callback
static bool classof(const ProgramPointTag *T)
StringRef getTagDescription() const override
std::optional< std::string > generateMessage(BugReporterContext &BRC, PathSensitiveBugReport &R) const
llvm::SmallSet< const LocationContext *, 2 > InterestingLocationContexts
A set of location contexts that correspoind to call sites which should be considered "interesting".
void markInteresting(SymbolRef sym, bugreporter::TrackingKind TKind=bugreporter::TrackingKind::Thorough)
Marks a symbol as interesting.
void addVisitor(Args &&... ConstructorArgs)
llvm::SmallSet< const ExplodedNode *, 4 > TrackedConditions
Conditions we're already tracking.
PathDiagnosticLocation getUniqueingLocation() const override
Get the location on which the report should be uniqued.
VisitorList Callbacks
A set of custom visitors which generate "event" diagnostics at interesting points in the path.
const Stmt * getStmt() const
std::string getCallStackMessage(PathDiagnosticPieceRef Piece, const ExplodedNode *N) const
Produce the hint for the given node.
PathDiagnosticLocation getLocation() const override
The primary location of the bug report that points at the undesirable behavior in the code.
const Decl * getDeclWithIssue() const override
The smallest declaration that contains the bug location.
std::map< PathDiagnosticPieceRef, std::unique_ptr< StackHintGenerator > > StackHints
If an event occurs in a different frame than the final diagnostic, supply a message that will be used...
std::pair< const void *, const void * > InvalidationRecord
Used to track unique reasons why a bug report might be invalid.
bool shouldPrunePath() const
Indicates whether or not any path pruning should take place when generating a PathDiagnostic from thi...
PathDiagnosticLocation UniqueingLocation
Reports with different uniqueing locations are considered to be different for the purposes of dedupli...
ArrayRef< SourceRange > getRanges() const override
Get the SourceRanges associated with the report.
visitor_iterator visitor_end()
llvm::DenseMap< SymbolRef, bugreporter::TrackingKind > InterestingSymbols
Profile to identify equivalent bug reports for error report coalescing.
const Decl * getUniqueingDecl() const override
Get the declaration containing the uniqueing location.
llvm::SmallSet< InvalidationRecord, 4 > Invalidations
If non-empty, this bug report is likely a false positive and should not be shown to the user.
const ExplodedNode * getErrorNode() const
PathSensitiveBugReport(const BugType &bt, StringRef desc, const ExplodedNode *errorNode)
static bool classof(const BugReport *R)
const ExplodedNode * ErrorNode
The ExplodedGraph node against which the report was thrown.
PathSensitiveBugReport(const BugType &bt, StringRef shortDesc, StringRef desc, const ExplodedNode *errorNode)
bool addTrackedCondition(const ExplodedNode *Cond)
Notes that the condition of the CFGBlock associated with Cond is being tracked.
visitor_iterator visitor_begin()
Iterators through the custom diagnostic visitors.
void addCallStackHint(PathDiagnosticPieceRef Piece, std::unique_ptr< StackHintGenerator > StackHint)
void markInvalid(const void *Tag, const void *Data)
Marks the current report as invalid, meaning that it is probably a false positive and should not be r...
void Profile(llvm::FoldingSetNodeID &hash) const override
Profile to identify equivalent bug reports for error report coalescing.
void clearVisitors()
Remove all visitors attached to this bug report.
bool hasCallStackHint(PathDiagnosticPieceRef Piece) const
void addVisitor(std::unique_ptr< BugReporterVisitor > visitor)
Add custom or predefined bug report visitors to this report.
bool isValid() const
Returns whether or not this report should be considered valid.
std::optional< bugreporter::TrackingKind > getInterestingnessKind(SymbolRef sym) const
void markNotInteresting(SymbolRef sym)
bool DoNotPrunePath
When set, this flag disables all callstack pruning from a diagnostic path.
PathSensitiveBugReport(const BugType &bt, StringRef desc, const ExplodedNode *errorNode, PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique)
Create a PathSensitiveBugReport with a custom uniqueing location.
llvm::DenseMap< const MemRegion *, bugreporter::TrackingKind > InterestingRegions
A (stack of) set of regions that are registered with this report as being "interesting",...
llvm::iterator_range< visitor_iterator > visitor_range
bool isInteresting(SymbolRef sym) const
const SourceRange ErrorNodeRange
The range that corresponds to ErrorNode's program point.
VisitorList::iterator visitor_iterator
llvm::FoldingSet< BugReporterVisitor > CallbacksSet
Used for ensuring the visitors are only added once.
void disablePathPruning()
Disable all path pruning when generating a PathDiagnostic.
const Decl * UniqueingDecl
GRBugReporter is used for generating path-sensitive reports.
const ExplodedGraph & getGraph() const
getGraph - Get the exploded graph created by the analysis engine for the analyzed method or function.
std::unique_ptr< DiagnosticForConsumerMapTy > generatePathDiagnostics(ArrayRef< PathDiagnosticConsumer * > consumers, ArrayRef< PathSensitiveBugReport * > &bugReports)
bugReports A set of bug reports within a single equivalence class
void emitReport(std::unique_ptr< BugReport > R) override
Add the given report to the set of reports tracked by BugReporter.
ProgramStateManager & getStateManager() const
getStateManager - Return the state manager used by the analysis engine.
PathSensitiveBugReporter(BugReporterData &d, ExprEngine &eng)
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Constructs a Stack hint for the given symbol.
StackHintGeneratorForSymbol(SymbolRef S, StringRef M)
std::string getMessage(const ExplodedNode *N) override
Search the call expression for the symbol Sym and dispatch the 'getMessageForX()' methods to construc...
virtual std::string getMessageForSymbolNotFound()
virtual std::string getMessageForReturn(const CallExpr *CallExpr)
virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex)
Produces the message of the following form: 'Msg via Nth parameter'.
~StackHintGeneratorForSymbol() override=default
Interface for classes constructing Stack hints.
virtual ~StackHintGenerator()=0
virtual std::string getMessage(const ExplodedNode *N)=0
Construct the Diagnostic message for the given ExplodedNode.
The visitor detects NoteTags and displays the event notes they contain.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
TrackingKind
Specifies the type of tracking for an expression.
@ Thorough
Default tracking kind – specifies that as much information should be gathered about the tracked expre...
llvm::DenseMap< PathDiagnosticConsumer *, std::unique_ptr< PathDiagnostic > > DiagnosticForConsumerMapTy
A mapping from diagnostic consumers to the diagnostics they should consume.
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T