clang 23.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
41class BinaryOperator;
42class CallEnter;
43class CallExitEnd;
45class Decl;
46class MemberExpr;
47class ProgramPoint;
48class SourceManager;
49
50namespace ento {
51
52//===----------------------------------------------------------------------===//
53// High-level interface for handlers of path-sensitive diagnostics.
54//===----------------------------------------------------------------------===//
55
56class PathDiagnostic;
57
58/// These options tweak the behavior of path diangostic consumers.
59/// Most of these options are currently supported by very few consumers.
61 /// Run-line of the tool that produced the diagnostic.
62 /// It can be included with the diagnostic for debugging purposes.
63 std::string ToolInvocation;
64
65 /// Whether to include additional information about macro expansions
66 /// with the diagnostics, because otherwise they can be hard to obtain
67 /// without re-compiling the program under analysis.
69
70 /// Whether to include LLVM statistics of the process in the diagnostic.
71 /// Useful for profiling the tool on large real-world codebases.
73
74 /// If the consumer intends to produce multiple output files, should it
75 /// use a pseudo-random file name or a human-readable file name.
77
78 /// Whether the consumer should treat consumed diagnostics as hard errors.
79 /// Useful for breaking your build when issues are found.
81
82 /// Whether the consumer should attempt to rewrite the source file
83 /// with fix-it hints attached to the diagnostics it consumes.
84 bool ShouldApplyFixIts = false;
85
86 /// Whether the consumer should present the name of the entity that emitted
87 /// the diagnostic (eg., a checker) so that the user knew how to disable it.
89};
90
92public:
93 class PDFileEntry : public llvm::FoldingSetNode {
94 public:
95 PDFileEntry(llvm::FoldingSetNodeID &NodeID) : NodeID(NodeID) {}
96
97 using ConsumerFiles = std::vector<std::pair<StringRef, StringRef>>;
98
99 /// A vector of <consumer,file> pairs.
101
102 /// A precomputed hash tag used for uniquing PDFileEntry objects.
103 const llvm::FoldingSetNodeID NodeID;
104
105 /// Used for profiling in the FoldingSet.
106 void Profile(llvm::FoldingSetNodeID &ID) { ID = NodeID; }
107 };
108
109 class FilesMade {
110 llvm::BumpPtrAllocator Alloc;
111 llvm::FoldingSet<PDFileEntry> Set;
112
113 public:
114 ~FilesMade();
115
116 bool empty() const { return Set.empty(); }
117
118 void addDiagnostic(const PathDiagnostic &PD,
119 StringRef ConsumerName,
120 StringRef fileName);
121
123 };
124
125private:
126 virtual void anchor();
127
128public:
130 virtual ~PathDiagnosticConsumer();
131
133
134 virtual void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
135 FilesMade *filesMade) = 0;
136
137 virtual StringRef getName() const = 0;
138
139 void HandlePathDiagnostic(std::unique_ptr<PathDiagnostic> D);
140
142 /// Only runs visitors, no output generated.
144
145 /// Used for SARIF and text output.
147
148 /// Used for plist output, used for "arrows" generation.
150
151 /// Used for HTML, shows both "arrows" and control notes.
153 };
154
156
158 return getGenerationScheme() != None;
159 }
160
163 return getGenerationScheme() == Minimal ||
165 }
166
167 virtual bool supportsLogicalOpControlFlow() const { return false; }
168
169 /// Return true if the PathDiagnosticConsumer supports individual
170 /// PathDiagnostics that span multiple files.
171 virtual bool supportsCrossFileDiagnostics() const { return false; }
172
173protected:
174 bool flushed = false;
175 llvm::FoldingSet<PathDiagnostic> Diags;
176};
177
178//===----------------------------------------------------------------------===//
179// Path-sensitive diagnostics.
180//===----------------------------------------------------------------------===//
181
183public:
184 bool isPoint = false;
185
186 PathDiagnosticRange(SourceRange R, bool isP = false)
187 : SourceRange(R), isPoint(isP) {}
189};
190
192 llvm::PointerUnion<const StackFrame *, AnalysisDeclContext *>;
193
194class PathDiagnosticLocation {
195private:
196 enum Kind { RangeK, SingleLocK, StmtK, DeclK } K = SingleLocK;
197
198 const Stmt *S = nullptr;
199 const Decl *D = nullptr;
200 const SourceManager *SM = nullptr;
201 FullSourceLoc Loc;
203
205 : K(kind), SM(&sm), Loc(genLocation(L)), Range(genRange()) {}
206
209 (AnalysisDeclContext *)nullptr) const;
210
212 (AnalysisDeclContext *)nullptr) const;
213
214public:
215 /// Create an invalid location.
217
218 /// Create a location corresponding to the given statement.
221 : K(s->getBeginLoc().isValid() ? StmtK : SingleLocK),
222 S(K == StmtK ? s : nullptr), SM(&sm),
223 Loc(genLocation(SourceLocation(), SFAC)), Range(genRange(SFAC)) {
224 assert(K == SingleLocK || S);
225 assert(K == SingleLocK || Loc.isValid());
226 assert(K == SingleLocK || Range.isValid());
227 }
228
229 /// Create a location corresponding to the given declaration.
231 : K(DeclK), D(d), SM(&sm), Loc(genLocation()), Range(genRange()) {
232 assert(D);
233 assert(Loc.isValid());
234 assert(Range.isValid());
235 }
236
237 /// Create a location at an explicit offset in the source.
238 ///
239 /// This should only be used if there are no more appropriate constructors.
241 : SM(&sm), Loc(loc, sm), Range(genRange()) {
242 assert(Loc.isValid());
243 assert(Range.isValid());
244 }
245
246 /// Create a location corresponding to the given declaration.
247 static PathDiagnosticLocation create(const Decl *D,
248 const SourceManager &SM) {
249 return PathDiagnosticLocation(D, SM);
250 }
251
252 /// Create a location for the beginning of the declaration.
254 const SourceManager &SM);
255
256 /// Create a location for the beginning of the declaration.
257 /// The third argument is ignored, useful for generic treatment
258 /// of statements and declarations.
260 createBegin(const Decl *D, const SourceManager &SM,
262 return createBegin(D, SM);
263 }
264
265 /// Create a location for the beginning of the statement.
267 createBegin(const Stmt *S, const SourceManager &SM,
269
270 /// Create a location for the end of the statement.
271 ///
272 /// If the statement is a CompoundStatement, the location will point to the
273 /// closing brace instead of following it.
275 createEnd(const Stmt *S, const SourceManager &SM,
277
278 /// Create the location for the operator of the binary expression.
279 /// Assumes the statement has a valid location.
281 const SourceManager &SM);
283 const ConditionalOperator *CO,
284 const SourceManager &SM);
285
286 /// For member expressions, return the location of the '.' or '->'.
287 /// Assumes the statement has a valid location.
289 const SourceManager &SM);
290
291 /// Create a location for the beginning of the compound statement.
292 /// Assumes the statement has a valid location.
294 const SourceManager &SM);
295
296 /// Create a location for the end of the compound statement.
297 /// Assumes the statement has a valid location.
299 const SourceManager &SM);
300
301 /// Create a location for the beginning of the enclosing declaration body.
302 /// Defaults to the beginning of the first statement in the declaration body.
304 const SourceManager &SM);
305
306 /// Constructs a location for the end of the enclosing declaration body.
307 /// Defaults to the end of brace.
309 const SourceManager &SM);
310
311 /// Create a location corresponding to the given valid ProgramPoint.
313 const SourceManager &SMng);
314
315 /// Convert the given location into a single kind location.
317 const PathDiagnosticLocation &PDL);
318
319 /// Construct a source location that corresponds to either the beginning
320 /// or the end of the given statement, or a nearby valid source location
321 /// if the statement does not have a valid source location of its own.
322 static SourceLocation
324 bool UseEndOfStatement = false);
325
326 bool operator==(const PathDiagnosticLocation &X) const {
327 return K == X.K && Loc == X.Loc && Range == X.Range;
328 }
329
330 bool operator!=(const PathDiagnosticLocation &X) const {
331 return !(*this == X);
332 }
333
334 bool isValid() const {
335 return SM != nullptr;
336 }
337
339 return Loc;
340 }
341
343 return Range;
344 }
345
346 const Stmt *asStmt() const { assert(isValid()); return S; }
347 const Stmt *getStmtOrNull() const {
348 if (!isValid())
349 return nullptr;
350 return asStmt();
351 }
352
353 const Decl *asDecl() const { assert(isValid()); return D; }
354
355 bool hasRange() const { return K == StmtK || K == RangeK || K == DeclK; }
356
357 bool hasValidLocation() const { return asLocation().isValid(); }
358
359 void invalidate() {
360 *this = PathDiagnosticLocation();
361 }
362
363 void flatten();
364
365 const SourceManager& getManager() const { assert(isValid()); return *SM; }
366
367 void Profile(llvm::FoldingSetNodeID &ID) const;
368
369 void dump() const;
370};
371
373private:
374 PathDiagnosticLocation Start, End;
375
376public:
378 const PathDiagnosticLocation &end)
379 : Start(start), End(end) {}
380
381 const PathDiagnosticLocation &getStart() const { return Start; }
382 const PathDiagnosticLocation &getEnd() const { return End; }
383
384 void setStart(const PathDiagnosticLocation &L) { Start = L; }
385 void setEnd(const PathDiagnosticLocation &L) { End = L; }
386
387 void flatten() {
388 Start.flatten();
389 End.flatten();
390 }
391
392 void Profile(llvm::FoldingSetNodeID &ID) const {
393 Start.Profile(ID);
394 End.Profile(ID);
395 }
396};
397
398//===----------------------------------------------------------------------===//
399// Path "pieces" for path-sensitive diagnostics.
400//===----------------------------------------------------------------------===//
401
402class PathDiagnosticPiece: public llvm::FoldingSetNode {
403public:
406
407private:
408 const std::string str;
409 const Kind kind;
410 const DisplayHint Hint;
411
412 /// In the containing bug report, this piece is the last piece from
413 /// the main source file.
414 bool LastInMainSourceFile = false;
415
416 /// A constant string that can be used to tag the PathDiagnosticPiece,
417 /// typically with the identification of the creator. The actual pointer
418 /// value is meant to be an identifier; the string itself is useful for
419 /// debugging.
420 StringRef Tag;
421
422 std::vector<SourceRange> ranges;
423 std::vector<FixItHint> fixits;
424
425protected:
426 PathDiagnosticPiece(StringRef s, Kind k, DisplayHint hint = Below);
427 PathDiagnosticPiece(Kind k, DisplayHint hint = Below);
428
429public:
434
435 StringRef getString() const { return str; }
436
437 /// Tag this PathDiagnosticPiece with the given C-string.
438 void setTag(const char *tag) { Tag = tag; }
439
440 /// Return the opaque tag (if any) on the PathDiagnosticPiece.
441 const void *getTag() const { return Tag.data(); }
442
443 /// Return the string representation of the tag. This is useful
444 /// for debugging.
445 StringRef getTagStr() const { return Tag; }
446
447 /// getDisplayHint - Return a hint indicating where the diagnostic should
448 /// be displayed by the PathDiagnosticConsumer.
449 DisplayHint getDisplayHint() const { return Hint; }
450
452 virtual void flattenLocations() = 0;
453
454 Kind getKind() const { return kind; }
455
457 if (!R.isValid())
458 return;
459 ranges.push_back(R);
460 }
461
463 if (!B.isValid() || !E.isValid())
464 return;
465 ranges.push_back(SourceRange(B,E));
466 }
467
469 fixits.push_back(F);
470 }
471
472 /// Return the SourceRanges associated with this PathDiagnosticPiece.
473 ArrayRef<SourceRange> getRanges() const { return ranges; }
474
475 /// Return the fix-it hints associated with this PathDiagnosticPiece.
476 ArrayRef<FixItHint> getFixits() const { return fixits; }
477
478 virtual void Profile(llvm::FoldingSetNodeID &ID) const;
479
481 LastInMainSourceFile = true;
482 }
483
485 return LastInMainSourceFile;
486 }
487
488 virtual void dump() const = 0;
489};
490
491using PathDiagnosticPieceRef = std::shared_ptr<PathDiagnosticPiece>;
492
493class PathPieces : public std::list<PathDiagnosticPieceRef> {
494 void flattenTo(PathPieces &Primary, PathPieces &Current,
495 bool ShouldFlattenMacros) const;
496
497public:
498 PathPieces flatten(bool ShouldFlattenMacros) const {
500 flattenTo(Result, Result, ShouldFlattenMacros);
501 return Result;
502 }
503
504 void dump() const;
505};
506
508private:
510
511public:
513 StringRef s,
515 bool addPosRange = true)
516 : PathDiagnosticPiece(s, k), Pos(pos) {
517 assert(Pos.isValid() && Pos.hasValidLocation() &&
518 "PathDiagnosticSpotPiece's must have a valid location.");
519 if (addPosRange && Pos.hasRange()) addRange(Pos.asRange());
520 }
521
522 PathDiagnosticLocation getLocation() const override { return Pos; }
523 void flattenLocations() override { Pos.flatten(); }
524
525 void Profile(llvm::FoldingSetNodeID &ID) const override;
526
527 static bool classof(const PathDiagnosticPiece *P) {
528 return P->getKind() == Event || P->getKind() == Macro ||
529 P->getKind() == Note || P->getKind() == PopUp;
530 }
531};
532
534 std::optional<bool> IsPrunable;
535
536public:
538 StringRef s, bool addPosRange = true)
539 : PathDiagnosticSpotPiece(pos, s, Event, addPosRange) {}
541
542 /// Mark the diagnostic piece as being potentially prunable. This
543 /// flag may have been previously set, at which point it will not
544 /// be reset unless one specifies to do so.
545 void setPrunable(bool isPrunable, bool override = false) {
546 if (IsPrunable && !override)
547 return;
548 IsPrunable = isPrunable;
549 }
550
551 /// Return true if the diagnostic piece is prunable.
552 bool isPrunable() const { return IsPrunable.value_or(false); }
553
554 void dump() const override;
555
556 static bool classof(const PathDiagnosticPiece *P) {
557 return P->getKind() == Event;
558 }
559};
560
561class PathDiagnosticCallPiece : public PathDiagnosticPiece {
562 const Decl *Caller;
563 const Decl *Callee = nullptr;
564
565 // Flag signifying that this diagnostic has only call enter and no matching
566 // call exit.
567 bool NoExit;
568
569 // Flag signifying that the callee function is an Objective-C autosynthesized
570 // property getter or setter.
571 bool IsCalleeAnAutosynthesizedPropertyAccessor = false;
572
573 // The custom string, which should appear after the call Return Diagnostic.
574 // TODO: Should we allow multiple diagnostics?
575 std::string CallStackMessage;
576
577 PathDiagnosticCallPiece(const Decl *callerD,
578 const PathDiagnosticLocation &callReturnPos)
579 : PathDiagnosticPiece(Call), Caller(callerD), NoExit(false),
580 callReturn(callReturnPos) {}
581 PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller)
582 : PathDiagnosticPiece(Call), Caller(caller), NoExit(true),
583 path(oldPath) {}
584
585public:
590
592
593 const Decl *getCaller() const { return Caller; }
594
595 const Decl *getCallee() const { return Callee; }
596 void setCallee(const CallEnter &CE, const SourceManager &SM);
597
598 bool hasCallStackMessage() { return !CallStackMessage.empty(); }
599 void setCallStackMessage(StringRef st) { CallStackMessage = std::string(st); }
600
601 PathDiagnosticLocation getLocation() const override { return callEnter; }
602
603 std::shared_ptr<PathDiagnosticEventPiece> getCallEnterEvent() const;
604 std::shared_ptr<PathDiagnosticEventPiece>
606 std::shared_ptr<PathDiagnosticEventPiece> getCallExitEvent() const;
607
608 void flattenLocations() override {
609 callEnter.flatten();
610 callReturn.flatten();
611 for (const auto &I : path)
612 I->flattenLocations();
613 }
614
615 static std::shared_ptr<PathDiagnosticCallPiece>
616 construct(const CallExitEnd &CE,
617 const SourceManager &SM);
618
620 const Decl *caller);
621
622 void dump() const override;
623
624 void Profile(llvm::FoldingSetNodeID &ID) const override;
625
626 static bool classof(const PathDiagnosticPiece *P) {
627 return P->getKind() == Call;
628 }
629};
630
632 std::vector<PathDiagnosticLocationPair> LPairs;
633
634public:
636 const PathDiagnosticLocation &endPos,
637 StringRef s)
639 LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
640 }
641
643 const PathDiagnosticLocation &endPos)
645 LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
646 }
647
649
651 assert(!LPairs.empty() &&
652 "PathDiagnosticControlFlowPiece needs at least one location.");
653 return LPairs[0].getStart();
654 }
655
657 assert(!LPairs.empty() &&
658 "PathDiagnosticControlFlowPiece needs at least one location.");
659 return LPairs[0].getEnd();
660 }
661
663 LPairs[0].setStart(L);
664 }
665
667 LPairs[0].setEnd(L);
668 }
669
670 void push_back(const PathDiagnosticLocationPair &X) { LPairs.push_back(X); }
671
673 return getStartLocation();
674 }
675
676 using iterator = std::vector<PathDiagnosticLocationPair>::iterator;
677
678 iterator begin() { return LPairs.begin(); }
679 iterator end() { return LPairs.end(); }
680
681 void flattenLocations() override {
682 for (auto &I : *this)
683 I.flatten();
684 }
685
687 std::vector<PathDiagnosticLocationPair>::const_iterator;
688
689 const_iterator begin() const { return LPairs.begin(); }
690 const_iterator end() const { return LPairs.end(); }
691
692 static bool classof(const PathDiagnosticPiece *P) {
693 return P->getKind() == ControlFlow;
694 }
695
696 void dump() const override;
697
698 void Profile(llvm::FoldingSetNodeID &ID) const override;
699};
700
702public:
706
708
709 void flattenLocations() override {
711 for (const auto &I : subPieces)
712 I->flattenLocations();
713 }
714
715 static bool classof(const PathDiagnosticPiece *P) {
716 return P->getKind() == Macro;
717 }
718
719 void dump() const override;
720
721 void Profile(llvm::FoldingSetNodeID &ID) const override;
722};
723
725public:
727 bool AddPosRange = true)
728 : PathDiagnosticSpotPiece(Pos, S, Note, AddPosRange) {}
730
731 static bool classof(const PathDiagnosticPiece *P) {
732 return P->getKind() == Note;
733 }
734
735 void dump() const override;
736
737 void Profile(llvm::FoldingSetNodeID &ID) const override;
738};
739
741public:
743 bool AddPosRange = true)
744 : PathDiagnosticSpotPiece(Pos, S, PopUp, AddPosRange) {}
746
747 static bool classof(const PathDiagnosticPiece *P) {
748 return P->getKind() == PopUp;
749 }
750
751 void dump() const override;
752
753 void Profile(llvm::FoldingSetNodeID &ID) const override;
754};
755
756/// File IDs mapped to sets of line numbers.
757using FilesToLineNumsMap = std::map<FileID, std::set<unsigned>>;
758
759/// PathDiagnostic - PathDiagnostic objects represent a single path-sensitive
760/// diagnostic. It represents an ordered-collection of PathDiagnosticPieces,
761/// each which represent the pieces of the path.
762class PathDiagnostic : public llvm::FoldingSetNode {
763 std::string CheckerName;
764 const Decl *DeclWithIssue;
765 std::string BugType;
766 std::string VerboseDesc;
767 std::string ShortDesc;
768 std::string Category;
769 std::deque<std::string> OtherDesc;
770
771 /// Loc The location of the path diagnostic report.
773
774 PathPieces pathImpl;
776
777 /// Important bug uniqueing location.
778 /// The location info is useful to differentiate between bugs.
779 PathDiagnosticLocation UniqueingLoc;
780 const Decl *UniqueingDecl;
781
782 /// The top-level entry point from which this issue was discovered.
783 const Decl *AnalysisEntryPoint = nullptr;
784
785 /// Lines executed in the path.
786 std::unique_ptr<FilesToLineNumsMap> ExecutedLines;
787
788public:
789 PathDiagnostic() = delete;
790 PathDiagnostic(StringRef CheckerName, const Decl *DeclWithIssue,
791 StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,
792 StringRef category, PathDiagnosticLocation LocationToUnique,
793 const Decl *DeclToUnique, const Decl *AnalysisEntryPoint,
794 std::unique_ptr<FilesToLineNumsMap> ExecutedLines);
796
798
799 /// Return the path currently used by builders for constructing the
800 /// PathDiagnostic.
802 if (pathStack.empty())
803 return pathImpl;
804 return *pathStack.back();
805 }
806
807 /// Return a mutable version of 'path'.
809 return pathImpl;
810 }
811
812 /// Return the unrolled size of the path.
813 unsigned full_size();
814
815 void pushActivePath(PathPieces *p) { pathStack.push_back(p); }
816 void popActivePath() { if (!pathStack.empty()) pathStack.pop_back(); }
817
818 bool isWithinCall() const { return !pathStack.empty(); }
819
821 assert(!Loc.isValid() && "End location already set!");
822 Loc = EndPiece->getLocation();
823 assert(Loc.isValid() && "Invalid location for end-of-path piece");
824 getActivePath().push_back(std::move(EndPiece));
825 }
826
827 void appendToDesc(StringRef S) {
828 if (!ShortDesc.empty())
829 ShortDesc += S;
830 VerboseDesc += S;
831 }
832
833 StringRef getVerboseDescription() const { return VerboseDesc; }
834
835 StringRef getShortDescription() const {
836 return ShortDesc.empty() ? VerboseDesc : ShortDesc;
837 }
838
839 StringRef getCheckerName() const { return CheckerName; }
840 StringRef getBugType() const { return BugType; }
841 StringRef getCategory() const { return Category; }
842
843 using meta_iterator = std::deque<std::string>::const_iterator;
844
845 meta_iterator meta_begin() const { return OtherDesc.begin(); }
846 meta_iterator meta_end() const { return OtherDesc.end(); }
847 void addMeta(StringRef s) { OtherDesc.push_back(std::string(s)); }
848
850 return *ExecutedLines;
851 }
852
854 return *ExecutedLines;
855 }
856
857 /// Get the top-level entry point from which this issue was discovered.
858 const Decl *getAnalysisEntryPoint() const { return AnalysisEntryPoint; }
859
860 /// Return the semantic context where an issue occurred. If the
861 /// issue occurs along a path, this represents the "central" area
862 /// where the bug manifests.
863 const Decl *getDeclWithIssue() const { return DeclWithIssue; }
864
865 void setDeclWithIssue(const Decl *D) {
866 DeclWithIssue = D;
867 }
868
870 return Loc;
871 }
872
874 Loc = NewLoc;
875 }
876
877 /// Get the location on which the report should be uniqued.
879 return UniqueingLoc;
880 }
881
882 /// Get the declaration containing the uniqueing location.
883 const Decl *getUniqueingDecl() const {
884 return UniqueingDecl;
885 }
886
887 /// Get a hash that identifies the issue.
889 const LangOptions &LangOpts) const;
890
892 Loc.flatten();
893 for (const auto &I : pathImpl)
894 I->flattenLocations();
895 }
896
897 /// Profiles the diagnostic, independent of the path it references.
898 ///
899 /// This can be used to merge diagnostics that refer to the same issue
900 /// along different paths.
901 void Profile(llvm::FoldingSetNodeID &ID) const;
902
903 /// Profiles the diagnostic, including its path.
904 ///
905 /// Two diagnostics with the same issue along different paths will generate
906 /// different profiles.
907 void FullProfile(llvm::FoldingSetNodeID &ID) const;
908};
909
910} // namespace ento
911} // namespace clang
912
913#endif // LLVM_CLANG_ANALYSIS_PATHDIAGNOSTIC_H
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
#define X(type, name)
Definition Value.h:97
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
#define SM(sm)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
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:4041
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 }.
Definition Stmt.h:1750
ConditionalOperator - The ?
Definition Expr.h:4394
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:80
A SourceLocation and its associated SourceManager.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition Expr.h:3367
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.
SourceRange()=default
It represents a stack frame of the call stack.
Stmt - This represents one statement.
Definition Stmt.h:86
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.
void Profile(llvm::FoldingSetNodeID &ID)
Used for profiling in the FoldingSet.
ConsumerFiles files
A vector of <consumer,file> pairs.
std::vector< std::pair< StringRef, StringRef > > ConsumerFiles
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 StackFrame *SF, const SourceManager &SM)
Create a location for the beginning of the enclosing declaration body.
static SourceLocation getValidSourceLocation(const Stmt *S, StackFrameOrAnalysisDeclContext SFAC, bool UseEndOfStatement=false)
Construct a source location that corresponds to either the beginning or the end of the given statemen...
static PathDiagnosticLocation createDeclEnd(const StackFrame *SF, const SourceManager &SM)
Constructs a location for the end 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 createEnd(const Stmt *S, const SourceManager &SM, const StackFrameOrAnalysisDeclContext SFAC)
Create a location for the end of the statement.
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.
PathDiagnosticLocation(const Stmt *s, const SourceManager &sm, StackFrameOrAnalysisDeclContext SFAC)
Create a location corresponding to the given 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 createBegin(const Decl *D, const SourceManager &SM, const StackFrameOrAnalysisDeclContext SFAC)
Create a location for the beginning of the declaration.
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 createSingleLocation(const PathDiagnosticLocation &PDL)
Convert the given location into a single kind location.
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
PathDiagnosticPiece(StringRef s, Kind k, DisplayHint hint=Below)
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)
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
SmallString< 32 > getIssueHash(const SourceManager &SrcMgr, const LangOptions &LangOpts) const
Get a hash that identifies the issue.
PathDiagnosticLocation getLocation() const
PathPieces flatten(bool ShouldFlattenMacros) const
Public enums and private classes that are part of the SourceManager implementation.
llvm::PointerUnion< const StackFrame *, AnalysisDeclContext * > StackFrameOrAnalysisDeclContext
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
std::map< FileID, std::set< unsigned > > FilesToLineNumsMap
File IDs mapped to sets of line numbers.
The JSON file list parser is used to communicate input to InstallAPI.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ Result
The result type of a method or function.
Definition TypeBase.h:905
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....