clang  7.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 <map>
27 #include <set>
28 #include <string>
29 #include <vector>
30 
31 namespace clang {
32 class ConditionalOperator;
33 class AnalysisDeclContext;
34 class BinaryOperator;
35 class CompoundStmt;
36 class Decl;
37 class LocationContext;
38 class MemberExpr;
39 class ParentMap;
40 class ProgramPoint;
41 class SourceManager;
42 class Stmt;
43 class CallExpr;
44 
45 namespace ento {
46 
47 class ExplodedNode;
48 class SymExpr;
49 typedef const SymExpr* SymbolRef;
50 
51 //===----------------------------------------------------------------------===//
52 // High-level interface for handlers of path-sensitive diagnostics.
53 //===----------------------------------------------------------------------===//
54 
55 class PathDiagnostic;
56 
58 public:
59  class PDFileEntry : public llvm::FoldingSetNode {
60  public:
61  PDFileEntry(llvm::FoldingSetNodeID &NodeID) : NodeID(NodeID) {}
62 
63  typedef std::vector<std::pair<StringRef, StringRef> > ConsumerFiles;
64 
65  /// \brief A vector of <consumer,file> pairs.
66  ConsumerFiles files;
67 
68  /// \brief A precomputed hash tag used for uniquing PDFileEntry objects.
69  const llvm::FoldingSetNodeID NodeID;
70 
71  /// \brief Used for profiling in the FoldingSet.
72  void Profile(llvm::FoldingSetNodeID &ID) { ID = NodeID; }
73  };
74 
75  class FilesMade {
76  llvm::BumpPtrAllocator Alloc;
77  llvm::FoldingSet<PDFileEntry> Set;
78 
79  public:
80  ~FilesMade();
81 
82  bool empty() const { return Set.empty(); }
83 
84  void addDiagnostic(const PathDiagnostic &PD,
85  StringRef ConsumerName,
86  StringRef fileName);
87 
88  PDFileEntry::ConsumerFiles *getFiles(const PathDiagnostic &PD);
89  };
90 
91 private:
92  virtual void anchor();
93 public:
95  virtual ~PathDiagnosticConsumer();
96 
98 
99  virtual void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
100  FilesMade *filesMade) = 0;
101 
102  virtual StringRef getName() const = 0;
103 
104  void HandlePathDiagnostic(std::unique_ptr<PathDiagnostic> D);
105 
108  virtual bool supportsLogicalOpControlFlow() const { return false; }
109 
110  /// Return true if the PathDiagnosticConsumer supports individual
111  /// PathDiagnostics that span multiple files.
112  virtual bool supportsCrossFileDiagnostics() const { return false; }
113 
114 protected:
115  bool flushed;
116  llvm::FoldingSet<PathDiagnostic> Diags;
117 };
118 
119 //===----------------------------------------------------------------------===//
120 // Path-sensitive diagnostics.
121 //===----------------------------------------------------------------------===//
122 
124 public:
125  bool isPoint;
126 
127  PathDiagnosticRange(SourceRange R, bool isP = false)
128  : SourceRange(R), isPoint(isP) {}
129 
130  PathDiagnosticRange() : isPoint(false) {}
131 };
132 
133 typedef llvm::PointerUnion<const LocationContext*, AnalysisDeclContext*>
135 
137 private:
138  enum Kind { RangeK, SingleLocK, StmtK, DeclK } K;
139  const Stmt *S;
140  const Decl *D;
141  const SourceManager *SM;
143  PathDiagnosticRange Range;
144 
146  Kind kind)
147  : K(kind), S(nullptr), D(nullptr), SM(&sm),
148  Loc(genLocation(L)), Range(genRange()) {
149  }
150 
151  FullSourceLoc genLocation(
153  LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext *)nullptr) const;
154 
155  PathDiagnosticRange genRange(
156  LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext *)nullptr) const;
157 
158 public:
159  /// Create an invalid location.
161  : K(SingleLocK), S(nullptr), D(nullptr), SM(nullptr) {}
162 
163  /// Create a location corresponding to the given statement.
165  const SourceManager &sm,
167  : K(s->getLocStart().isValid() ? StmtK : SingleLocK),
168  S(K == StmtK ? s : nullptr),
169  D(nullptr), SM(&sm),
170  Loc(genLocation(SourceLocation(), lac)),
171  Range(genRange(lac)) {
172  assert(K == SingleLocK || S);
173  assert(K == SingleLocK || Loc.isValid());
174  assert(K == SingleLocK || Range.isValid());
175  }
176 
177  /// Create a location corresponding to the given declaration.
179  : K(DeclK), S(nullptr), D(d), SM(&sm),
180  Loc(genLocation()), Range(genRange()) {
181  assert(D);
182  assert(Loc.isValid());
183  assert(Range.isValid());
184  }
185 
186  /// Create a location at an explicit offset in the source.
187  ///
188  /// This should only be used if there are no more appropriate constructors.
190  : K(SingleLocK), S(nullptr), D(nullptr), SM(&sm), Loc(loc, sm),
191  Range(genRange()) {
192  assert(Loc.isValid());
193  assert(Range.isValid());
194  }
195 
196  /// Create a location corresponding to the given declaration.
198  const SourceManager &SM) {
199  return PathDiagnosticLocation(D, SM);
200  }
201 
202  /// Create a location for the beginning of the declaration.
203  static PathDiagnosticLocation createBegin(const Decl *D,
204  const SourceManager &SM);
205 
206  /// Create a location for the beginning of the statement.
207  static PathDiagnosticLocation createBegin(const Stmt *S,
208  const SourceManager &SM,
210 
211  /// Create a location for the end of the statement.
212  ///
213  /// If the statement is a CompoundStatement, the location will point to the
214  /// closing brace instead of following it.
215  static PathDiagnosticLocation createEnd(const Stmt *S,
216  const SourceManager &SM,
218 
219  /// Create the location for the operator of the binary expression.
220  /// Assumes the statement has a valid location.
221  static PathDiagnosticLocation createOperatorLoc(const BinaryOperator *BO,
222  const SourceManager &SM);
223  static PathDiagnosticLocation createConditionalColonLoc(
224  const ConditionalOperator *CO,
225  const SourceManager &SM);
226 
227  /// For member expressions, return the location of the '.' or '->'.
228  /// Assumes the statement has a valid location.
229  static PathDiagnosticLocation createMemberLoc(const MemberExpr *ME,
230  const SourceManager &SM);
231 
232  /// Create a location for the beginning of the compound statement.
233  /// Assumes the statement has a valid location.
234  static PathDiagnosticLocation createBeginBrace(const CompoundStmt *CS,
235  const SourceManager &SM);
236 
237  /// Create a location for the end of the compound statement.
238  /// Assumes the statement has a valid location.
239  static PathDiagnosticLocation createEndBrace(const CompoundStmt *CS,
240  const SourceManager &SM);
241 
242  /// Create a location for the beginning of the enclosing declaration body.
243  /// Defaults to the beginning of the first statement in the declaration body.
244  static PathDiagnosticLocation createDeclBegin(const LocationContext *LC,
245  const SourceManager &SM);
246 
247  /// Constructs a location for the end of the enclosing declaration body.
248  /// Defaults to the end of brace.
249  static PathDiagnosticLocation createDeclEnd(const LocationContext *LC,
250  const SourceManager &SM);
251 
252  /// Create a location corresponding to the given valid ExplodedNode.
254  const SourceManager &SMng);
255 
256  /// Create a location corresponding to the next valid ExplodedNode as end
257  /// of path location.
258  static PathDiagnosticLocation createEndOfPath(const ExplodedNode* N,
259  const SourceManager &SM);
260 
261  /// Convert the given location into a single kind location.
262  static PathDiagnosticLocation createSingleLocation(
263  const PathDiagnosticLocation &PDL);
264 
265  bool operator==(const PathDiagnosticLocation &X) const {
266  return K == X.K && Loc == X.Loc && Range == X.Range;
267  }
268 
269  bool operator!=(const PathDiagnosticLocation &X) const {
270  return !(*this == X);
271  }
272 
273  bool isValid() const {
274  return SM != nullptr;
275  }
276 
278  return Loc;
279  }
280 
282  return Range;
283  }
284 
285  const Stmt *asStmt() const { assert(isValid()); return S; }
286  const Decl *asDecl() const { assert(isValid()); return D; }
287 
288  bool hasRange() const { return K == StmtK || K == RangeK || K == DeclK; }
289 
290  void invalidate() {
291  *this = PathDiagnosticLocation();
292  }
293 
294  void flatten();
295 
296  const SourceManager& getManager() const { assert(isValid()); return *SM; }
297 
298  void Profile(llvm::FoldingSetNodeID &ID) const;
299 
300  void dump() const;
301 
302  /// \brief Given an exploded node, retrieve the statement that should be used
303  /// for the diagnostic location.
304  static const Stmt *getStmt(const ExplodedNode *N);
305 
306  /// \brief Retrieve the statement corresponding to the successor node.
307  static const Stmt *getNextStmt(const ExplodedNode *N);
308 };
309 
311 private:
313 public:
315  const PathDiagnosticLocation &end)
316  : Start(start), End(end) {}
317 
318  const PathDiagnosticLocation &getStart() const { return Start; }
319  const PathDiagnosticLocation &getEnd() const { return End; }
320 
321  void setStart(const PathDiagnosticLocation &L) { Start = L; }
322  void setEnd(const PathDiagnosticLocation &L) { End = L; }
323 
324  void flatten() {
325  Start.flatten();
326  End.flatten();
327  }
328 
329  void Profile(llvm::FoldingSetNodeID &ID) const {
330  Start.Profile(ID);
331  End.Profile(ID);
332  }
333 };
334 
335 //===----------------------------------------------------------------------===//
336 // Path "pieces" for path-sensitive diagnostics.
337 //===----------------------------------------------------------------------===//
338 
339 class PathDiagnosticPiece: public llvm::FoldingSetNode {
340 public:
341  enum Kind { ControlFlow, Event, Macro, Call, Note };
342  enum DisplayHint { Above, Below };
343 
344 private:
345  const std::string str;
346  const Kind kind;
347  const DisplayHint Hint;
348 
349  /// \brief In the containing bug report, this piece is the last piece from
350  /// the main source file.
351  bool LastInMainSourceFile;
352 
353  /// A constant string that can be used to tag the PathDiagnosticPiece,
354  /// typically with the identification of the creator. The actual pointer
355  /// value is meant to be an identifier; the string itself is useful for
356  /// debugging.
357  StringRef Tag;
358 
359  std::vector<SourceRange> ranges;
360 
361  PathDiagnosticPiece() = delete;
362  PathDiagnosticPiece(const PathDiagnosticPiece &P) = delete;
363  void operator=(const PathDiagnosticPiece &P) = delete;
364 
365 protected:
366  PathDiagnosticPiece(StringRef s, Kind k, DisplayHint hint = Below);
367 
368  PathDiagnosticPiece(Kind k, DisplayHint hint = Below);
369 
370 public:
371  virtual ~PathDiagnosticPiece();
372 
373  StringRef getString() const { return str; }
374 
375  /// Tag this PathDiagnosticPiece with the given C-string.
376  void setTag(const char *tag) { Tag = tag; }
377 
378  /// Return the opaque tag (if any) on the PathDiagnosticPiece.
379  const void *getTag() const { return Tag.data(); }
380 
381  /// Return the string representation of the tag. This is useful
382  /// for debugging.
383  StringRef getTagStr() const { return Tag; }
384 
385  /// getDisplayHint - Return a hint indicating where the diagnostic should
386  /// be displayed by the PathDiagnosticConsumer.
387  DisplayHint getDisplayHint() const { return Hint; }
388 
389  virtual PathDiagnosticLocation getLocation() const = 0;
390  virtual void flattenLocations() = 0;
391 
392  Kind getKind() const { return kind; }
393 
395  if (!R.isValid())
396  return;
397  ranges.push_back(R);
398  }
399 
401  if (!B.isValid() || !E.isValid())
402  return;
403  ranges.push_back(SourceRange(B,E));
404  }
405 
406  /// Return the SourceRanges associated with this PathDiagnosticPiece.
407  ArrayRef<SourceRange> getRanges() const { return ranges; }
408 
409  virtual void Profile(llvm::FoldingSetNodeID &ID) const;
410 
412  LastInMainSourceFile = true;
413  }
414 
415  bool isLastInMainSourceFile() const {
416  return LastInMainSourceFile;
417  }
418 
419  virtual void dump() const = 0;
420 };
421 
422 class PathPieces : public std::list<std::shared_ptr<PathDiagnosticPiece>> {
423  void flattenTo(PathPieces &Primary, PathPieces &Current,
424  bool ShouldFlattenMacros) const;
425 public:
426 
427  PathPieces flatten(bool ShouldFlattenMacros) const {
428  PathPieces Result;
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  P->getKind() == Note;
458  }
459 };
460 
461 /// \brief Interface for classes constructing Stack hints.
462 ///
463 /// If a PathDiagnosticEvent occurs in a different frame than the final
464 /// diagnostic the hints can be used to summarize the effect of the call.
466 public:
467  virtual ~StackHintGenerator() = 0;
468 
469  /// \brief Construct the Diagnostic message for the given ExplodedNode.
470  virtual std::string getMessage(const ExplodedNode *N) = 0;
471 };
472 
473 /// \brief Constructs a Stack hint for the given symbol.
474 ///
475 /// The class knows how to construct the stack hint message based on
476 /// traversing the CallExpr associated with the call and checking if the given
477 /// symbol is returned or is one of the arguments.
478 /// The hint can be customized by redefining 'getMessageForX()' methods.
480 private:
481  SymbolRef Sym;
482  std::string Msg;
483 
484 public:
485  StackHintGeneratorForSymbol(SymbolRef S, StringRef M) : Sym(S), Msg(M) {}
487 
488  /// \brief Search the call expression for the symbol Sym and dispatch the
489  /// 'getMessageForX()' methods to construct a specific message.
490  std::string getMessage(const ExplodedNode *N) override;
491 
492  /// Produces the message of the following form:
493  /// 'Msg via Nth parameter'
494  virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex);
495  virtual std::string getMessageForReturn(const CallExpr *CallExpr) {
496  return Msg;
497  }
498  virtual std::string getMessageForSymbolNotFound() {
499  return Msg;
500  }
501 };
502 
504  Optional<bool> IsPrunable;
505 
506  /// If the event occurs in a different frame than the final diagnostic,
507  /// supply a message that will be used to construct an extra hint on the
508  /// returns from all the calls on the stack from this event to the final
509  /// diagnostic.
510  std::unique_ptr<StackHintGenerator> CallStackHint;
511 
512 public:
514  StringRef s, bool addPosRange = true,
515  StackHintGenerator *stackHint = nullptr)
516  : PathDiagnosticSpotPiece(pos, s, Event, addPosRange),
517  CallStackHint(stackHint) {}
518 
519  ~PathDiagnosticEventPiece() override;
520 
521  /// Mark the diagnostic piece as being potentially prunable. This
522  /// flag may have been previously set, at which point it will not
523  /// be reset unless one specifies to do so.
524  void setPrunable(bool isPrunable, bool override = false) {
525  if (IsPrunable.hasValue() && !override)
526  return;
527  IsPrunable = isPrunable;
528  }
529 
530  /// Return true if the diagnostic piece is prunable.
531  bool isPrunable() const {
532  return IsPrunable.hasValue() ? IsPrunable.getValue() : false;
533  }
534 
535  bool hasCallStackHint() { return (bool)CallStackHint; }
536 
537  /// Produce the hint for the given node. The node contains
538  /// information about the call for which the diagnostic can be generated.
539  std::string getCallStackMessage(const ExplodedNode *N) {
540  if (CallStackHint)
541  return CallStackHint->getMessage(N);
542  return "";
543  }
544 
545  void dump() const override;
546 
547  static inline bool classof(const PathDiagnosticPiece *P) {
548  return P->getKind() == Event;
549  }
550 };
551 
553  PathDiagnosticCallPiece(const Decl *callerD,
554  const PathDiagnosticLocation &callReturnPos)
555  : PathDiagnosticPiece(Call), Caller(callerD), Callee(nullptr),
556  NoExit(false), IsCalleeAnAutosynthesizedPropertyAccessor(false),
557  callReturn(callReturnPos) {}
558 
559  PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller)
560  : PathDiagnosticPiece(Call), Caller(caller), Callee(nullptr),
561  NoExit(true), IsCalleeAnAutosynthesizedPropertyAccessor(false),
562  path(oldPath) {}
563 
564  const Decl *Caller;
565  const Decl *Callee;
566 
567  // Flag signifying that this diagnostic has only call enter and no matching
568  // call exit.
569  bool NoExit;
570 
571  // Flag signifying that the callee function is an Objective-C autosynthesized
572  // property getter or setter.
573  bool IsCalleeAnAutosynthesizedPropertyAccessor;
574 
575  // The custom string, which should appear after the call Return Diagnostic.
576  // TODO: Should we allow multiple diagnostics?
577  std::string CallStackMessage;
578 
579 public:
584 
585  ~PathDiagnosticCallPiece() override;
586 
587  const Decl *getCaller() const { return Caller; }
588 
589  const Decl *getCallee() const { return Callee; }
590  void setCallee(const CallEnter &CE, const SourceManager &SM);
591 
592  bool hasCallStackMessage() { return !CallStackMessage.empty(); }
593  void setCallStackMessage(StringRef st) {
594  CallStackMessage = st;
595  }
596 
598  return callEnter;
599  }
600 
601  std::shared_ptr<PathDiagnosticEventPiece> getCallEnterEvent() const;
602  std::shared_ptr<PathDiagnosticEventPiece>
603  getCallEnterWithinCallerEvent() const;
604  std::shared_ptr<PathDiagnosticEventPiece> getCallExitEvent() const;
605 
606  void flattenLocations() override {
607  callEnter.flatten();
608  callReturn.flatten();
609  for (PathPieces::iterator I = path.begin(),
610  E = path.end(); I != E; ++I) (*I)->flattenLocations();
611  }
612 
613  static std::shared_ptr<PathDiagnosticCallPiece>
614  construct(const ExplodedNode *N, const CallExitEnd &CE,
615  const SourceManager &SM);
616 
617  static PathDiagnosticCallPiece *construct(PathPieces &pieces,
618  const Decl *caller);
619 
620  void dump() const override;
621 
622  void Profile(llvm::FoldingSetNodeID &ID) const override;
623 
624  static inline bool classof(const PathDiagnosticPiece *P) {
625  return P->getKind() == Call;
626  }
627 };
628 
630  std::vector<PathDiagnosticLocationPair> LPairs;
631 public:
633  const PathDiagnosticLocation &endPos,
634  StringRef s)
635  : PathDiagnosticPiece(s, ControlFlow) {
636  LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
637  }
638 
640  const PathDiagnosticLocation &endPos)
641  : PathDiagnosticPiece(ControlFlow) {
642  LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
643  }
644 
645  ~PathDiagnosticControlFlowPiece() override;
646 
648  assert(!LPairs.empty() &&
649  "PathDiagnosticControlFlowPiece needs at least one location.");
650  return LPairs[0].getStart();
651  }
652 
654  assert(!LPairs.empty() &&
655  "PathDiagnosticControlFlowPiece needs at least one location.");
656  return LPairs[0].getEnd();
657  }
658 
660  LPairs[0].setStart(L);
661  }
662 
664  LPairs[0].setEnd(L);
665  }
666 
667  void push_back(const PathDiagnosticLocationPair &X) { LPairs.push_back(X); }
668 
670  return getStartLocation();
671  }
672 
673  typedef std::vector<PathDiagnosticLocationPair>::iterator iterator;
674  iterator begin() { return LPairs.begin(); }
675  iterator end() { return LPairs.end(); }
676 
677  void flattenLocations() override {
678  for (iterator I=begin(), E=end(); I!=E; ++I) I->flatten();
679  }
680 
681  typedef std::vector<PathDiagnosticLocationPair>::const_iterator
683  const_iterator begin() const { return LPairs.begin(); }
684  const_iterator end() const { return LPairs.end(); }
685 
686  static inline bool classof(const PathDiagnosticPiece *P) {
687  return P->getKind() == ControlFlow;
688  }
689 
690  void dump() const override;
691 
692  void Profile(llvm::FoldingSetNodeID &ID) const override;
693 };
694 
696 public:
698  : PathDiagnosticSpotPiece(pos, "", Macro) {}
699 
700  ~PathDiagnosticMacroPiece() override;
701 
703 
704  bool containsEvent() const;
705 
706  void flattenLocations() override {
708  for (PathPieces::iterator I = subPieces.begin(),
709  E = subPieces.end(); I != E; ++I) (*I)->flattenLocations();
710  }
711 
712  static inline bool classof(const PathDiagnosticPiece *P) {
713  return P->getKind() == Macro;
714  }
715 
716  void dump() const override;
717 
718  void Profile(llvm::FoldingSetNodeID &ID) const override;
719 };
720 
722 public:
724  bool AddPosRange = true)
725  : PathDiagnosticSpotPiece(Pos, S, Note, AddPosRange) {}
726 
727  ~PathDiagnosticNotePiece() override;
728 
729  static inline bool classof(const PathDiagnosticPiece *P) {
730  return P->getKind() == Note;
731  }
732 
733  void dump() const override;
734 
735  void Profile(llvm::FoldingSetNodeID &ID) const override;
736 };
737 
738 /// File IDs mapped to sets of line numbers.
739 typedef std::map<unsigned, std::set<unsigned>> FilesToLineNumsMap;
740 
741 /// PathDiagnostic - PathDiagnostic objects represent a single path-sensitive
742 /// diagnostic. It represents an ordered-collection of PathDiagnosticPieces,
743 /// each which represent the pieces of the path.
744 class PathDiagnostic : public llvm::FoldingSetNode {
745  std::string CheckName;
746  const Decl *DeclWithIssue;
747  std::string BugType;
748  std::string VerboseDesc;
749  std::string ShortDesc;
750  std::string Category;
751  std::deque<std::string> OtherDesc;
752 
753  /// \brief Loc The location of the path diagnostic report.
755 
756  PathPieces pathImpl;
758 
759  /// \brief Important bug uniqueing location.
760  /// The location info is useful to differentiate between bugs.
761  PathDiagnosticLocation UniqueingLoc;
762  const Decl *UniqueingDecl;
763 
764  /// Lines executed in the path.
765  std::unique_ptr<FilesToLineNumsMap> ExecutedLines;
766 
767  PathDiagnostic() = delete;
768 public:
769  PathDiagnostic(StringRef CheckName, const Decl *DeclWithIssue,
770  StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,
771  StringRef category, PathDiagnosticLocation LocationToUnique,
772  const Decl *DeclToUnique,
773  std::unique_ptr<FilesToLineNumsMap> ExecutedLines);
774 
775  ~PathDiagnostic();
776 
777  const PathPieces &path;
778 
779  /// Return the path currently used by builders for constructing the
780  /// PathDiagnostic.
782  if (pathStack.empty())
783  return pathImpl;
784  return *pathStack.back();
785  }
786 
787  /// Return a mutable version of 'path'.
789  return pathImpl;
790  }
791 
792  /// Return the unrolled size of the path.
793  unsigned full_size();
794 
795  void pushActivePath(PathPieces *p) { pathStack.push_back(p); }
796  void popActivePath() { if (!pathStack.empty()) pathStack.pop_back(); }
797 
798  bool isWithinCall() const { return !pathStack.empty(); }
799 
800  void setEndOfPath(std::unique_ptr<PathDiagnosticPiece> EndPiece) {
801  assert(!Loc.isValid() && "End location already set!");
802  Loc = EndPiece->getLocation();
803  assert(Loc.isValid() && "Invalid location for end-of-path piece");
804  getActivePath().push_back(std::move(EndPiece));
805  }
806 
807  void appendToDesc(StringRef S) {
808  if (!ShortDesc.empty())
809  ShortDesc += S;
810  VerboseDesc += S;
811  }
812 
813  void resetPath() {
814  pathStack.clear();
815  pathImpl.clear();
816  Loc = PathDiagnosticLocation();
817  }
818 
819  /// \brief If the last piece of the report point to the header file, resets
820  /// the location of the report to be the last location in the main source
821  /// file.
822  void resetDiagnosticLocationToMainFile();
823 
824  StringRef getVerboseDescription() const { return VerboseDesc; }
825  StringRef getShortDescription() const {
826  return ShortDesc.empty() ? VerboseDesc : ShortDesc;
827  }
828  StringRef getCheckName() const { return CheckName; }
829  StringRef getBugType() const { return BugType; }
830  StringRef getCategory() const { return Category; }
831 
832  /// Return the semantic context where an issue occurred. If the
833  /// issue occurs along a path, this represents the "central" area
834  /// where the bug manifests.
835  const Decl *getDeclWithIssue() const { return DeclWithIssue; }
836 
837  typedef std::deque<std::string>::const_iterator meta_iterator;
838  meta_iterator meta_begin() const { return OtherDesc.begin(); }
839  meta_iterator meta_end() const { return OtherDesc.end(); }
840  void addMeta(StringRef s) { OtherDesc.push_back(s); }
841 
842  typedef FilesToLineNumsMap::const_iterator filesmap_iterator;
843  filesmap_iterator executedLines_begin() const {
844  return ExecutedLines->begin();
845  }
846  filesmap_iterator executedLines_end() const { return ExecutedLines->end(); }
847 
849  assert(Loc.isValid() && "No report location set yet!");
850  return Loc;
851  }
852 
853  /// \brief Get the location on which the report should be uniqued.
855  return UniqueingLoc;
856  }
857 
858  /// \brief Get the declaration containing the uniqueing location.
859  const Decl *getUniqueingDecl() const {
860  return UniqueingDecl;
861  }
862 
864  Loc.flatten();
865  for (PathPieces::iterator I = pathImpl.begin(), E = pathImpl.end();
866  I != E; ++I) (*I)->flattenLocations();
867  }
868 
869  /// Profiles the diagnostic, independent of the path it references.
870  ///
871  /// This can be used to merge diagnostics that refer to the same issue
872  /// along different paths.
873  void Profile(llvm::FoldingSetNodeID &ID) const;
874 
875  /// Profiles the diagnostic, including its path.
876  ///
877  /// Two diagnostics with the same issue along different paths will generate
878  /// different profiles.
879  void FullProfile(llvm::FoldingSetNodeID &ID) const;
880 };
881 
882 } // end GR namespace
883 
884 } //end clang namespace
885 
886 #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:66
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
virtual StringRef getName() const =0
Represents a point when we begin processing an inlined call.
Definition: ProgramPoint.h:600
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.
filesmap_iterator executedLines_begin() const
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:1525
std::vector< PathDiagnosticLocationPair >::iterator iterator
virtual bool supportsLogicalOpControlFlow() const
PathPieces & getMutablePieces()
Return a mutable version of &#39;path&#39;.
PDFileEntry(llvm::FoldingSetNodeID &NodeID)
std::map< unsigned, std::set< unsigned > > FilesToLineNumsMap
File IDs mapped to sets of line numbers.
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:2998
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:3282
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:595
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:658
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:1412
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
FilesToLineNumsMap::const_iterator filesmap_iterator
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:13401
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:2400
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:2218
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)
filesmap_iterator executedLines_end() const
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)