14 #ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H 15 #define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H 21 #include "llvm/ADT/ArrayRef.h" 22 #include "llvm/ADT/FoldingSet.h" 23 #include "llvm/ADT/Optional.h" 24 #include "llvm/ADT/PointerUnion.h" 25 #include "llvm/ADT/SmallVector.h" 26 #include "llvm/ADT/StringRef.h" 27 #include "llvm/Support/Allocator.h" 41 class AnalysisDeclContext;
46 class ConditionalOperator;
49 class LocationContext;
86 llvm::BumpPtrAllocator Alloc;
87 llvm::FoldingSet<PDFileEntry> Set;
92 bool empty()
const {
return Set.empty(); }
95 StringRef ConsumerName,
102 virtual void anchor();
111 FilesMade *filesMade) = 0;
113 virtual StringRef
getName()
const = 0;
137 llvm::FoldingSet<PathDiagnostic>
Diags;
146 bool isPoint =
false;
154 llvm::PointerUnion<const LocationContext *, AnalysisDeclContext *>;
158 enum Kind { RangeK, SingleLocK, StmtK, DeclK } K = SingleLocK;
160 const Stmt *S =
nullptr;
161 const Decl *D =
nullptr;
167 : K(kind),
SM(&sm), Loc(genLocation(L)), Range(genRange()) {}
183 : K(s->getBeginLoc().isValid() ? StmtK : SingleLocK),
184 S(K == StmtK ? s : nullptr), SM(&sm),
186 assert(K == SingleLocK || S);
187 assert(K == SingleLocK || Loc.
isValid());
188 assert(K == SingleLocK || Range.
isValid());
193 : K(DeclK), D(d), SM(&sm), Loc(genLocation()), Range(genRange()) {
203 : SM(&sm), Loc(loc, sm), Range(genRange()) {
224 return createBegin(D, SM);
287 return K == X.K && Loc == X.Loc && Range == X.Range;
291 return !(*
this ==
X);
295 return SM !=
nullptr;
315 bool hasRange()
const {
return K == StmtK || K == RangeK || K == DeclK; }
325 void Profile(llvm::FoldingSetNodeID &
ID)
const;
344 : Start(start), End(end) {}
369 enum Kind { ControlFlow, Event, Macro, Call, Note };
373 const std::string
str;
379 bool LastInMainSourceFile =
false;
387 std::vector<SourceRange> ranges;
402 void setTag(
const char *tag) { Tag = tag; }
405 const void *
getTag()
const {
return Tag.data(); }
416 virtual void flattenLocations() = 0;
435 virtual void Profile(llvm::FoldingSetNodeID &
ID)
const;
438 LastInMainSourceFile =
true;
442 return LastInMainSourceFile;
445 virtual void dump()
const = 0;
448 class PathPieces :
public std::list<std::shared_ptr<PathDiagnosticPiece>> {
450 bool ShouldFlattenMacros)
const;
455 flattenTo(Result, Result, ShouldFlattenMacros);
470 bool addPosRange =
true)
473 "PathDiagnosticSpotPiece's must have a valid location.");
480 void Profile(llvm::FoldingSetNodeID &
ID)
const override;
497 virtual std::string getMessage(
const ExplodedNode *N) = 0;
521 virtual std::string getMessageForArg(
const Expr *ArgE,
unsigned ArgIndex);
539 std::unique_ptr<StackHintGenerator> CallStackHint;
543 StringRef s,
bool addPosRange =
true,
546 CallStackHint(stackHint) {}
553 if (IsPrunable.hasValue() && !
override)
555 IsPrunable = isPrunable;
560 return IsPrunable.hasValue() ? IsPrunable.getValue() :
false;
569 return CallStackHint->getMessage(N);
573 void dump()
const override;
582 const Decl *Callee =
nullptr;
590 bool IsCalleeAnAutosynthesizedPropertyAccessor =
false;
594 std::string CallStackMessage;
599 callReturn(callReturnPos) {}
622 std::shared_ptr<PathDiagnosticEventPiece> getCallEnterEvent()
const;
623 std::shared_ptr<PathDiagnosticEventPiece>
624 getCallEnterWithinCallerEvent()
const;
625 std::shared_ptr<PathDiagnosticEventPiece> getCallExitEvent()
const;
630 for (
const auto &I : path)
631 I->flattenLocations();
634 static std::shared_ptr<PathDiagnosticCallPiece>
641 void dump()
const override;
643 void Profile(llvm::FoldingSetNodeID &
ID)
const override;
651 std::vector<PathDiagnosticLocationPair> LPairs;
670 assert(!LPairs.empty() &&
671 "PathDiagnosticControlFlowPiece needs at least one location.");
672 return LPairs[0].getStart();
676 assert(!LPairs.empty() &&
677 "PathDiagnosticControlFlowPiece needs at least one location.");
678 return LPairs[0].getEnd();
682 LPairs[0].setStart(L);
692 return getStartLocation();
695 using iterator = std::vector<PathDiagnosticLocationPair>::iterator;
701 for (
auto &I : *
this)
706 std::vector<PathDiagnosticLocationPair>::const_iterator;
712 return P->
getKind() == ControlFlow;
715 void dump()
const override;
717 void Profile(llvm::FoldingSetNodeID &
ID)
const override;
728 bool containsEvent()
const;
732 for (
const auto &I : subPieces)
733 I->flattenLocations();
740 void dump()
const override;
742 void Profile(llvm::FoldingSetNodeID &
ID)
const override;
748 bool AddPosRange =
true)
756 void dump()
const override;
758 void Profile(llvm::FoldingSetNodeID &
ID)
const override;
769 const Decl *DeclWithIssue;
771 std::string VerboseDesc;
772 std::string ShortDesc;
774 std::deque<std::string> OtherDesc;
785 const Decl *UniqueingDecl;
788 std::unique_ptr<FilesToLineNumsMap> ExecutedLines;
793 StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,
795 const Decl *DeclToUnique,
796 std::unique_ptr<FilesToLineNumsMap> ExecutedLines);
804 if (pathStack.empty())
806 return *pathStack.back();
815 unsigned full_size();
823 assert(!Loc.
isValid() &&
"End location already set!");
824 Loc = EndPiece->getLocation();
825 assert(Loc.isValid() &&
"Invalid location for end-of-path piece");
826 getActivePath().push_back(std::move(EndPiece));
830 if (!ShortDesc.empty())
838 void resetDiagnosticLocationToMainFile();
843 return ShortDesc.empty() ? VerboseDesc : ShortDesc;
859 void addMeta(StringRef s) { OtherDesc.push_back(s); }
862 return *ExecutedLines;
866 return *ExecutedLines;
880 return UniqueingDecl;
885 for (
const auto &I : pathImpl)
886 I->flattenLocations();
893 void Profile(llvm::FoldingSetNodeID &
ID)
const;
899 void FullProfile(llvm::FoldingSetNodeID &ID)
const;
906 #endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H
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
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
A Range represents the closed range [from, to].
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)
const FilesToLineNumsMap & getExecutedLines() const
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)
FilesToLineNumsMap & getExecutedLines()
virtual ~PathDiagnosticConsumer()
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)
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)
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
std::vector< std::pair< StringRef, StringRef > > ConsumerFiles
bool operator!=(const PathDiagnosticLocation &X) const
A builtin binary operation expression such as "x + y" or "x <= y".
StringRef getBugType() const
void setEndOfPath(std::shared_ptr< PathDiagnosticPiece > EndPiece)
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.
const Stmt * getStmtOrNull() const
void HandlePathDiagnostic(std::unique_ptr< PathDiagnostic > D)
std::vector< PathDiagnosticLocationPair >::const_iterator const_iterator
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...
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.
std::vector< PathDiagnosticLocationPair >::iterator iterator
const SourceManager & getManager() const
llvm::PointerUnion< const LocationContext *, AnalysisDeclContext * > LocationOrAnalysisDeclContext
const_iterator end() const
PathDiagnosticRange(SourceRange R, bool isP=false)
virtual std::string getMessageForSymbolNotFound()
Interface for classes constructing Stack hints.
std::map< FileID, std::set< unsigned > > FilesToLineNumsMap
File IDs mapped to sets of line numbers.
PathPieces flatten(bool ShouldFlattenMacros) const
StringRef getCategory() const
Only runs visitors, no output generated.
PathDiagnosticConsumer()=default
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
std::deque< std::string >::const_iterator meta_iterator
FullSourceLoc asLocation() const
virtual bool supportsCrossFileDiagnostics() const
Return true if the PathDiagnosticConsumer supports individual PathDiagnostics that span multiple file...
PathDiagnosticLocation getLocation() const override
Used for plist output, used for "arrows" generation.
void flattenLocations() override
ConsumerFiles files
A vector of <consumer,file> pairs.
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM, const LocationOrAnalysisDeclContext LAC)
Create a location for the beginning of the declaration.
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
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 ...
Used for HTML, SARIF, and text output.
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.
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)