clang  3.9.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(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:
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 
426  PathPieces flatten(bool ShouldFlattenMacros) const {
428  flattenTo(Result, Result, ShouldFlattenMacros);
429  return Result;
430  }
431 
432  void dump() const;
433 };
434 
436 private:
438 public:
440  StringRef s,
442  bool addPosRange = true)
443  : PathDiagnosticPiece(s, k), Pos(pos) {
444  assert(Pos.isValid() && Pos.asLocation().isValid() &&
445  "PathDiagnosticSpotPiece's must have a valid location.");
446  if (addPosRange && Pos.hasRange()) addRange(Pos.asRange());
447  }
448 
449  PathDiagnosticLocation getLocation() const override { return Pos; }
450  void flattenLocations() override { Pos.flatten(); }
451 
452  void Profile(llvm::FoldingSetNodeID &ID) const override;
453 
454  static bool classof(const PathDiagnosticPiece *P) {
455  return P->getKind() == Event || P->getKind() == Macro;
456  }
457 };
458 
459 /// \brief Interface for classes constructing Stack hints.
460 ///
461 /// If a PathDiagnosticEvent occurs in a different frame than the final
462 /// diagnostic the hints can be used to summarize the effect of the call.
464 public:
465  virtual ~StackHintGenerator() = 0;
466 
467  /// \brief Construct the Diagnostic message for the given ExplodedNode.
468  virtual std::string getMessage(const ExplodedNode *N) = 0;
469 };
470 
471 /// \brief Constructs a Stack hint for the given symbol.
472 ///
473 /// The class knows how to construct the stack hint message based on
474 /// traversing the CallExpr associated with the call and checking if the given
475 /// symbol is returned or is one of the arguments.
476 /// The hint can be customized by redefining 'getMessageForX()' methods.
478 private:
479  SymbolRef Sym;
480  std::string Msg;
481 
482 public:
483  StackHintGeneratorForSymbol(SymbolRef S, StringRef M) : Sym(S), Msg(M) {}
485 
486  /// \brief Search the call expression for the symbol Sym and dispatch the
487  /// 'getMessageForX()' methods to construct a specific message.
488  std::string getMessage(const ExplodedNode *N) override;
489 
490  /// Produces the message of the following form:
491  /// 'Msg via Nth parameter'
492  virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex);
493  virtual std::string getMessageForReturn(const CallExpr *CallExpr) {
494  return Msg;
495  }
496  virtual std::string getMessageForSymbolNotFound() {
497  return Msg;
498  }
499 };
500 
502  Optional<bool> IsPrunable;
503 
504  /// If the event occurs in a different frame than the final diagnostic,
505  /// supply a message that will be used to construct an extra hint on the
506  /// returns from all the calls on the stack from this event to the final
507  /// diagnostic.
508  std::unique_ptr<StackHintGenerator> CallStackHint;
509 
510 public:
512  StringRef s, bool addPosRange = true,
513  StackHintGenerator *stackHint = nullptr)
514  : PathDiagnosticSpotPiece(pos, s, Event, addPosRange),
515  CallStackHint(stackHint) {}
516 
517  ~PathDiagnosticEventPiece() override;
518 
519  /// Mark the diagnostic piece as being potentially prunable. This
520  /// flag may have been previously set, at which point it will not
521  /// be reset unless one specifies to do so.
522  void setPrunable(bool isPrunable, bool override = false) {
523  if (IsPrunable.hasValue() && !override)
524  return;
525  IsPrunable = isPrunable;
526  }
527 
528  /// Return true if the diagnostic piece is prunable.
529  bool isPrunable() const {
530  return IsPrunable.hasValue() ? IsPrunable.getValue() : false;
531  }
532 
533  bool hasCallStackHint() { return (bool)CallStackHint; }
534 
535  /// Produce the hint for the given node. The node contains
536  /// information about the call for which the diagnostic can be generated.
537  std::string getCallStackMessage(const ExplodedNode *N) {
538  if (CallStackHint)
539  return CallStackHint->getMessage(N);
540  return "";
541  }
542 
543  void dump() const override;
544 
545  static inline bool classof(const PathDiagnosticPiece *P) {
546  return P->getKind() == Event;
547  }
548 };
549 
551  PathDiagnosticCallPiece(const Decl *callerD,
552  const PathDiagnosticLocation &callReturnPos)
553  : PathDiagnosticPiece(Call), Caller(callerD), Callee(nullptr),
554  NoExit(false), callReturn(callReturnPos) {}
555 
556  PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller)
557  : PathDiagnosticPiece(Call), Caller(caller), Callee(nullptr),
558  NoExit(true), path(oldPath) {}
559 
560  const Decl *Caller;
561  const Decl *Callee;
562 
563  // Flag signifying that this diagnostic has only call enter and no matching
564  // call exit.
565  bool NoExit;
566 
567  // The custom string, which should appear after the call Return Diagnostic.
568  // TODO: Should we allow multiple diagnostics?
569  std::string CallStackMessage;
570 
571 public:
576 
577  ~PathDiagnosticCallPiece() override;
578 
579  const Decl *getCaller() const { return Caller; }
580 
581  const Decl *getCallee() const { return Callee; }
582  void setCallee(const CallEnter &CE, const SourceManager &SM);
583 
584  bool hasCallStackMessage() { return !CallStackMessage.empty(); }
585  void setCallStackMessage(StringRef st) {
586  CallStackMessage = st;
587  }
588 
590  return callEnter;
591  }
592 
597 
598  void flattenLocations() override {
599  callEnter.flatten();
601  for (PathPieces::iterator I = path.begin(),
602  E = path.end(); I != E; ++I) (*I)->flattenLocations();
603  }
604 
606  const CallExitEnd &CE,
607  const SourceManager &SM);
608 
610  const Decl *caller);
611 
612  void dump() const override;
613 
614  void Profile(llvm::FoldingSetNodeID &ID) const override;
615 
616  static inline bool classof(const PathDiagnosticPiece *P) {
617  return P->getKind() == Call;
618  }
619 };
620 
622  std::vector<PathDiagnosticLocationPair> LPairs;
623 public:
625  const PathDiagnosticLocation &endPos,
626  StringRef s)
628  LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
629  }
630 
632  const PathDiagnosticLocation &endPos)
634  LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
635  }
636 
638 
640  assert(!LPairs.empty() &&
641  "PathDiagnosticControlFlowPiece needs at least one location.");
642  return LPairs[0].getStart();
643  }
644 
646  assert(!LPairs.empty() &&
647  "PathDiagnosticControlFlowPiece needs at least one location.");
648  return LPairs[0].getEnd();
649  }
650 
652  LPairs[0].setStart(L);
653  }
654 
656  LPairs[0].setEnd(L);
657  }
658 
659  void push_back(const PathDiagnosticLocationPair &X) { LPairs.push_back(X); }
660 
662  return getStartLocation();
663  }
664 
666  iterator begin() { return LPairs.begin(); }
667  iterator end() { return LPairs.end(); }
668 
669  void flattenLocations() override {
670  for (iterator I=begin(), E=end(); I!=E; ++I) I->flatten();
671  }
672 
673  typedef std::vector<PathDiagnosticLocationPair>::const_iterator
675  const_iterator begin() const { return LPairs.begin(); }
676  const_iterator end() const { return LPairs.end(); }
677 
678  static inline bool classof(const PathDiagnosticPiece *P) {
679  return P->getKind() == ControlFlow;
680  }
681 
682  void dump() const override;
683 
684  void Profile(llvm::FoldingSetNodeID &ID) const override;
685 };
686 
688 public:
690  : PathDiagnosticSpotPiece(pos, "", Macro) {}
691 
692  ~PathDiagnosticMacroPiece() override;
693 
695 
696  bool containsEvent() const;
697 
698  void flattenLocations() override {
700  for (PathPieces::iterator I = subPieces.begin(),
701  E = subPieces.end(); I != E; ++I) (*I)->flattenLocations();
702  }
703 
704  static inline bool classof(const PathDiagnosticPiece *P) {
705  return P->getKind() == Macro;
706  }
707 
708  void dump() const override;
709 
710  void Profile(llvm::FoldingSetNodeID &ID) const override;
711 };
712 
713 /// PathDiagnostic - PathDiagnostic objects represent a single path-sensitive
714 /// diagnostic. It represents an ordered-collection of PathDiagnosticPieces,
715 /// each which represent the pieces of the path.
716 class PathDiagnostic : public llvm::FoldingSetNode {
717  std::string CheckName;
718  const Decl *DeclWithIssue;
719  std::string BugType;
720  std::string VerboseDesc;
721  std::string ShortDesc;
722  std::string Category;
723  std::deque<std::string> OtherDesc;
724 
725  /// \brief Loc The location of the path diagnostic report.
727 
728  PathPieces pathImpl;
730 
731  /// \brief Important bug uniqueing location.
732  /// The location info is useful to differentiate between bugs.
733  PathDiagnosticLocation UniqueingLoc;
734  const Decl *UniqueingDecl;
735 
736  PathDiagnostic() = delete;
737 public:
738  PathDiagnostic(StringRef CheckName, const Decl *DeclWithIssue,
739  StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,
740  StringRef category, PathDiagnosticLocation LocationToUnique,
741  const Decl *DeclToUnique);
742 
743  ~PathDiagnostic();
744 
745  const PathPieces &path;
746 
747  /// Return the path currently used by builders for constructing the
748  /// PathDiagnostic.
750  if (pathStack.empty())
751  return pathImpl;
752  return *pathStack.back();
753  }
754 
755  /// Return a mutable version of 'path'.
757  return pathImpl;
758  }
759 
760  /// Return the unrolled size of the path.
761  unsigned full_size();
762 
763  void pushActivePath(PathPieces *p) { pathStack.push_back(p); }
764  void popActivePath() { if (!pathStack.empty()) pathStack.pop_back(); }
765 
766  bool isWithinCall() const { return !pathStack.empty(); }
767 
768  void setEndOfPath(std::unique_ptr<PathDiagnosticPiece> EndPiece) {
769  assert(!Loc.isValid() && "End location already set!");
770  Loc = EndPiece->getLocation();
771  assert(Loc.isValid() && "Invalid location for end-of-path piece");
772  getActivePath().push_back(EndPiece.release());
773  }
774 
775  void appendToDesc(StringRef S) {
776  if (!ShortDesc.empty())
777  ShortDesc += S;
778  VerboseDesc += S;
779  }
780 
781  void resetPath() {
782  pathStack.clear();
783  pathImpl.clear();
785  }
786 
787  /// \brief If the last piece of the report point to the header file, resets
788  /// the location of the report to be the last location in the main source
789  /// file.
791 
792  StringRef getVerboseDescription() const { return VerboseDesc; }
793  StringRef getShortDescription() const {
794  return ShortDesc.empty() ? VerboseDesc : ShortDesc;
795  }
796  StringRef getCheckName() const { return CheckName; }
797  StringRef getBugType() const { return BugType; }
798  StringRef getCategory() const { return Category; }
799 
800  /// Return the semantic context where an issue occurred. If the
801  /// issue occurs along a path, this represents the "central" area
802  /// where the bug manifests.
803  const Decl *getDeclWithIssue() const { return DeclWithIssue; }
804 
805  typedef std::deque<std::string>::const_iterator meta_iterator;
806  meta_iterator meta_begin() const { return OtherDesc.begin(); }
807  meta_iterator meta_end() const { return OtherDesc.end(); }
808  void addMeta(StringRef s) { OtherDesc.push_back(s); }
809 
811  assert(Loc.isValid() && "No report location set yet!");
812  return Loc;
813  }
814 
815  /// \brief Get the location on which the report should be uniqued.
817  return UniqueingLoc;
818  }
819 
820  /// \brief Get the declaration containing the uniqueing location.
821  const Decl *getUniqueingDecl() const {
822  return UniqueingDecl;
823  }
824 
826  Loc.flatten();
827  for (PathPieces::iterator I = pathImpl.begin(), E = pathImpl.end();
828  I != E; ++I) (*I)->flattenLocations();
829  }
830 
831  /// Profiles the diagnostic, independent of the path it references.
832  ///
833  /// This can be used to merge diagnostics that refer to the same issue
834  /// along different paths.
835  void Profile(llvm::FoldingSetNodeID &ID) const;
836 
837  /// Profiles the diagnostic, including its path.
838  ///
839  /// Two diagnostics with the same issue along different paths will generate
840  /// different profiles.
841  void FullProfile(llvm::FoldingSetNodeID &ID) const;
842 };
843 
844 } // end GR namespace
845 
846 } //end clang namespace
847 
848 #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
Represents a point when we begin processing an inlined call.
Definition: ProgramPoint.h:584
static PathDiagnosticLocation createBeginBrace(const CompoundStmt *CS, const SourceManager &SM)
Create a location for the beginning of the compound statement.
PathPieces flatten(bool ShouldFlattenMacros) const
StringRef getCategory() const
StringRef P
Constructs a Stack hint for the given symbol.
virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex)
Produces the message of the following form: 'Msg via Nth parameter'.
PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos)
void setPrunable(bool isPrunable, bool override=false)
Mark the diagnostic piece as being potentially prunable.
static PathDiagnosticLocation createEndBrace(const CompoundStmt *CS, const SourceManager &SM)
Create a location for the end of the compound statement.
ArrayRef< SourceRange > getRanges() const
Return the SourceRanges associated with this PathDiagnosticPiece.
PathDiagnosticLocation getLocation() const
const Decl * getDeclWithIssue() const
Return the semantic context where an issue occurred.
static PathDiagnosticLocation createDeclEnd(const LocationContext *LC, const SourceManager &SM)
Constructs a location for the end of the enclosing declaration body.
static PathDiagnosticLocation createSingleLocation(const PathDiagnosticLocation &PDL)
Convert the given location into a single kind location.
FullSourceLoc asLocation() const
Symbolic value.
Definition: SymExpr.h:29
PathDiagnostic - PathDiagnostic objects represent a single path-sensitive diagnostic.
void setStartLocation(const PathDiagnosticLocation &L)
void addRange(SourceLocation B, SourceLocation E)
AnalysisDeclContext contains the context data for the function or method under analysis.
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:2897
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
iterator end() const
PathDiagnosticLocation(const Stmt *s, const SourceManager &sm, LocationOrAnalysisDeclContext lac)
Create a location corresponding to the given statement.
detail::InMemoryDirectory::const_iterator I
virtual PathDiagnosticLocation getLocation() const =0
static PathDiagnosticLocation createMemberLoc(const MemberExpr *ME, const SourceManager &SM)
For member expressions, return the location of the '.
void Profile(llvm::FoldingSetNodeID &ID) const
ConditionalOperator - The ?: ternary operator.
Definition: Expr.h:3170
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:551
void HandlePathDiagnostic(std::unique_ptr< PathDiagnostic > D)
PDFileEntry::ConsumerFiles * getFiles(const PathDiagnostic &PD)
IntrusiveRefCntPtr< PathDiagnosticEventPiece > getCallEnterWithinCallerEvent() const
Represents a point when we finish the call exit sequence (for inlined call).
Definition: ProgramPoint.h:638
Expr - This represents one expression.
Definition: Expr.h:105
void FullProfile(llvm::FoldingSetNodeID &ID) const
Profiles the diagnostic, including its path.
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
PathDiagnosticRange(SourceRange R, bool isP=false)
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()
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
Return true if the PathDiagnosticConsumer supports individual PathDiagnostics that span multiple file...
PathDiagnosticLocation getStartLocation() const
const SourceManager & SM
Definition: Format.cpp:1184
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)
Create a location for the beginning of the enclosing declaration body.
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.
const TemplateArgument * iterator
Definition: Type.h:4233
std::string getCallStackMessage(const ExplodedNode *N)
Produce the hint for the given node.
virtual PathGenerationScheme getGenerationScheme() const
bool isValid() const
Return true if this is a valid SourceLocation object.
StringRef getVerboseDescription() const
const std::string ID
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)
Create a location for the end of the statement.
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)
void FlushDiagnostics(FilesMade *FilesMade)
DisplayHint getDisplayHint() const
getDisplayHint - Return a hint indicating where the diagnostic should be displayed by the PathDiagnos...
detail::InMemoryDirectory::const_iterator E
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
Profiles the diagnostic, independent of the path it references.
void setEndOfPath(std::unique_ptr< PathDiagnosticPiece > EndPiece)
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)
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)
Create the location for the operator of the binary expression.
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:12171
PathDiagnosticRange asRange() const
StringRef getTagStr() const
Return the string representation of the tag.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:2315
Defines the clang::SourceLocation class and associated facilities.
FormatToken * Current
PathPieces & getActivePath()
Return the path currently used by builders for constructing the PathDiagnostic.
const PathDiagnosticLocation & getEnd() const
static PathDiagnosticLocation createEndOfPath(const ExplodedNode *N, const SourceManager &SM)
Create a location corresponding to the next valid ExplodedNode as end of path location.
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)
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2148
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)