clang  6.0.0svn
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.
64  ConsumerFiles files;
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 
86  PDFileEntry::ConsumerFiles *getFiles(const PathDiagnostic &PD);
87  };
88 
89 private:
90  virtual void anchor();
91 public:
93  virtual ~PathDiagnosticConsumer();
94 
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 
128  PathDiagnosticRange() : isPoint(false) {}
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.
219  static PathDiagnosticLocation createOperatorLoc(const BinaryOperator *BO,
220  const SourceManager &SM);
221  static PathDiagnosticLocation createConditionalColonLoc(
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.
227  static PathDiagnosticLocation createMemberLoc(const MemberExpr *ME,
228  const SourceManager &SM);
229 
230  /// Create a location for the beginning of the compound statement.
231  /// Assumes the statement has a valid location.
232  static PathDiagnosticLocation createBeginBrace(const CompoundStmt *CS,
233  const SourceManager &SM);
234 
235  /// Create a location for the end of the compound statement.
236  /// Assumes the statement has a valid location.
237  static PathDiagnosticLocation createEndBrace(const CompoundStmt *CS,
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.
242  static PathDiagnosticLocation createDeclBegin(const LocationContext *LC,
243  const SourceManager &SM);
244 
245  /// Constructs a location for the end of the enclosing declaration body.
246  /// Defaults to the end of brace.
247  static PathDiagnosticLocation createDeclEnd(const LocationContext *LC,
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.
256  static PathDiagnosticLocation createEndOfPath(const ExplodedNode* N,
257  const SourceManager &SM);
258 
259  /// Convert the given location into a single kind location.
260  static PathDiagnosticLocation createSingleLocation(
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:
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 
338 public:
339  enum Kind { ControlFlow, Event, Macro, Call, Note };
340  enum DisplayHint { Above, Below };
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 
366  PathDiagnosticPiece(Kind k, DisplayHint hint = Below);
367 
368 public:
369  virtual ~PathDiagnosticPiece();
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 class PathPieces : public std::list<std::shared_ptr<PathDiagnosticPiece>> {
421  void flattenTo(PathPieces &Primary, PathPieces &Current,
422  bool ShouldFlattenMacros) const;
423 public:
424 
425  PathPieces flatten(bool ShouldFlattenMacros) const {
426  PathPieces Result;
427  flattenTo(Result, Result, ShouldFlattenMacros);
428  return Result;
429  }
430 
431  void dump() const;
432 };
433 
435 private:
437 public:
439  StringRef s,
441  bool addPosRange = true)
442  : PathDiagnosticPiece(s, k), Pos(pos) {
443  assert(Pos.isValid() && Pos.asLocation().isValid() &&
444  "PathDiagnosticSpotPiece's must have a valid location.");
445  if (addPosRange && Pos.hasRange()) addRange(Pos.asRange());
446  }
447 
448  PathDiagnosticLocation getLocation() const override { return Pos; }
449  void flattenLocations() override { Pos.flatten(); }
450 
451  void Profile(llvm::FoldingSetNodeID &ID) const override;
452 
453  static bool classof(const PathDiagnosticPiece *P) {
454  return P->getKind() == Event || P->getKind() == Macro ||
455  P->getKind() == Note;
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), IsCalleeAnAutosynthesizedPropertyAccessor(false),
555  callReturn(callReturnPos) {}
556 
557  PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller)
558  : PathDiagnosticPiece(Call), Caller(caller), Callee(nullptr),
559  NoExit(true), IsCalleeAnAutosynthesizedPropertyAccessor(false),
560  path(oldPath) {}
561 
562  const Decl *Caller;
563  const Decl *Callee;
564 
565  // Flag signifying that this diagnostic has only call enter and no matching
566  // call exit.
567  bool NoExit;
568 
569  // Flag signifying that the callee function is an Objective-C autosynthesized
570  // property getter or setter.
571  bool IsCalleeAnAutosynthesizedPropertyAccessor;
572 
573  // The custom string, which should appear after the call Return Diagnostic.
574  // TODO: Should we allow multiple diagnostics?
575  std::string CallStackMessage;
576 
577 public:
582 
583  ~PathDiagnosticCallPiece() override;
584 
585  const Decl *getCaller() const { return Caller; }
586 
587  const Decl *getCallee() const { return Callee; }
588  void setCallee(const CallEnter &CE, const SourceManager &SM);
589 
590  bool hasCallStackMessage() { return !CallStackMessage.empty(); }
591  void setCallStackMessage(StringRef st) {
592  CallStackMessage = st;
593  }
594 
596  return callEnter;
597  }
598 
599  std::shared_ptr<PathDiagnosticEventPiece> getCallEnterEvent() const;
600  std::shared_ptr<PathDiagnosticEventPiece>
601  getCallEnterWithinCallerEvent() const;
602  std::shared_ptr<PathDiagnosticEventPiece> getCallExitEvent() const;
603 
604  void flattenLocations() override {
605  callEnter.flatten();
606  callReturn.flatten();
607  for (PathPieces::iterator I = path.begin(),
608  E = path.end(); I != E; ++I) (*I)->flattenLocations();
609  }
610 
611  static std::shared_ptr<PathDiagnosticCallPiece>
612  construct(const ExplodedNode *N, const CallExitEnd &CE,
613  const SourceManager &SM);
614 
615  static PathDiagnosticCallPiece *construct(PathPieces &pieces,
616  const Decl *caller);
617 
618  void dump() const override;
619 
620  void Profile(llvm::FoldingSetNodeID &ID) const override;
621 
622  static inline bool classof(const PathDiagnosticPiece *P) {
623  return P->getKind() == Call;
624  }
625 };
626 
628  std::vector<PathDiagnosticLocationPair> LPairs;
629 public:
631  const PathDiagnosticLocation &endPos,
632  StringRef s)
633  : PathDiagnosticPiece(s, ControlFlow) {
634  LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
635  }
636 
638  const PathDiagnosticLocation &endPos)
639  : PathDiagnosticPiece(ControlFlow) {
640  LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
641  }
642 
643  ~PathDiagnosticControlFlowPiece() override;
644 
646  assert(!LPairs.empty() &&
647  "PathDiagnosticControlFlowPiece needs at least one location.");
648  return LPairs[0].getStart();
649  }
650 
652  assert(!LPairs.empty() &&
653  "PathDiagnosticControlFlowPiece needs at least one location.");
654  return LPairs[0].getEnd();
655  }
656 
658  LPairs[0].setStart(L);
659  }
660 
662  LPairs[0].setEnd(L);
663  }
664 
665  void push_back(const PathDiagnosticLocationPair &X) { LPairs.push_back(X); }
666 
668  return getStartLocation();
669  }
670 
671  typedef std::vector<PathDiagnosticLocationPair>::iterator iterator;
672  iterator begin() { return LPairs.begin(); }
673  iterator end() { return LPairs.end(); }
674 
675  void flattenLocations() override {
676  for (iterator I=begin(), E=end(); I!=E; ++I) I->flatten();
677  }
678 
679  typedef std::vector<PathDiagnosticLocationPair>::const_iterator
681  const_iterator begin() const { return LPairs.begin(); }
682  const_iterator end() const { return LPairs.end(); }
683 
684  static inline bool classof(const PathDiagnosticPiece *P) {
685  return P->getKind() == ControlFlow;
686  }
687 
688  void dump() const override;
689 
690  void Profile(llvm::FoldingSetNodeID &ID) const override;
691 };
692 
694 public:
696  : PathDiagnosticSpotPiece(pos, "", Macro) {}
697 
698  ~PathDiagnosticMacroPiece() override;
699 
701 
702  bool containsEvent() const;
703 
704  void flattenLocations() override {
706  for (PathPieces::iterator I = subPieces.begin(),
707  E = subPieces.end(); I != E; ++I) (*I)->flattenLocations();
708  }
709 
710  static inline bool classof(const PathDiagnosticPiece *P) {
711  return P->getKind() == Macro;
712  }
713 
714  void dump() const override;
715 
716  void Profile(llvm::FoldingSetNodeID &ID) const override;
717 };
718 
720 public:
722  bool AddPosRange = true)
723  : PathDiagnosticSpotPiece(Pos, S, Note, AddPosRange) {}
724 
725  ~PathDiagnosticNotePiece() override;
726 
727  static inline bool classof(const PathDiagnosticPiece *P) {
728  return P->getKind() == Note;
729  }
730 
731  void dump() const override;
732 
733  void Profile(llvm::FoldingSetNodeID &ID) const override;
734 };
735 
736 /// PathDiagnostic - PathDiagnostic objects represent a single path-sensitive
737 /// diagnostic. It represents an ordered-collection of PathDiagnosticPieces,
738 /// each which represent the pieces of the path.
739 class PathDiagnostic : public llvm::FoldingSetNode {
740  std::string CheckName;
741  const Decl *DeclWithIssue;
742  std::string BugType;
743  std::string VerboseDesc;
744  std::string ShortDesc;
745  std::string Category;
746  std::deque<std::string> OtherDesc;
747 
748  /// \brief Loc The location of the path diagnostic report.
750 
751  PathPieces pathImpl;
753 
754  /// \brief Important bug uniqueing location.
755  /// The location info is useful to differentiate between bugs.
756  PathDiagnosticLocation UniqueingLoc;
757  const Decl *UniqueingDecl;
758 
759  PathDiagnostic() = delete;
760 public:
761  PathDiagnostic(StringRef CheckName, const Decl *DeclWithIssue,
762  StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,
763  StringRef category, PathDiagnosticLocation LocationToUnique,
764  const Decl *DeclToUnique);
765 
766  ~PathDiagnostic();
767 
768  const PathPieces &path;
769 
770  /// Return the path currently used by builders for constructing the
771  /// PathDiagnostic.
773  if (pathStack.empty())
774  return pathImpl;
775  return *pathStack.back();
776  }
777 
778  /// Return a mutable version of 'path'.
780  return pathImpl;
781  }
782 
783  /// Return the unrolled size of the path.
784  unsigned full_size();
785 
786  void pushActivePath(PathPieces *p) { pathStack.push_back(p); }
787  void popActivePath() { if (!pathStack.empty()) pathStack.pop_back(); }
788 
789  bool isWithinCall() const { return !pathStack.empty(); }
790 
791  void setEndOfPath(std::unique_ptr<PathDiagnosticPiece> EndPiece) {
792  assert(!Loc.isValid() && "End location already set!");
793  Loc = EndPiece->getLocation();
794  assert(Loc.isValid() && "Invalid location for end-of-path piece");
795  getActivePath().push_back(std::move(EndPiece));
796  }
797 
798  void appendToDesc(StringRef S) {
799  if (!ShortDesc.empty())
800  ShortDesc += S;
801  VerboseDesc += S;
802  }
803 
804  void resetPath() {
805  pathStack.clear();
806  pathImpl.clear();
807  Loc = PathDiagnosticLocation();
808  }
809 
810  /// \brief If the last piece of the report point to the header file, resets
811  /// the location of the report to be the last location in the main source
812  /// file.
813  void resetDiagnosticLocationToMainFile();
814 
815  StringRef getVerboseDescription() const { return VerboseDesc; }
816  StringRef getShortDescription() const {
817  return ShortDesc.empty() ? VerboseDesc : ShortDesc;
818  }
819  StringRef getCheckName() const { return CheckName; }
820  StringRef getBugType() const { return BugType; }
821  StringRef getCategory() const { return Category; }
822 
823  /// Return the semantic context where an issue occurred. If the
824  /// issue occurs along a path, this represents the "central" area
825  /// where the bug manifests.
826  const Decl *getDeclWithIssue() const { return DeclWithIssue; }
827 
828  typedef std::deque<std::string>::const_iterator meta_iterator;
829  meta_iterator meta_begin() const { return OtherDesc.begin(); }
830  meta_iterator meta_end() const { return OtherDesc.end(); }
831  void addMeta(StringRef s) { OtherDesc.push_back(s); }
832 
834  assert(Loc.isValid() && "No report location set yet!");
835  return Loc;
836  }
837 
838  /// \brief Get the location on which the report should be uniqued.
840  return UniqueingLoc;
841  }
842 
843  /// \brief Get the declaration containing the uniqueing location.
844  const Decl *getUniqueingDecl() const {
845  return UniqueingDecl;
846  }
847 
849  Loc.flatten();
850  for (PathPieces::iterator I = pathImpl.begin(), E = pathImpl.end();
851  I != E; ++I) (*I)->flattenLocations();
852  }
853 
854  /// Profiles the diagnostic, independent of the path it references.
855  ///
856  /// This can be used to merge diagnostics that refer to the same issue
857  /// along different paths.
858  void Profile(llvm::FoldingSetNodeID &ID) const;
859 
860  /// Profiles the diagnostic, including its path.
861  ///
862  /// Two diagnostics with the same issue along different paths will generate
863  /// different profiles.
864  void FullProfile(llvm::FoldingSetNodeID &ID) const;
865 };
866 
867 } // end GR namespace
868 
869 } //end clang namespace
870 
871 #endif
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
std::deque< std::string >::const_iterator meta_iterator
const SymExpr * SymbolRef
Stmt - This represents one statement.
Definition: Stmt.h:60
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:81
virtual StringRef getName() const =0
Represents a point when we begin processing an inlined call.
Definition: ProgramPoint.h:585
StringRef P
Constructs a Stack hint for the given symbol.
void Profile(llvm::FoldingSetNodeID &ID) const
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
PathDiagnosticLocation getLocation() const
Symbolic value.
Definition: SymExpr.h:29
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:1319
std::vector< PathDiagnosticLocationPair >::iterator iterator
virtual bool supportsLogicalOpControlFlow() const
PathPieces & getMutablePieces()
Return a mutable version of &#39;path&#39;.
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)
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
bool operator!=(const PathDiagnosticLocation &X) const
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:2986
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.
StringRef getCheckName() const
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:3270
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:575
const void * getTag() const
Return the opaque tag (if any) on the PathDiagnosticPiece.
void HandlePathDiagnostic(std::unique_ptr< PathDiagnostic > D)
Represents a point when we finish the call exit sequence (for inlined call).
Definition: ProgramPoint.h:639
DisplayHint getDisplayHint() const
getDisplayHint - Return a hint indicating where the diagnostic should be displayed by the PathDiagnos...
Expr - This represents one expression.
Definition: Expr.h:106
bool isPrunable() const
Return true if the diagnostic piece is prunable.
SourceLocation End
PathDiagnosticLocation getUniqueingLoc() const
Get the location on which the report should be uniqued.
const SourceManager & getManager() const
PathDiagnosticRange(SourceRange R, bool isP=false)
virtual std::string getMessageForSymbolNotFound()
std::vector< std::pair< StringRef, StringRef > > ConsumerFiles
Interface for classes constructing Stack hints.
PathPieces flatten(bool ShouldFlattenMacros) const
const SourceManager & SM
Definition: Format.cpp:1308
StringRef getCategory() const
llvm::PointerUnion< const LocationContext *, AnalysisDeclContext * > LocationOrAnalysisDeclContext
#define false
Definition: stdbool.h:33
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::string getCallStackMessage(const ExplodedNode *N)
Produce the hint for the given node.
virtual bool supportsCrossFileDiagnostics() const
Return true if the PathDiagnosticConsumer supports individual PathDiagnostics that span multiple file...
PathDiagnosticLocation getLocation() const override
ConsumerFiles files
A vector of <consumer,file> pairs.
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.
PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, StringRef s, bool addPosRange=true, StackHintGenerator *stackHint=nullptr)
void setEndLocation(const PathDiagnosticLocation &L)
PathDiagnosticLocationPair(const PathDiagnosticLocation &start, const PathDiagnosticLocation &end)
void appendToDesc(StringRef S)
virtual PathGenerationScheme getGenerationScheme() const
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)
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:13160
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:2387
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:61
PathDiagnosticLocation()
Create an invalid location.
static bool classof(const PathDiagnosticPiece *P)
StringRef getTagStr() const
Return the string representation of the tag.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2209
A SourceLocation and its associated SourceManager.
PathDiagnosticLocation callEnterWithin
const Decl * getUniqueingDecl() const
Get the declaration containing the uniqueing location.
A trivial tuple used to represent a source range.
static bool classof(const PathDiagnosticPiece *P)
StackHintGeneratorForSymbol(SymbolRef S, StringRef M)
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)