clang  10.0.0svn
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_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H
14 #define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_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/Optional.h"
23 #include "llvm/ADT/PointerUnion.h"
24 #include "llvm/ADT/SmallVector.h"
25 #include "llvm/ADT/StringRef.h"
26 #include "llvm/Support/Allocator.h"
27 #include <cassert>
28 #include <deque>
29 #include <iterator>
30 #include <list>
31 #include <map>
32 #include <memory>
33 #include <set>
34 #include <string>
35 #include <utility>
36 #include <vector>
37 
38 namespace clang {
39 
40 class AnalysisDeclContext;
41 class BinaryOperator;
42 class CallEnter;
43 class CallExitEnd;
44 class CallExpr;
45 class ConditionalOperator;
46 class Decl;
47 class Expr;
48 class LocationContext;
49 class MemberExpr;
50 class ProgramPoint;
51 class SourceManager;
52 
53 namespace ento {
54 
55 //===----------------------------------------------------------------------===//
56 // High-level interface for handlers of path-sensitive diagnostics.
57 //===----------------------------------------------------------------------===//
58 
59 class PathDiagnostic;
60 
62 public:
63  class PDFileEntry : public llvm::FoldingSetNode {
64  public:
65  PDFileEntry(llvm::FoldingSetNodeID &NodeID) : NodeID(NodeID) {}
66 
67  using ConsumerFiles = std::vector<std::pair<StringRef, StringRef>>;
68 
69  /// A vector of <consumer,file> pairs.
71 
72  /// A precomputed hash tag used for uniquing PDFileEntry objects.
73  const llvm::FoldingSetNodeID NodeID;
74 
75  /// Used for profiling in the FoldingSet.
76  void Profile(llvm::FoldingSetNodeID &ID) { ID = NodeID; }
77  };
78 
79  class FilesMade {
80  llvm::BumpPtrAllocator Alloc;
81  llvm::FoldingSet<PDFileEntry> Set;
82 
83  public:
84  ~FilesMade();
85 
86  bool empty() const { return Set.empty(); }
87 
88  void addDiagnostic(const PathDiagnostic &PD,
89  StringRef ConsumerName,
90  StringRef fileName);
91 
92  PDFileEntry::ConsumerFiles *getFiles(const PathDiagnostic &PD);
93  };
94 
95 private:
96  virtual void anchor();
97 
98 public:
99  PathDiagnosticConsumer() = default;
100  virtual ~PathDiagnosticConsumer();
101 
103 
104  virtual void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
105  FilesMade *filesMade) = 0;
106 
107  virtual StringRef getName() const = 0;
108 
109  void HandlePathDiagnostic(std::unique_ptr<PathDiagnostic> D);
110 
112  /// Only runs visitors, no output generated.
114 
115  /// Used for HTML, SARIF, and text output.
117 
118  /// Used for plist output, used for "arrows" generation.
120  };
121 
123 
125  return getGenerationScheme() != None;
126  }
127 
128  bool shouldAddPathEdges() const { return getGenerationScheme() == Extensive; }
129 
130  virtual bool supportsLogicalOpControlFlow() const { return false; }
131 
132  /// Return true if the PathDiagnosticConsumer supports individual
133  /// PathDiagnostics that span multiple files.
134  virtual bool supportsCrossFileDiagnostics() const { return false; }
135 
136 protected:
137  bool flushed = false;
138  llvm::FoldingSet<PathDiagnostic> Diags;
139 };
140 
141 //===----------------------------------------------------------------------===//
142 // Path-sensitive diagnostics.
143 //===----------------------------------------------------------------------===//
144 
146 public:
147  bool isPoint = false;
148 
149  PathDiagnosticRange(SourceRange R, bool isP = false)
150  : SourceRange(R), isPoint(isP) {}
151  PathDiagnosticRange() = default;
152 };
153 
155  llvm::PointerUnion<const LocationContext *, AnalysisDeclContext *>;
156 
158 private:
159  enum Kind { RangeK, SingleLocK, StmtK, DeclK } K = SingleLocK;
160 
161  const Stmt *S = nullptr;
162  const Decl *D = nullptr;
163  const SourceManager *SM = nullptr;
166 
168  : K(kind), SM(&sm), Loc(genLocation(L)), Range(genRange()) {}
169 
170  FullSourceLoc genLocation(
172  LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext *)nullptr) const;
173 
174  PathDiagnosticRange genRange(
175  LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext *)nullptr) const;
176 
177 public:
178  /// Create an invalid location.
179  PathDiagnosticLocation() = default;
180 
181  /// Create a location corresponding to the given statement.
184  : K(s->getBeginLoc().isValid() ? StmtK : SingleLocK),
185  S(K == StmtK ? s : nullptr), SM(&sm),
186  Loc(genLocation(SourceLocation(), lac)), Range(genRange(lac)) {
187  assert(K == SingleLocK || S);
188  assert(K == SingleLocK || Loc.isValid());
189  assert(K == SingleLocK || Range.isValid());
190  }
191 
192  /// Create a location corresponding to the given declaration.
194  : K(DeclK), D(d), SM(&sm), Loc(genLocation()), Range(genRange()) {
195  assert(D);
196  assert(Loc.isValid());
197  assert(Range.isValid());
198  }
199 
200  /// Create a location at an explicit offset in the source.
201  ///
202  /// This should only be used if there are no more appropriate constructors.
204  : SM(&sm), Loc(loc, sm), Range(genRange()) {
205  assert(Loc.isValid());
206  assert(Range.isValid());
207  }
208 
209  /// Create a location corresponding to the given declaration.
211  const SourceManager &SM) {
212  return PathDiagnosticLocation(D, SM);
213  }
214 
215  /// Create a location for the beginning of the declaration.
216  static PathDiagnosticLocation createBegin(const Decl *D,
217  const SourceManager &SM);
218 
219  /// Create a location for the beginning of the declaration.
220  /// The third argument is ignored, useful for generic treatment
221  /// of statements and declarations.
223  createBegin(const Decl *D, const SourceManager &SM,
224  const LocationOrAnalysisDeclContext LAC) {
225  return createBegin(D, SM);
226  }
227 
228  /// Create a location for the beginning of the statement.
229  static PathDiagnosticLocation createBegin(const Stmt *S,
230  const SourceManager &SM,
232 
233  /// Create a location for the end of the statement.
234  ///
235  /// If the statement is a CompoundStatement, the location will point to the
236  /// closing brace instead of following it.
237  static PathDiagnosticLocation createEnd(const Stmt *S,
238  const SourceManager &SM,
240 
241  /// Create the location for the operator of the binary expression.
242  /// Assumes the statement has a valid location.
243  static PathDiagnosticLocation createOperatorLoc(const BinaryOperator *BO,
244  const SourceManager &SM);
245  static PathDiagnosticLocation createConditionalColonLoc(
246  const ConditionalOperator *CO,
247  const SourceManager &SM);
248 
249  /// For member expressions, return the location of the '.' or '->'.
250  /// Assumes the statement has a valid location.
251  static PathDiagnosticLocation createMemberLoc(const MemberExpr *ME,
252  const SourceManager &SM);
253 
254  /// Create a location for the beginning of the compound statement.
255  /// Assumes the statement has a valid location.
256  static PathDiagnosticLocation createBeginBrace(const CompoundStmt *CS,
257  const SourceManager &SM);
258 
259  /// Create a location for the end of the compound statement.
260  /// Assumes the statement has a valid location.
261  static PathDiagnosticLocation createEndBrace(const CompoundStmt *CS,
262  const SourceManager &SM);
263 
264  /// Create a location for the beginning of the enclosing declaration body.
265  /// Defaults to the beginning of the first statement in the declaration body.
266  static PathDiagnosticLocation createDeclBegin(const LocationContext *LC,
267  const SourceManager &SM);
268 
269  /// Constructs a location for the end of the enclosing declaration body.
270  /// Defaults to the end of brace.
271  static PathDiagnosticLocation createDeclEnd(const LocationContext *LC,
272  const SourceManager &SM);
273 
274  /// Create a location corresponding to the given valid ProgramPoint.
276  const SourceManager &SMng);
277 
278  /// Convert the given location into a single kind location.
279  static PathDiagnosticLocation createSingleLocation(
280  const PathDiagnosticLocation &PDL);
281 
282  /// Construct a source location that corresponds to either the beginning
283  /// or the end of the given statement, or a nearby valid source location
284  /// if the statement does not have a valid source location of its own.
285  static SourceLocation
286  getValidSourceLocation(const Stmt *S, LocationOrAnalysisDeclContext LAC,
287  bool UseEndOfStatement = false);
288 
289  bool operator==(const PathDiagnosticLocation &X) const {
290  return K == X.K && Loc == X.Loc && Range == X.Range;
291  }
292 
293  bool operator!=(const PathDiagnosticLocation &X) const {
294  return !(*this == X);
295  }
296 
297  bool isValid() const {
298  return SM != nullptr;
299  }
300 
302  return Loc;
303  }
304 
306  return Range;
307  }
308 
309  const Stmt *asStmt() const { assert(isValid()); return S; }
310  const Stmt *getStmtOrNull() const {
311  if (!isValid())
312  return nullptr;
313  return asStmt();
314  }
315 
316  const Decl *asDecl() const { assert(isValid()); return D; }
317 
318  bool hasRange() const { return K == StmtK || K == RangeK || K == DeclK; }
319 
320  bool hasValidLocation() const { return asLocation().isValid(); }
321 
322  void invalidate() {
323  *this = PathDiagnosticLocation();
324  }
325 
326  void flatten();
327 
328  const SourceManager& getManager() const { assert(isValid()); return *SM; }
329 
330  void Profile(llvm::FoldingSetNodeID &ID) const;
331 
332  void dump() const;
333 };
334 
336 private:
338 
339 public:
341  const PathDiagnosticLocation &end)
342  : Start(start), End(end) {}
343 
344  const PathDiagnosticLocation &getStart() const { return Start; }
345  const PathDiagnosticLocation &getEnd() const { return End; }
346 
347  void setStart(const PathDiagnosticLocation &L) { Start = L; }
348  void setEnd(const PathDiagnosticLocation &L) { End = L; }
349 
350  void flatten() {
351  Start.flatten();
352  End.flatten();
353  }
354 
355  void Profile(llvm::FoldingSetNodeID &ID) const {
356  Start.Profile(ID);
357  End.Profile(ID);
358  }
359 };
360 
361 //===----------------------------------------------------------------------===//
362 // Path "pieces" for path-sensitive diagnostics.
363 //===----------------------------------------------------------------------===//
364 
365 class PathDiagnosticPiece: public llvm::FoldingSetNode {
366 public:
367  enum Kind { ControlFlow, Event, Macro, Call, Note, PopUp };
368  enum DisplayHint { Above, Below };
369 
370 private:
371  const std::string str;
372  const Kind kind;
373  const DisplayHint Hint;
374 
375  /// In the containing bug report, this piece is the last piece from
376  /// the main source file.
377  bool LastInMainSourceFile = false;
378 
379  /// A constant string that can be used to tag the PathDiagnosticPiece,
380  /// typically with the identification of the creator. The actual pointer
381  /// value is meant to be an identifier; the string itself is useful for
382  /// debugging.
383  StringRef Tag;
384 
385  std::vector<SourceRange> ranges;
386  std::vector<FixItHint> fixits;
387 
388 protected:
389  PathDiagnosticPiece(StringRef s, Kind k, DisplayHint hint = Below);
390  PathDiagnosticPiece(Kind k, DisplayHint hint = Below);
391 
392 public:
393  PathDiagnosticPiece() = delete;
394  PathDiagnosticPiece(const PathDiagnosticPiece &) = delete;
395  PathDiagnosticPiece &operator=(const PathDiagnosticPiece &) = delete;
396  virtual ~PathDiagnosticPiece();
397 
398  StringRef getString() const { return str; }
399 
400  /// Tag this PathDiagnosticPiece with the given C-string.
401  void setTag(const char *tag) { Tag = tag; }
402 
403  /// Return the opaque tag (if any) on the PathDiagnosticPiece.
404  const void *getTag() const { return Tag.data(); }
405 
406  /// Return the string representation of the tag. This is useful
407  /// for debugging.
408  StringRef getTagStr() const { return Tag; }
409 
410  /// getDisplayHint - Return a hint indicating where the diagnostic should
411  /// be displayed by the PathDiagnosticConsumer.
412  DisplayHint getDisplayHint() const { return Hint; }
413 
414  virtual PathDiagnosticLocation getLocation() const = 0;
415  virtual void flattenLocations() = 0;
416 
417  Kind getKind() const { return kind; }
418 
420  if (!R.isValid())
421  return;
422  ranges.push_back(R);
423  }
424 
426  if (!B.isValid() || !E.isValid())
427  return;
428  ranges.push_back(SourceRange(B,E));
429  }
430 
431  void addFixit(FixItHint F) {
432  fixits.push_back(F);
433  }
434 
435  /// Return the SourceRanges associated with this PathDiagnosticPiece.
436  ArrayRef<SourceRange> getRanges() const { return ranges; }
437 
438  /// Return the fix-it hints associated with this PathDiagnosticPiece.
439  ArrayRef<FixItHint> getFixits() const { return fixits; }
440 
441  virtual void Profile(llvm::FoldingSetNodeID &ID) const;
442 
444  LastInMainSourceFile = true;
445  }
446 
447  bool isLastInMainSourceFile() const {
448  return LastInMainSourceFile;
449  }
450 
451  virtual void dump() const = 0;
452 };
453 
454 using PathDiagnosticPieceRef = std::shared_ptr<PathDiagnosticPiece>;
455 
456 class PathPieces : public std::list<PathDiagnosticPieceRef> {
457  void flattenTo(PathPieces &Primary, PathPieces &Current,
458  bool ShouldFlattenMacros) const;
459 
460 public:
461  PathPieces flatten(bool ShouldFlattenMacros) const {
462  PathPieces Result;
463  flattenTo(Result, Result, ShouldFlattenMacros);
464  return Result;
465  }
466 
467  void dump() const;
468 };
469 
471 private:
473 
474 public:
476  StringRef s,
478  bool addPosRange = true)
479  : PathDiagnosticPiece(s, k), Pos(pos) {
480  assert(Pos.isValid() && Pos.hasValidLocation() &&
481  "PathDiagnosticSpotPiece's must have a valid location.");
482  if (addPosRange && Pos.hasRange()) addRange(Pos.asRange());
483  }
484 
485  PathDiagnosticLocation getLocation() const override { return Pos; }
486  void flattenLocations() override { Pos.flatten(); }
487 
488  void Profile(llvm::FoldingSetNodeID &ID) const override;
489 
490  static bool classof(const PathDiagnosticPiece *P) {
491  return P->getKind() == Event || P->getKind() == Macro ||
492  P->getKind() == Note || P->getKind() == PopUp;
493  }
494 };
495 
497  Optional<bool> IsPrunable;
498 
499 public:
501  StringRef s, bool addPosRange = true)
502  : PathDiagnosticSpotPiece(pos, s, Event, addPosRange) {}
503  ~PathDiagnosticEventPiece() override;
504 
505  /// Mark the diagnostic piece as being potentially prunable. This
506  /// flag may have been previously set, at which point it will not
507  /// be reset unless one specifies to do so.
508  void setPrunable(bool isPrunable, bool override = false) {
509  if (IsPrunable.hasValue() && !override)
510  return;
511  IsPrunable = isPrunable;
512  }
513 
514  /// Return true if the diagnostic piece is prunable.
515  bool isPrunable() const {
516  return IsPrunable.hasValue() ? IsPrunable.getValue() : false;
517  }
518 
519  void dump() const override;
520 
521  static bool classof(const PathDiagnosticPiece *P) {
522  return P->getKind() == Event;
523  }
524 };
525 
527  const Decl *Caller;
528  const Decl *Callee = nullptr;
529 
530  // Flag signifying that this diagnostic has only call enter and no matching
531  // call exit.
532  bool NoExit;
533 
534  // Flag signifying that the callee function is an Objective-C autosynthesized
535  // property getter or setter.
536  bool IsCalleeAnAutosynthesizedPropertyAccessor = false;
537 
538  // The custom string, which should appear after the call Return Diagnostic.
539  // TODO: Should we allow multiple diagnostics?
540  std::string CallStackMessage;
541 
542  PathDiagnosticCallPiece(const Decl *callerD,
543  const PathDiagnosticLocation &callReturnPos)
544  : PathDiagnosticPiece(Call), Caller(callerD), NoExit(false),
545  callReturn(callReturnPos) {}
546  PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller)
547  : PathDiagnosticPiece(Call), Caller(caller), NoExit(true),
548  path(oldPath) {}
549 
550 public:
555 
556  ~PathDiagnosticCallPiece() override;
557 
558  const Decl *getCaller() const { return Caller; }
559 
560  const Decl *getCallee() const { return Callee; }
561  void setCallee(const CallEnter &CE, const SourceManager &SM);
562 
563  bool hasCallStackMessage() { return !CallStackMessage.empty(); }
564  void setCallStackMessage(StringRef st) { CallStackMessage = st; }
565 
566  PathDiagnosticLocation getLocation() const override { return callEnter; }
567 
568  std::shared_ptr<PathDiagnosticEventPiece> getCallEnterEvent() const;
569  std::shared_ptr<PathDiagnosticEventPiece>
570  getCallEnterWithinCallerEvent() const;
571  std::shared_ptr<PathDiagnosticEventPiece> getCallExitEvent() const;
572 
573  void flattenLocations() override {
574  callEnter.flatten();
575  callReturn.flatten();
576  for (const auto &I : path)
577  I->flattenLocations();
578  }
579 
580  static std::shared_ptr<PathDiagnosticCallPiece>
581  construct(const CallExitEnd &CE,
582  const SourceManager &SM);
583 
584  static PathDiagnosticCallPiece *construct(PathPieces &pieces,
585  const Decl *caller);
586 
587  void dump() const override;
588 
589  void Profile(llvm::FoldingSetNodeID &ID) const override;
590 
591  static bool classof(const PathDiagnosticPiece *P) {
592  return P->getKind() == Call;
593  }
594 };
595 
597  std::vector<PathDiagnosticLocationPair> LPairs;
598 
599 public:
601  const PathDiagnosticLocation &endPos,
602  StringRef s)
603  : PathDiagnosticPiece(s, ControlFlow) {
604  LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
605  }
606 
608  const PathDiagnosticLocation &endPos)
609  : PathDiagnosticPiece(ControlFlow) {
610  LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
611  }
612 
613  ~PathDiagnosticControlFlowPiece() override;
614 
616  assert(!LPairs.empty() &&
617  "PathDiagnosticControlFlowPiece needs at least one location.");
618  return LPairs[0].getStart();
619  }
620 
622  assert(!LPairs.empty() &&
623  "PathDiagnosticControlFlowPiece needs at least one location.");
624  return LPairs[0].getEnd();
625  }
626 
628  LPairs[0].setStart(L);
629  }
630 
632  LPairs[0].setEnd(L);
633  }
634 
635  void push_back(const PathDiagnosticLocationPair &X) { LPairs.push_back(X); }
636 
638  return getStartLocation();
639  }
640 
641  using iterator = std::vector<PathDiagnosticLocationPair>::iterator;
642 
643  iterator begin() { return LPairs.begin(); }
644  iterator end() { return LPairs.end(); }
645 
646  void flattenLocations() override {
647  for (auto &I : *this)
648  I.flatten();
649  }
650 
651  using const_iterator =
652  std::vector<PathDiagnosticLocationPair>::const_iterator;
653 
654  const_iterator begin() const { return LPairs.begin(); }
655  const_iterator end() const { return LPairs.end(); }
656 
657  static bool classof(const PathDiagnosticPiece *P) {
658  return P->getKind() == ControlFlow;
659  }
660 
661  void dump() const override;
662 
663  void Profile(llvm::FoldingSetNodeID &ID) const override;
664 };
665 
667 public:
669  : PathDiagnosticSpotPiece(pos, "", Macro) {}
670  ~PathDiagnosticMacroPiece() override;
671 
673 
674  void flattenLocations() override {
676  for (const auto &I : subPieces)
677  I->flattenLocations();
678  }
679 
680  static bool classof(const PathDiagnosticPiece *P) {
681  return P->getKind() == Macro;
682  }
683 
684  void dump() const override;
685 
686  void Profile(llvm::FoldingSetNodeID &ID) const override;
687 };
688 
690 public:
692  bool AddPosRange = true)
693  : PathDiagnosticSpotPiece(Pos, S, Note, AddPosRange) {}
694  ~PathDiagnosticNotePiece() override;
695 
696  static bool classof(const PathDiagnosticPiece *P) {
697  return P->getKind() == Note;
698  }
699 
700  void dump() const override;
701 
702  void Profile(llvm::FoldingSetNodeID &ID) const override;
703 };
704 
706 public:
708  bool AddPosRange = true)
709  : PathDiagnosticSpotPiece(Pos, S, PopUp, AddPosRange) {}
710  ~PathDiagnosticPopUpPiece() override;
711 
712  static bool classof(const PathDiagnosticPiece *P) {
713  return P->getKind() == PopUp;
714  }
715 
716  void dump() const override;
717 
718  void Profile(llvm::FoldingSetNodeID &ID) const override;
719 };
720 
721 /// File IDs mapped to sets of line numbers.
722 using FilesToLineNumsMap = std::map<FileID, std::set<unsigned>>;
723 
724 /// PathDiagnostic - PathDiagnostic objects represent a single path-sensitive
725 /// diagnostic. It represents an ordered-collection of PathDiagnosticPieces,
726 /// each which represent the pieces of the path.
727 class PathDiagnostic : public llvm::FoldingSetNode {
728  std::string CheckerName;
729  const Decl *DeclWithIssue;
730  std::string BugType;
731  std::string VerboseDesc;
732  std::string ShortDesc;
733  std::string Category;
734  std::deque<std::string> OtherDesc;
735 
736  /// Loc The location of the path diagnostic report.
738 
739  PathPieces pathImpl;
741 
742  /// Important bug uniqueing location.
743  /// The location info is useful to differentiate between bugs.
744  PathDiagnosticLocation UniqueingLoc;
745  const Decl *UniqueingDecl;
746 
747  /// Lines executed in the path.
748  std::unique_ptr<FilesToLineNumsMap> ExecutedLines;
749 
750 public:
751  PathDiagnostic() = delete;
752  PathDiagnostic(StringRef CheckerName, const Decl *DeclWithIssue,
753  StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,
754  StringRef category, PathDiagnosticLocation LocationToUnique,
755  const Decl *DeclToUnique,
756  std::unique_ptr<FilesToLineNumsMap> ExecutedLines);
757  ~PathDiagnostic();
758 
759  const PathPieces &path;
760 
761  /// Return the path currently used by builders for constructing the
762  /// PathDiagnostic.
764  if (pathStack.empty())
765  return pathImpl;
766  return *pathStack.back();
767  }
768 
769  /// Return a mutable version of 'path'.
771  return pathImpl;
772  }
773 
774  /// Return the unrolled size of the path.
775  unsigned full_size();
776 
777  void pushActivePath(PathPieces *p) { pathStack.push_back(p); }
778  void popActivePath() { if (!pathStack.empty()) pathStack.pop_back(); }
779 
780  bool isWithinCall() const { return !pathStack.empty(); }
781 
783  assert(!Loc.isValid() && "End location already set!");
784  Loc = EndPiece->getLocation();
785  assert(Loc.isValid() && "Invalid location for end-of-path piece");
786  getActivePath().push_back(std::move(EndPiece));
787  }
788 
789  void appendToDesc(StringRef S) {
790  if (!ShortDesc.empty())
791  ShortDesc += S;
792  VerboseDesc += S;
793  }
794 
795  StringRef getVerboseDescription() const { return VerboseDesc; }
796 
797  StringRef getShortDescription() const {
798  return ShortDesc.empty() ? VerboseDesc : ShortDesc;
799  }
800 
801  StringRef getCheckerName() const { return CheckerName; }
802  StringRef getBugType() const { return BugType; }
803  StringRef getCategory() const { return Category; }
804 
805  using meta_iterator = std::deque<std::string>::const_iterator;
806 
807  meta_iterator meta_begin() const { return OtherDesc.begin(); }
808  meta_iterator meta_end() const { return OtherDesc.end(); }
809  void addMeta(StringRef s) { OtherDesc.push_back(s); }
810 
812  return *ExecutedLines;
813  }
814 
816  return *ExecutedLines;
817  }
818 
819  /// Return the semantic context where an issue occurred. If the
820  /// issue occurs along a path, this represents the "central" area
821  /// where the bug manifests.
822  const Decl *getDeclWithIssue() const { return DeclWithIssue; }
823 
824  void setDeclWithIssue(const Decl *D) {
825  DeclWithIssue = D;
826  }
827 
829  return Loc;
830  }
831 
833  Loc = NewLoc;
834  }
835 
836  /// Get the location on which the report should be uniqued.
838  return UniqueingLoc;
839  }
840 
841  /// Get the declaration containing the uniqueing location.
842  const Decl *getUniqueingDecl() const {
843  return UniqueingDecl;
844  }
845 
847  Loc.flatten();
848  for (const auto &I : pathImpl)
849  I->flattenLocations();
850  }
851 
852  /// Profiles the diagnostic, independent of the path it references.
853  ///
854  /// This can be used to merge diagnostics that refer to the same issue
855  /// along different paths.
856  void Profile(llvm::FoldingSetNodeID &ID) const;
857 
858  /// Profiles the diagnostic, including its path.
859  ///
860  /// Two diagnostics with the same issue along different paths will generate
861  /// different profiles.
862  void FullProfile(llvm::FoldingSetNodeID &ID) const;
863 };
864 
865 } // namespace ento
866 } // namespace clang
867 
868 #endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H
static bool classof(const PathDiagnosticPiece *P)
PathDiagnosticSpotPiece(const PathDiagnosticLocation &pos, StringRef s, PathDiagnosticPiece::Kind k, bool addPosRange=true)
virtual void FlushDiagnosticsImpl(std::vector< const PathDiagnostic *> &Diags, FilesMade *filesMade)=0
void setTag(const char *tag)
Tag this PathDiagnosticPiece with the given C-string.
PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, const PathDiagnosticLocation &endPos, StringRef s)
PathDiagnosticLocation getLocation() const override
Stmt - This represents one statement.
Definition: Stmt.h:66
void setLocation(PathDiagnosticLocation NewLoc)
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:88
virtual StringRef getName() const =0
Represents a point when we begin processing an inlined call.
Definition: ProgramPoint.h:630
StringRef P
void Profile(llvm::FoldingSetNodeID &ID) const
A Range represents the closed range [from, to].
PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos)
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
void setPrunable(bool isPrunable, bool override=false)
Mark the diagnostic piece as being potentially prunable.
PathDiagnosticLocation getStartLocation() const
const PathDiagnosticLocation & getEnd() const
bool operator==(const PathDiagnosticLocation &X) const
meta_iterator meta_begin() const
const FilesToLineNumsMap & getExecutedLines() const
PathDiagnosticLocation getLocation() const
PathDiagnostic - PathDiagnostic objects represent a single path-sensitive diagnostic.
PathDiagnosticNotePiece(const PathDiagnosticLocation &Pos, StringRef S, bool AddPosRange=true)
void setStartLocation(const PathDiagnosticLocation &L)
void addRange(SourceLocation B, SourceLocation E)
AnalysisDeclContext contains the context data for the function or method under analysis.
static bool classof(const PathDiagnosticPiece *P)
StringRef getVerboseDescription() const
void pushActivePath(PathPieces *p)
int Category
Definition: Format.cpp:1810
FilesToLineNumsMap & getExecutedLines()
virtual bool supportsLogicalOpControlFlow() const
PathPieces & getMutablePieces()
Return a mutable version of &#39;path&#39;.
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
PDFileEntry(llvm::FoldingSetNodeID &NodeID)
llvm::FoldingSet< PathDiagnostic > Diags
void setStart(const PathDiagnosticLocation &L)
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
std::vector< std::pair< StringRef, StringRef > > ConsumerFiles
bool operator!=(const PathDiagnosticLocation &X) const
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3409
StringRef getBugType() const
meta_iterator meta_end() const
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
PathDiagnosticLocation(const Stmt *s, const SourceManager &sm, LocationOrAnalysisDeclContext lac)
Create a location corresponding to the given statement.
PathDiagnosticLocation getEndLocation() const
ConditionalOperator - The ?: ternary operator.
Definition: Expr.h:3707
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:1320
const void * getTag() const
Return the opaque tag (if any) on the PathDiagnosticPiece.
PathDiagnosticPopUpPiece(const PathDiagnosticLocation &Pos, StringRef S, bool AddPosRange=true)
void HandlePathDiagnostic(std::unique_ptr< PathDiagnostic > D)
std::vector< PathDiagnosticLocationPair >::const_iterator const_iterator
Represents a point when we finish the call exit sequence (for inlined call).
Definition: ProgramPoint.h:688
DisplayHint getDisplayHint() const
getDisplayHint - Return a hint indicating where the diagnostic should be displayed by the PathDiagnos...
bool isPrunable() const
Return true if the diagnostic piece is prunable.
SourceLocation End
StringRef getCheckerName() const
PathDiagnosticLocation getUniqueingLoc() const
Get the location on which the report should be uniqued.
std::vector< PathDiagnosticLocationPair >::iterator iterator
const SourceManager & getManager() const
llvm::PointerUnion< const LocationContext *, AnalysisDeclContext * > LocationOrAnalysisDeclContext
PathDiagnosticRange(SourceRange R, bool isP=false)
std::map< FileID, std::set< unsigned > > FilesToLineNumsMap
File IDs mapped to sets of line numbers.
PathPieces flatten(bool ShouldFlattenMacros) const
const SourceManager & SM
Definition: Format.cpp:1667
StringRef getCategory() const
Only runs visitors, no output generated.
PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, StringRef s, bool addPosRange=true)
const llvm::FoldingSetNodeID NodeID
A precomputed hash tag used for uniquing PDFileEntry objects.
void Profile(llvm::FoldingSetNodeID &ID) const
Encodes a location in the source.
std::deque< std::string >::const_iterator meta_iterator
void setEndOfPath(PathDiagnosticPieceRef EndPiece)
virtual bool supportsCrossFileDiagnostics() const
Return true if the PathDiagnosticConsumer supports individual PathDiagnostics that span multiple file...
PathDiagnosticLocation getLocation() const override
Used for plist output, used for "arrows" generation.
ConsumerFiles files
A vector of <consumer,file> pairs.
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM, const LocationOrAnalysisDeclContext LAC)
Create a location for the beginning of the declaration.
ArrayRef< SourceRange > getRanges() const
Return the SourceRanges associated with this PathDiagnosticPiece.
Dataflow Directional Tag Classes.
const PathDiagnosticLocation & getStart() const
bool isValid() const
Return true if this is a valid SourceLocation object.
PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, const PathDiagnosticLocation &endPos)
void FlushDiagnostics(FilesMade *FilesMade)
PathDiagnosticRange asRange() const
std::unique_ptr< DiagnosticConsumer > create(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords=false)
Returns a DiagnosticConsumer that serializes diagnostics to a bitcode file.
void setEndLocation(const PathDiagnosticLocation &L)
PathDiagnosticLocationPair(const PathDiagnosticLocation &start, const PathDiagnosticLocation &end)
void appendToDesc(StringRef S)
virtual PathGenerationScheme getGenerationScheme() const
PathDiagnosticLocation(SourceLocation loc, const SourceManager &sm)
Create a location at an explicit offset in the source.
PathDiagnosticLocation(const Decl *d, const SourceManager &sm)
Create a location corresponding to the given declaration.
void push_back(const PathDiagnosticLocationPair &X)
ArrayRef< FixItHint > getFixits() const
Return the fix-it hints associated with this PathDiagnosticPiece.
static bool classof(const PathDiagnosticPiece *P)
void Profile(llvm::FoldingSetNodeID &ID)
Used for profiling in the FoldingSet.
PathDiagnosticLocation getLocation() const override
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
Definition: SemaDecl.cpp:14652
Used for HTML, SARIF, and text output.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:2811
Defines the clang::SourceLocation class and associated facilities.
PathPieces & getActivePath()
Return the path currently used by builders for constructing the PathDiagnostic.
bool isValid() const
unsigned kind
All of the diagnostics that can be emitted by the frontend.
Definition: DiagnosticIDs.h:60
static bool classof(const PathDiagnosticPiece *P)
StringRef getTagStr() const
Return the string representation of the tag.
A SourceLocation and its associated SourceManager.
PathDiagnosticLocation callEnterWithin
const Decl * getUniqueingDecl() const
Get the declaration containing the uniqueing location.
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
Definition: Diagnostic.h:66
A trivial tuple used to represent a source range.
void setDeclWithIssue(const Decl *D)
static bool classof(const PathDiagnosticPiece *P)
This class handles loading and caching of source files into memory.
static bool classof(const PathDiagnosticPiece *P)
StringRef getShortDescription() const
const Decl * getDeclWithIssue() const
Return the semantic context where an issue occurred.
void setEnd(const PathDiagnosticLocation &L)
static bool classof(const PathDiagnosticPiece *P)