clang  10.0.0svn
BugReporter.h
Go to the documentation of this file.
1 //===- BugReporter.h - Generate PathDiagnostics -----------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines BugReporter, a utility class for generating
10 // PathDiagnostics for analyses based on ProgramState.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
15 #define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
16 
18 #include "clang/Basic/LLVM.h"
26 #include "llvm/ADT/ArrayRef.h"
27 #include "llvm/ADT/DenseSet.h"
28 #include "llvm/ADT/FoldingSet.h"
29 #include "llvm/ADT/ImmutableSet.h"
30 #include "llvm/ADT/None.h"
31 #include "llvm/ADT/SmallSet.h"
32 #include "llvm/ADT/SmallVector.h"
33 #include "llvm/ADT/StringMap.h"
34 #include "llvm/ADT/StringRef.h"
35 #include "llvm/ADT/ilist.h"
36 #include "llvm/ADT/ilist_node.h"
37 #include "llvm/ADT/iterator_range.h"
38 #include <cassert>
39 #include <memory>
40 #include <string>
41 #include <utility>
42 #include <vector>
43 
44 namespace clang {
45 
46 class AnalyzerOptions;
47 class ASTContext;
48 class Decl;
49 class DiagnosticsEngine;
50 class LocationContext;
51 class SourceManager;
52 class Stmt;
53 
54 namespace ento {
55 
56 class BugType;
57 class CheckerBase;
58 class ExplodedGraph;
59 class ExplodedNode;
60 class ExprEngine;
61 class MemRegion;
62 class SValBuilder;
63 
64 //===----------------------------------------------------------------------===//
65 // Interface for individual bug reports.
66 //===----------------------------------------------------------------------===//
67 
68 /// A mapping from diagnostic consumers to the diagnostics they should
69 /// consume.
71  llvm::DenseMap<PathDiagnosticConsumer *, std::unique_ptr<PathDiagnostic>>;
72 
73 /// Interface for classes constructing Stack hints.
74 ///
75 /// If a PathDiagnosticEvent occurs in a different frame than the final
76 /// diagnostic the hints can be used to summarize the effect of the call.
78 public:
79  virtual ~StackHintGenerator() = 0;
80 
81  /// Construct the Diagnostic message for the given ExplodedNode.
82  virtual std::string getMessage(const ExplodedNode *N) = 0;
83 };
84 
85 /// Constructs a Stack hint for the given symbol.
86 ///
87 /// The class knows how to construct the stack hint message based on
88 /// traversing the CallExpr associated with the call and checking if the given
89 /// symbol is returned or is one of the arguments.
90 /// The hint can be customized by redefining 'getMessageForX()' methods.
92 private:
93  SymbolRef Sym;
94  std::string Msg;
95 
96 public:
97  StackHintGeneratorForSymbol(SymbolRef S, StringRef M) : Sym(S), Msg(M) {}
98  ~StackHintGeneratorForSymbol() override = default;
99 
100  /// Search the call expression for the symbol Sym and dispatch the
101  /// 'getMessageForX()' methods to construct a specific message.
102  std::string getMessage(const ExplodedNode *N) override;
103 
104  /// Produces the message of the following form:
105  /// 'Msg via Nth parameter'
106  virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex);
107 
108  virtual std::string getMessageForReturn(const CallExpr *CallExpr) {
109  return Msg;
110  }
111 
112  virtual std::string getMessageForSymbolNotFound() {
113  return Msg;
114  }
115 };
116 
117 /// This class provides an interface through which checkers can create
118 /// individual bug reports.
119 class BugReport {
120 public:
121  enum class Kind { Basic, PathSensitive };
122 
123 protected:
124  friend class BugReportEquivClass;
125  friend class BugReporter;
126 
128  const BugType& BT;
129  std::string ShortDescription;
130  std::string Description;
131 
135 
136  BugReport(Kind kind, const BugType &bt, StringRef desc)
137  : K(kind), BT(bt), Description(desc) {}
138 
139  BugReport(Kind K, const BugType &BT, StringRef ShortDescription,
140  StringRef Description)
141  : K(K), BT(BT), ShortDescription(ShortDescription),
142  Description(Description) {}
143 
144 public:
145  virtual ~BugReport() = default;
146 
147  Kind getKind() const { return K; }
148 
149  const BugType& getBugType() const { return BT; }
150 
151  /// A verbose warning message that is appropriate for displaying next to
152  /// the source code that introduces the problem. The description should be
153  /// at least a full sentence starting with a capital letter. The period at
154  /// the end of the warning is traditionally omitted. If the description
155  /// consists of multiple sentences, periods between the sentences are
156  /// encouraged, but the period at the end of the description is still omitted.
157  StringRef getDescription() const { return Description; }
158 
159  /// A short general warning message that is appropriate for displaying in
160  /// the list of all reported bugs. It should describe what kind of bug is found
161  /// but does not need to try to go into details of that specific bug.
162  /// Grammatical conventions of getDescription() apply here as well.
163  StringRef getShortDescription(bool UseFallback = true) const {
164  if (ShortDescription.empty() && UseFallback)
165  return Description;
166  return ShortDescription;
167  }
168 
169  /// The primary location of the bug report that points at the undesirable
170  /// behavior in the code. UIs should attach the warning description to this
171  /// location. The warning description should describe the bad behavior
172  /// at this location.
173  virtual PathDiagnosticLocation getLocation() const = 0;
174 
175  /// The smallest declaration that contains the bug location.
176  /// This is purely cosmetic; the declaration can be displayed to the user
177  /// but it does not affect whether the report is emitted.
178  virtual const Decl *getDeclWithIssue() const = 0;
179 
180  /// Get the location on which the report should be uniqued. Two warnings are
181  /// considered to be equivalent whenever they have the same bug types,
182  /// descriptions, and uniqueing locations. Out of a class of equivalent
183  /// warnings only one gets displayed to the user. For most warnings the
184  /// uniqueing location coincides with their location, but sometimes
185  /// it makes sense to use different locations. For example, a leak
186  /// checker can place the warning at the location where the last reference
187  /// to the leaking resource is dropped but at the same time unique the warning
188  /// by where that resource is acquired (allocated).
189  virtual PathDiagnosticLocation getUniqueingLocation() const = 0;
190 
191  /// Get the declaration that corresponds to (usually contains) the uniqueing
192  /// location. This is not actively used for uniqueing, i.e. otherwise
193  /// identical reports that have different uniqueing decls will be considered
194  /// equivalent.
195  virtual const Decl *getUniqueingDecl() const = 0;
196 
197  /// Add new item to the list of additional notes that need to be attached to
198  /// this report. If the report is path-sensitive, these notes will not be
199  /// displayed as part of the execution path explanation, but will be displayed
200  /// separately. Use bug visitors if you need to add an extra path note.
201  void addNote(StringRef Msg, const PathDiagnosticLocation &Pos,
202  ArrayRef<SourceRange> Ranges = {}) {
203  auto P = std::make_shared<PathDiagnosticNotePiece>(Pos, Msg);
204 
205  for (const auto &R : Ranges)
206  P->addRange(R);
207 
208  Notes.push_back(std::move(P));
209  }
210 
212  return Notes;
213  }
214 
215  /// Add a range to a bug report.
216  ///
217  /// Ranges are used to highlight regions of interest in the source code.
218  /// They should be at the same source code line as the BugReport location.
219  /// By default, the source range of the statement corresponding to the error
220  /// node will be used; add a single invalid range to specify absence of
221  /// ranges.
223  assert((R.isValid() || Ranges.empty()) && "Invalid range can only be used "
224  "to specify that the report does not have a range.");
225  Ranges.push_back(R);
226  }
227 
228  /// Get the SourceRanges associated with the report.
230  return Ranges;
231  }
232 
233  /// Add a fix-it hint to the bug report.
234  ///
235  /// Fix-it hints are the suggested edits to the code that would resolve
236  /// the problem explained by the bug report. Fix-it hints should be
237  /// as conservative as possible because it is not uncommon for the user
238  /// to blindly apply all fixits to their project. Note that it is very hard
239  /// to produce a good fix-it hint for most path-sensitive warnings.
240  void addFixItHint(const FixItHint &F) {
241  Fixits.push_back(F);
242  }
243 
244  llvm::ArrayRef<FixItHint> getFixits() const { return Fixits; }
245 
246  /// Reports are uniqued to ensure that we do not emit multiple diagnostics
247  /// for each bug.
248  virtual void Profile(llvm::FoldingSetNodeID& hash) const = 0;
249 };
250 
251 class BasicBugReport : public BugReport {
252  PathDiagnosticLocation Location;
253  const Decl *DeclWithIssue = nullptr;
254 
255 public:
256  BasicBugReport(const BugType &bt, StringRef desc, PathDiagnosticLocation l)
257  : BugReport(Kind::Basic, bt, desc), Location(l) {}
258 
259  static bool classof(const BugReport *R) {
260  return R->getKind() == Kind::Basic;
261  }
262 
264  assert(Location.isValid());
265  return Location;
266  }
267 
268  const Decl *getDeclWithIssue() const override {
269  return DeclWithIssue;
270  }
271 
273  return getLocation();
274  }
275 
276  const Decl *getUniqueingDecl() const override {
277  return getDeclWithIssue();
278  }
279 
280  /// Specifically set the Decl where an issue occurred. This isn't necessary
281  /// for BugReports that cover a path as it will be automatically inferred.
282  void setDeclWithIssue(const Decl *declWithIssue) {
283  DeclWithIssue = declWithIssue;
284  }
285 
286  void Profile(llvm::FoldingSetNodeID& hash) const override;
287 };
288 
290 public:
292  using visitor_iterator = VisitorList::iterator;
293  using visitor_range = llvm::iterator_range<visitor_iterator>;
294 
295 protected:
296  /// The ExplodedGraph node against which the report was thrown. It corresponds
297  /// to the end of the execution path that demonstrates the bug.
298  const ExplodedNode *ErrorNode = nullptr;
299 
300  /// The range that corresponds to ErrorNode's program point. It is usually
301  /// highlighted in the report.
303 
304  /// Profile to identify equivalent bug reports for error report coalescing.
305 
306  /// A (stack of) a set of symbols that are registered with this
307  /// report as being "interesting", and thus used to help decide which
308  /// diagnostics to include when constructing the final path diagnostic.
309  /// The stack is largely used by BugReporter when generating PathDiagnostics
310  /// for multiple PathDiagnosticConsumers.
311  llvm::DenseMap<SymbolRef, bugreporter::TrackingKind> InterestingSymbols;
312 
313  /// A (stack of) set of regions that are registered with this report as being
314  /// "interesting", and thus used to help decide which diagnostics
315  /// to include when constructing the final path diagnostic.
316  /// The stack is largely used by BugReporter when generating PathDiagnostics
317  /// for multiple PathDiagnosticConsumers.
318  llvm::DenseMap<const MemRegion *, bugreporter::TrackingKind>
320 
321  /// A set of location contexts that correspoind to call sites which should be
322  /// considered "interesting".
323  llvm::SmallSet<const LocationContext *, 2> InterestingLocationContexts;
324 
325  /// A set of custom visitors which generate "event" diagnostics at
326  /// interesting points in the path.
328 
329  /// Used for ensuring the visitors are only added once.
330  llvm::FoldingSet<BugReporterVisitor> CallbacksSet;
331 
332  /// When set, this flag disables all callstack pruning from a diagnostic
333  /// path. This is useful for some reports that want maximum fidelty
334  /// when reporting an issue.
335  bool DoNotPrunePath = false;
336 
337  /// Used to track unique reasons why a bug report might be invalid.
338  ///
339  /// \sa markInvalid
340  /// \sa removeInvalidation
341  using InvalidationRecord = std::pair<const void *, const void *>;
342 
343  /// If non-empty, this bug report is likely a false positive and should not be
344  /// shown to the user.
345  ///
346  /// \sa markInvalid
347  /// \sa removeInvalidation
348  llvm::SmallSet<InvalidationRecord, 4> Invalidations;
349 
350  /// Conditions we're already tracking.
351  llvm::SmallSet<const ExplodedNode *, 4> TrackedConditions;
352 
353  /// Reports with different uniqueing locations are considered to be different
354  /// for the purposes of deduplication.
357 
358  const Stmt *getStmt() const;
359 
360  /// If an event occurs in a different frame than the final diagnostic,
361  /// supply a message that will be used to construct an extra hint on the
362  /// returns from all the calls on the stack from this event to the final
363  /// diagnostic.
364  // FIXME: Allow shared_ptr keys in DenseMap?
365  std::map<PathDiagnosticPieceRef, std::unique_ptr<StackHintGenerator>>
367 
368 public:
369  PathSensitiveBugReport(const BugType &bt, StringRef desc,
370  const ExplodedNode *errorNode)
371  : BugReport(Kind::PathSensitive, bt, desc), ErrorNode(errorNode),
372  ErrorNodeRange(getStmt() ? getStmt()->getSourceRange()
373  : SourceRange()) {}
374 
375  PathSensitiveBugReport(const BugType &bt, StringRef shortDesc, StringRef desc,
376  const ExplodedNode *errorNode)
377  : BugReport(Kind::PathSensitive, bt, shortDesc, desc),
378  ErrorNode(errorNode),
379  ErrorNodeRange(getStmt() ? getStmt()->getSourceRange()
380  : SourceRange()) {}
381 
382  /// Create a PathSensitiveBugReport with a custom uniqueing location.
383  ///
384  /// The reports that have the same report location, description, bug type, and
385  /// ranges are uniqued - only one of the equivalent reports will be presented
386  /// to the user. This method allows to rest the location which should be used
387  /// for uniquing reports. For example, memory leaks checker, could set this to
388  /// the allocation site, rather then the location where the bug is reported.
389  PathSensitiveBugReport(BugType &bt, StringRef desc,
390  const ExplodedNode *errorNode,
391  PathDiagnosticLocation LocationToUnique,
392  const Decl *DeclToUnique)
393  : BugReport(Kind::PathSensitive, bt, desc), ErrorNode(errorNode),
394  ErrorNodeRange(getStmt() ? getStmt()->getSourceRange() : SourceRange()),
395  UniqueingLocation(LocationToUnique), UniqueingDecl(DeclToUnique) {
396  assert(errorNode);
397  }
398 
399  static bool classof(const BugReport *R) {
400  return R->getKind() == Kind::PathSensitive;
401  }
402 
403  const ExplodedNode *getErrorNode() const { return ErrorNode; }
404 
405  /// Indicates whether or not any path pruning should take place
406  /// when generating a PathDiagnostic from this BugReport.
407  bool shouldPrunePath() const { return !DoNotPrunePath; }
408 
409  /// Disable all path pruning when generating a PathDiagnostic.
410  void disablePathPruning() { DoNotPrunePath = true; }
411 
412  /// Get the location on which the report should be uniqued.
414  return UniqueingLocation;
415  }
416 
417  /// Get the declaration containing the uniqueing location.
418  const Decl *getUniqueingDecl() const override {
419  return UniqueingDecl;
420  }
421 
422  const Decl *getDeclWithIssue() const override;
423 
424  ArrayRef<SourceRange> getRanges() const override;
425 
426  PathDiagnosticLocation getLocation() const override;
427 
428  /// Marks a symbol as interesting. Different kinds of interestingness will
429  /// be processed differently by visitors (e.g. if the tracking kind is
430  /// condition, will append "will be used as a condition" to the message).
431  void markInteresting(SymbolRef sym, bugreporter::TrackingKind TKind =
432  bugreporter::TrackingKind::Thorough);
433 
434  /// Marks a region as interesting. Different kinds of interestingness will
435  /// be processed differently by visitors (e.g. if the tracking kind is
436  /// condition, will append "will be used as a condition" to the message).
437  void markInteresting(
438  const MemRegion *R,
439  bugreporter::TrackingKind TKind = bugreporter::TrackingKind::Thorough);
440 
441  /// Marks a symbolic value as interesting. Different kinds of interestingness
442  /// will be processed differently by visitors (e.g. if the tracking kind is
443  /// condition, will append "will be used as a condition" to the message).
444  void markInteresting(SVal V, bugreporter::TrackingKind TKind =
445  bugreporter::TrackingKind::Thorough);
446  void markInteresting(const LocationContext *LC);
447 
448  bool isInteresting(SymbolRef sym) const;
449  bool isInteresting(const MemRegion *R) const;
450  bool isInteresting(SVal V) const;
451  bool isInteresting(const LocationContext *LC) const;
452 
454  getInterestingnessKind(SymbolRef sym) const;
455 
457  getInterestingnessKind(const MemRegion *R) const;
458 
459  Optional<bugreporter::TrackingKind> getInterestingnessKind(SVal V) const;
460 
461  /// Returns whether or not this report should be considered valid.
462  ///
463  /// Invalid reports are those that have been classified as likely false
464  /// positives after the fact.
465  bool isValid() const {
466  return Invalidations.empty();
467  }
468 
469  /// Marks the current report as invalid, meaning that it is probably a false
470  /// positive and should not be reported to the user.
471  ///
472  /// The \p Tag and \p Data arguments are intended to be opaque identifiers for
473  /// this particular invalidation, where \p Tag represents the visitor
474  /// responsible for invalidation, and \p Data represents the reason this
475  /// visitor decided to invalidate the bug report.
476  ///
477  /// \sa removeInvalidation
478  void markInvalid(const void *Tag, const void *Data) {
479  Invalidations.insert(std::make_pair(Tag, Data));
480  }
481 
482  /// Profile to identify equivalent bug reports for error report coalescing.
483  /// Reports are uniqued to ensure that we do not emit multiple diagnostics
484  /// for each bug.
485  void Profile(llvm::FoldingSetNodeID &hash) const override;
486 
487  /// Add custom or predefined bug report visitors to this report.
488  ///
489  /// The visitors should be used when the default trace is not sufficient.
490  /// For example, they allow constructing a more elaborate trace.
491  /// \sa registerConditionVisitor(), registerTrackNullOrUndefValue(),
492  /// registerFindLastStore(), registerNilReceiverVisitor(), and
493  /// registerVarDeclsLastStore().
494  void addVisitor(std::unique_ptr<BugReporterVisitor> visitor);
495 
496  /// Remove all visitors attached to this bug report.
497  void clearVisitors();
498 
499  /// Iterators through the custom diagnostic visitors.
500  visitor_iterator visitor_begin() { return Callbacks.begin(); }
501  visitor_iterator visitor_end() { return Callbacks.end(); }
502  visitor_range visitors() { return {visitor_begin(), visitor_end()}; }
503 
504  /// Notes that the condition of the CFGBlock associated with \p Cond is
505  /// being tracked.
506  /// \returns false if the condition is already being tracked.
507  bool addTrackedCondition(const ExplodedNode *Cond) {
508  return TrackedConditions.insert(Cond).second;
509  }
510 
512  std::unique_ptr<StackHintGenerator> StackHint) {
513  StackHints[Piece] = std::move(StackHint);
514  }
515 
517  return StackHints.count(Piece) > 0;
518  }
519 
520  /// Produce the hint for the given node. The node contains
521  /// information about the call for which the diagnostic can be generated.
522  std::string
524  const ExplodedNode *N) const {
525  auto I = StackHints.find(Piece);
526  if (I != StackHints.end())
527  return I->second->getMessage(N);
528  return "";
529  }
530 };
531 
532 //===----------------------------------------------------------------------===//
533 // BugTypes (collections of related reports).
534 //===----------------------------------------------------------------------===//
535 
536 class BugReportEquivClass : public llvm::FoldingSetNode {
537  friend class BugReporter;
538 
539  /// List of *owned* BugReport objects.
541 
542  void AddReport(std::unique_ptr<BugReport> &&R) {
543  Reports.push_back(std::move(R));
544  }
545 
546 public:
547  BugReportEquivClass(std::unique_ptr<BugReport> R) { AddReport(std::move(R)); }
548 
549  ArrayRef<std::unique_ptr<BugReport>> getReports() const { return Reports; }
550 
551  void Profile(llvm::FoldingSetNodeID& ID) const {
552  assert(!Reports.empty());
553  Reports.front()->Profile(ID);
554  }
555 };
556 
557 //===----------------------------------------------------------------------===//
558 // BugReporter and friends.
559 //===----------------------------------------------------------------------===//
560 
562 public:
563  virtual ~BugReporterData() = default;
564 
565  virtual ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() = 0;
566  virtual ASTContext &getASTContext() = 0;
567  virtual SourceManager &getSourceManager() = 0;
568  virtual AnalyzerOptions &getAnalyzerOptions() = 0;
569 };
570 
571 /// BugReporter is a utility class for generating PathDiagnostics for analysis.
572 /// It collects the BugReports and BugTypes and knows how to generate
573 /// and flush the corresponding diagnostics.
574 ///
575 /// The base class is used for generating path-insensitive
576 class BugReporter {
577 private:
578  BugReporterData& D;
579 
580  /// Generate and flush the diagnostics for the given bug report.
581  void FlushReport(BugReportEquivClass& EQ);
582 
583  /// The set of bug reports tracked by the BugReporter.
584  llvm::FoldingSet<BugReportEquivClass> EQClasses;
585 
586  /// A vector of BugReports for tracking the allocated pointers and cleanup.
587  std::vector<BugReportEquivClass *> EQClassesVector;
588 
589 public:
591  virtual ~BugReporter();
592 
593  /// Generate and flush diagnostics for all bug reports.
594  void FlushReports();
595 
597  return D.getPathDiagnosticConsumers();
598  }
599 
600  /// Iterator over the set of BugReports tracked by the BugReporter.
601  using EQClasses_iterator = llvm::FoldingSet<BugReportEquivClass>::iterator;
602  EQClasses_iterator EQClasses_begin() { return EQClasses.begin(); }
603  EQClasses_iterator EQClasses_end() { return EQClasses.end(); }
604 
606 
608 
610 
611  /// Add the given report to the set of reports tracked by BugReporter.
612  ///
613  /// The reports are usually generated by the checkers. Further, they are
614  /// folded based on the profile value, which is done to coalesce similar
615  /// reports.
616  virtual void emitReport(std::unique_ptr<BugReport> R);
617 
618  void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker,
619  StringRef BugName, StringRef BugCategory,
620  StringRef BugStr, PathDiagnosticLocation Loc,
621  ArrayRef<SourceRange> Ranges = None,
622  ArrayRef<FixItHint> Fixits = None);
623 
624  void EmitBasicReport(const Decl *DeclWithIssue, CheckerNameRef CheckerName,
625  StringRef BugName, StringRef BugCategory,
626  StringRef BugStr, PathDiagnosticLocation Loc,
627  ArrayRef<SourceRange> Ranges = None,
628  ArrayRef<FixItHint> Fixits = None);
629 
630 private:
631  llvm::StringMap<BugType *> StrBugTypes;
632 
633  /// Returns a BugType that is associated with the given name and
634  /// category.
635  BugType *getBugTypeForName(CheckerNameRef CheckerName, StringRef name,
636  StringRef category);
637 
638  virtual BugReport *
639  findReportInEquivalenceClass(BugReportEquivClass &eqClass,
640  SmallVectorImpl<BugReport *> &bugReports) {
641  return eqClass.getReports()[0].get();
642  }
643 
644 protected:
645  /// Generate the diagnostics for the given bug report.
646  virtual std::unique_ptr<DiagnosticForConsumerMapTy>
647  generateDiagnosticForConsumerMap(BugReport *exampleReport,
649  ArrayRef<BugReport *> bugReports);
650 };
651 
652 /// GRBugReporter is used for generating path-sensitive reports.
653 class PathSensitiveBugReporter final : public BugReporter {
654  ExprEngine& Eng;
655 
656  BugReport *findReportInEquivalenceClass(
657  BugReportEquivClass &eqClass,
658  SmallVectorImpl<BugReport *> &bugReports) override;
659 
660  /// Generate the diagnostics for the given bug report.
661  std::unique_ptr<DiagnosticForConsumerMapTy>
662  generateDiagnosticForConsumerMap(BugReport *exampleReport,
664  ArrayRef<BugReport *> bugReports) override;
665 public:
667  : BugReporter(d), Eng(eng) {}
668 
669  /// getGraph - Get the exploded graph created by the analysis engine
670  /// for the analyzed method or function.
671  const ExplodedGraph &getGraph() const;
672 
673  /// getStateManager - Return the state manager used by the analysis
674  /// engine.
675  ProgramStateManager &getStateManager() const;
676 
677  /// \p bugReports A set of bug reports within a *single* equivalence class
678  ///
679  /// \return A mapping from consumers to the corresponding diagnostics.
680  /// Iterates through the bug reports within a single equivalence class,
681  /// stops at a first non-invalidated report.
682  std::unique_ptr<DiagnosticForConsumerMapTy> generatePathDiagnostics(
685 
686  void emitReport(std::unique_ptr<BugReport> R) override;
687 };
688 
689 
692 
693  virtual void anchor();
694 
695 public:
697 
698  virtual ~BugReporterContext() = default;
699 
701 
703  return BR.getStateManager();
704  }
705 
707  return BR.getContext();
708  }
709 
711  return BR.getSourceManager();
712  }
713 
715  return BR.getAnalyzerOptions();
716  }
717 };
718 
719 
720 /// The tag upon which the TagVisitor reacts. Add these in order to display
721 /// additional PathDiagnosticEventPieces along the path.
722 class NoteTag : public ProgramPointTag {
723 public:
724  using Callback =
725  std::function<std::string(BugReporterContext &, BugReport &)>;
726 
727 private:
728  static int Kind;
729 
730  const Callback Cb;
731  const bool IsPrunable;
732 
733  NoteTag(Callback &&Cb, bool IsPrunable)
734  : ProgramPointTag(&Kind), Cb(std::move(Cb)), IsPrunable(IsPrunable) {}
735 
736 public:
737  static bool classof(const ProgramPointTag *T) {
738  return T->getTagKind() == &Kind;
739  }
740 
742  BugReport &R) const {
743  std::string Msg = Cb(BRC, R);
744  if (Msg.empty())
745  return None;
746 
747  return std::move(Msg);
748  }
749 
750  StringRef getTagDescription() const override {
751  // TODO: Remember a few examples of generated messages
752  // and display them in the ExplodedGraph dump by
753  // returning them from this function.
754  return "Note Tag";
755  }
756 
757  bool isPrunable() const { return IsPrunable; }
758 
759  // Manage memory for NoteTag objects.
760  class Factory {
761  std::vector<std::unique_ptr<NoteTag>> Tags;
762 
763  public:
764  const NoteTag *makeNoteTag(Callback &&Cb, bool IsPrunable = false) {
765  // We cannot use std::make_unique because we cannot access the private
766  // constructor from inside it.
767  std::unique_ptr<NoteTag> T(new NoteTag(std::move(Cb), IsPrunable));
768  Tags.push_back(std::move(T));
769  return Tags.back().get();
770  }
771  };
772 
773  friend class TagVisitor;
774 };
775 
776 } // namespace ento
777 
778 } // namespace clang
779 
780 #endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
GRBugReporter is used for generating path-sensitive reports.
Definition: BugReporter.h:653
BugReporter(BugReporterData &d)
Definition: BugReporter.h:590
ProgramStateManager & getStateManager() const
getStateManager - Return the state manager used by the analysis engine.
PathDiagnosticLocation UniqueingLocation
Reports with different uniqueing locations are considered to be different for the purposes of dedupli...
Definition: BugReporter.h:355
This wrapper is used to ensure that only StringRefs originating from the CheckerRegistry are used as ...
MemRegion - The root abstract class for all memory regions.
Definition: MemRegion.h:94
PathSensitiveBugReport(BugType &bt, StringRef desc, const ExplodedNode *errorNode, PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique)
Create a PathSensitiveBugReport with a custom uniqueing location.
Definition: BugReporter.h:389
std::string getCallStackMessage(PathDiagnosticPieceRef Piece, const ExplodedNode *N) const
Produce the hint for the given node.
Definition: BugReporter.h:523
llvm::DenseMap< const MemRegion *, bugreporter::TrackingKind > InterestingRegions
A (stack of) set of regions that are registered with this report as being "interesting", and thus used to help decide which diagnostics to include when constructing the final path diagnostic.
Definition: BugReporter.h:319
void addFixItHint(const FixItHint &F)
Add a fix-it hint to the bug report.
Definition: BugReporter.h:240
visitor_iterator visitor_begin()
Iterators through the custom diagnostic visitors.
Definition: BugReporter.h:500
Stmt - This represents one statement.
Definition: Stmt.h:66
PathSensitiveBugReporter(BugReporterData &d, ExprEngine &eng)
Definition: BugReporter.h:666
const NoteTag * makeNoteTag(Callback &&Cb, bool IsPrunable=false)
Definition: BugReporter.h:764
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:88
ASTContext & getASTContext() const
Definition: BugReporter.h:706
StringRef getDescription() const
A verbose warning message that is appropriate for displaying next to the source code that introduces ...
Definition: BugReporter.h:157
PathSensitiveBugReport(const BugType &bt, StringRef desc, const ExplodedNode *errorNode)
Definition: BugReporter.h:369
StringRef P
ArrayRef< PathDiagnosticConsumer * > getPathDiagnosticConsumers()
Definition: BugReporter.h:596
Constructs a Stack hint for the given symbol.
Definition: BugReporter.h:91
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
llvm::FoldingSet< BugReporterVisitor > CallbacksSet
Used for ensuring the visitors are only added once.
Definition: BugReporter.h:330
SmallVector< SourceRange, 4 > Ranges
Definition: BugReporter.h:132
virtual AnalyzerOptions & getAnalyzerOptions()=0
const BugType & BT
Definition: BugReporter.h:128
llvm::SmallSet< InvalidationRecord, 4 > Invalidations
If non-empty, this bug report is likely a false positive and should not be shown to the user...
Definition: BugReporter.h:348
CharSourceRange getSourceRange(const SourceRange &Range)
Returns the token CharSourceRange corresponding to Range.
Definition: FixIt.h:32
llvm::DenseMap< PathDiagnosticConsumer *, std::unique_ptr< PathDiagnostic > > DiagnosticForConsumerMapTy
A mapping from diagnostic consumers to the diagnostics they should consume.
Definition: BugReporter.h:71
Symbolic value.
Definition: SymExpr.h:29
const Decl * getDeclWithIssue() const override
The smallest declaration that contains the bug location.
Definition: BugReporter.h:268
const Decl * getUniqueingDecl() const override
Get the declaration that corresponds to (usually contains) the uniqueing location.
Definition: BugReporter.h:276
void addRange(SourceRange R)
Add a range to a bug report.
Definition: BugReporter.h:222
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:160
std::function< std::string(BugReporterContext &, BugReport &)> Callback
Definition: BugReporter.h:725
Definition: Format.h:2392
std::string ShortDescription
Definition: BugReporter.h:129
const ExplodedNode * getErrorNode() const
Definition: BugReporter.h:403
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
const BugType & getBugType() const
Definition: BugReporter.h:149
virtual std::string getMessageForReturn(const CallExpr *CallExpr)
Definition: BugReporter.h:108
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
ASTContext & getContext()
Definition: BugReporter.h:605
BugReport(Kind kind, const BugType &bt, StringRef desc)
Definition: BugReporter.h:136
bool shouldPrunePath() const
Indicates whether or not any path pruning should take place when generating a PathDiagnostic from thi...
Definition: BugReporter.h:407
static bool classof(const BugReport *R)
Definition: BugReporter.h:399
RangeSelector name(std::string ID)
Given a node with a "name", (like NamedDecl, DeclRefExpr or CxxCtorInitializer) selects the name&#39;s to...
void Profile(llvm::FoldingSetNodeID &ID) const
Definition: BugReporter.h:551
std::pair< const void *, const void * > InvalidationRecord
Used to track unique reasons why a bug report might be invalid.
Definition: BugReporter.h:341
static bool classof(const ProgramPointTag *T)
Definition: BugReporter.h:737
BugReportEquivClass(std::unique_ptr< BugReport > R)
Definition: BugReporter.h:547
void disablePathPruning()
Disable all path pruning when generating a PathDiagnostic.
Definition: BugReporter.h:410
PathSensitiveBugReport(const BugType &bt, StringRef shortDesc, StringRef desc, const ExplodedNode *errorNode)
Definition: BugReporter.h:375
This represents one expression.
Definition: Expr.h:108
bool isValid() const
Returns whether or not this report should be considered valid.
Definition: BugReporter.h:465
Kind getKind() const
Definition: BugReporter.h:147
#define V(N, I)
Definition: ASTContext.h:2921
void addNote(StringRef Msg, const PathDiagnosticLocation &Pos, ArrayRef< SourceRange > Ranges={})
Add new item to the list of additional notes that need to be attached to this report.
Definition: BugReporter.h:201
virtual SourceManager & getSourceManager()=0
static bool classof(const BugReport *R)
Definition: BugReporter.h:259
PathDiagnosticLocation getUniqueingLocation() const override
Get the location on which the report should be uniqued.
Definition: BugReporter.h:272
virtual ArrayRef< SourceRange > getRanges() const
Get the SourceRanges associated with the report.
Definition: BugReporter.h:229
PathDiagnosticLocation getUniqueingLocation() const override
Get the location on which the report should be uniqued.
Definition: BugReporter.h:413
virtual std::string getMessageForSymbolNotFound()
Definition: BugReporter.h:112
PathDiagnosticLocation getLocation() const override
The primary location of the bug report that points at the undesirable behavior in the code...
Definition: BugReporter.h:263
Interface for classes constructing Stack hints.
Definition: BugReporter.h:77
llvm::SmallSet< const LocationContext *, 2 > InterestingLocationContexts
A set of location contexts that correspoind to call sites which should be considered "interesting"...
Definition: BugReporter.h:323
BugReporterContext(PathSensitiveBugReporter &br)
Definition: BugReporter.h:696
The tag upon which the TagVisitor reacts.
Definition: BugReporter.h:722
virtual ArrayRef< PathDiagnosticConsumer * > getPathDiagnosticConsumers()=0
VisitorList Callbacks
A set of custom visitors which generate "event" diagnostics at interesting points in the path...
Definition: BugReporter.h:327
PathSensitiveBugReporter & getBugReporter()
Definition: BugReporter.h:700
const SourceManager & getSourceManager() const
Definition: BugReporter.h:710
BugReporter is a utility class for generating PathDiagnostics for analysis.
Definition: BugReporter.h:576
Kind
EQClasses_iterator EQClasses_begin()
Definition: BugReporter.h:602
llvm::SmallSet< const ExplodedNode *, 4 > TrackedConditions
Conditions we&#39;re already tracking.
Definition: BugReporter.h:351
const Decl * getUniqueingDecl() const override
Get the declaration containing the uniqueing location.
Definition: BugReporter.h:418
ProgramPoints can be "tagged" as representing points specific to a given analysis entity...
Definition: ProgramPoint.h:39
const AnalyzerOptions & getAnalyzerOptions() const
Definition: BugReporter.h:714
std::string Description
Definition: BugReporter.h:130
BasicBugReport(const BugType &bt, StringRef desc, PathDiagnosticLocation l)
Definition: BugReporter.h:256
llvm::DenseMap< SymbolRef, bugreporter::TrackingKind > InterestingSymbols
Profile to identify equivalent bug reports for error report coalescing.
Definition: BugReporter.h:311
bool addTrackedCondition(const ExplodedNode *Cond)
Notes that the condition of the CFGBlock associated with Cond is being tracked.
Definition: BugReporter.h:507
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:75
bool isPrunable() const
Definition: BugReporter.h:757
VisitorList::iterator visitor_iterator
Definition: BugReporter.h:292
void addCallStackHint(PathDiagnosticPieceRef Piece, std::unique_ptr< StackHintGenerator > StackHint)
Definition: BugReporter.h:511
Dataflow Directional Tag Classes.
ProgramStateManager & getStateManager() const
Definition: BugReporter.h:702
bool hasCallStackHint(PathDiagnosticPieceRef Piece) const
Definition: BugReporter.h:516
Optional< std::string > generateMessage(BugReporterContext &BRC, BugReport &R) const
Definition: BugReporter.h:741
StringRef getTagDescription() const override
Definition: BugReporter.h:750
virtual std::string getMessage(const ExplodedNode *N)=0
Construct the Diagnostic message for the given ExplodedNode.
std::map< PathDiagnosticPieceRef, std::unique_ptr< StackHintGenerator > > StackHints
If an event occurs in a different frame than the final diagnostic, supply a message that will be used...
Definition: BugReporter.h:366
const AnalyzerOptions & getAnalyzerOptions()
Definition: BugReporter.h:609
llvm::ArrayRef< FixItHint > getFixits() const
Definition: BugReporter.h:244
EQClasses_iterator EQClasses_end()
Definition: BugReporter.h:603
StringRef getShortDescription(bool UseFallback=true) const
A short general warning message that is appropriate for displaying in the list of all reported bugs...
Definition: BugReporter.h:163
llvm::FoldingSet< BugReportEquivClass >::iterator EQClasses_iterator
Iterator over the set of BugReports tracked by the BugReporter.
Definition: BugReporter.h:601
Stores options for the analyzer from the command line.
void markInvalid(const void *Tag, const void *Data)
Marks the current report as invalid, meaning that it is probably a false positive and should not be r...
Definition: BugReporter.h:478
SmallVector< std::shared_ptr< PathDiagnosticNotePiece >, 4 > Notes
Definition: BugReporter.h:133
SmallVector< FixItHint, 4 > Fixits
Definition: BugReporter.h:134
Defines the clang::SourceLocation class and associated facilities.
ArrayRef< std::unique_ptr< BugReport > > getReports() const
Definition: BugReporter.h:549
bool isValid() const
llvm::iterator_range< visitor_iterator > visitor_range
Definition: BugReporter.h:293
BugReport(Kind K, const BugType &BT, StringRef ShortDescription, StringRef Description)
Definition: BugReporter.h:139
unsigned kind
All of the diagnostics that can be emitted by the frontend.
Definition: DiagnosticIDs.h:60
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2521
Annotates a diagnostic with some code that should be inserted, removed, or replaced to fix the proble...
Definition: Diagnostic.h:66
ArrayRef< std::shared_ptr< PathDiagnosticNotePiece > > getNotes()
Definition: BugReporter.h:211
A trivial tuple used to represent a source range.
This class provides an interface through which checkers can create individual bug reports...
Definition: BugReporter.h:119
StackHintGeneratorForSymbol(SymbolRef S, StringRef M)
Definition: BugReporter.h:97
This class handles loading and caching of source files into memory.
const void * getTagKind() const
Used to implement &#39;isKind&#39; in subclasses.
Definition: ProgramPoint.h:46
virtual ASTContext & getASTContext()=0
const SourceManager & getSourceManager()
Definition: BugReporter.h:607
bool EQ(InterpState &S, CodePtr OpPC)
Definition: Interp.h:219
void setDeclWithIssue(const Decl *declWithIssue)
Specifically set the Decl where an issue occurred.
Definition: BugReporter.h:282
const SourceRange ErrorNodeRange
The range that corresponds to ErrorNode&#39;s program point.
Definition: BugReporter.h:302