clang: include/clang/Analysis/PathDiagnostic.h Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13#ifndef LLVM_CLANG_ANALYSIS_PATHDIAGNOSTIC_H
14#define LLVM_CLANG_ANALYSIS_PATHDIAGNOSTIC_H
15
20#include "llvm/ADT/ArrayRef.h"
21#include "llvm/ADT/FoldingSet.h"
22#include "llvm/ADT/PointerUnion.h"
23#include "llvm/ADT/SmallVector.h"
24#include "llvm/ADT/StringRef.h"
25#include "llvm/Support/Allocator.h"
26#include
27#include
28#include
29#include
30#include
31#include
32#include
33#include
34#include
35#include
36#include
37
39
40class AnalysisDeclContext;
41class BinaryOperator;
42class CallEnter;
43class CallExitEnd;
44class ConditionalOperator;
46class LocationContext;
47class MemberExpr;
48class ProgramPoint;
49class SourceManager;
50
51namespace ento {
52
53
54
55
56
57class PathDiagnostic;
58
59
60
62
63
65
66
67
68
70
71
72
74
75
76
78
79
80
82
83
84
86
87
88
90};
91
93public:
95 public:
97
98 using ConsumerFiles = std::vector<std::pair<StringRef, StringRef>>;
99
100
102
103
104 const llvm::FoldingSetNodeID NodeID;
105
106
108 };
109
111 llvm::BumpPtrAllocator Alloc;
112 llvm::FoldingSet Set;
113
114 public:
116
117 bool empty() const { return Set.empty(); }
118
120 StringRef ConsumerName,
121 StringRef fileName);
122
124 };
125
126private:
127 virtual void anchor();
128
129public:
132
134
137
138 virtual StringRef getName() const = 0;
139
141
143
145
146
148
149
151
152
155
157
160 }
161
166 }
167
169
170
171
173
174protected:
177};
178
179
180
181
182
184public:
186
190};
191
193 llvm::PointerUnion<const LocationContext *, AnalysisDeclContext *>;
194
196private:
197 enum Kind { RangeK, SingleLocK, StmtK, DeclK } K = SingleLocK;
198
199 const Stmt *S = nullptr;
200 const Decl *D = nullptr;
204
206 : K(kind), SM(&sm), Loc(genLocation(L)), Range(genRange()) {}
207
211
214
215public:
216
218
219
222 : K(s->getBeginLoc().isValid() ? StmtK : SingleLocK),
223 S(K == StmtK ? s : nullptr), SM(&sm),
225 assert(K == SingleLocK || S);
226 assert(K == SingleLocK || Loc.isValid());
227 assert(K == SingleLocK || Range.isValid());
228 }
229
230
232 : K(DeclK), D(d), SM(&sm), Loc(genLocation()), Range(genRange()) {
233 assert(D);
235 assert(Range.isValid());
236 }
237
238
239
240
242 : SM(&sm), Loc(loc, sm), Range(genRange()) {
244 assert(Range.isValid());
245 }
246
247
251 }
252
253
256
257
258
259
264 }
265
266
270
271
272
273
274
278
279
280
286
287
288
291
292
293
296
297
298
301
302
303
306
307
308
311
312
315
316
319
320
321
322
325 bool UseEndOfStatement = false);
326
328 return K == X.K && Loc == X.Loc && Range == X.Range;
329 }
330
332 return !(*this == X);
333 }
334
336 return SM != nullptr;
337 }
338
340 return Loc;
341 }
342
345 }
346
350 return nullptr;
352 }
353
355
356 bool hasRange() const { return K == StmtK || K == RangeK || K == DeclK; }
357
359
362 }
363
365
367
368 void Profile(llvm::FoldingSetNodeID &ID) const;
369
370 void dump() const;
371};
372
374private:
376
377public:
380 : Start(start), End(end) {}
381
384
387
390 End.flatten();
391 }
392
393 void Profile(llvm::FoldingSetNodeID &ID) const {
395 End.Profile(ID);
396 }
397};
398
399
400
401
402
404public:
407
408private:
409 const std::string str;
410 const Kind kind;
412
413
414
415 bool LastInMainSourceFile = false;
416
417
418
419
420
421 StringRef Tag;
422
423 std::vector ranges;
424 std::vector fixits;
425
426protected:
429
430public:
435
437
438
439 void setTag(const char *tag) { Tag = tag; }
440
441
442 const void *getTag() const { return Tag.data(); }
443
444
445
447
448
449
451
454
456
459 return;
460 ranges.push_back(R);
461 }
462
464 if (!B.isValid() || .isValid())
465 return;
467 }
468
470 fixits.push_back(F);
471 }
472
473
475
476
478
479 virtual void Profile(llvm::FoldingSetNodeID &ID) const;
480
482 LastInMainSourceFile = true;
483 }
484
486 return LastInMainSourceFile;
487 }
488
489 virtual void dump() const = 0;
490};
491
493
494class PathPieces : public std::list {
496 bool ShouldFlattenMacros) const;
497
498public:
501 flattenTo(Result, Result, ShouldFlattenMacros);
503 }
504
505 void dump() const;
506};
507
509private:
511
512public:
514 StringRef s,
516 bool addPosRange = true)
519 "PathDiagnosticSpotPiece's must have a valid location.");
521 }
522
525
526 void Profile(llvm::FoldingSetNodeID &ID) const override;
527
529 return P->getKind() == Event || P->getKind() == Macro ||
530 P->getKind() == Note || P->getKind() == PopUp;
531 }
532};
533
535 std::optional IsPrunable;
536
537public:
539 StringRef s, bool addPosRange = true)
542
543
544
545
547 if (IsPrunable && !override)
548 return;
550 }
551
552
553 bool isPrunable() const { return IsPrunable.value_or(false); }
554
555 void dump() const override;
556
558 return P->getKind() == Event;
559 }
560};
561
563 const Decl *Caller;
564 const Decl *Callee = nullptr;
565
566
567
568 bool NoExit;
569
570
571
572 bool IsCalleeAnAutosynthesizedPropertyAccessor = false;
573
574
575
576 std::string CallStackMessage;
577
584 path(oldPath) {}
585
586public:
591
593
595
598
601
603
604 std::shared_ptr getCallEnterEvent() const;
605 std::shared_ptr
607 std::shared_ptr getCallExitEvent() const;
608
612 for (const auto &I : path)
613 I->flattenLocations();
614 }
615
616 static std::shared_ptr
619
621 const Decl *caller);
622
623 void dump() const override;
624
625 void Profile(llvm::FoldingSetNodeID &ID) const override;
626
628 return P->getKind() == Call;
629 }
630};
631
633 std::vector LPairs;
634
635public:
638 StringRef s)
641 }
642
647 }
648
650
652 assert(!LPairs.empty() &&
653 "PathDiagnosticControlFlowPiece needs at least one location.");
654 return LPairs[0].getStart();
655 }
656
658 assert(!LPairs.empty() &&
659 "PathDiagnosticControlFlowPiece needs at least one location.");
660 return LPairs[0].getEnd();
661 }
662
664 LPairs[0].setStart(L);
665 }
666
668 LPairs[0].setEnd(L);
669 }
670
672
675 }
676
677 using iterator = std::vector::iterator;
678
681
683 for (auto &I : *this)
684 I.flatten();
685 }
686
688 std::vector::const_iterator;
689
692
695 }
696
697 void dump() const override;
698
699 void Profile(llvm::FoldingSetNodeID &ID) const override;
700};
701
703public:
707
709
713 I->flattenLocations();
714 }
715
717 return P->getKind() == Macro;
718 }
719
720 void dump() const override;
721
722 void Profile(llvm::FoldingSetNodeID &ID) const override;
723};
724
726public:
728 bool AddPosRange = true)
731
733 return P->getKind() == Note;
734 }
735
736 void dump() const override;
737
738 void Profile(llvm::FoldingSetNodeID &ID) const override;
739};
740
742public:
744 bool AddPosRange = true)
747
749 return P->getKind() == PopUp;
750 }
751
752 void dump() const override;
753
754 void Profile(llvm::FoldingSetNodeID &ID) const override;
755};
756
757
759
760
761
762
764 std::string CheckerName;
765 const Decl *DeclWithIssue;
767 std::string VerboseDesc;
768 std::string ShortDesc;
769 std::string Category;
770 std::dequestd::string OtherDesc;
771
772
774
777
778
779
781 const Decl *UniqueingDecl;
782
783
784 const Decl *AnalysisEntryPoint = nullptr;
785
786
787 std::unique_ptr ExecutedLines;
788
789public:
792 StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,
794 const Decl *DeclToUnique, const Decl *AnalysisEntryPoint,
795 std::unique_ptr ExecutedLines);
797
799
800
801
803 if (pathStack.empty())
804 return pathImpl;
805 return *pathStack.back();
806 }
807
808
810 return pathImpl;
811 }
812
813
815
817 void popActivePath() { if (!pathStack.empty()) pathStack.pop_back(); }
818
820
822 assert(.isValid() && "End location already set!");
823 Loc = EndPiece->getLocation();
824 assert(Loc.isValid() && "Invalid location for end-of-path piece");
826 }
827
829 if (!ShortDesc.empty())
830 ShortDesc += S;
831 VerboseDesc += S;
832 }
833
835
837 return ShortDesc.empty() ? VerboseDesc : ShortDesc;
838 }
839
843
844 using meta_iterator = std::dequestd::string::const_iterator;
845
848 void addMeta(StringRef s) { OtherDesc.push_back(std::string(s)); }
849
851 return *ExecutedLines;
852 }
853
855 return *ExecutedLines;
856 }
857
858
860
861
862
863
865
867 DeclWithIssue = D;
868 }
869
871 return Loc;
872 }
873
875 Loc = NewLoc;
876 }
877
878
880 return UniqueingLoc;
881 }
882
883
885 return UniqueingDecl;
886 }
887
889 Loc.flatten();
890 for (const auto &I : pathImpl)
891 I->flattenLocations();
892 }
893
894
895
896
897
898 void Profile(llvm::FoldingSetNodeID &ID) const;
899
900
901
902
903
904 void FullProfile(llvm::FoldingSetNodeID &ID) const;
905};
906
907}
908}
909
910#endif
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines the clang::SourceLocation class and associated facilities.
__device__ __2f16 float __ockl_bool s
AnalysisDeclContext contains the context data for the function, method or block under analysis.
A builtin binary operation expression such as "x + y" or "x <= y".
Represents a point when we begin processing an inlined call.
Represents a point when we finish the call exit sequence (for inlined call).
CompoundStmt - This represents a group of statements like { stmt stmt }.
ConditionalOperator - The ?: ternary operator.
Decl - This represents one declaration (or definition), e.g.
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
A SourceLocation and its associated SourceManager.
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
This class handles loading and caching of source files into memory.
A trivial tuple used to represent a source range.
Stmt - This represents one statement.
bool isValid() const =delete
~PathDiagnosticCallPiece() override
PathDiagnosticLocation getLocation() const override
void setCallee(const CallEnter &CE, const SourceManager &SM)
PathDiagnosticLocation callEnter
void dump() const override
std::shared_ptr< PathDiagnosticEventPiece > getCallExitEvent() const
void setCallStackMessage(StringRef st)
bool hasCallStackMessage()
static bool classof(const PathDiagnosticPiece *P)
const Decl * getCallee() const
static std::shared_ptr< PathDiagnosticCallPiece > construct(const CallExitEnd &CE, const SourceManager &SM)
PathDiagnosticLocation callReturn
void flattenLocations() override
std::shared_ptr< PathDiagnosticEventPiece > getCallEnterWithinCallerEvent() const
void Profile(llvm::FoldingSetNodeID &ID) const override
const Decl * getCaller() const
std::shared_ptr< PathDiagnosticEventPiece > getCallEnterEvent() const
PathDiagnosticLocation callEnterWithin
PDFileEntry::ConsumerFiles * getFiles(const PathDiagnostic &PD)
void addDiagnostic(const PathDiagnostic &PD, StringRef ConsumerName, StringRef fileName)
const llvm::FoldingSetNodeID NodeID
A precomputed hash tag used for uniquing PDFileEntry objects.
std::vector< std::pair< StringRef, StringRef > > ConsumerFiles
void Profile(llvm::FoldingSetNodeID &ID)
Used for profiling in the FoldingSet.
ConsumerFiles files
A vector of <consumer,file> pairs.
PDFileEntry(llvm::FoldingSetNodeID &NodeID)
@ None
Only runs visitors, no output generated.
@ Everything
Used for HTML, shows both "arrows" and control notes.
@ Extensive
Used for plist output, used for "arrows" generation.
@ Minimal
Used for SARIF and text output.
PathDiagnosticConsumer()=default
virtual bool supportsLogicalOpControlFlow() const
virtual void FlushDiagnosticsImpl(std::vector< const PathDiagnostic * > &Diags, FilesMade *filesMade)=0
bool shouldAddPathEdges() const
virtual bool supportsCrossFileDiagnostics() const
Return true if the PathDiagnosticConsumer supports individual PathDiagnostics that span multiple file...
void HandlePathDiagnostic(std::unique_ptr< PathDiagnostic > D)
virtual StringRef getName() const =0
virtual PathGenerationScheme getGenerationScheme() const
llvm::FoldingSet< PathDiagnostic > Diags
virtual ~PathDiagnosticConsumer()
void FlushDiagnostics(FilesMade *FilesMade)
bool shouldAddControlNotes() const
bool shouldGenerateDiagnostics() const
PathDiagnosticLocation getStartLocation() const
PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, const PathDiagnosticLocation &endPos)
std::vector< PathDiagnosticLocationPair >::const_iterator const_iterator
void push_back(const PathDiagnosticLocationPair &X)
void setEndLocation(const PathDiagnosticLocation &L)
static bool classof(const PathDiagnosticPiece *P)
void dump() const override
PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, const PathDiagnosticLocation &endPos, StringRef s)
std::vector< PathDiagnosticLocationPair >::iterator iterator
const_iterator begin() const
PathDiagnosticLocation getLocation() const override
void setStartLocation(const PathDiagnosticLocation &L)
const_iterator end() const
~PathDiagnosticControlFlowPiece() override
PathDiagnosticLocation getEndLocation() const
void Profile(llvm::FoldingSetNodeID &ID) const override
void flattenLocations() override
void setPrunable(bool isPrunable, bool override=false)
Mark the diagnostic piece as being potentially prunable.
static bool classof(const PathDiagnosticPiece *P)
~PathDiagnosticEventPiece() override
PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, StringRef s, bool addPosRange=true)
void dump() const override
bool isPrunable() const
Return true if the diagnostic piece is prunable.
const PathDiagnosticLocation & getEnd() const
void Profile(llvm::FoldingSetNodeID &ID) const
const PathDiagnosticLocation & getStart() const
void setStart(const PathDiagnosticLocation &L)
void setEnd(const PathDiagnosticLocation &L)
PathDiagnosticLocationPair(const PathDiagnosticLocation &start, const PathDiagnosticLocation &end)
static PathDiagnosticLocation createMemberLoc(const MemberExpr *ME, const SourceManager &SM)
For member expressions, return the location of the '.
const Stmt * asStmt() const
static PathDiagnosticLocation createDeclBegin(const LocationContext *LC, const SourceManager &SM)
Create a location for the beginning of the enclosing declaration body.
void Profile(llvm::FoldingSetNodeID &ID) const
PathDiagnosticLocation(const Decl *d, const SourceManager &sm)
Create a location corresponding to the given declaration.
PathDiagnosticRange asRange() const
const Decl * asDecl() const
bool operator!=(const PathDiagnosticLocation &X) const
const SourceManager & getManager() const
static PathDiagnosticLocation createOperatorLoc(const BinaryOperator *BO, const SourceManager &SM)
Create the location for the operator of the binary expression.
static PathDiagnosticLocation createEndBrace(const CompoundStmt *CS, const SourceManager &SM)
Create a location for the end of the compound statement.
static PathDiagnosticLocation createBeginBrace(const CompoundStmt *CS, const SourceManager &SM)
Create a location for the beginning of the compound statement.
static SourceLocation getValidSourceLocation(const Stmt *S, LocationOrAnalysisDeclContext LAC, bool UseEndOfStatement=false)
Construct a source location that corresponds to either the beginning or the end of the given statemen...
static PathDiagnosticLocation createEnd(const Stmt *S, const SourceManager &SM, const LocationOrAnalysisDeclContext LAC)
Create a location for the end of the statement.
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
FullSourceLoc asLocation() const
bool operator==(const PathDiagnosticLocation &X) const
PathDiagnosticLocation(SourceLocation loc, const SourceManager &sm)
Create a location at an explicit offset in the source.
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
static PathDiagnosticLocation createConditionalColonLoc(const ConditionalOperator *CO, const SourceManager &SM)
PathDiagnosticLocation()=default
Create an invalid location.
static PathDiagnosticLocation createDeclEnd(const LocationContext *LC, const SourceManager &SM)
Constructs a location for the end of the enclosing declaration body.
PathDiagnosticLocation(const Stmt *s, const SourceManager &sm, LocationOrAnalysisDeclContext lac)
Create a location corresponding to the given statement.
const Stmt * getStmtOrNull() const
static PathDiagnosticLocation createSingleLocation(const PathDiagnosticLocation &PDL)
Convert the given location into a single kind location.
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM, const LocationOrAnalysisDeclContext LAC)
Create a location for the beginning of the declaration.
bool hasValidLocation() const
void dump() const override
void flattenLocations() override
PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos)
static bool classof(const PathDiagnosticPiece *P)
void Profile(llvm::FoldingSetNodeID &ID) const override
~PathDiagnosticMacroPiece() override
void Profile(llvm::FoldingSetNodeID &ID) const override
void dump() const override
PathDiagnosticNotePiece(const PathDiagnosticLocation &Pos, StringRef S, bool AddPosRange=true)
~PathDiagnosticNotePiece() override
static bool classof(const PathDiagnosticPiece *P)
ArrayRef< SourceRange > getRanges() const
Return the SourceRanges associated with this PathDiagnosticPiece.
void addRange(SourceRange R)
virtual PathDiagnosticLocation getLocation() const =0
void addFixit(FixItHint F)
void setAsLastInMainSourceFile()
virtual void dump() const =0
void setTag(const char *tag)
Tag this PathDiagnosticPiece with the given C-string.
bool isLastInMainSourceFile() const
PathDiagnosticPiece(const PathDiagnosticPiece &)=delete
virtual void Profile(llvm::FoldingSetNodeID &ID) const
StringRef getTagStr() const
Return the string representation of the tag.
PathDiagnosticPiece & operator=(const PathDiagnosticPiece &)=delete
virtual ~PathDiagnosticPiece()
void addRange(SourceLocation B, SourceLocation E)
PathDiagnosticPiece()=delete
virtual void flattenLocations()=0
DisplayHint getDisplayHint() const
getDisplayHint - Return a hint indicating where the diagnostic should be displayed by the PathDiagnos...
const void * getTag() const
Return the opaque tag (if any) on the PathDiagnosticPiece.
StringRef getString() const
ArrayRef< FixItHint > getFixits() const
Return the fix-it hints associated with this PathDiagnosticPiece.
PathDiagnosticRange()=default
PathDiagnosticRange(SourceRange R, bool isP=false)
void flattenLocations() override
void Profile(llvm::FoldingSetNodeID &ID) const override
static bool classof(const PathDiagnosticPiece *P)
PathDiagnosticSpotPiece(const PathDiagnosticLocation &pos, StringRef s, PathDiagnosticPiece::Kind k, bool addPosRange=true)
PathDiagnosticLocation getLocation() const override
PathDiagnostic - PathDiagnostic objects represent a single path-sensitive diagnostic.
StringRef getCheckerName() const
PathPieces & getActivePath()
Return the path currently used by builders for constructing the PathDiagnostic.
void addMeta(StringRef s)
meta_iterator meta_end() const
void setDeclWithIssue(const Decl *D)
FilesToLineNumsMap & getExecutedLines()
void FullProfile(llvm::FoldingSetNodeID &ID) const
Profiles the diagnostic, including its path.
PathDiagnosticLocation getUniqueingLoc() const
Get the location on which the report should be uniqued.
std::deque< std::string >::const_iterator meta_iterator
StringRef getVerboseDescription() const
void appendToDesc(StringRef S)
const Decl * getDeclWithIssue() const
Return the semantic context where an issue occurred.
void pushActivePath(PathPieces *p)
const Decl * getAnalysisEntryPoint() const
Get the top-level entry point from which this issue was discovered.
void Profile(llvm::FoldingSetNodeID &ID) const
Profiles the diagnostic, independent of the path it references.
void setLocation(PathDiagnosticLocation NewLoc)
const FilesToLineNumsMap & getExecutedLines() const
unsigned full_size()
Return the unrolled size of the path.
void setEndOfPath(PathDiagnosticPieceRef EndPiece)
StringRef getBugType() const
const Decl * getUniqueingDecl() const
Get the declaration containing the uniqueing location.
PathPieces & getMutablePieces()
Return a mutable version of 'path'.
StringRef getCategory() const
StringRef getShortDescription() const
meta_iterator meta_begin() const
bool isWithinCall() const
PathDiagnosticLocation getLocation() const
PathPieces flatten(bool ShouldFlattenMacros) const
A Range represents the closed range [from, to].
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
std::map< FileID, std::set< unsigned > > FilesToLineNumsMap
File IDs mapped to sets of line numbers.
llvm::PointerUnion< const LocationContext *, AnalysisDeclContext * > LocationOrAnalysisDeclContext
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
These options tweak the behavior of path diangostic consumers.
bool ShouldDisplayMacroExpansions
Whether to include additional information about macro expansions with the diagnostics,...
bool ShouldDisplayWarningsAsErrors
Whether the consumer should treat consumed diagnostics as hard errors.
bool ShouldApplyFixIts
Whether the consumer should attempt to rewrite the source file with fix-it hints attached to the diag...
bool ShouldWriteVerboseReportFilename
If the consumer intends to produce multiple output files, should it use a pseudo-random file name or ...
bool ShouldSerializeStats
Whether to include LLVM statistics of the process in the diagnostic.
std::string ToolInvocation
Run-line of the tool that produced the diagnostic.
bool ShouldDisplayDiagnosticName
Whether the consumer should present the name of the entity that emitted the diagnostic (eg....