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()) {
188 : K(SingleLocK), S(nullptr), D(nullptr), SM(&sm), Loc(loc, sm),
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) {}
339 enum Kind { ControlFlow, Event, Macro, Call, Note };
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(); }
388 virtual void flattenLocations() = 0;
407 virtual void Profile(llvm::FoldingSetNodeID &
ID)
const;
410 LastInMainSourceFile =
true;
414 return LastInMainSourceFile;
417 virtual void dump()
const = 0;
420 class PathPieces :
public std::list<std::shared_ptr<PathDiagnosticPiece>> {
422 bool ShouldFlattenMacros)
const;
427 flattenTo(Result, Result, ShouldFlattenMacros);
441 bool addPosRange =
true)
444 "PathDiagnosticSpotPiece's must have a valid location.");
451 void Profile(llvm::FoldingSetNodeID &
ID)
const override;
468 virtual std::string getMessage(
const ExplodedNode *N) = 0;
492 virtual std::string getMessageForArg(
const Expr *ArgE,
unsigned ArgIndex);
508 std::unique_ptr<StackHintGenerator> CallStackHint;
512 StringRef s,
bool addPosRange =
true,
515 CallStackHint(stackHint) {}
523 if (IsPrunable.hasValue() && !
override)
525 IsPrunable = isPrunable;
530 return IsPrunable.hasValue() ? IsPrunable.getValue() :
false;
539 return CallStackHint->getMessage(N);
543 void dump()
const override;
554 NoExit(
false), IsCalleeAnAutosynthesizedPropertyAccessor(
false),
555 callReturn(callReturnPos) {}
559 NoExit(
true), IsCalleeAnAutosynthesizedPropertyAccessor(
false),
571 bool IsCalleeAnAutosynthesizedPropertyAccessor;
575 std::string CallStackMessage;
592 CallStackMessage = st;
599 std::shared_ptr<PathDiagnosticEventPiece> getCallEnterEvent()
const;
600 std::shared_ptr<PathDiagnosticEventPiece>
601 getCallEnterWithinCallerEvent()
const;
602 std::shared_ptr<PathDiagnosticEventPiece> getCallExitEvent()
const;
607 for (PathPieces::iterator I = path.begin(),
608 E = path.end(); I != E; ++I) (*I)->flattenLocations();
611 static std::shared_ptr<PathDiagnosticCallPiece>
618 void dump()
const override;
620 void Profile(llvm::FoldingSetNodeID &
ID)
const override;
628 std::vector<PathDiagnosticLocationPair> LPairs;
646 assert(!LPairs.empty() &&
647 "PathDiagnosticControlFlowPiece needs at least one location.");
648 return LPairs[0].getStart();
652 assert(!LPairs.empty() &&
653 "PathDiagnosticControlFlowPiece needs at least one location.");
654 return LPairs[0].getEnd();
658 LPairs[0].setStart(L);
668 return getStartLocation();
671 typedef std::vector<PathDiagnosticLocationPair>::iterator
iterator;
672 iterator
begin() {
return LPairs.begin(); }
673 iterator
end() {
return LPairs.end(); }
676 for (iterator I=begin(), E=end(); I!=E; ++I) I->flatten();
679 typedef std::vector<PathDiagnosticLocationPair>::const_iterator
685 return P->
getKind() == ControlFlow;
688 void dump()
const override;
690 void Profile(llvm::FoldingSetNodeID &
ID)
const override;
702 bool containsEvent()
const;
706 for (PathPieces::iterator I = subPieces.begin(),
707 E = subPieces.end(); I != E; ++I) (*I)->flattenLocations();
714 void dump()
const override;
716 void Profile(llvm::FoldingSetNodeID &
ID)
const override;
722 bool AddPosRange =
true)
731 void dump()
const override;
733 void Profile(llvm::FoldingSetNodeID &
ID)
const override;
741 const Decl *DeclWithIssue;
743 std::string VerboseDesc;
744 std::string ShortDesc;
746 std::deque<std::string> OtherDesc;
757 const Decl *UniqueingDecl;
762 StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,
764 const Decl *DeclToUnique);
773 if (pathStack.empty())
775 return *pathStack.back();
784 unsigned full_size();
792 assert(!Loc.
isValid() &&
"End location already set!");
793 Loc = EndPiece->getLocation();
794 assert(Loc.isValid() &&
"Invalid location for end-of-path piece");
795 getActivePath().push_back(std::move(EndPiece));
799 if (!ShortDesc.empty())
813 void resetDiagnosticLocationToMainFile();
817 return ShortDesc.empty() ? VerboseDesc : ShortDesc;
829 meta_iterator
meta_begin()
const {
return OtherDesc.begin(); }
830 meta_iterator
meta_end()
const {
return OtherDesc.end(); }
831 void addMeta(StringRef s) { OtherDesc.push_back(s); }
834 assert(Loc.
isValid() &&
"No report location set yet!");
845 return UniqueingDecl;
850 for (PathPieces::iterator I = pathImpl.begin(), E = pathImpl.end();
851 I != E; ++I) (*I)->flattenLocations();
858 void Profile(llvm::FoldingSetNodeID &
ID)
const;
864 void FullProfile(llvm::FoldingSetNodeID &ID)
const;
bool isLastInMainSourceFile() const
PathDiagnosticSpotPiece(const PathDiagnosticLocation &pos, StringRef s, PathDiagnosticPiece::Kind k, bool addPosRange=true)
virtual void FlushDiagnosticsImpl(std::vector< const PathDiagnostic *> &Diags, FilesMade *filesMade)=0
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
std::deque< std::string >::const_iterator meta_iterator
const SymExpr * SymbolRef
Stmt - This represents one statement.
Decl - This represents one declaration (or definition), e.g.
virtual StringRef getName() const =0
Represents a point when we begin processing an inlined call.
Constructs a Stack hint for the given symbol.
void Profile(llvm::FoldingSetNodeID &ID) const
PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos)
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
void setPrunable(bool isPrunable, bool override=false)
Mark the diagnostic piece as being potentially prunable.
void flattenLocations() override
PathDiagnosticLocation getStartLocation() const
const PathDiagnosticLocation & getEnd() const
bool operator==(const PathDiagnosticLocation &X) const
void setAsLastInMainSourceFile()
meta_iterator meta_begin() const
void addRange(SourceRange R)
PathDiagnosticLocation getLocation() const
PathDiagnostic - PathDiagnostic objects represent a single path-sensitive diagnostic.
PathDiagnosticNotePiece(const PathDiagnosticLocation &Pos, StringRef S, bool AddPosRange=true)
void setStartLocation(const PathDiagnosticLocation &L)
void addRange(SourceLocation B, SourceLocation E)
AnalysisDeclContext contains the context data for the function or method under analysis.
static bool classof(const PathDiagnosticPiece *P)
StringRef getVerboseDescription() const
void pushActivePath(PathPieces *p)
virtual ~PathDiagnosticConsumer()
std::vector< PathDiagnosticLocationPair >::iterator iterator
virtual bool supportsLogicalOpControlFlow() const
PathPieces & getMutablePieces()
Return a mutable version of 'path'.
const Decl * asDecl() const
PDFileEntry(llvm::FoldingSetNodeID &NodeID)
const_iterator begin() const
llvm::FoldingSet< PathDiagnostic > Diags
void setStart(const PathDiagnosticLocation &L)
std::vector< PathDiagnosticLocationPair >::const_iterator const_iterator
const Stmt * asStmt() const
virtual std::string getMessageForReturn(const CallExpr *CallExpr)
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
bool operator!=(const PathDiagnosticLocation &X) const
A builtin binary operation expression such as "x + y" or "x <= y".
StringRef getBugType() const
meta_iterator meta_end() const
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
StringRef getCheckName() const
PathDiagnosticLocation callEnter
PathDiagnosticLocation(const Stmt *s, const SourceManager &sm, LocationOrAnalysisDeclContext lac)
Create a location corresponding to the given statement.
PathDiagnosticLocation getEndLocation() const
ConditionalOperator - The ?: ternary operator.
CompoundStmt - This represents a group of statements like { stmt stmt }.
const void * getTag() const
Return the opaque tag (if any) on the PathDiagnosticPiece.
void HandlePathDiagnostic(std::unique_ptr< PathDiagnostic > D)
Represents a point when we finish the call exit sequence (for inlined call).
DisplayHint getDisplayHint() const
getDisplayHint - Return a hint indicating where the diagnostic should be displayed by the PathDiagnos...
Expr - This represents one expression.
bool isPrunable() const
Return true if the diagnostic piece is prunable.
PathDiagnosticLocation getUniqueingLoc() const
Get the location on which the report should be uniqued.
const SourceManager & getManager() const
const_iterator end() const
PathDiagnosticRange(SourceRange R, bool isP=false)
virtual std::string getMessageForSymbolNotFound()
std::vector< std::pair< StringRef, StringRef > > ConsumerFiles
Interface for classes constructing Stack hints.
PathPieces flatten(bool ShouldFlattenMacros) const
StringRef getCategory() const
llvm::PointerUnion< const LocationContext *, AnalysisDeclContext * > LocationOrAnalysisDeclContext
const Decl * getCallee() const
const llvm::FoldingSetNodeID NodeID
A precomputed hash tag used for uniquing PDFileEntry objects.
void flattenLocations() override
void Profile(llvm::FoldingSetNodeID &ID) const
Encodes a location in the source.
std::string getCallStackMessage(const ExplodedNode *N)
Produce the hint for the given node.
void addMeta(StringRef s)
PathDiagnosticLocation callReturn
FullSourceLoc asLocation() const
virtual bool supportsCrossFileDiagnostics() const
Return true if the PathDiagnosticConsumer supports individual PathDiagnostics that span multiple file...
PathDiagnosticLocation getLocation() const override
void flattenLocations() override
ConsumerFiles files
A vector of <consumer,file> pairs.
ArrayRef< SourceRange > getRanges() const
Return the SourceRanges associated with this PathDiagnosticPiece.
Dataflow Directional Tag Classes.
const PathDiagnosticLocation & getStart() const
bool isValid() const
Return true if this is a valid SourceLocation object.
PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, const PathDiagnosticLocation &endPos)
void FlushDiagnostics(FilesMade *FilesMade)
PathDiagnosticRange asRange() const
std::unique_ptr< DiagnosticConsumer > create(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords=false)
Returns a DiagnosticConsumer that serializes diagnostics to a bitcode file.
PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, StringRef s, bool addPosRange=true, StackHintGenerator *stackHint=nullptr)
void setEndLocation(const PathDiagnosticLocation &L)
PathDiagnosticLocationPair(const PathDiagnosticLocation &start, const PathDiagnosticLocation &end)
bool isWithinCall() const
void appendToDesc(StringRef S)
virtual PathGenerationScheme getGenerationScheme() const
~StackHintGeneratorForSymbol() override
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)
void push_back(const PathDiagnosticLocationPair &X)
static bool classof(const PathDiagnosticPiece *P)
void Profile(llvm::FoldingSetNodeID &ID)
Used for profiling in the FoldingSet.
PathDiagnosticLocation getLocation() const override
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
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.
const Decl * getCaller() const
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
StringRef getTagStr() const
Return the string representation of the tag.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
A SourceLocation and its associated SourceManager.
PathDiagnosticLocation callEnterWithin
const Decl * getUniqueingDecl() const
Get the declaration containing the uniqueing location.
A trivial tuple used to represent a source range.
static bool classof(const PathDiagnosticPiece *P)
StackHintGeneratorForSymbol(SymbolRef S, StringRef M)
StringRef getString() const
This class handles loading and caching of source files into memory.
static bool classof(const PathDiagnosticPiece *P)
StringRef getShortDescription() const
const Decl * getDeclWithIssue() const
Return the semantic context where an issue occurred.
void setEnd(const PathDiagnosticLocation &L)
static bool classof(const PathDiagnosticPiece *P)