13 #ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H 14 #define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H 20 #include "llvm/ADT/ArrayRef.h" 21 #include "llvm/ADT/FoldingSet.h" 22 #include "llvm/ADT/Optional.h" 23 #include "llvm/ADT/PointerUnion.h" 24 #include "llvm/ADT/SmallVector.h" 25 #include "llvm/ADT/StringRef.h" 26 #include "llvm/Support/Allocator.h" 40 class AnalysisDeclContext;
45 class ConditionalOperator;
48 class LocationContext;
80 llvm::BumpPtrAllocator Alloc;
81 llvm::FoldingSet<PDFileEntry> Set;
86 bool empty()
const {
return Set.empty(); }
89 StringRef ConsumerName,
96 virtual void anchor();
105 FilesMade *filesMade) = 0;
107 virtual StringRef
getName()
const = 0;
138 llvm::FoldingSet<PathDiagnostic>
Diags;
147 bool isPoint =
false;
155 llvm::PointerUnion<const LocationContext *, AnalysisDeclContext *>;
159 enum Kind { RangeK, SingleLocK, StmtK, DeclK } K = SingleLocK;
161 const Stmt *S =
nullptr;
162 const Decl *D =
nullptr;
168 : K(kind),
SM(&sm), Loc(genLocation(L)), Range(genRange()) {}
184 : K(s->getBeginLoc().isValid() ? StmtK : SingleLocK),
185 S(K == StmtK ? s : nullptr), SM(&sm),
187 assert(K == SingleLocK || S);
188 assert(K == SingleLocK || Loc.
isValid());
189 assert(K == SingleLocK || Range.
isValid());
194 : K(DeclK), D(d), SM(&sm), Loc(genLocation()), Range(genRange()) {
204 : SM(&sm), Loc(loc, sm), Range(genRange()) {
225 return createBegin(D, SM);
287 bool UseEndOfStatement =
false);
290 return K == X.K && Loc == X.Loc && Range == X.Range;
294 return !(*
this ==
X);
298 return SM !=
nullptr;
318 bool hasRange()
const {
return K == StmtK || K == RangeK || K == DeclK; }
330 void Profile(llvm::FoldingSetNodeID &
ID)
const;
342 : Start(start), End(end) {}
367 enum Kind { ControlFlow, Event, Macro, Call, Note, PopUp };
371 const std::string str;
377 bool LastInMainSourceFile =
false;
385 std::vector<SourceRange> ranges;
386 std::vector<FixItHint> fixits;
401 void setTag(
const char *tag) { Tag = tag; }
404 const void *
getTag()
const {
return Tag.data(); }
415 virtual void flattenLocations() = 0;
441 virtual void Profile(llvm::FoldingSetNodeID &
ID)
const;
444 LastInMainSourceFile =
true;
448 return LastInMainSourceFile;
451 virtual void dump()
const = 0;
456 class PathPieces :
public std::list<PathDiagnosticPieceRef> {
458 bool ShouldFlattenMacros)
const;
463 flattenTo(Result, Result, ShouldFlattenMacros);
478 bool addPosRange =
true)
481 "PathDiagnosticSpotPiece's must have a valid location.");
488 void Profile(llvm::FoldingSetNodeID &
ID)
const override;
501 StringRef s,
bool addPosRange =
true)
509 if (IsPrunable.hasValue() && !
override)
511 IsPrunable = isPrunable;
516 return IsPrunable.hasValue() ? IsPrunable.getValue() :
false;
519 void dump()
const override;
528 const Decl *Callee =
nullptr;
536 bool IsCalleeAnAutosynthesizedPropertyAccessor =
false;
540 std::string CallStackMessage;
545 callReturn(callReturnPos) {}
568 std::shared_ptr<PathDiagnosticEventPiece> getCallEnterEvent()
const;
569 std::shared_ptr<PathDiagnosticEventPiece>
570 getCallEnterWithinCallerEvent()
const;
571 std::shared_ptr<PathDiagnosticEventPiece> getCallExitEvent()
const;
576 for (
const auto &I : path)
577 I->flattenLocations();
580 static std::shared_ptr<PathDiagnosticCallPiece>
587 void dump()
const override;
589 void Profile(llvm::FoldingSetNodeID &
ID)
const override;
597 std::vector<PathDiagnosticLocationPair> LPairs;
616 assert(!LPairs.empty() &&
617 "PathDiagnosticControlFlowPiece needs at least one location.");
618 return LPairs[0].getStart();
622 assert(!LPairs.empty() &&
623 "PathDiagnosticControlFlowPiece needs at least one location.");
624 return LPairs[0].getEnd();
628 LPairs[0].setStart(L);
638 return getStartLocation();
641 using iterator = std::vector<PathDiagnosticLocationPair>::iterator;
647 for (
auto &I : *
this)
652 std::vector<PathDiagnosticLocationPair>::const_iterator;
658 return P->
getKind() == ControlFlow;
661 void dump()
const override;
663 void Profile(llvm::FoldingSetNodeID &
ID)
const override;
676 for (
const auto &I : subPieces)
677 I->flattenLocations();
684 void dump()
const override;
686 void Profile(llvm::FoldingSetNodeID &
ID)
const override;
692 bool AddPosRange =
true)
700 void dump()
const override;
702 void Profile(llvm::FoldingSetNodeID &
ID)
const override;
708 bool AddPosRange =
true)
716 void dump()
const override;
718 void Profile(llvm::FoldingSetNodeID &
ID)
const override;
728 std::string CheckerName;
729 const Decl *DeclWithIssue;
731 std::string VerboseDesc;
732 std::string ShortDesc;
734 std::deque<std::string> OtherDesc;
745 const Decl *UniqueingDecl;
748 std::unique_ptr<FilesToLineNumsMap> ExecutedLines;
753 StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,
755 const Decl *DeclToUnique,
756 std::unique_ptr<FilesToLineNumsMap> ExecutedLines);
764 if (pathStack.empty())
766 return *pathStack.back();
775 unsigned full_size();
783 assert(!Loc.
isValid() &&
"End location already set!");
784 Loc = EndPiece->getLocation();
785 assert(Loc.isValid() &&
"Invalid location for end-of-path piece");
786 getActivePath().push_back(std::move(EndPiece));
790 if (!ShortDesc.empty())
798 return ShortDesc.empty() ? VerboseDesc : ShortDesc;
809 void addMeta(StringRef s) { OtherDesc.push_back(s); }
812 return *ExecutedLines;
816 return *ExecutedLines;
843 return UniqueingDecl;
848 for (
const auto &I : pathImpl)
849 I->flattenLocations();
856 void Profile(llvm::FoldingSetNodeID &
ID)
const;
862 void FullProfile(llvm::FoldingSetNodeID &ID)
const;
868 #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.
void setLocation(PathDiagnosticLocation NewLoc)
Decl - This represents one declaration (or definition), e.g.
virtual StringRef getName() const =0
Represents a point when we begin processing an inlined call.
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'.
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
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
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
meta_iterator meta_end() const
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
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...
bool isPrunable() const
Return true if the diagnostic piece is prunable.
StringRef getCheckerName() const
PathDiagnosticLocation getUniqueingLoc() const
Get the location on which the report should be uniqued.
const SourceManager & getManager() const
llvm::PointerUnion< const LocationContext *, AnalysisDeclContext * > LocationOrAnalysisDeclContext
const_iterator end() const
PathDiagnosticRange(SourceRange R, bool isP=false)
std::map< FileID, std::set< unsigned > > FilesToLineNumsMap
File IDs mapped to sets of line numbers.
PathPieces flatten(bool ShouldFlattenMacros) const
void addFixit(FixItHint F)
StringRef getCategory() const
Only runs visitors, no output generated.
PathDiagnosticConsumer()=default
PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, StringRef s, bool addPosRange=true)
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.
void addMeta(StringRef s)
PathDiagnosticLocation callReturn
std::deque< std::string >::const_iterator meta_iterator
bool shouldAddPathEdges() const
void setEndOfPath(PathDiagnosticPieceRef EndPiece)
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.
bool hasValidLocation() const
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.
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)
ArrayRef< FixItHint > getFixits() const
Return the fix-it hints associated with this PathDiagnosticPiece.
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.
A SourceLocation and its associated SourceManager.
PathDiagnosticLocation callEnterWithin
const Decl * getUniqueingDecl() const
Get the declaration containing the uniqueing location.
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
A trivial tuple used to represent a source range.
void setDeclWithIssue(const Decl *D)
static bool classof(const PathDiagnosticPiece *P)
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.
bool shouldGenerateDiagnostics() const
void setEnd(const PathDiagnosticLocation &L)
static bool classof(const PathDiagnosticPiece *P)