clang 20.0.0git
PathDiagnostic.h
Go to the documentation of this file.
1//===- PathDiagnostic.h - Path-Specific Diagnostic Handling -----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the PathDiagnostic-related interfaces.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_ANALYSIS_PATHDIAGNOSTIC_H
14#define LLVM_CLANG_ANALYSIS_PATHDIAGNOSTIC_H
15
16#include "clang/AST/Stmt.h"
18#include "clang/Basic/LLVM.h"
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 <cassert>
27#include <deque>
28#include <iterator>
29#include <list>
30#include <map>
31#include <memory>
32#include <optional>
33#include <set>
34#include <string>
35#include <utility>
36#include <vector>
37
38namespace clang {
39
40class AnalysisDeclContext;
41class BinaryOperator;
42class CallEnter;
43class CallExitEnd;
44class ConditionalOperator;
45class Decl;
46class LocationContext;
47class MemberExpr;
48class ProgramPoint;
49class SourceManager;
50
51namespace ento {
52
53//===----------------------------------------------------------------------===//
54// High-level interface for handlers of path-sensitive diagnostics.
55//===----------------------------------------------------------------------===//
56
57class PathDiagnostic;
58
59/// These options tweak the behavior of path diangostic consumers.
60/// Most of these options are currently supported by very few consumers.
62 /// Run-line of the tool that produced the diagnostic.
63 /// It can be included with the diagnostic for debugging purposes.
64 std::string ToolInvocation;
65
66 /// Whether to include additional information about macro expansions
67 /// with the diagnostics, because otherwise they can be hard to obtain
68 /// without re-compiling the program under analysis.
70
71 /// Whether to include LLVM statistics of the process in the diagnostic.
72 /// Useful for profiling the tool on large real-world codebases.
74
75 /// If the consumer intends to produce multiple output files, should it
76 /// use a pseudo-random file name or a human-readable file name.
78
79 /// Whether the consumer should treat consumed diagnostics as hard errors.
80 /// Useful for breaking your build when issues are found.
82
83 /// Whether the consumer should attempt to rewrite the source file
84 /// with fix-it hints attached to the diagnostics it consumes.
85 bool ShouldApplyFixIts = false;
86
87 /// Whether the consumer should present the name of the entity that emitted
88 /// the diagnostic (eg., a checker) so that the user knew how to disable it.
90};
91
93public:
94 class PDFileEntry : public llvm::FoldingSetNode {
95 public:
96 PDFileEntry(llvm::FoldingSetNodeID &NodeID) : NodeID(NodeID) {}
97
98 using ConsumerFiles = std::vector<std::pair<StringRef, StringRef>>;
99
100 /// A vector of <consumer,file> pairs.
102
103 /// A precomputed hash tag used for uniquing PDFileEntry objects.
104 const llvm::FoldingSetNodeID NodeID;
105
106 /// Used for profiling in the FoldingSet.
107 void Profile(llvm::FoldingSetNodeID &ID) { ID = NodeID; }
108 };
109
110 class FilesMade {
111 llvm::BumpPtrAllocator Alloc;
112 llvm::FoldingSet<PDFileEntry> Set;
113
114 public:
115 ~FilesMade();
116
117 bool empty() const { return Set.empty(); }
118
119 void addDiagnostic(const PathDiagnostic &PD,
120 StringRef ConsumerName,
121 StringRef fileName);
122
124 };
125
126private:
127 virtual void anchor();
128
129public:
131 virtual ~PathDiagnosticConsumer();
132
134
135 virtual void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
136 FilesMade *filesMade) = 0;
137
138 virtual StringRef getName() const = 0;
139
140 void HandlePathDiagnostic(std::unique_ptr<PathDiagnostic> D);
141
143 /// Only runs visitors, no output generated.
145
146 /// Used for SARIF and text output.
148
149 /// Used for plist output, used for "arrows" generation.
151
152 /// Used for HTML, shows both "arrows" and control notes.
154 };
155
157
159 return getGenerationScheme() != None;
160 }
161
164 return getGenerationScheme() == Minimal ||
166 }
167
168 virtual bool supportsLogicalOpControlFlow() const { return false; }
169
170 /// Return true if the PathDiagnosticConsumer supports individual
171 /// PathDiagnostics that span multiple files.
172 virtual bool supportsCrossFileDiagnostics() const { return false; }
173
174protected:
175 bool flushed = false;
176 llvm::FoldingSet<PathDiagnostic> Diags;
177};
178
179//===----------------------------------------------------------------------===//
180// Path-sensitive diagnostics.
181//===----------------------------------------------------------------------===//
182
184public:
185 bool isPoint = false;
186
187 PathDiagnosticRange(SourceRange R, bool isP = false)
188 : SourceRange(R), isPoint(isP) {}
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;
201 const SourceManager *SM = nullptr;
204
206 : K(kind), SM(&sm), Loc(genLocation(L)), Range(genRange()) {}
207
208 FullSourceLoc genLocation(
211
212 PathDiagnosticRange genRange(
214
215public:
216 /// Create an invalid location.
218
219 /// Create a location corresponding to the given statement.
222 : K(s->getBeginLoc().isValid() ? StmtK : SingleLocK),
223 S(K == StmtK ? s : nullptr), SM(&sm),
224 Loc(genLocation(SourceLocation(), lac)), Range(genRange(lac)) {
225 assert(K == SingleLocK || S);
226 assert(K == SingleLocK || Loc.isValid());
227 assert(K == SingleLocK || Range.isValid());
228 }
229
230 /// Create a location corresponding to the given declaration.
232 : K(DeclK), D(d), SM(&sm), Loc(genLocation()), Range(genRange()) {
233 assert(D);
234 assert(Loc.isValid());
235 assert(Range.isValid());
236 }
237
238 /// Create a location at an explicit offset in the source.
239 ///
240 /// This should only be used if there are no more appropriate constructors.
242 : SM(&sm), Loc(loc, sm), Range(genRange()) {
243 assert(Loc.isValid());
244 assert(Range.isValid());
245 }
246
247 /// Create a location corresponding to the given declaration.
249 const SourceManager &SM) {
250 return PathDiagnosticLocation(D, SM);
251 }
252
253 /// Create a location for the beginning of the declaration.
255 const SourceManager &SM);
256
257 /// Create a location for the beginning of the declaration.
258 /// The third argument is ignored, useful for generic treatment
259 /// of statements and declarations.
261 createBegin(const Decl *D, const SourceManager &SM,
263 return createBegin(D, SM);
264 }
265
266 /// Create a location for the beginning of the statement.
268 const SourceManager &SM,
270
271 /// Create a location for the end of the statement.
272 ///
273 /// If the statement is a CompoundStatement, the location will point to the
274 /// closing brace instead of following it.
275 static PathDiagnosticLocation createEnd(const Stmt *S,
276 const SourceManager &SM,
278
279 /// Create the location for the operator of the binary expression.
280 /// Assumes the statement has a valid location.
282 const SourceManager &SM);
284 const ConditionalOperator *CO,
285 const SourceManager &SM);
286
287 /// For member expressions, return the location of the '.' or '->'.
288 /// Assumes the statement has a valid location.
290 const SourceManager &SM);
291
292 /// Create a location for the beginning of the compound statement.
293 /// Assumes the statement has a valid location.
295 const SourceManager &SM);
296
297 /// Create a location for the end of the compound statement.
298 /// Assumes the statement has a valid location.
300 const SourceManager &SM);
301
302 /// Create a location for the beginning of the enclosing declaration body.
303 /// Defaults to the beginning of the first statement in the declaration body.
305 const SourceManager &SM);
306
307 /// Constructs a location for the end of the enclosing declaration body.
308 /// Defaults to the end of brace.
310 const SourceManager &SM);
311
312 /// Create a location corresponding to the given valid ProgramPoint.
314 const SourceManager &SMng);
315
316 /// Convert the given location into a single kind location.
318 const PathDiagnosticLocation &PDL);
319
320 /// Construct a source location that corresponds to either the beginning
321 /// or the end of the given statement, or a nearby valid source location
322 /// if the statement does not have a valid source location of its own.
323 static SourceLocation
325 bool UseEndOfStatement = false);
326
328 return K == X.K && Loc == X.Loc && Range == X.Range;
329 }
330
332 return !(*this == X);
333 }
334
335 bool isValid() const {
336 return SM != nullptr;
337 }
338
340 return Loc;
341 }
342
344 return Range;
345 }
346
347 const Stmt *asStmt() const { assert(isValid()); return S; }
348 const Stmt *getStmtOrNull() const {
349 if (!isValid())
350 return nullptr;
351 return asStmt();
352 }
353
354 const Decl *asDecl() const { assert(isValid()); return D; }
355
356 bool hasRange() const { return K == StmtK || K == RangeK || K == DeclK; }
357
358 bool hasValidLocation() const { return asLocation().isValid(); }
359
360 void invalidate() {
361 *this = PathDiagnosticLocation();
362 }
363
364 void flatten();
365
366 const SourceManager& getManager() const { assert(isValid()); return *SM; }
367
368 void Profile(llvm::FoldingSetNodeID &ID) const;
369
370 void dump() const;
371};
372
374private:
375 PathDiagnosticLocation Start, End;
376
377public:
379 const PathDiagnosticLocation &end)
380 : Start(start), End(end) {}
381
382 const PathDiagnosticLocation &getStart() const { return Start; }
383 const PathDiagnosticLocation &getEnd() const { return End; }
384
385 void setStart(const PathDiagnosticLocation &L) { Start = L; }
386 void setEnd(const PathDiagnosticLocation &L) { End = L; }
387
388 void flatten() {
389 Start.flatten();
390 End.flatten();
391 }
392
393 void Profile(llvm::FoldingSetNodeID &ID) const {
394 Start.Profile(ID);
395 End.Profile(ID);
396 }
397};
398
399//===----------------------------------------------------------------------===//
400// Path "pieces" for path-sensitive diagnostics.
401//===----------------------------------------------------------------------===//
402
403class PathDiagnosticPiece: public llvm::FoldingSetNode {
404public:
407
408private:
409 const std::string str;
410 const Kind kind;
411 const DisplayHint Hint;
412
413 /// In the containing bug report, this piece is the last piece from
414 /// the main source file.
415 bool LastInMainSourceFile = false;
416
417 /// A constant string that can be used to tag the PathDiagnosticPiece,
418 /// typically with the identification of the creator. The actual pointer
419 /// value is meant to be an identifier; the string itself is useful for
420 /// debugging.
421 StringRef Tag;
422
423 std::vector<SourceRange> ranges;
424 std::vector<FixItHint> fixits;
425
426protected:
427 PathDiagnosticPiece(StringRef s, Kind k, DisplayHint hint = Below);
429
430public:
435
436 StringRef getString() const { return str; }
437
438 /// Tag this PathDiagnosticPiece with the given C-string.
439 void setTag(const char *tag) { Tag = tag; }
440
441 /// Return the opaque tag (if any) on the PathDiagnosticPiece.
442 const void *getTag() const { return Tag.data(); }
443
444 /// Return the string representation of the tag. This is useful
445 /// for debugging.
446 StringRef getTagStr() const { return Tag; }
447
448 /// getDisplayHint - Return a hint indicating where the diagnostic should
449 /// be displayed by the PathDiagnosticConsumer.
450 DisplayHint getDisplayHint() const { return Hint; }
451
453 virtual void flattenLocations() = 0;
454
455 Kind getKind() const { return kind; }
456
458 if (!R.isValid())
459 return;
460 ranges.push_back(R);
461 }
462
464 if (!B.isValid() || !E.isValid())
465 return;
466 ranges.push_back(SourceRange(B,E));
467 }
468
470 fixits.push_back(F);
471 }
472
473 /// Return the SourceRanges associated with this PathDiagnosticPiece.
474 ArrayRef<SourceRange> getRanges() const { return ranges; }
475
476 /// Return the fix-it hints associated with this PathDiagnosticPiece.
477 ArrayRef<FixItHint> getFixits() const { return fixits; }
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
492using PathDiagnosticPieceRef = std::shared_ptr<PathDiagnosticPiece>;
493
494class PathPieces : public std::list<PathDiagnosticPieceRef> {
495 void flattenTo(PathPieces &Primary, PathPieces &Current,
496 bool ShouldFlattenMacros) const;
497
498public:
499 PathPieces flatten(bool ShouldFlattenMacros) const {
501 flattenTo(Result, Result, ShouldFlattenMacros);
502 return Result;
503 }
504
505 void dump() const;
506};
507
509private:
511
512public:
514 StringRef s,
516 bool addPosRange = true)
517 : PathDiagnosticPiece(s, k), Pos(pos) {
518 assert(Pos.isValid() && Pos.hasValidLocation() &&
519 "PathDiagnosticSpotPiece's must have a valid location.");
520 if (addPosRange && Pos.hasRange()) addRange(Pos.asRange());
521 }
522
523 PathDiagnosticLocation getLocation() const override { return Pos; }
524 void flattenLocations() override { Pos.flatten(); }
525
526 void Profile(llvm::FoldingSetNodeID &ID) const override;
527
528 static bool classof(const PathDiagnosticPiece *P) {
529 return P->getKind() == Event || P->getKind() == Macro ||
530 P->getKind() == Note || P->getKind() == PopUp;
531 }
532};
533
535 std::optional<bool> IsPrunable;
536
537public:
539 StringRef s, bool addPosRange = true)
540 : PathDiagnosticSpotPiece(pos, s, Event, addPosRange) {}
542
543 /// Mark the diagnostic piece as being potentially prunable. This
544 /// flag may have been previously set, at which point it will not
545 /// be reset unless one specifies to do so.
546 void setPrunable(bool isPrunable, bool override = false) {
547 if (IsPrunable && !override)
548 return;
549 IsPrunable = isPrunable;
550 }
551
552 /// Return true if the diagnostic piece is prunable.
553 bool isPrunable() const { return IsPrunable.value_or(false); }
554
555 void dump() const override;
556
557 static bool classof(const PathDiagnosticPiece *P) {
558 return P->getKind() == Event;
559 }
560};
561
563 const Decl *Caller;
564 const Decl *Callee = nullptr;
565
566 // Flag signifying that this diagnostic has only call enter and no matching
567 // call exit.
568 bool NoExit;
569
570 // Flag signifying that the callee function is an Objective-C autosynthesized
571 // property getter or setter.
572 bool IsCalleeAnAutosynthesizedPropertyAccessor = false;
573
574 // The custom string, which should appear after the call Return Diagnostic.
575 // TODO: Should we allow multiple diagnostics?
576 std::string CallStackMessage;
577
578 PathDiagnosticCallPiece(const Decl *callerD,
579 const PathDiagnosticLocation &callReturnPos)
580 : PathDiagnosticPiece(Call), Caller(callerD), NoExit(false),
581 callReturn(callReturnPos) {}
582 PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller)
583 : PathDiagnosticPiece(Call), Caller(caller), NoExit(true),
584 path(oldPath) {}
585
586public:
591
593
594 const Decl *getCaller() const { return Caller; }
595
596 const Decl *getCallee() const { return Callee; }
597 void setCallee(const CallEnter &CE, const SourceManager &SM);
598
599 bool hasCallStackMessage() { return !CallStackMessage.empty(); }
600 void setCallStackMessage(StringRef st) { CallStackMessage = std::string(st); }
601
602 PathDiagnosticLocation getLocation() const override { return callEnter; }
603
604 std::shared_ptr<PathDiagnosticEventPiece> getCallEnterEvent() const;
605 std::shared_ptr<PathDiagnosticEventPiece>
607 std::shared_ptr<PathDiagnosticEventPiece> getCallExitEvent() const;
608
609 void flattenLocations() override {
612 for (const auto &I : path)
613 I->flattenLocations();
614 }
615
616 static std::shared_ptr<PathDiagnosticCallPiece>
617 construct(const CallExitEnd &CE,
618 const SourceManager &SM);
619
621 const Decl *caller);
622
623 void dump() const override;
624
625 void Profile(llvm::FoldingSetNodeID &ID) const override;
626
627 static bool classof(const PathDiagnosticPiece *P) {
628 return P->getKind() == Call;
629 }
630};
631
633 std::vector<PathDiagnosticLocationPair> LPairs;
634
635public:
637 const PathDiagnosticLocation &endPos,
638 StringRef s)
640 LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
641 }
642
644 const PathDiagnosticLocation &endPos)
646 LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
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
671 void push_back(const PathDiagnosticLocationPair &X) { LPairs.push_back(X); }
672
674 return getStartLocation();
675 }
676
677 using iterator = std::vector<PathDiagnosticLocationPair>::iterator;
678
679 iterator begin() { return LPairs.begin(); }
680 iterator end() { return LPairs.end(); }
681
682 void flattenLocations() override {
683 for (auto &I : *this)
684 I.flatten();
685 }
686
688 std::vector<PathDiagnosticLocationPair>::const_iterator;
689
690 const_iterator begin() const { return LPairs.begin(); }
691 const_iterator end() const { return LPairs.end(); }
692
693 static bool classof(const PathDiagnosticPiece *P) {
694 return P->getKind() == ControlFlow;
695 }
696
697 void dump() const override;
698
699 void Profile(llvm::FoldingSetNodeID &ID) const override;
700};
701
703public:
705 : PathDiagnosticSpotPiece(pos, "", Macro) {}
707
709
710 void flattenLocations() override {
712 for (const auto &I : subPieces)
713 I->flattenLocations();
714 }
715
716 static bool classof(const PathDiagnosticPiece *P) {
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)
729 : PathDiagnosticSpotPiece(Pos, S, Note, AddPosRange) {}
731
732 static bool classof(const PathDiagnosticPiece *P) {
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)
745 : PathDiagnosticSpotPiece(Pos, S, PopUp, AddPosRange) {}
747
748 static bool classof(const PathDiagnosticPiece *P) {
749 return P->getKind() == PopUp;
750 }
751
752 void dump() const override;
753
754 void Profile(llvm::FoldingSetNodeID &ID) const override;
755};
756
757/// File IDs mapped to sets of line numbers.
758using FilesToLineNumsMap = std::map<FileID, std::set<unsigned>>;
759
760/// PathDiagnostic - PathDiagnostic objects represent a single path-sensitive
761/// diagnostic. It represents an ordered-collection of PathDiagnosticPieces,
762/// each which represent the pieces of the path.
763class PathDiagnostic : public llvm::FoldingSetNode {
764 std::string CheckerName;
765 const Decl *DeclWithIssue;
766 std::string BugType;
767 std::string VerboseDesc;
768 std::string ShortDesc;
769 std::string Category;
770 std::deque<std::string> OtherDesc;
771
772 /// Loc The location of the path diagnostic report.
774
775 PathPieces pathImpl;
777
778 /// Important bug uniqueing location.
779 /// The location info is useful to differentiate between bugs.
780 PathDiagnosticLocation UniqueingLoc;
781 const Decl *UniqueingDecl;
782
783 /// The top-level entry point from which this issue was discovered.
784 const Decl *AnalysisEntryPoint = nullptr;
785
786 /// Lines executed in the path.
787 std::unique_ptr<FilesToLineNumsMap> ExecutedLines;
788
789public:
790 PathDiagnostic() = delete;
791 PathDiagnostic(StringRef CheckerName, const Decl *DeclWithIssue,
792 StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,
793 StringRef category, PathDiagnosticLocation LocationToUnique,
794 const Decl *DeclToUnique, const Decl *AnalysisEntryPoint,
795 std::unique_ptr<FilesToLineNumsMap> ExecutedLines);
797
799
800 /// Return the path currently used by builders for constructing the
801 /// PathDiagnostic.
803 if (pathStack.empty())
804 return pathImpl;
805 return *pathStack.back();
806 }
807
808 /// Return a mutable version of 'path'.
810 return pathImpl;
811 }
812
813 /// Return the unrolled size of the path.
814 unsigned full_size();
815
816 void pushActivePath(PathPieces *p) { pathStack.push_back(p); }
817 void popActivePath() { if (!pathStack.empty()) pathStack.pop_back(); }
818
819 bool isWithinCall() const { return !pathStack.empty(); }
820
822 assert(!Loc.isValid() && "End location already set!");
823 Loc = EndPiece->getLocation();
824 assert(Loc.isValid() && "Invalid location for end-of-path piece");
825 getActivePath().push_back(std::move(EndPiece));
826 }
827
828 void appendToDesc(StringRef S) {
829 if (!ShortDesc.empty())
830 ShortDesc += S;
831 VerboseDesc += S;
832 }
833
834 StringRef getVerboseDescription() const { return VerboseDesc; }
835
836 StringRef getShortDescription() const {
837 return ShortDesc.empty() ? VerboseDesc : ShortDesc;
838 }
839
840 StringRef getCheckerName() const { return CheckerName; }
841 StringRef getBugType() const { return BugType; }
842 StringRef getCategory() const { return Category; }
843
844 using meta_iterator = std::deque<std::string>::const_iterator;
845
846 meta_iterator meta_begin() const { return OtherDesc.begin(); }
847 meta_iterator meta_end() const { return OtherDesc.end(); }
848 void addMeta(StringRef s) { OtherDesc.push_back(std::string(s)); }
849
851 return *ExecutedLines;
852 }
853
855 return *ExecutedLines;
856 }
857
858 /// Get the top-level entry point from which this issue was discovered.
859 const Decl *getAnalysisEntryPoint() const { return AnalysisEntryPoint; }
860
861 /// Return the semantic context where an issue occurred. If the
862 /// issue occurs along a path, this represents the "central" area
863 /// where the bug manifests.
864 const Decl *getDeclWithIssue() const { return DeclWithIssue; }
865
866 void setDeclWithIssue(const Decl *D) {
867 DeclWithIssue = D;
868 }
869
871 return Loc;
872 }
873
875 Loc = NewLoc;
876 }
877
878 /// Get the location on which the report should be uniqued.
880 return UniqueingLoc;
881 }
882
883 /// Get the declaration containing the uniqueing location.
884 const Decl *getUniqueingDecl() const {
885 return UniqueingDecl;
886 }
887
889 Loc.flatten();
890 for (const auto &I : pathImpl)
891 I->flattenLocations();
892 }
893
894 /// Profiles the diagnostic, independent of the path it references.
895 ///
896 /// This can be used to merge diagnostics that refer to the same issue
897 /// along different paths.
898 void Profile(llvm::FoldingSetNodeID &ID) const;
899
900 /// Profiles the diagnostic, including its path.
901 ///
902 /// Two diagnostics with the same issue along different paths will generate
903 /// different profiles.
904 void FullProfile(llvm::FoldingSetNodeID &ID) const;
905};
906
907} // namespace ento
908} // namespace clang
909
910#endif // LLVM_CLANG_ANALYSIS_PATHDIAGNOSTIC_H
StringRef P
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
static char ID
Definition: Arena.cpp:183
#define SM(sm)
Definition: Cuda.cpp:83
const Decl * D
Expr * E
int Category
Definition: Format.cpp:3017
#define X(type, name)
Definition: Value.h:143
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".
Definition: Expr.h:3860
Represents a point when we begin processing an inlined call.
Definition: ProgramPoint.h:628
Represents a point when we finish the call exit sequence (for inlined call).
Definition: ProgramPoint.h:686
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:1611
ConditionalOperator - The ?: ternary operator.
Definition: Expr.h:4213
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
Definition: Diagnostic.h:71
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.
Definition: Expr.h:3187
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.
bool isValid() const
Stmt - This represents one statement.
Definition: Stmt.h:84
bool isValid() const =delete
PathDiagnosticLocation getLocation() const override
void setCallee(const CallEnter &CE, const SourceManager &SM)
std::shared_ptr< PathDiagnosticEventPiece > getCallExitEvent() const
static bool classof(const PathDiagnosticPiece *P)
static std::shared_ptr< PathDiagnosticCallPiece > construct(const CallExitEnd &CE, const SourceManager &SM)
std::shared_ptr< PathDiagnosticEventPiece > getCallEnterWithinCallerEvent() const
void Profile(llvm::FoldingSetNodeID &ID) const override
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.
virtual bool supportsLogicalOpControlFlow() const
virtual void FlushDiagnosticsImpl(std::vector< const PathDiagnostic * > &Diags, FilesMade *filesMade)=0
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
void FlushDiagnostics(FilesMade *FilesMade)
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)
PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, const PathDiagnosticLocation &endPos, StringRef s)
std::vector< PathDiagnosticLocationPair >::iterator iterator
PathDiagnosticLocation getLocation() const override
void setStartLocation(const PathDiagnosticLocation &L)
PathDiagnosticLocation getEndLocation() const
void Profile(llvm::FoldingSetNodeID &ID) const override
void setPrunable(bool isPrunable, bool override=false)
Mark the diagnostic piece as being potentially prunable.
static bool classof(const PathDiagnosticPiece *P)
PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, StringRef s, bool addPosRange=true)
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 '.
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
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.
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.
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.
PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos)
static bool classof(const PathDiagnosticPiece *P)
void Profile(llvm::FoldingSetNodeID &ID) const override
void Profile(llvm::FoldingSetNodeID &ID) const override
PathDiagnosticNotePiece(const PathDiagnosticLocation &Pos, StringRef S, bool AddPosRange=true)
static bool classof(const PathDiagnosticPiece *P)
ArrayRef< SourceRange > getRanges() const
Return the SourceRanges associated with this PathDiagnosticPiece.
virtual PathDiagnosticLocation getLocation() const =0
virtual void dump() const =0
void setTag(const char *tag)
Tag this PathDiagnosticPiece with the given C-string.
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
void addRange(SourceLocation B, SourceLocation E)
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.
ArrayRef< FixItHint > getFixits() const
Return the fix-it hints associated with this PathDiagnosticPiece.
void Profile(llvm::FoldingSetNodeID &ID) const override
static bool classof(const PathDiagnosticPiece *P)
PathDiagnosticPopUpPiece(const PathDiagnosticLocation &Pos, StringRef S, bool AddPosRange=true)
PathDiagnosticRange(SourceRange R, bool isP=false)
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.
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
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....