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