14 #ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H 15 #define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H 26 #include "llvm/ADT/ArrayRef.h" 27 #include "llvm/ADT/DenseSet.h" 28 #include "llvm/ADT/FoldingSet.h" 29 #include "llvm/ADT/ImmutableSet.h" 30 #include "llvm/ADT/None.h" 31 #include "llvm/ADT/SmallSet.h" 32 #include "llvm/ADT/SmallVector.h" 33 #include "llvm/ADT/StringMap.h" 34 #include "llvm/ADT/StringRef.h" 35 #include "llvm/ADT/ilist.h" 36 #include "llvm/ADT/ilist_node.h" 37 #include "llvm/ADT/iterator_range.h" 46 class AnalyzerOptions;
49 class DiagnosticsEngine;
50 class LocationContext;
71 llvm::DenseMap<PathDiagnosticConsumer *, std::unique_ptr<PathDiagnostic>>;
106 virtual std::string getMessageForArg(
const Expr *ArgE,
unsigned ArgIndex);
121 enum class Kind { Basic, PathSensitive };
137 : K(kind), BT(bt), Description(desc) {}
140 StringRef Description)
141 : K(K), BT(BT), ShortDescription(ShortDescription),
142 Description(Description) {}
164 if (ShortDescription.empty() && UseFallback)
166 return ShortDescription;
178 virtual const Decl *getDeclWithIssue()
const = 0;
195 virtual const Decl *getUniqueingDecl()
const = 0;
203 auto P = std::make_shared<PathDiagnosticNotePiece>(Pos, Msg);
205 for (
const auto &R : Ranges)
208 Notes.push_back(std::move(
P));
223 assert((R.
isValid() || Ranges.empty()) &&
"Invalid range can only be used " 224 "to specify that the report does not have a range.");
248 virtual void Profile(llvm::FoldingSetNodeID& hash)
const = 0;
253 const Decl *DeclWithIssue =
nullptr;
260 return R->
getKind() == Kind::Basic;
269 return DeclWithIssue;
273 return getLocation();
277 return getDeclWithIssue();
283 DeclWithIssue = declWithIssue;
286 void Profile(llvm::FoldingSetNodeID& hash)
const override;
318 llvm::DenseMap<const MemRegion *, bugreporter::TrackingKind>
335 bool DoNotPrunePath =
false;
358 const Stmt *getStmt()
const;
365 std::map<PathDiagnosticPieceRef, std::unique_ptr<StackHintGenerator>>
371 :
BugReport(
Kind::PathSensitive, bt, desc), ErrorNode(errorNode),
378 ErrorNode(errorNode),
392 const Decl *DeclToUnique)
393 :
BugReport(
Kind::PathSensitive, bt, desc), ErrorNode(errorNode),
395 UniqueingLocation(LocationToUnique), UniqueingDecl(DeclToUnique) {
400 return R->
getKind() == Kind::PathSensitive;
414 return UniqueingLocation;
419 return UniqueingDecl;
422 const Decl *getDeclWithIssue()
const override;
431 void markInteresting(
SymbolRef sym, bugreporter::TrackingKind TKind =
432 bugreporter::TrackingKind::Thorough);
437 void markInteresting(
439 bugreporter::TrackingKind TKind = bugreporter::TrackingKind::Thorough);
444 void markInteresting(
SVal V, bugreporter::TrackingKind TKind =
445 bugreporter::TrackingKind::Thorough);
449 bool isInteresting(
const MemRegion *R)
const;
450 bool isInteresting(
SVal V)
const;
454 getInterestingnessKind(
SymbolRef sym)
const;
457 getInterestingnessKind(
const MemRegion *R)
const;
466 return Invalidations.empty();
479 Invalidations.insert(std::make_pair(Tag, Data));
485 void Profile(llvm::FoldingSetNodeID &hash)
const override;
494 void addVisitor(std::unique_ptr<BugReporterVisitor> visitor);
497 void clearVisitors();
508 return TrackedConditions.insert(Cond).second;
512 std::unique_ptr<StackHintGenerator> StackHint) {
513 StackHints[Piece] = std::move(StackHint);
517 return StackHints.count(Piece) > 0;
525 auto I = StackHints.find(Piece);
526 if (I != StackHints.end())
527 return I->second->getMessage(N);
542 void AddReport(std::unique_ptr<BugReport> &&R) {
543 Reports.push_back(std::move(R));
552 assert(!Reports.empty());
553 Reports.front()->Profile(ID);
584 llvm::FoldingSet<BugReportEquivClass> EQClasses;
587 std::vector<BugReportEquivClass *> EQClassesVector;
616 virtual void emitReport(std::unique_ptr<BugReport> R);
619 StringRef BugName, StringRef BugCategory,
625 StringRef BugName, StringRef BugCategory,
631 llvm::StringMap<BugType *> StrBugTypes;
646 virtual std::unique_ptr<DiagnosticForConsumerMapTy>
647 generateDiagnosticForConsumerMap(
BugReport *exampleReport,
661 std::unique_ptr<DiagnosticForConsumerMapTy>
662 generateDiagnosticForConsumerMap(
BugReport *exampleReport,
682 std::unique_ptr<DiagnosticForConsumerMapTy> generatePathDiagnostics(
686 void emitReport(std::unique_ptr<BugReport> R)
override;
693 virtual void anchor();
725 std::function<std::string(BugReporterContext &, BugReport &)>;
731 const bool IsPrunable;
743 std::string Msg = Cb(BRC, R);
747 return std::move(Msg);
761 std::vector<std::unique_ptr<NoteTag>> Tags;
767 std::unique_ptr<NoteTag> T(
new NoteTag(std::move(Cb), IsPrunable));
768 Tags.push_back(std::move(T));
769 return Tags.back().get();
773 friend class TagVisitor;
780 #endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H GRBugReporter is used for generating path-sensitive reports.
BugReporter(BugReporterData &d)
ProgramStateManager & getStateManager() const
getStateManager - Return the state manager used by the analysis engine.
PathDiagnosticLocation UniqueingLocation
Reports with different uniqueing locations are considered to be different for the purposes of dedupli...
This wrapper is used to ensure that only StringRefs originating from the CheckerRegistry are used as ...
MemRegion - The root abstract class for all memory regions.
std::string getCallStackMessage(PathDiagnosticPieceRef Piece, const ExplodedNode *N) const
Produce the hint for the given node.
llvm::DenseMap< const MemRegion *, bugreporter::TrackingKind > InterestingRegions
A (stack of) set of regions that are registered with this report as being "interesting", and thus used to help decide which diagnostics to include when constructing the final path diagnostic.
void addFixItHint(const FixItHint &F)
Add a fix-it hint to the bug report.
visitor_iterator visitor_begin()
Iterators through the custom diagnostic visitors.
Stmt - This represents one statement.
PathSensitiveBugReporter(BugReporterData &d, ExprEngine &eng)
const NoteTag * makeNoteTag(Callback &&Cb, bool IsPrunable=false)
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const
StringRef getDescription() const
A verbose warning message that is appropriate for displaying next to the source code that introduces ...
PathSensitiveBugReport(const BugType &bt, StringRef desc, const ExplodedNode *errorNode)
ArrayRef< PathDiagnosticConsumer * > getPathDiagnosticConsumers()
Constructs a Stack hint for the given symbol.
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
virtual ~StackHintGenerator()=0
llvm::FoldingSet< BugReporterVisitor > CallbacksSet
Used for ensuring the visitors are only added once.
SmallVector< SourceRange, 4 > Ranges
virtual AnalyzerOptions & getAnalyzerOptions()=0
llvm::SmallSet< InvalidationRecord, 4 > Invalidations
If non-empty, this bug report is likely a false positive and should not be shown to the user...
llvm::DenseMap< PathDiagnosticConsumer *, std::unique_ptr< PathDiagnostic > > DiagnosticForConsumerMapTy
A mapping from diagnostic consumers to the diagnostics they should consume.
const Decl * getDeclWithIssue() const override
The smallest declaration that contains the bug location.
const Decl * getUniqueingDecl() const override
Get the declaration that corresponds to (usually contains) the uniqueing location.
void addRange(SourceRange R)
Add a range to a bug report.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
std::function< std::string(BugReporterContext &, BugReport &)> Callback
std::string ShortDescription
const ExplodedNode * getErrorNode() const
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
const BugType & getBugType() const
virtual std::string getMessageForReturn(const CallExpr *CallExpr)
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
ASTContext & getContext()
BugReport(Kind kind, const BugType &bt, StringRef desc)
bool shouldPrunePath() const
Indicates whether or not any path pruning should take place when generating a PathDiagnostic from thi...
static bool classof(const BugReport *R)
void Profile(llvm::FoldingSetNodeID &ID) const
std::pair< const void *, const void * > InvalidationRecord
Used to track unique reasons why a bug report might be invalid.
static bool classof(const ProgramPointTag *T)
BugReportEquivClass(std::unique_ptr< BugReport > R)
void disablePathPruning()
Disable all path pruning when generating a PathDiagnostic.
PathSensitiveBugReport(const BugType &bt, StringRef shortDesc, StringRef desc, const ExplodedNode *errorNode)
This represents one expression.
bool isValid() const
Returns whether or not this report should be considered valid.
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 SourceManager & getSourceManager()=0
static bool classof(const BugReport *R)
PathDiagnosticLocation getUniqueingLocation() const override
Get the location on which the report should be uniqued.
virtual ArrayRef< SourceRange > getRanges() const
Get the SourceRanges associated with the report.
PathDiagnosticLocation getUniqueingLocation() const override
Get the location on which the report should be uniqued.
PathSensitiveBugReport(const BugType &bt, StringRef desc, const ExplodedNode *errorNode, PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique)
Create a PathSensitiveBugReport with a custom uniqueing location.
virtual std::string getMessageForSymbolNotFound()
PathDiagnosticLocation getLocation() const override
The primary location of the bug report that points at the undesirable behavior in the code...
Interface for classes constructing Stack hints.
llvm::SmallSet< const LocationContext *, 2 > InterestingLocationContexts
A set of location contexts that correspoind to call sites which should be considered "interesting"...
BugReporterContext(PathSensitiveBugReporter &br)
The tag upon which the TagVisitor reacts.
virtual ArrayRef< PathDiagnosticConsumer * > getPathDiagnosticConsumers()=0
VisitorList Callbacks
A set of custom visitors which generate "event" diagnostics at interesting points in the path...
PathSensitiveBugReporter & getBugReporter()
const SourceManager & getSourceManager() const
BugReporter is a utility class for generating PathDiagnostics for analysis.
EQClasses_iterator EQClasses_begin()
llvm::SmallSet< const ExplodedNode *, 4 > TrackedConditions
Conditions we're already tracking.
const Decl * getUniqueingDecl() const override
Get the declaration containing the uniqueing location.
ProgramPoints can be "tagged" as representing points specific to a given analysis entity...
visitor_iterator visitor_end()
const AnalyzerOptions & getAnalyzerOptions() const
BasicBugReport(const BugType &bt, StringRef desc, PathDiagnosticLocation l)
llvm::DenseMap< SymbolRef, bugreporter::TrackingKind > InterestingSymbols
Profile to identify equivalent bug reports for error report coalescing.
bool addTrackedCondition(const ExplodedNode *Cond)
Notes that the condition of the CFGBlock associated with Cond is being tracked.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
VisitorList::iterator visitor_iterator
void addCallStackHint(PathDiagnosticPieceRef Piece, std::unique_ptr< StackHintGenerator > StackHint)
Dataflow Directional Tag Classes.
ProgramStateManager & getStateManager() const
bool hasCallStackHint(PathDiagnosticPieceRef Piece) const
Optional< std::string > generateMessage(BugReporterContext &BRC, BugReport &R) const
StringRef getTagDescription() const override
virtual std::string getMessage(const ExplodedNode *N)=0
Construct the Diagnostic message for the given ExplodedNode.
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...
const AnalyzerOptions & getAnalyzerOptions()
const Decl * UniqueingDecl
llvm::ArrayRef< FixItHint > getFixits() const
EQClasses_iterator EQClasses_end()
StringRef getShortDescription(bool UseFallback=true) const
A short general warning message that is appropriate for displaying in the list of all reported bugs...
llvm::FoldingSet< BugReportEquivClass >::iterator EQClasses_iterator
Iterator over the set of BugReports tracked by the BugReporter.
Stores options for the analyzer from the command line.
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...
SmallVector< std::shared_ptr< PathDiagnosticNotePiece >, 4 > Notes
SmallVector< FixItHint, 4 > Fixits
Defines the clang::SourceLocation class and associated facilities.
ArrayRef< std::unique_ptr< BugReport > > getReports() const
llvm::iterator_range< visitor_iterator > visitor_range
BugReport(Kind K, const BugType &BT, StringRef ShortDescription, StringRef Description)
unsigned kind
All of the diagnostics that can be emitted by the frontend.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
ArrayRef< std::shared_ptr< PathDiagnosticNotePiece > > getNotes()
A trivial tuple used to represent a source range.
This class provides an interface through which checkers can create individual bug reports...
StackHintGeneratorForSymbol(SymbolRef S, StringRef M)
This class handles loading and caching of source files into memory.
const void * getTagKind() const
Used to implement 'isKind' in subclasses.
virtual ASTContext & getASTContext()=0
const SourceManager & getSourceManager()
bool EQ(InterpState &S, CodePtr OpPC)
void setDeclWithIssue(const Decl *declWithIssue)
Specifically set the Decl where an issue occurred.
const SourceRange ErrorNodeRange
The range that corresponds to ErrorNode's program point.