clang  3.7.0
PathDiagnostic.h
Go to the documentation of this file.
1 //===--- PathDiagnostic.h - Path-Specific Diagnostic Handling ---*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the PathDiagnostic-related interfaces.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H
15 #define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H
16 
19 #include "llvm/ADT/FoldingSet.h"
20 #include "llvm/ADT/IntrusiveRefCntPtr.h"
21 #include "llvm/ADT/Optional.h"
22 #include "llvm/ADT/PointerUnion.h"
23 #include <deque>
24 #include <iterator>
25 #include <list>
26 #include <string>
27 #include <vector>
28 
29 namespace clang {
30 class ConditionalOperator;
31 class AnalysisDeclContext;
32 class BinaryOperator;
33 class CompoundStmt;
34 class Decl;
35 class LocationContext;
36 class MemberExpr;
37 class ParentMap;
38 class ProgramPoint;
39 class SourceManager;
40 class Stmt;
41 class CallExpr;
42 
43 namespace ento {
44 
45 class ExplodedNode;
46 class SymExpr;
47 typedef const SymExpr* SymbolRef;
48 
49 //===----------------------------------------------------------------------===//
50 // High-level interface for handlers of path-sensitive diagnostics.
51 //===----------------------------------------------------------------------===//
52 
53 class PathDiagnostic;
54 
56 public:
57  class PDFileEntry : public llvm::FoldingSetNode {
58  public:
59  PDFileEntry(llvm::FoldingSetNodeID &NodeID) : NodeID(NodeID) {}
60 
61  typedef std::vector<std::pair<StringRef, StringRef> > ConsumerFiles;
62 
63  /// \brief A vector of <consumer,file> pairs.
65 
66  /// \brief A precomputed hash tag used for uniquing PDFileEntry objects.
67  const llvm::FoldingSetNodeID NodeID;
68 
69  /// \brief Used for profiling in the FoldingSet.
70  void Profile(llvm::FoldingSetNodeID &ID) { ID = NodeID; }
71  };
72 
73  class FilesMade {
74  llvm::BumpPtrAllocator Alloc;
75  llvm::FoldingSet<PDFileEntry> Set;
76 
77  public:
78  ~FilesMade();
79 
80  bool empty() const { return Set.empty(); }
81 
82  void addDiagnostic(const PathDiagnostic &PD,
83  StringRef ConsumerName,
84  StringRef fileName);
85 
87  };
88 
89 private:
90  virtual void anchor();
91 public:
93  virtual ~PathDiagnosticConsumer();
94 
95  void FlushDiagnostics(FilesMade *FilesMade);
96 
97  virtual void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
98  FilesMade *filesMade) = 0;
99 
100  virtual StringRef getName() const = 0;
101 
102  void HandlePathDiagnostic(std::unique_ptr<PathDiagnostic> D);
103 
106  virtual bool supportsLogicalOpControlFlow() const { return false; }
107 
108  /// Return true if the PathDiagnosticConsumer supports individual
109  /// PathDiagnostics that span multiple files.
110  virtual bool supportsCrossFileDiagnostics() const { return false; }
111 
112 protected:
113  bool flushed;
114  llvm::FoldingSet<PathDiagnostic> Diags;
115 };
116 
117 //===----------------------------------------------------------------------===//
118 // Path-sensitive diagnostics.
119 //===----------------------------------------------------------------------===//
120 
122 public:
123  bool isPoint;
124 
125  PathDiagnosticRange(const SourceRange &R, bool isP = false)
126  : SourceRange(R), isPoint(isP) {}
127 
129 };
130 
131 typedef llvm::PointerUnion<const LocationContext*, AnalysisDeclContext*>
133 
135 private:
136  enum Kind { RangeK, SingleLocK, StmtK, DeclK } K;
137  const Stmt *S;
138  const Decl *D;
139  const SourceManager *SM;
141  PathDiagnosticRange Range;
142 
144  Kind kind)
145  : K(kind), S(nullptr), D(nullptr), SM(&sm),
146  Loc(genLocation(L)), Range(genRange()) {
147  }
148 
149  FullSourceLoc genLocation(
151  LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext *)nullptr) const;
152 
153  PathDiagnosticRange genRange(
154  LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext *)nullptr) const;
155 
156 public:
157  /// Create an invalid location.
159  : K(SingleLocK), S(nullptr), D(nullptr), SM(nullptr) {}
160 
161  /// Create a location corresponding to the given statement.
163  const SourceManager &sm,
165  : K(s->getLocStart().isValid() ? StmtK : SingleLocK),
166  S(K == StmtK ? s : nullptr),
167  D(nullptr), SM(&sm),
168  Loc(genLocation(SourceLocation(), lac)),
169  Range(genRange(lac)) {
170  assert(K == SingleLocK || S);
171  assert(K == SingleLocK || Loc.isValid());
172  assert(K == SingleLocK || Range.isValid());
173  }
174 
175  /// Create a location corresponding to the given declaration.
177  : K(DeclK), S(nullptr), D(d), SM(&sm),
178  Loc(genLocation()), Range(genRange()) {
179  assert(D);
180  assert(Loc.isValid());
181  assert(Range.isValid());
182  }
183 
184  /// Create a location at an explicit offset in the source.
185  ///
186  /// This should only be used if there are no more appropriate constructors.
188  : K(SingleLocK), S(nullptr), D(nullptr), SM(&sm), Loc(loc, sm),
189  Range(genRange()) {
190  assert(Loc.isValid());
191  assert(Range.isValid());
192  }
193 
194  /// Create a location corresponding to the given declaration.
196  const SourceManager &SM) {
197  return PathDiagnosticLocation(D, SM);
198  }
199 
200  /// Create a location for the beginning of the declaration.
201  static PathDiagnosticLocation createBegin(const Decl *D,
202  const SourceManager &SM);
203 
204  /// Create a location for the beginning of the statement.
205  static PathDiagnosticLocation createBegin(const Stmt *S,
206  const SourceManager &SM,
208 
209  /// Create a location for the end of the statement.
210  ///
211  /// If the statement is a CompoundStatement, the location will point to the
212  /// closing brace instead of following it.
213  static PathDiagnosticLocation createEnd(const Stmt *S,
214  const SourceManager &SM,
216 
217  /// Create the location for the operator of the binary expression.
218  /// Assumes the statement has a valid location.
220  const SourceManager &SM);
222  const ConditionalOperator *CO,
223  const SourceManager &SM);
224 
225  /// For member expressions, return the location of the '.' or '->'.
226  /// Assumes the statement has a valid location.
228  const SourceManager &SM);
229 
230  /// Create a location for the beginning of the compound statement.
231  /// Assumes the statement has a valid location.
233  const SourceManager &SM);
234 
235  /// Create a location for the end of the compound statement.
236  /// Assumes the statement has a valid location.
238  const SourceManager &SM);
239 
240  /// Create a location for the beginning of the enclosing declaration body.
241  /// Defaults to the beginning of the first statement in the declaration body.
243  const SourceManager &SM);
244 
245  /// Constructs a location for the end of the enclosing declaration body.
246  /// Defaults to the end of brace.
248  const SourceManager &SM);
249 
250  /// Create a location corresponding to the given valid ExplodedNode.
252  const SourceManager &SMng);
253 
254  /// Create a location corresponding to the next valid ExplodedNode as end
255  /// of path location.
257  const SourceManager &SM);
258 
259  /// Convert the given location into a single kind location.
261  const PathDiagnosticLocation &PDL);
262 
263  bool operator==(const PathDiagnosticLocation &X) const {
264  return K == X.K && Loc == X.Loc && Range == X.Range;
265  }
266 
267  bool operator!=(const PathDiagnosticLocation &X) const {
268  return !(*this == X);
269  }
270 
271  bool isValid() const {
272  return SM != nullptr;
273  }
274 
276  return Loc;
277  }
278 
280  return Range;
281  }
282 
283  const Stmt *asStmt() const { assert(isValid()); return S; }
284  const Decl *asDecl() const { assert(isValid()); return D; }
285 
286  bool hasRange() const { return K == StmtK || K == RangeK || K == DeclK; }
287 
288  void invalidate() {
289  *this = PathDiagnosticLocation();
290  }
291 
292  void flatten();
293 
294  const SourceManager& getManager() const { assert(isValid()); return *SM; }
295 
296  void Profile(llvm::FoldingSetNodeID &ID) const;
297 
298  void dump() const;
299 
300  /// \brief Given an exploded node, retrieve the statement that should be used
301  /// for the diagnostic location.
302  static const Stmt *getStmt(const ExplodedNode *N);
303 
304  /// \brief Retrieve the statement corresponding to the successor node.
305  static const Stmt *getNextStmt(const ExplodedNode *N);
306 };
307 
309 private:
310  PathDiagnosticLocation Start, End;
311 public:
313  const PathDiagnosticLocation &end)
314  : Start(start), End(end) {}
315 
316  const PathDiagnosticLocation &getStart() const { return Start; }
317  const PathDiagnosticLocation &getEnd() const { return End; }
318 
319  void setStart(const PathDiagnosticLocation &L) { Start = L; }
320  void setEnd(const PathDiagnosticLocation &L) { End = L; }
321 
322  void flatten() {
323  Start.flatten();
324  End.flatten();
325  }
326 
327  void Profile(llvm::FoldingSetNodeID &ID) const {
328  Start.Profile(ID);
329  End.Profile(ID);
330  }
331 };
332 
333 //===----------------------------------------------------------------------===//
334 // Path "pieces" for path-sensitive diagnostics.
335 //===----------------------------------------------------------------------===//
336 
337 class PathDiagnosticPiece : public RefCountedBaseVPTR {
338 public:
341 
342 private:
343  const std::string str;
344  const Kind kind;
345  const DisplayHint Hint;
346 
347  /// \brief In the containing bug report, this piece is the last piece from
348  /// the main source file.
349  bool LastInMainSourceFile;
350 
351  /// A constant string that can be used to tag the PathDiagnosticPiece,
352  /// typically with the identification of the creator. The actual pointer
353  /// value is meant to be an identifier; the string itself is useful for
354  /// debugging.
355  StringRef Tag;
356 
357  std::vector<SourceRange> ranges;
358 
359  PathDiagnosticPiece() = delete;
360  PathDiagnosticPiece(const PathDiagnosticPiece &P) = delete;
361  void operator=(const PathDiagnosticPiece &P) = delete;
362 
363 protected:
364  PathDiagnosticPiece(StringRef s, Kind k, DisplayHint hint = Below);
365 
367 
368 public:
369  ~PathDiagnosticPiece() override;
370 
371  StringRef getString() const { return str; }
372 
373  /// Tag this PathDiagnosticPiece with the given C-string.
374  void setTag(const char *tag) { Tag = tag; }
375 
376  /// Return the opaque tag (if any) on the PathDiagnosticPiece.
377  const void *getTag() const { return Tag.data(); }
378 
379  /// Return the string representation of the tag. This is useful
380  /// for debugging.
381  StringRef getTagStr() const { return Tag; }
382 
383  /// getDisplayHint - Return a hint indicating where the diagnostic should
384  /// be displayed by the PathDiagnosticConsumer.
385  DisplayHint getDisplayHint() const { return Hint; }
386 
387  virtual PathDiagnosticLocation getLocation() const = 0;
388  virtual void flattenLocations() = 0;
389 
390  Kind getKind() const { return kind; }
391 
393  if (!R.isValid())
394  return;
395  ranges.push_back(R);
396  }
397 
399  if (!B.isValid() || !E.isValid())
400  return;
401  ranges.push_back(SourceRange(B,E));
402  }
403 
404  /// Return the SourceRanges associated with this PathDiagnosticPiece.
405  ArrayRef<SourceRange> getRanges() const { return ranges; }
406 
407  virtual void Profile(llvm::FoldingSetNodeID &ID) const;
408 
410  LastInMainSourceFile = true;
411  }
412 
413  bool isLastInMainSourceFile() const {
414  return LastInMainSourceFile;
415  }
416 
417  virtual void dump() const = 0;
418 };
419 
420 
421 class PathPieces : public std::list<IntrusiveRefCntPtr<PathDiagnosticPiece> > {
422  void flattenTo(PathPieces &Primary, PathPieces &Current,
423  bool ShouldFlattenMacros) const;
424 public:
425  ~PathPieces();
426 
427  PathPieces flatten(bool ShouldFlattenMacros) const {
429  flattenTo(Result, Result, ShouldFlattenMacros);
430  return Result;
431  }
432 
433  void dump() const;
434 };
435 
437 private:
439 public:
441  StringRef s,
443  bool addPosRange = true)
444  : PathDiagnosticPiece(s, k), Pos(pos) {
445  assert(Pos.isValid() && Pos.asLocation().isValid() &&
446  "PathDiagnosticSpotPiece's must have a valid location.");
447  if (addPosRange && Pos.hasRange()) addRange(Pos.asRange());
448  }
449 
450  PathDiagnosticLocation getLocation() const override { return Pos; }
451  void flattenLocations() override { Pos.flatten(); }
452 
453  void Profile(llvm::FoldingSetNodeID &ID) const override;
454 
455  static bool classof(const PathDiagnosticPiece *P) {
456  return P->getKind() == Event || P->getKind() == Macro;
457  }
458 };
459 
460 /// \brief Interface for classes constructing Stack hints.
461 ///
462 /// If a PathDiagnosticEvent occurs in a different frame than the final
463 /// diagnostic the hints can be used to summarize the effect of the call.
465 public:
466  virtual ~StackHintGenerator() = 0;
467 
468  /// \brief Construct the Diagnostic message for the given ExplodedNode.
469  virtual std::string getMessage(const ExplodedNode *N) = 0;
470 };
471 
472 /// \brief Constructs a Stack hint for the given symbol.
473 ///
474 /// The class knows how to construct the stack hint message based on
475 /// traversing the CallExpr associated with the call and checking if the given
476 /// symbol is returned or is one of the arguments.
477 /// The hint can be customized by redefining 'getMessageForX()' methods.
479 private:
480  SymbolRef Sym;
481  std::string Msg;
482 
483 public:
484  StackHintGeneratorForSymbol(SymbolRef S, StringRef M) : Sym(S), Msg(M) {}
486 
487  /// \brief Search the call expression for the symbol Sym and dispatch the
488  /// 'getMessageForX()' methods to construct a specific message.
489  std::string getMessage(const ExplodedNode *N) override;
490 
491  /// Produces the message of the following form:
492  /// 'Msg via Nth parameter'
493  virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex);
494  virtual std::string getMessageForReturn(const CallExpr *CallExpr) {
495  return Msg;
496  }
497  virtual std::string getMessageForSymbolNotFound() {
498  return Msg;
499  }
500 };
501 
503  Optional<bool> IsPrunable;
504 
505  /// If the event occurs in a different frame than the final diagnostic,
506  /// supply a message that will be used to construct an extra hint on the
507  /// returns from all the calls on the stack from this event to the final
508  /// diagnostic.
509  std::unique_ptr<StackHintGenerator> CallStackHint;
510 
511 public:
513  StringRef s, bool addPosRange = true,
514  StackHintGenerator *stackHint = nullptr)
515  : PathDiagnosticSpotPiece(pos, s, Event, addPosRange),
516  CallStackHint(stackHint) {}
517 
518  ~PathDiagnosticEventPiece() override;
519 
520  /// Mark the diagnostic piece as being potentially prunable. This
521  /// flag may have been previously set, at which point it will not
522  /// be reset unless one specifies to do so.
523  void setPrunable(bool isPrunable, bool override = false) {
524  if (IsPrunable.hasValue() && !override)
525  return;
526  IsPrunable = isPrunable;
527  }
528 
529  /// Return true if the diagnostic piece is prunable.
530  bool isPrunable() const {
531  return IsPrunable.hasValue() ? IsPrunable.getValue() : false;
532  }
533 
534  bool hasCallStackHint() { return (bool)CallStackHint; }
535 
536  /// Produce the hint for the given node. The node contains
537  /// information about the call for which the diagnostic can be generated.
538  std::string getCallStackMessage(const ExplodedNode *N) {
539  if (CallStackHint)
540  return CallStackHint->getMessage(N);
541  return "";
542  }
543 
544  void dump() const override;
545 
546  static inline bool classof(const PathDiagnosticPiece *P) {
547  return P->getKind() == Event;
548  }
549 };
550 
552  PathDiagnosticCallPiece(const Decl *callerD,
553  const PathDiagnosticLocation &callReturnPos)
554  : PathDiagnosticPiece(Call), Caller(callerD), Callee(nullptr),
555  NoExit(false), callReturn(callReturnPos) {}
556 
557  PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller)
558  : PathDiagnosticPiece(Call), Caller(caller), Callee(nullptr),
559  NoExit(true), path(oldPath) {}
560 
561  const Decl *Caller;
562  const Decl *Callee;
563 
564  // Flag signifying that this diagnostic has only call enter and no matching
565  // call exit.
566  bool NoExit;
567 
568  // The custom string, which should appear after the call Return Diagnostic.
569  // TODO: Should we allow multiple diagnostics?
570  std::string CallStackMessage;
571 
572 public:
577 
578  ~PathDiagnosticCallPiece() override;
579 
580  const Decl *getCaller() const { return Caller; }
581 
582  const Decl *getCallee() const { return Callee; }
583  void setCallee(const CallEnter &CE, const SourceManager &SM);
584 
585  bool hasCallStackMessage() { return !CallStackMessage.empty(); }
586  void setCallStackMessage(StringRef st) {
587  CallStackMessage = st;
588  }
589 
591  return callEnter;
592  }
593 
598 
599  void flattenLocations() override {
600  callEnter.flatten();
602  for (PathPieces::iterator I = path.begin(),
603  E = path.end(); I != E; ++I) (*I)->flattenLocations();
604  }
605 
607  const CallExitEnd &CE,
608  const SourceManager &SM);
609 
611  const Decl *caller);
612 
613  void dump() const override;
614 
615  void Profile(llvm::FoldingSetNodeID &ID) const override;
616 
617  static inline bool classof(const PathDiagnosticPiece *P) {
618  return P->getKind() == Call;
619  }
620 };
621 
623  std::vector<PathDiagnosticLocationPair> LPairs;
624 public:
626  const PathDiagnosticLocation &endPos,
627  StringRef s)
629  LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
630  }
631 
633  const PathDiagnosticLocation &endPos)
635  LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
636  }
637 
639 
641  assert(!LPairs.empty() &&
642  "PathDiagnosticControlFlowPiece needs at least one location.");
643  return LPairs[0].getStart();
644  }
645 
647  assert(!LPairs.empty() &&
648  "PathDiagnosticControlFlowPiece needs at least one location.");
649  return LPairs[0].getEnd();
650  }
651 
653  LPairs[0].setStart(L);
654  }
655 
657  LPairs[0].setEnd(L);
658  }
659 
660  void push_back(const PathDiagnosticLocationPair &X) { LPairs.push_back(X); }
661 
663  return getStartLocation();
664  }
665 
666  typedef std::vector<PathDiagnosticLocationPair>::iterator iterator;
667  iterator begin() { return LPairs.begin(); }
668  iterator end() { return LPairs.end(); }
669 
670  void flattenLocations() override {
671  for (iterator I=begin(), E=end(); I!=E; ++I) I->flatten();
672  }
673 
674  typedef std::vector<PathDiagnosticLocationPair>::const_iterator
676  const_iterator begin() const { return LPairs.begin(); }
677  const_iterator end() const { return LPairs.end(); }
678 
679  static inline bool classof(const PathDiagnosticPiece *P) {
680  return P->getKind() == ControlFlow;
681  }
682 
683  void dump() const override;
684 
685  void Profile(llvm::FoldingSetNodeID &ID) const override;
686 };
687 
689 public:
691  : PathDiagnosticSpotPiece(pos, "", Macro) {}
692 
693  ~PathDiagnosticMacroPiece() override;
694 
696 
697  bool containsEvent() const;
698 
699  void flattenLocations() override {
701  for (PathPieces::iterator I = subPieces.begin(),
702  E = subPieces.end(); I != E; ++I) (*I)->flattenLocations();
703  }
704 
705  static inline bool classof(const PathDiagnosticPiece *P) {
706  return P->getKind() == Macro;
707  }
708 
709  void dump() const override;
710 
711  void Profile(llvm::FoldingSetNodeID &ID) const override;
712 };
713 
714 /// PathDiagnostic - PathDiagnostic objects represent a single path-sensitive
715 /// diagnostic. It represents an ordered-collection of PathDiagnosticPieces,
716 /// each which represent the pieces of the path.
717 class PathDiagnostic : public llvm::FoldingSetNode {
718  std::string CheckName;
719  const Decl *DeclWithIssue;
720  std::string BugType;
721  std::string VerboseDesc;
722  std::string ShortDesc;
723  std::string Category;
724  std::deque<std::string> OtherDesc;
725 
726  /// \brief Loc The location of the path diagnostic report.
728 
729  PathPieces pathImpl;
731 
732  /// \brief Important bug uniqueing location.
733  /// The location info is useful to differentiate between bugs.
734  PathDiagnosticLocation UniqueingLoc;
735  const Decl *UniqueingDecl;
736 
737  PathDiagnostic() = delete;
738 public:
739  PathDiagnostic(StringRef CheckName, const Decl *DeclWithIssue,
740  StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,
741  StringRef category, PathDiagnosticLocation LocationToUnique,
742  const Decl *DeclToUnique);
743 
744  ~PathDiagnostic();
745 
746  const PathPieces &path;
747 
748  /// Return the path currently used by builders for constructing the
749  /// PathDiagnostic.
751  if (pathStack.empty())
752  return pathImpl;
753  return *pathStack.back();
754  }
755 
756  /// Return a mutable version of 'path'.
758  return pathImpl;
759  }
760 
761  /// Return the unrolled size of the path.
762  unsigned full_size();
763 
764  void pushActivePath(PathPieces *p) { pathStack.push_back(p); }
765  void popActivePath() { if (!pathStack.empty()) pathStack.pop_back(); }
766 
767  bool isWithinCall() const { return !pathStack.empty(); }
768 
769  void setEndOfPath(std::unique_ptr<PathDiagnosticPiece> EndPiece) {
770  assert(!Loc.isValid() && "End location already set!");
771  Loc = EndPiece->getLocation();
772  assert(Loc.isValid() && "Invalid location for end-of-path piece");
773  getActivePath().push_back(EndPiece.release());
774  }
775 
776  void appendToDesc(StringRef S) {
777  if (!ShortDesc.empty())
778  ShortDesc.append(S);
779  VerboseDesc.append(S);
780  }
781 
782  void resetPath() {
783  pathStack.clear();
784  pathImpl.clear();
786  }
787 
788  /// \brief If the last piece of the report point to the header file, resets
789  /// the location of the report to be the last location in the main source
790  /// file.
792 
793  StringRef getVerboseDescription() const { return VerboseDesc; }
794  StringRef getShortDescription() const {
795  return ShortDesc.empty() ? VerboseDesc : ShortDesc;
796  }
797  StringRef getCheckName() const { return CheckName; }
798  StringRef getBugType() const { return BugType; }
799  StringRef getCategory() const { return Category; }
800 
801  /// Return the semantic context where an issue occurred. If the
802  /// issue occurs along a path, this represents the "central" area
803  /// where the bug manifests.
804  const Decl *getDeclWithIssue() const { return DeclWithIssue; }
805 
806  typedef std::deque<std::string>::const_iterator meta_iterator;
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  assert(Loc.isValid() && "No report location set yet!");
813  return Loc;
814  }
815 
816  /// \brief Get the location on which the report should be uniqued.
818  return UniqueingLoc;
819  }
820 
821  /// \brief Get the declaration containing the uniqueing location.
822  const Decl *getUniqueingDecl() const {
823  return UniqueingDecl;
824  }
825 
827  Loc.flatten();
828  for (PathPieces::iterator I = pathImpl.begin(), E = pathImpl.end();
829  I != E; ++I) (*I)->flattenLocations();
830  }
831 
832  /// Profiles the diagnostic, independent of the path it references.
833  ///
834  /// This can be used to merge diagnostics that refer to the same issue
835  /// along different paths.
836  void Profile(llvm::FoldingSetNodeID &ID) const;
837 
838  /// Profiles the diagnostic, including its path.
839  ///
840  /// Two diagnostics with the same issue along different paths will generate
841  /// different profiles.
842  void FullProfile(llvm::FoldingSetNodeID &ID) const;
843 };
844 
845 } // end GR namespace
846 
847 } //end clang namespace
848 
849 #endif
PathDiagnosticLocation getUniqueingLoc() const
Get the location on which the report should be uniqued.
PathDiagnosticSpotPiece(const PathDiagnosticLocation &pos, StringRef s, PathDiagnosticPiece::Kind k, bool addPosRange=true)
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
std::deque< std::string >::const_iterator meta_iterator
const SymExpr * SymbolRef
virtual StringRef getName() const =0
static PathDiagnosticLocation createBeginBrace(const CompoundStmt *CS, const SourceManager &SM)
PathPieces flatten(bool ShouldFlattenMacros) const
StringRef getCategory() const
Constructs a Stack hint for the given symbol.
virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex)
PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos)
void setPrunable(bool isPrunable, bool override=false)
static PathDiagnosticLocation createEndBrace(const CompoundStmt *CS, const SourceManager &SM)
ArrayRef< SourceRange > getRanges() const
Return the SourceRanges associated with this PathDiagnosticPiece.
PathDiagnosticLocation getLocation() const
const Decl * getDeclWithIssue() const
static PathDiagnosticLocation createDeclEnd(const LocationContext *LC, const SourceManager &SM)
static PathDiagnosticLocation createSingleLocation(const PathDiagnosticLocation &PDL)
Convert the given location into a single kind location.
FullSourceLoc asLocation() const
Symbolic value. These values used to capture symbolic execution of the program.
Definition: SymbolManager.h:42
void setStartLocation(const PathDiagnosticLocation &L)
void addRange(SourceLocation B, SourceLocation E)
bool operator==(const PathDiagnosticLocation &X) const
void pushActivePath(PathPieces *p)
std::vector< PathDiagnosticLocationPair >::iterator iterator
PathPieces & getMutablePieces()
Return a mutable version of 'path'.
bool isPrunable() const
Return true if the diagnostic piece is prunable.
virtual void Profile(llvm::FoldingSetNodeID &ID) const
PDFileEntry(llvm::FoldingSetNodeID &NodeID)
llvm::FoldingSet< PathDiagnostic > Diags
void setStart(const PathDiagnosticLocation &L)
std::vector< PathDiagnosticLocationPair >::const_iterator const_iterator
virtual std::string getMessageForReturn(const CallExpr *CallExpr)
IntrusiveRefCntPtr< PathDiagnosticEventPiece > getCallExitEvent() const
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:2918
std::string getMessage(const ExplodedNode *N) override
Search the call expression for the symbol Sym and dispatch the 'getMessageForX()' methods to construc...
static PathDiagnosticCallPiece * construct(const ExplodedNode *N, const CallExitEnd &CE, const SourceManager &SM)
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
const void * getTag() const
Return the opaque tag (if any) on the PathDiagnosticPiece.
meta_iterator meta_begin() const
PathDiagnosticLocation(const Stmt *s, const SourceManager &sm, LocationOrAnalysisDeclContext lac)
Create a location corresponding to the given statement.
virtual PathDiagnosticLocation getLocation() const =0
static PathDiagnosticLocation createMemberLoc(const MemberExpr *ME, const SourceManager &SM)
AnnotatingParser & P
void Profile(llvm::FoldingSetNodeID &ID) const
void HandlePathDiagnostic(std::unique_ptr< PathDiagnostic > D)
PDFileEntry::ConsumerFiles * getFiles(const PathDiagnostic &PD)
IntrusiveRefCntPtr< PathDiagnosticEventPiece > getCallEnterWithinCallerEvent() const
ID
Defines the set of possible language-specific address spaces.
Definition: AddressSpaces.h:27
SourceManager & SM
void FullProfile(llvm::FoldingSetNodeID &ID) const
StringRef getShortDescription() const
const SourceManager & getManager() const
PathDiagnosticLocation getEndLocation() const
IntrusiveRefCntPtr< PathDiagnosticEventPiece > getCallEnterEvent() const
static const Stmt * getNextStmt(const ExplodedNode *N)
Retrieve the statement corresponding to the successor node.
virtual bool supportsLogicalOpControlFlow() const
void resetDiagnosticLocationToMainFile()
If the last piece of the report point to the header file, resets the location of the report to be the...
virtual std::string getMessageForSymbolNotFound()
PathDiagnosticRange(const SourceRange &R, bool isP=false)
std::vector< std::pair< StringRef, StringRef > > ConsumerFiles
Interface for classes constructing Stack hints.
The result type of a method or function.
virtual bool supportsCrossFileDiagnostics() const
PathDiagnosticLocation getStartLocation() const
llvm::PointerUnion< const LocationContext *, AnalysisDeclContext * > LocationOrAnalysisDeclContext
meta_iterator meta_end() const
static const Stmt * getStmt(const ExplodedNode *N)
Given an exploded node, retrieve the statement that should be used for the diagnostic location...
static PathDiagnosticLocation createDeclBegin(const LocationContext *LC, const SourceManager &SM)
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
#define false
Definition: stdbool.h:33
const llvm::FoldingSetNodeID NodeID
A precomputed hash tag used for uniquing PDFileEntry objects.
Kind
virtual void FlushDiagnosticsImpl(std::vector< const PathDiagnostic * > &Diags, FilesMade *filesMade)=0
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
std::string getCallStackMessage(const ExplodedNode *N)
virtual PathGenerationScheme getGenerationScheme() const
bool isValid() const
Return true if this is a valid SourceLocation object.
StringRef getVerboseDescription() const
bool isValid() const
void Profile(llvm::FoldingSetNodeID &ID) const
void setCallee(const CallEnter &CE, const SourceManager &SM)
static PathDiagnosticLocation createConditionalColonLoc(const ConditionalOperator *CO, const SourceManager &SM)
const PathDiagnosticLocation & getStart() const
static PathDiagnosticLocation createEnd(const Stmt *S, const SourceManager &SM, const LocationOrAnalysisDeclContext LAC)
const Decl * getUniqueingDecl() const
Get the declaration containing the uniqueing location.
PathDiagnosticLocation getLocation() const override
ConsumerFiles files
A vector of <consumer,file> pairs.
virtual void dump() const =0
PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, const PathDiagnosticLocation &endPos)
static __inline__ uint32_t volatile uint32_t * p
Definition: arm_acle.h:75
void FlushDiagnostics(FilesMade *FilesMade)
DisplayHint getDisplayHint() const
PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, StringRef s, bool addPosRange=true, StackHintGenerator *stackHint=nullptr)
void Profile(llvm::FoldingSetNodeID &ID) const override
void setEndLocation(const PathDiagnosticLocation &L)
PathDiagnosticLocationPair(const PathDiagnosticLocation &start, const PathDiagnosticLocation &end)
void appendToDesc(StringRef S)
virtual std::string getMessage(const ExplodedNode *N)=0
Construct the Diagnostic message for the given ExplodedNode.
void Profile(llvm::FoldingSetNodeID &ID) const
void setEndOfPath(std::unique_ptr< PathDiagnosticPiece > EndPiece)
PathDiagnosticLocation(SourceLocation loc, const SourceManager &sm)
PathDiagnosticLocation(const Decl *d, const SourceManager &sm)
Create a location corresponding to the given declaration.
void push_back(const PathDiagnosticLocationPair &X)
static bool classof(const PathDiagnosticPiece *P)
void Profile(llvm::FoldingSetNodeID &ID) const override
void Profile(llvm::FoldingSetNodeID &ID)
Used for profiling in the FoldingSet.
static PathDiagnosticLocation createOperatorLoc(const BinaryOperator *BO, const SourceManager &SM)
PathDiagnosticLocation getLocation() const override
X
Definition: SemaDecl.cpp:11429
PathDiagnosticRange asRange() const
Defines the clang::SourceLocation class and associated facilities.
FormatToken * Current
const PathDiagnosticLocation & getEnd() const
static PathDiagnosticLocation createEndOfPath(const ExplodedNode *N, const SourceManager &SM)
unsigned kind
All of the diagnostics that can be emitted by the frontend.
Definition: DiagnosticIDs.h:43
PathDiagnosticLocation()
Create an invalid location.
static bool classof(const PathDiagnosticPiece *P)
A SourceLocation and its associated SourceManager.
PathDiagnosticLocation callEnterWithin
void Profile(llvm::FoldingSetNodeID &ID) const override
StringRef getBugType() const
void addDiagnostic(const PathDiagnostic &PD, StringRef ConsumerName, StringRef fileName)
A trivial tuple used to represent a source range.
static bool classof(const PathDiagnosticPiece *P)
StringRef getCheckName() const
StackHintGeneratorForSymbol(SymbolRef S, StringRef M)
bool operator!=(const PathDiagnosticLocation &X) const
This class handles loading and caching of source files into memory.
static bool classof(const PathDiagnosticPiece *P)
unsigned full_size()
Return the unrolled size of the path.
void Profile(llvm::FoldingSetNodeID &ID) const override
void setEnd(const PathDiagnosticLocation &L)
static bool classof(const PathDiagnosticPiece *P)