14 #ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H
15 #define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H
19 #include "llvm/ADT/FoldingSet.h"
20 #include "llvm/ADT/IntrusiveRefCntPtr.h"
21 #include "llvm/ADT/Optional.h"
22 #include "llvm/ADT/PointerUnion.h"
30 class ConditionalOperator;
31 class AnalysisDeclContext;
35 class LocationContext;
74 llvm::BumpPtrAllocator Alloc;
75 llvm::FoldingSet<PDFileEntry> Set;
80 bool empty()
const {
return Set.empty(); }
83 StringRef ConsumerName,
90 virtual void anchor();
98 FilesMade *filesMade) = 0;
100 virtual StringRef
getName()
const = 0;
114 llvm::FoldingSet<PathDiagnostic>
Diags;
131 typedef llvm::PointerUnion<const LocationContext*, AnalysisDeclContext*>
136 enum Kind { RangeK, SingleLocK, StmtK, DeclK } K;
145 : K(kind), S(
nullptr), D(
nullptr), SM(&sm),
146 Loc(genLocation(L)), Range(genRange()) {
159 : K(SingleLocK), S(nullptr), D(nullptr), SM(nullptr) {}
165 : K(s->getLocStart().
isValid() ? StmtK : SingleLocK),
166 S(K == StmtK ? s : nullptr),
169 Range(genRange(lac)) {
170 assert(K == SingleLocK || S);
171 assert(K == SingleLocK ||
Loc.isValid());
172 assert(K == SingleLocK || Range.
isValid());
177 : K(DeclK), S(nullptr), D(d), SM(&sm),
178 Loc(genLocation()), Range(genRange()) {
180 assert(
Loc.isValid());
188 : K(SingleLocK), S(nullptr), D(nullptr), SM(&sm),
Loc(loc, sm),
190 assert(
Loc.isValid());
264 return K == X.K &&
Loc == X.Loc && Range == X.Range;
268 return !(*
this ==
X);
272 return SM !=
nullptr;
286 bool hasRange()
const {
return K == StmtK || K == RangeK || K == DeclK; }
296 void Profile(llvm::FoldingSetNodeID &
ID)
const;
314 : Start(start), End(end) {}
343 const std::string str;
349 bool LastInMainSourceFile;
357 std::vector<SourceRange> ranges;
374 void setTag(
const char *tag) { Tag = tag; }
377 const void *
getTag()
const {
return Tag.data(); }
407 virtual void Profile(llvm::FoldingSetNodeID &
ID)
const;
410 LastInMainSourceFile =
true;
414 return LastInMainSourceFile;
417 virtual void dump()
const = 0;
421 class PathPieces :
public std::list<IntrusiveRefCntPtr<PathDiagnosticPiece> > {
423 bool ShouldFlattenMacros)
const;
428 flattenTo(Result, Result, ShouldFlattenMacros);
442 bool addPosRange =
true)
445 "PathDiagnosticSpotPiece's must have a valid location.");
452 void Profile(llvm::FoldingSetNodeID &
ID)
const override;
508 std::unique_ptr<StackHintGenerator> CallStackHint;
512 StringRef s,
bool addPosRange =
true,
515 CallStackHint(stackHint) {}
523 if (IsPrunable.hasValue() && !
override)
530 return IsPrunable.hasValue() ? IsPrunable.getValue() :
false;
539 return CallStackHint->getMessage(N);
543 void dump()
const override;
558 NoExit(
true),
path(oldPath) {}
569 std::string CallStackMessage;
586 CallStackMessage = st;
602 E =
path.end();
I !=
E; ++
I) (*I)->flattenLocations();
612 void dump()
const override;
614 void Profile(llvm::FoldingSetNodeID &
ID)
const override;
622 std::vector<PathDiagnosticLocationPair> LPairs;
640 assert(!LPairs.empty() &&
641 "PathDiagnosticControlFlowPiece needs at least one location.");
642 return LPairs[0].getStart();
646 assert(!LPairs.empty() &&
647 "PathDiagnosticControlFlowPiece needs at least one location.");
648 return LPairs[0].getEnd();
652 LPairs[0].setStart(L);
673 typedef std::vector<PathDiagnosticLocationPair>::const_iterator
682 void dump()
const override;
684 void Profile(llvm::FoldingSetNodeID &
ID)
const override;
708 void dump()
const override;
710 void Profile(llvm::FoldingSetNodeID &
ID)
const override;
718 const Decl *DeclWithIssue;
720 std::string VerboseDesc;
721 std::string ShortDesc;
722 std::string Category;
723 std::deque<std::string> OtherDesc;
734 const Decl *UniqueingDecl;
739 StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,
741 const Decl *DeclToUnique);
750 if (pathStack.empty())
752 return *pathStack.back();
769 assert(!
Loc.isValid() &&
"End location already set!");
770 Loc = EndPiece->getLocation();
771 assert(Loc.isValid() &&
"Invalid location for end-of-path piece");
776 if (!ShortDesc.empty())
794 return ShortDesc.empty() ? VerboseDesc : ShortDesc;
808 void addMeta(StringRef s) { OtherDesc.push_back(s); }
811 assert(
Loc.isValid() &&
"No report location set yet!");
822 return UniqueingDecl;
828 I !=
E; ++
I) (*I)->flattenLocations();
835 void Profile(llvm::FoldingSetNodeID &
ID)
const;
PathDiagnosticLocation getUniqueingLoc() const
Get the location on which the report should be uniqued.
PathDiagnosticSpotPiece(const PathDiagnosticLocation &pos, StringRef s, PathDiagnosticPiece::Kind k, bool addPosRange=true)
void setTag(const char *tag)
Tag this PathDiagnosticPiece with the given C-string.
PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, const PathDiagnosticLocation &endPos, StringRef s)
bool hasCallStackMessage()
PathDiagnosticLocation getLocation() const override
~PathDiagnosticMacroPiece() override
std::deque< std::string >::const_iterator meta_iterator
const SymExpr * SymbolRef
virtual StringRef getName() const =0
Represents a point when we begin processing an inlined call.
static PathDiagnosticLocation createBeginBrace(const CompoundStmt *CS, const SourceManager &SM)
Create a location for the beginning of the compound statement.
~PathDiagnosticEventPiece() override
PathPieces flatten(bool ShouldFlattenMacros) const
StringRef getCategory() const
Constructs a Stack hint for the given symbol.
const_iterator begin() const
virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex)
Produces the message of the following form: 'Msg via Nth parameter'.
PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos)
virtual ~StackHintGenerator()=0
void setPrunable(bool isPrunable, bool override=false)
Mark the diagnostic piece as being potentially prunable.
void flattenLocations() override
void dump() const override
static PathDiagnosticLocation createEndBrace(const CompoundStmt *CS, const SourceManager &SM)
Create a location for the end of the compound statement.
ArrayRef< SourceRange > getRanges() const
Return the SourceRanges associated with this PathDiagnosticPiece.
PathDiagnosticLocation getLocation() const
void setAsLastInMainSourceFile()
const Decl * getDeclWithIssue() const
Return the semantic context where an issue occurred.
static PathDiagnosticLocation createDeclEnd(const LocationContext *LC, const SourceManager &SM)
Constructs a location for the end of the enclosing declaration body.
~PathDiagnosticPiece() override
void addRange(SourceRange R)
static PathDiagnosticLocation createSingleLocation(const PathDiagnosticLocation &PDL)
Convert the given location into a single kind location.
FullSourceLoc asLocation() const
PathDiagnostic - PathDiagnostic objects represent a single path-sensitive diagnostic.
void setStartLocation(const PathDiagnosticLocation &L)
void addRange(SourceLocation B, SourceLocation E)
AnalysisDeclContext contains the context data for the function or method under analysis.
bool operator==(const PathDiagnosticLocation &X) const
StringRef getString() const
~PathDiagnosticControlFlowPiece() override
void pushActivePath(PathPieces *p)
bool containsEvent() const
virtual ~PathDiagnosticConsumer()
std::vector< PathDiagnosticLocationPair >::iterator iterator
PathPieces & getMutablePieces()
Return a mutable version of 'path'.
bool isPrunable() const
Return true if the diagnostic piece is prunable.
virtual void Profile(llvm::FoldingSetNodeID &ID) const
PDFileEntry(llvm::FoldingSetNodeID &NodeID)
llvm::FoldingSet< PathDiagnostic > Diags
void setStart(const PathDiagnosticLocation &L)
std::vector< PathDiagnosticLocationPair >::const_iterator const_iterator
virtual std::string getMessageForReturn(const CallExpr *CallExpr)
IntrusiveRefCntPtr< PathDiagnosticEventPiece > getCallExitEvent() const
const Decl * asDecl() const
A builtin binary operation expression such as "x + y" or "x <= y".
void dump() const override
std::string getMessage(const ExplodedNode *N) override
Search the call expression for the symbol Sym and dispatch the 'getMessageForX()' methods to construc...
static PathDiagnosticCallPiece * construct(const ExplodedNode *N, const CallExitEnd &CE, const SourceManager &SM)
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
const void * getTag() const
Return the opaque tag (if any) on the PathDiagnosticPiece.
meta_iterator meta_begin() const
PathDiagnosticLocation callEnter
PathDiagnosticLocation(const Stmt *s, const SourceManager &sm, LocationOrAnalysisDeclContext lac)
Create a location corresponding to the given statement.
detail::InMemoryDirectory::const_iterator I
virtual PathDiagnosticLocation getLocation() const =0
const_iterator end() const
const Stmt * asStmt() const
static PathDiagnosticLocation createMemberLoc(const MemberExpr *ME, const SourceManager &SM)
For member expressions, return the location of the '.
void Profile(llvm::FoldingSetNodeID &ID) const
ConditionalOperator - The ?: ternary operator.
CompoundStmt - This represents a group of statements like { stmt stmt }.
void HandlePathDiagnostic(std::unique_ptr< PathDiagnostic > D)
PDFileEntry::ConsumerFiles * getFiles(const PathDiagnostic &PD)
IntrusiveRefCntPtr< PathDiagnosticEventPiece > getCallEnterWithinCallerEvent() const
Represents a point when we finish the call exit sequence (for inlined call).
const Decl * getCallee() const
Expr - This represents one expression.
void FullProfile(llvm::FoldingSetNodeID &ID) const
Profiles the diagnostic, including its path.
StringRef getShortDescription() const
const SourceManager & getManager() const
PathDiagnosticLocation getEndLocation() const
IntrusiveRefCntPtr< PathDiagnosticEventPiece > getCallEnterEvent() const
static const Stmt * getNextStmt(const ExplodedNode *N)
Retrieve the statement corresponding to the successor node.
virtual bool supportsLogicalOpControlFlow() const
PathDiagnosticRange(SourceRange R, bool isP=false)
void resetDiagnosticLocationToMainFile()
If the last piece of the report point to the header file, resets the location of the report to be the...
virtual std::string getMessageForSymbolNotFound()
std::vector< std::pair< StringRef, StringRef > > ConsumerFiles
Interface for classes constructing Stack hints.
The result type of a method or function.
virtual bool supportsCrossFileDiagnostics() const
Return true if the PathDiagnosticConsumer supports individual PathDiagnostics that span multiple file...
PathDiagnosticLocation getStartLocation() const
llvm::PointerUnion< const LocationContext *, AnalysisDeclContext * > LocationOrAnalysisDeclContext
meta_iterator meta_end() const
static const Stmt * getStmt(const ExplodedNode *N)
Given an exploded node, retrieve the statement that should be used for the diagnostic location...
static PathDiagnosticLocation createDeclBegin(const LocationContext *LC, const SourceManager &SM)
Create a location for the beginning of the enclosing declaration body.
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
~PathDiagnosticCallPiece() override
const llvm::FoldingSetNodeID NodeID
A precomputed hash tag used for uniquing PDFileEntry objects.
void flattenLocations() override
virtual void FlushDiagnosticsImpl(std::vector< const PathDiagnostic * > &Diags, FilesMade *filesMade)=0
Encodes a location in the source.
const TemplateArgument * iterator
std::string getCallStackMessage(const ExplodedNode *N)
Produce the hint for the given node.
void addMeta(StringRef s)
virtual PathGenerationScheme getGenerationScheme() const
bool isValid() const
Return true if this is a valid SourceLocation object.
StringRef getVerboseDescription() const
virtual void flattenLocations()=0
PathDiagnosticLocation callReturn
void Profile(llvm::FoldingSetNodeID &ID) const
void setCallee(const CallEnter &CE, const SourceManager &SM)
static PathDiagnosticLocation createConditionalColonLoc(const ConditionalOperator *CO, const SourceManager &SM)
const PathDiagnosticLocation & getStart() const
static PathDiagnosticLocation createEnd(const Stmt *S, const SourceManager &SM, const LocationOrAnalysisDeclContext LAC)
Create a location for the end of the statement.
const Decl * getUniqueingDecl() const
Get the declaration containing the uniqueing location.
PathDiagnosticLocation getLocation() const override
void dump() const override
void flattenLocations() override
ConsumerFiles files
A vector of <consumer,file> pairs.
virtual void dump() const =0
PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, const PathDiagnosticLocation &endPos)
void FlushDiagnostics(FilesMade *FilesMade)
bool isLastInMainSourceFile() const
DisplayHint getDisplayHint() const
getDisplayHint - Return a hint indicating where the diagnostic should be displayed by the PathDiagnos...
detail::InMemoryDirectory::const_iterator E
PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, StringRef s, bool addPosRange=true, StackHintGenerator *stackHint=nullptr)
void Profile(llvm::FoldingSetNodeID &ID) const override
void setEndLocation(const PathDiagnosticLocation &L)
PathDiagnosticLocationPair(const PathDiagnosticLocation &start, const PathDiagnosticLocation &end)
void appendToDesc(StringRef S)
virtual std::string getMessage(const ExplodedNode *N)=0
Construct the Diagnostic message for the given ExplodedNode.
~StackHintGeneratorForSymbol() override
void Profile(llvm::FoldingSetNodeID &ID) const
Profiles the diagnostic, independent of the path it references.
void setEndOfPath(std::unique_ptr< PathDiagnosticPiece > EndPiece)
PathDiagnosticLocation(SourceLocation loc, const SourceManager &sm)
Create a location at an explicit offset in the source.
PathDiagnosticLocation(const Decl *d, const SourceManager &sm)
Create a location corresponding to the given declaration.
void setCallStackMessage(StringRef st)
const Decl * getCaller() const
void push_back(const PathDiagnosticLocationPair &X)
static bool classof(const PathDiagnosticPiece *P)
void Profile(llvm::FoldingSetNodeID &ID) const override
void Profile(llvm::FoldingSetNodeID &ID)
Used for profiling in the FoldingSet.
static PathDiagnosticLocation createOperatorLoc(const BinaryOperator *BO, const SourceManager &SM)
Create the location for the operator of the binary expression.
PathDiagnosticLocation getLocation() const override
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
PathDiagnosticRange asRange() const
StringRef getTagStr() const
Return the string representation of the tag.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Defines the clang::SourceLocation class and associated facilities.
PathPieces & getActivePath()
Return the path currently used by builders for constructing the PathDiagnostic.
void dump() const override
const PathDiagnosticLocation & getEnd() const
static PathDiagnosticLocation createEndOfPath(const ExplodedNode *N, const SourceManager &SM)
Create a location corresponding to the next valid ExplodedNode as end of path location.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
PathDiagnosticLocation()
Create an invalid location.
static bool classof(const PathDiagnosticPiece *P)
void flattenLocations() override
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
A SourceLocation and its associated SourceManager.
PathDiagnosticLocation callEnterWithin
void Profile(llvm::FoldingSetNodeID &ID) const override
StringRef getBugType() const
void addDiagnostic(const PathDiagnostic &PD, StringRef ConsumerName, StringRef fileName)
A trivial tuple used to represent a source range.
static bool classof(const PathDiagnosticPiece *P)
bool isWithinCall() const
StringRef getCheckName() const
StackHintGeneratorForSymbol(SymbolRef S, StringRef M)
bool operator!=(const PathDiagnosticLocation &X) const
This class handles loading and caching of source files into memory.
static bool classof(const PathDiagnosticPiece *P)
unsigned full_size()
Return the unrolled size of the path.
void Profile(llvm::FoldingSetNodeID &ID) const override
void setEnd(const PathDiagnosticLocation &L)
static bool classof(const PathDiagnosticPiece *P)