]> granicus.if.org Git - clang/commitdiff
[analyzer] NFC: Introduce sub-classes for path-sensitive and basic reports.
authorArtem Dergachev <artem.dergachev@gmail.com>
Mon, 9 Sep 2019 20:34:40 +0000 (20:34 +0000)
committerArtem Dergachev <artem.dergachev@gmail.com>
Mon, 9 Sep 2019 20:34:40 +0000 (20:34 +0000)
Checkers are now required to specify whether they're creating a
path-sensitive report or a path-insensitive report by constructing an
object of the respective type.

This makes BugReporter more independent from the rest of the Static Analyzer
because all Analyzer-specific code is now in sub-classes.

Differential Revision: https://reviews.llvm.org/D66572

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@371450 91177308-0d34-0410-b5e6-96231b3b80d8

75 files changed:
include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h
include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
lib/Analysis/plugins/SampleAnalyzer/MainCallChecker.cpp
lib/StaticAnalyzer/Checkers/ArrayBoundChecker.cpp
lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
lib/StaticAnalyzer/Checkers/CStringChecker.cpp
lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp
lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
lib/StaticAnalyzer/Checkers/CloneChecker.cpp
lib/StaticAnalyzer/Checkers/ConversionChecker.cpp
lib/StaticAnalyzer/Checkers/DebugCheckers.cpp
lib/StaticAnalyzer/Checkers/DeleteWithNonVirtualDtorChecker.cpp
lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp
lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp
lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp
lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp
lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
lib/StaticAnalyzer/Checkers/MIGChecker.cpp
lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.cpp
lib/StaticAnalyzer/Checkers/MPI-Checker/MPIBugReporter.h
lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
lib/StaticAnalyzer/Checkers/MallocChecker.cpp
lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
lib/StaticAnalyzer/Checkers/MoveChecker.cpp
lib/StaticAnalyzer/Checkers/NSAutoreleasePoolChecker.cpp
lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
lib/StaticAnalyzer/Checkers/NonNullParamChecker.cpp
lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp
lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp
lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp
lib/StaticAnalyzer/Checkers/ObjCSuperDeallocChecker.cpp
lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp
lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp
lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h
lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp
lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp
lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
lib/StaticAnalyzer/Checkers/StreamChecker.cpp
lib/StaticAnalyzer/Checkers/Taint.cpp
lib/StaticAnalyzer/Checkers/Taint.h
lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp
lib/StaticAnalyzer/Checkers/TestAfterDivZeroChecker.cpp
lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp
lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp
lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp
lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp
lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp
lib/StaticAnalyzer/Checkers/ValistChecker.cpp
lib/StaticAnalyzer/Checkers/VforkChecker.cpp
lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
lib/StaticAnalyzer/Core/BugReporter.cpp
lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
lib/StaticAnalyzer/Core/ExprEngine.cpp
lib/StaticAnalyzer/Core/PathDiagnostic.cpp

index 28e9e94e897b64ad65aab8bfc395a78a8b804021..6243c8d76de8b76be3f5e0d6266034ccd5dc0bc2 100644 (file)
@@ -74,29 +74,190 @@ using DiagnosticForConsumerMapTy =
 /// individual bug reports.
 class BugReport : public llvm::ilist_node<BugReport> {
 public:
-  using ranges_iterator = const SourceRange *;
-  using VisitorList = SmallVector<std::unique_ptr<BugReporterVisitor>, 8>;
-  using visitor_iterator = VisitorList::iterator;
-  using visitor_range = llvm::iterator_range<visitor_iterator>;
-  using NoteList = SmallVector<std::shared_ptr<PathDiagnosticNotePiece>, 4>;
+  enum class Kind { Basic, PathSensitive };
 
 protected:
   friend class BugReportEquivClass;
   friend class BugReporter;
 
+  Kind K;
   const BugType& BT;
-  const Decl *DeclWithIssue = nullptr;
   std::string ShortDescription;
   std::string Description;
+
+  SmallVector<SourceRange, 4> Ranges;
+  SmallVector<std::shared_ptr<PathDiagnosticNotePiece>, 4> Notes;
+  SmallVector<FixItHint, 4> Fixits;
+
+  BugReport(Kind kind, const BugType &bt, StringRef desc)
+      : K(kind), BT(bt), Description(desc) {}
+
+  BugReport(Kind K, const BugType &BT, StringRef ShortDescription,
+            StringRef Description)
+      : K(K), BT(BT), ShortDescription(ShortDescription),
+        Description(Description) {}
+
+public:
+  virtual ~BugReport() = default;
+
+  Kind getKind() const { return K; }
+
+  const BugType& getBugType() const { return BT; }
+
+  /// A verbose warning message that is appropriate for displaying next to
+  /// the source code that introduces the problem. The description should be
+  /// at least a full sentence starting with a capital letter. The period at
+  /// the end of the warning is traditionally omitted. If the description
+  /// consists of multiple sentences, periods between the sentences are
+  /// encouraged, but the period at the end of the description is still omitted.
+  StringRef getDescription() const { return Description; }
+
+  /// A short general warning message that is appropriate for displaying in
+  /// the list of all reported bugs. It should describe what kind of bug is found
+  /// but does not need to try to go into details of that specific bug.
+  /// Grammatical conventions of getDescription() apply here as well.
+  StringRef getShortDescription(bool UseFallback = true) const {
+    if (ShortDescription.empty() && UseFallback)
+      return Description;
+    return ShortDescription;
+  }
+
+  /// The primary location of the bug report that points at the undesirable
+  /// behavior in the code. UIs should attach the warning description to this
+  /// location. The warning description should describe the bad behavior
+  /// at this location.
+  virtual PathDiagnosticLocation getLocation() const = 0;
+
+  /// The smallest declaration that contains the bug location.
+  /// This is purely cosmetic; the declaration can be displayed to the user
+  /// but it does not affect whether the report is emitted.
+  virtual const Decl *getDeclWithIssue() const = 0;
+
+  /// Get the location on which the report should be uniqued. Two warnings are
+  /// considered to be equivalent whenever they have the same bug types,
+  /// descriptions, and uniqueing locations. Out of a class of equivalent
+  /// warnings only one gets displayed to the user. For most warnings the
+  /// uniqueing location coincides with their location, but sometimes
+  /// it makes sense to use different locations. For example, a leak
+  /// checker can place the warning at the location where the last reference
+  /// to the leaking resource is dropped but at the same time unique the warning
+  /// by where that resource is acquired (allocated).
+  virtual PathDiagnosticLocation getUniqueingLocation() const = 0;
+
+  /// Get the declaration that corresponds to (usually contains) the uniqueing
+  /// location. This is not actively used for uniqueing, i.e. otherwise
+  /// identical reports that have different uniqueing decls will be considered
+  /// equivalent.
+  virtual const Decl *getUniqueingDecl() const = 0;
+
+  /// Add new item to the list of additional notes that need to be attached to
+  /// this report. If the report is path-sensitive, these notes will not be
+  /// displayed as part of the execution path explanation, but will be displayed
+  /// separately. Use bug visitors if you need to add an extra path note.
+  void addNote(StringRef Msg, const PathDiagnosticLocation &Pos,
+               ArrayRef<SourceRange> Ranges = {}) {
+    auto P = std::make_shared<PathDiagnosticNotePiece>(Pos, Msg);
+
+    for (const auto &R : Ranges)
+      P->addRange(R);
+
+    Notes.push_back(std::move(P));
+  }
+
+  ArrayRef<std::shared_ptr<PathDiagnosticNotePiece>> getNotes() {
+    return Notes;
+  }
+
+  /// Add a range to a bug report.
+  ///
+  /// Ranges are used to highlight regions of interest in the source code.
+  /// They should be at the same source code line as the BugReport location.
+  /// By default, the source range of the statement corresponding to the error
+  /// node will be used; add a single invalid range to specify absence of
+  /// ranges.
+  void addRange(SourceRange R) {
+    assert((R.isValid() || Ranges.empty()) && "Invalid range can only be used "
+                           "to specify that the report does not have a range.");
+    Ranges.push_back(R);
+  }
+
+  /// Get the SourceRanges associated with the report.
+  virtual ArrayRef<SourceRange> getRanges() const {
+    return Ranges;
+  }
+
+  /// Add a fix-it hint to the bug report.
+  ///
+  /// Fix-it hints are the suggested edits to the code that would resolve
+  /// the problem explained by the bug report. Fix-it hints should be
+  /// as conservative as possible because it is not uncommon for the user
+  /// to blindly apply all fixits to their project. Note that it is very hard
+  /// to produce a good fix-it hint for most path-sensitive warnings.
+  void addFixItHint(const FixItHint &F) {
+    Fixits.push_back(F);
+  }
+
+  llvm::ArrayRef<FixItHint> getFixits() const { return Fixits; }
+
+  /// Reports are uniqued to ensure that we do not emit multiple diagnostics
+  /// for each bug.
+  virtual void Profile(llvm::FoldingSetNodeID& hash) const = 0;
+};
+
+class BasicBugReport : public BugReport {
   PathDiagnosticLocation Location;
-  PathDiagnosticLocation UniqueingLocation;
-  const Decl *UniqueingDecl;
+  const Decl *DeclWithIssue = nullptr;
+
+public:
+  BasicBugReport(const BugType &bt, StringRef desc, PathDiagnosticLocation l)
+      : BugReport(Kind::Basic, bt, desc), Location(l) {}
+
+  static bool classof(const BugReport *R) {
+    return R->getKind() == Kind::Basic;
+  }
+
+  PathDiagnosticLocation getLocation() const override {
+    assert(Location.isValid());
+    return Location;
+  }
+
+  const Decl *getDeclWithIssue() const override {
+    return DeclWithIssue;
+  }
+
+  PathDiagnosticLocation getUniqueingLocation() const override {
+    return getLocation();
+  }
+
+  const Decl *getUniqueingDecl() const override {
+    return getDeclWithIssue();
+  }
+
+  /// Specifically set the Decl where an issue occurred. This isn't necessary
+  /// for BugReports that cover a path as it will be automatically inferred.
+  void setDeclWithIssue(const Decl *declWithIssue) {
+    DeclWithIssue = declWithIssue;
+  }
+
+  void Profile(llvm::FoldingSetNodeID& hash) const override;
+};
+
+class PathSensitiveBugReport : public BugReport {
+public:
+  using VisitorList = SmallVector<std::unique_ptr<BugReporterVisitor>, 8>;
+  using visitor_iterator = VisitorList::iterator;
+  using visitor_range = llvm::iterator_range<visitor_iterator>;
 
+protected:
+  /// The ExplodedGraph node against which the report was thrown. It corresponds
+  /// to the end of the execution path that demonstrates the bug.
   const ExplodedNode *ErrorNode = nullptr;
-  SmallVector<SourceRange, 4> Ranges;
+
+  /// The range that corresponds to ErrorNode's program point. It is usually
+  /// highlighted in the report.
   const SourceRange ErrorNodeRange;
-  NoteList Notes;
-  SmallVector<FixItHint, 4> Fixits;
+
+  /// Profile to identify equivalent bug reports for error report coalescing.
 
   /// A (stack of) a set of symbols that are registered with this
   /// report as being "interesting", and thus used to help decide which
@@ -145,65 +306,50 @@ protected:
   /// Conditions we're already tracking.
   llvm::SmallSet<const ExplodedNode *, 4> TrackedConditions;
 
-public:
-  BugReport(const BugType &bt, StringRef desc, const ExplodedNode *errornode)
-      : BT(bt), Description(desc), ErrorNode(errornode),
-        ErrorNodeRange(getStmt() ? getStmt()->getSourceRange()
-                                 : SourceRange()) {}
+  /// Reports with different uniqueing locations are considered to be different
+  /// for the purposes of deduplication.
+  PathDiagnosticLocation UniqueingLocation;
+  const Decl *UniqueingDecl;
 
-  BugReport(const BugType &bt, StringRef shortDesc, StringRef desc,
-            const ExplodedNode *errornode)
-      : BT(bt), ShortDescription(shortDesc), Description(desc),
-        ErrorNode(errornode),
+  const Stmt *getStmt() const;
+
+public:
+  PathSensitiveBugReport(const BugType &bt, StringRef desc,
+                         const ExplodedNode *errorNode)
+      : BugReport(Kind::PathSensitive, bt, desc), ErrorNode(errorNode),
         ErrorNodeRange(getStmt() ? getStmt()->getSourceRange()
                                  : SourceRange()) {}
 
-  BugReport(const BugType &bt, StringRef desc, PathDiagnosticLocation l)
-      : BT(bt), Description(desc), Location(l),
+  PathSensitiveBugReport(const BugType &bt, StringRef shortDesc, StringRef desc,
+                         const ExplodedNode *errorNode)
+      : BugReport(Kind::PathSensitive, bt, shortDesc, desc),
+        ErrorNode(errorNode),
         ErrorNodeRange(getStmt() ? getStmt()->getSourceRange()
                                  : SourceRange()) {}
 
-  /// Create a BugReport with a custom uniqueing location.
+  /// Create a PathSensitiveBugReport with a custom uniqueing location.
   ///
   /// The reports that have the same report location, description, bug type, and
   /// ranges are uniqued - only one of the equivalent reports will be presented
   /// to the user. This method allows to rest the location which should be used
   /// for uniquing reports. For example, memory leaks checker, could set this to
   /// the allocation site, rather then the location where the bug is reported.
-  BugReport(BugType &bt, StringRef desc, const ExplodedNode *errornode,
-            PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique)
-      : BT(bt), Description(desc), UniqueingLocation(LocationToUnique),
-        UniqueingDecl(DeclToUnique), ErrorNode(errornode),
-        ErrorNodeRange(getStmt() ? getStmt()->getSourceRange()
-                                 : SourceRange()) {}
-
-  virtual ~BugReport() = default;
-
-  const BugType& getBugType() const { return BT; }
-  //BugType& getBugType() { return BT; }
+  PathSensitiveBugReport(BugType &bt, StringRef desc,
+                         const ExplodedNode *errorNode,
+                         PathDiagnosticLocation LocationToUnique,
+                         const Decl *DeclToUnique)
+      : BugReport(Kind::PathSensitive, bt, desc), ErrorNode(errorNode),
+        ErrorNodeRange(getStmt() ? getStmt()->getSourceRange() : SourceRange()),
+        UniqueingLocation(LocationToUnique), UniqueingDecl(DeclToUnique) {
+    assert(errorNode);
+  }
 
-  /// True when the report has an execution path associated with it.
-  ///
-  /// A report is said to be path-sensitive if it was thrown against a
-  /// particular exploded node in the path-sensitive analysis graph.
-  /// Path-sensitive reports have their intermediate path diagnostics
-  /// auto-generated, perhaps with the help of checker-defined visitors,
-  /// and may contain extra notes.
-  /// Path-insensitive reports consist only of a single warning message
-  /// in a specific location, and perhaps extra notes.
-  /// Path-sensitive checkers are allowed to throw path-insensitive reports.
-  bool isPathSensitive() const { return ErrorNode != nullptr; }
+  static bool classof(const BugReport *R) {
+    return R->getKind() == Kind::PathSensitive;
+  }
 
   const ExplodedNode *getErrorNode() const { return ErrorNode; }
 
-  StringRef getDescription() const { return Description; }
-
-  StringRef getShortDescription(bool UseFallback = true) const {
-    if (ShortDescription.empty() && UseFallback)
-      return Description;
-    return ShortDescription;
-  }
-
   /// Indicates whether or not any path pruning should take place
   /// when generating a PathDiagnostic from this BugReport.
   bool shouldPrunePath() const { return !DoNotPrunePath; }
@@ -211,6 +357,22 @@ public:
   /// Disable all path pruning when generating a PathDiagnostic.
   void disablePathPruning() { DoNotPrunePath = true; }
 
+  /// Get the location on which the report should be uniqued.
+  PathDiagnosticLocation getUniqueingLocation() const override {
+    return UniqueingLocation;
+  }
+
+  /// Get the declaration containing the uniqueing location.
+  const Decl *getUniqueingDecl() const override {
+    return UniqueingDecl;
+  }
+
+  const Decl *getDeclWithIssue() const override;
+
+  ArrayRef<SourceRange> getRanges() const override;
+
+  PathDiagnosticLocation getLocation() const override;
+
   /// Marks a symbol as interesting. Different kinds of interestingness will
   /// be processed differently by visitors (e.g. if the tracking kind is
   /// condition, will append "will be used as a condition" to the message).
@@ -265,87 +427,10 @@ public:
     Invalidations.insert(std::make_pair(Tag, Data));
   }
 
-  /// Return the canonical declaration, be it a method or class, where
-  /// this issue semantically occurred.
-  const Decl *getDeclWithIssue() const;
-
-  /// Specifically set the Decl where an issue occurred.  This isn't necessary
-  /// for BugReports that cover a path as it will be automatically inferred.
-  void setDeclWithIssue(const Decl *declWithIssue) {
-    DeclWithIssue = declWithIssue;
-  }
-
-  /// Add new item to the list of additional notes that need to be attached to
-  /// this path-insensitive report. If you want to add extra notes to a
-  /// path-sensitive report, you need to use a BugReporterVisitor because it
-  /// allows you to specify where exactly in the auto-generated path diagnostic
-  /// the extra note should appear.
-  void addNote(StringRef Msg, const PathDiagnosticLocation &Pos,
-               ArrayRef<SourceRange> Ranges = {},
-               ArrayRef<FixItHint> Fixits = {}) {
-    auto P = std::make_shared<PathDiagnosticNotePiece>(Pos, Msg);
-
-    for (const auto &R : Ranges)
-      P->addRange(R);
-
-    for (const auto &F : Fixits)
-      P->addFixit(F);
-
-    Notes.push_back(std::move(P));
-  }
-
-  virtual const NoteList &getNotes() {
-    return Notes;
-  }
-
-  /// Return the "definitive" location of the reported bug.
-  ///
-  ///  While a bug can span an entire path, usually there is a specific
-  ///  location that can be used to identify where the key issue occurred.
-  ///  This location is used by clients rendering diagnostics.
-  virtual PathDiagnosticLocation getLocation(const SourceManager &SM) const;
-
-  /// Get the location on which the report should be uniqued.
-  PathDiagnosticLocation getUniqueingLocation() const {
-    return UniqueingLocation;
-  }
-
-  /// Get the declaration containing the uniqueing location.
-  const Decl *getUniqueingDecl() const {
-    return UniqueingDecl;
-  }
-
-  const Stmt *getStmt() const;
-
-  /// Add a range to the bug report.
-  ///
-  /// Ranges are used to highlight regions of interest in the source code.
-  /// They should be at the same source code line as the BugReport location.
-  /// By default, the source range of the statement corresponding to the error
-  /// node will be used; add a single invalid range to specify absence of
-  /// ranges.
-  void addRange(SourceRange R) {
-    assert((R.isValid() || Ranges.empty()) && "Invalid range can only be used "
-                           "to specify that the report does not have a range.");
-    Ranges.push_back(R);
-  }
-
-  /// Get the SourceRanges associated with the report.
-  virtual llvm::iterator_range<ranges_iterator> getRanges() const;
-
-  /// Add a fix-it hint to the warning message of the bug report.
-  ///
-  /// Fix-it hints are the suggested edits to the code that would resolve
-  /// the problem explained by the bug report. Fix-it hints should be
-  /// as conservative as possible because it is not uncommon for the user
-  /// to blindly apply all fixits to their project. It usually is very hard
-  /// to produce a good fix-it hint for most path-sensitive warnings.
-  /// Fix-it hints can also be added to notes through the addNote() interface.
-  void addFixItHint(const FixItHint &F) {
-    Fixits.push_back(F);
-  }
-
-  ArrayRef<FixItHint> getFixits() const { return Fixits; }
+  /// Profile to identify equivalent bug reports for error report coalescing.
+  /// Reports are uniqued to ensure that we do not emit multiple diagnostics
+  /// for each bug.
+  void Profile(llvm::FoldingSetNodeID &hash) const override;
 
   /// Add custom or predefined bug report visitors to this report.
   ///
@@ -370,11 +455,6 @@ public:
   bool addTrackedCondition(const ExplodedNode *Cond) {
     return TrackedConditions.insert(Cond).second;
   }
-
-  /// Profile to identify equivalent bug reports for error report coalescing.
-  /// Reports are uniqued to ensure that we do not emit multiple diagnostics
-  /// for each bug.
-  virtual void Profile(llvm::FoldingSetNodeID& hash) const;
 };
 
 //===----------------------------------------------------------------------===//
@@ -435,12 +515,6 @@ private:
   /// Generate and flush the diagnostics for the given bug report.
   void FlushReport(BugReportEquivClass& EQ);
 
-  /// Generate the diagnostics for the given bug report.
-  std::unique_ptr<DiagnosticForConsumerMapTy>
-  generateDiagnosticForConsumerMap(BugReport *exampleReport,
-                                   ArrayRef<PathDiagnosticConsumer *> consumers,
-                                   ArrayRef<BugReport *> bugReports);
-
   /// The set of bug reports tracked by the BugReporter.
   llvm::FoldingSet<BugReportEquivClass> EQClasses;
 
@@ -469,18 +543,12 @@ public:
 
   const AnalyzerOptions &getAnalyzerOptions() { return D.getAnalyzerOptions(); }
 
-  virtual std::unique_ptr<DiagnosticForConsumerMapTy>
-  generatePathDiagnostics(ArrayRef<PathDiagnosticConsumer *> consumers,
-                          ArrayRef<BugReport *> &bugReports) {
-    return {};
-  }
-
   /// Add the given report to the set of reports tracked by BugReporter.
   ///
   /// The reports are usually generated by the checkers. Further, they are
   /// folded based on the profile value, which is done to coalesce similar
   /// reports.
-  void emitReport(std::unique_ptr<BugReport> R);
+  virtual void emitReport(std::unique_ptr<BugReport> R);
 
   void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker,
                        StringRef BugName, StringRef BugCategory,
@@ -501,12 +569,34 @@ private:
   /// category.
   BugType *getBugTypeForName(CheckName CheckName, StringRef name,
                              StringRef category);
+
+  virtual BugReport *
+  findReportInEquivalenceClass(BugReportEquivClass &eqClass,
+                               SmallVectorImpl<BugReport *> &bugReports) {
+    return &*eqClass.begin();
+  }
+
+protected:
+  /// Generate the diagnostics for the given bug report.
+  virtual std::unique_ptr<DiagnosticForConsumerMapTy>
+  generateDiagnosticForConsumerMap(BugReport *exampleReport,
+                                   ArrayRef<PathDiagnosticConsumer *> consumers,
+                                   ArrayRef<BugReport *> bugReports);
 };
 
 /// GRBugReporter is used for generating path-sensitive reports.
-class PathSensitiveBugReporter : public BugReporter {
+class PathSensitiveBugReporter final : public BugReporter {
   ExprEngine& Eng;
 
+  BugReport *findReportInEquivalenceClass(
+      BugReportEquivClass &eqClass,
+      SmallVectorImpl<BugReport *> &bugReports) override;
+
+  /// Generate the diagnostics for the given bug report.
+  std::unique_ptr<DiagnosticForConsumerMapTy>
+  generateDiagnosticForConsumerMap(BugReport *exampleReport,
+                                   ArrayRef<PathDiagnosticConsumer *> consumers,
+                                   ArrayRef<BugReport *> bugReports) override;
 public:
   PathSensitiveBugReporter(BugReporterData& d, ExprEngine& eng)
       : BugReporter(d), Eng(eng) {}
@@ -524,9 +614,11 @@ public:
   /// \return A mapping from consumers to the corresponding diagnostics.
   /// Iterates through the bug reports within a single equivalence class,
   /// stops at a first non-invalidated report.
-  std::unique_ptr<DiagnosticForConsumerMapTy>
-  generatePathDiagnostics(ArrayRef<PathDiagnosticConsumer *> consumers,
-                          ArrayRef<BugReport *> &bugReports) override;
+  std::unique_ptr<DiagnosticForConsumerMapTy> generatePathDiagnostics(
+      ArrayRef<PathDiagnosticConsumer *> consumers,
+      ArrayRef<PathSensitiveBugReport *> &bugReports);
+
+  void emitReport(std::unique_ptr<BugReport> R) override;
 };
 
 
index 1d8167ad4f03d6024e5c935576cf1026d75b7821..de0ee5de81b53a948221f2fe9ec4df361fd4f315 100644 (file)
@@ -33,7 +33,7 @@ class Stmt;
 
 namespace ento {
 
-class BugReport;
+class PathSensitiveBugReport;
 class BugReporterContext;
 class ExplodedNode;
 class MemRegion;
@@ -60,29 +60,29 @@ public:
   /// BugReport while processing a node.
   virtual PathDiagnosticPieceRef VisitNode(const ExplodedNode *Succ,
                                            BugReporterContext &BRC,
-                                           BugReport &BR) = 0;
+                                           PathSensitiveBugReport &BR) = 0;
 
   /// Last function called on the visitor, no further calls to VisitNode
   /// would follow.
   virtual void finalizeVisitor(BugReporterContext &BRC,
                                const ExplodedNode *EndPathNode,
-                               BugReport &BR);
+                               PathSensitiveBugReport &BR);
 
   /// Provide custom definition for the final diagnostic piece on the
   /// path - the piece, which is displayed before the path is expanded.
   ///
   /// NOTE that this function can be implemented on at most one used visitor,
   /// and otherwise it crahes at runtime.
-  virtual PathDiagnosticPieceRef
-  getEndPath(BugReporterContext &BRC, const ExplodedNode *N,
-             BugReport &BR);
+  virtual PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC,
+                                            const ExplodedNode *N,
+                                            PathSensitiveBugReport &BR);
 
   virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0;
 
   /// Generates the default final diagnostic piece.
-  static PathDiagnosticPieceRef getDefaultEndPath(const BugReporterContext &BRC,
-                                                  const ExplodedNode *N,
-                                                  const BugReport &BR);
+  static PathDiagnosticPieceRef
+  getDefaultEndPath(const BugReporterContext &BRC, const ExplodedNode *N,
+                    const PathSensitiveBugReport &BR);
 };
 
 namespace bugreporter {
@@ -111,7 +111,8 @@ enum class TrackingKind {
 /// \return Whether or not the function was able to add visitors for this
 ///         statement. Note that returning \c true does not actually imply
 ///         that any visitors were added.
-bool trackExpressionValue(const ExplodedNode *N, const Expr *E, BugReport &R,
+bool trackExpressionValue(const ExplodedNode *N, const Expr *E,
+                          PathSensitiveBugReport &R,
                           TrackingKind TKind = TrackingKind::Thorough,
                           bool EnableNullFPSuppression = true);
 
@@ -157,7 +158,7 @@ public:
 
   PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                    BugReporterContext &BRC,
-                                   BugReport &BR) override;
+                                   PathSensitiveBugReport &BR) override;
 };
 
 class TrackConstraintBRVisitor final : public BugReporterVisitor {
@@ -183,7 +184,7 @@ public:
 
   PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                    BugReporterContext &BRC,
-                                   BugReport &BR) override;
+                                   PathSensitiveBugReport &BR) override;
 
 private:
   /// Checks if the constraint is valid in the current state.
@@ -201,7 +202,7 @@ public:
 
   PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                    BugReporterContext &BRC,
-                                   BugReport &BR) override;
+                                   PathSensitiveBugReport &BR) override;
 
   /// If the statement is a message send expression with nil receiver, returns
   /// the receiver expression. Returns NULL otherwise.
@@ -228,40 +229,42 @@ public:
 
   PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                    BugReporterContext &BRC,
-                                   BugReport &BR) override;
+                                   PathSensitiveBugReport &BR) override;
 
   PathDiagnosticPieceRef VisitNodeImpl(const ExplodedNode *N,
-                                       BugReporterContext &BRC, BugReport &BR);
+                                       BugReporterContext &BRC,
+                                       PathSensitiveBugReport &BR);
 
-  PathDiagnosticPieceRef VisitTerminator(const Stmt *Term,
-                                         const ExplodedNode *N,
-                                         const CFGBlock *SrcBlk,
-                                         const CFGBlock *DstBlk, BugReport &R,
-                                         BugReporterContext &BRC);
+  PathDiagnosticPieceRef
+  VisitTerminator(const Stmt *Term, const ExplodedNode *N,
+                  const CFGBlock *SrcBlk, const CFGBlock *DstBlk,
+                  PathSensitiveBugReport &R, BugReporterContext &BRC);
 
   PathDiagnosticPieceRef VisitTrueTest(const Expr *Cond,
-                                       BugReporterContext &BRC, BugReport &R,
+                                       BugReporterContext &BRC,
+                                       PathSensitiveBugReport &R,
                                        const ExplodedNode *N, bool TookTrue);
 
   PathDiagnosticPieceRef VisitTrueTest(const Expr *Cond, const DeclRefExpr *DR,
-                                       BugReporterContext &BRC, BugReport &R,
+                                       BugReporterContext &BRC,
+                                       PathSensitiveBugReport &R,
                                        const ExplodedNode *N, bool TookTrue,
                                        bool IsAssuming);
 
-  PathDiagnosticPieceRef VisitTrueTest(const Expr *Cond,
-                                       const BinaryOperator *BExpr,
-                                       BugReporterContext &BRC, BugReport &R,
-                                       const ExplodedNode *N, bool TookTrue,
-                                       bool IsAssuming);
+  PathDiagnosticPieceRef
+  VisitTrueTest(const Expr *Cond, const BinaryOperator *BExpr,
+                BugReporterContext &BRC, PathSensitiveBugReport &R,
+                const ExplodedNode *N, bool TookTrue, bool IsAssuming);
 
   PathDiagnosticPieceRef VisitTrueTest(const Expr *Cond, const MemberExpr *ME,
-                                       BugReporterContext &BRC, BugReport &R,
+                                       BugReporterContext &BRC,
+                                       PathSensitiveBugReport &R,
                                        const ExplodedNode *N, bool TookTrue,
                                        bool IsAssuming);
 
   PathDiagnosticPieceRef
   VisitConditionVariable(StringRef LhsString, const Expr *CondVarExpr,
-                         BugReporterContext &BRC, BugReport &R,
+                         BugReporterContext &BRC, PathSensitiveBugReport &R,
                          const ExplodedNode *N, bool TookTrue);
 
   /// Tries to print the value of the given expression.
@@ -280,7 +283,7 @@ public:
                     const Expr *ParentEx,
                     raw_ostream &Out,
                     BugReporterContext &BRC,
-                    BugReport &R,
+                    PathSensitiveBugReport &R,
                     const ExplodedNode *N,
                     Optional<bool> &prunable,
                     bool IsSameFieldName);
@@ -304,12 +307,12 @@ public:
   }
 
   PathDiagnosticPieceRef VisitNode(const ExplodedNode *, BugReporterContext &,
-                                   BugReport &) override {
+                                   PathSensitiveBugReport &) override {
     return nullptr;
   }
 
   void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *N,
-                       BugReport &BR) override;
+                       PathSensitiveBugReport &BR) override;
 };
 
 /// When a region containing undefined value or '0' value is passed
@@ -332,7 +335,7 @@ public:
 
   PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                    BugReporterContext &BRC,
-                                   BugReport &BR) override;
+                                   PathSensitiveBugReport &BR) override;
 };
 
 class SuppressInlineDefensiveChecksVisitor final : public BugReporterVisitor {
@@ -361,7 +364,7 @@ public:
 
   PathDiagnosticPieceRef VisitNode(const ExplodedNode *Succ,
                                    BugReporterContext &BRC,
-                                   BugReport &BR) override;
+                                   PathSensitiveBugReport &BR) override;
 };
 
 /// The bug visitor will walk all the nodes in a path and collect all the
@@ -379,10 +382,10 @@ public:
 
   PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                    BugReporterContext &BRC,
-                                   BugReport &BR) override;
+                                   PathSensitiveBugReport &BR) override;
 
   void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *EndPathNode,
-                       BugReport &BR) override;
+                       PathSensitiveBugReport &BR) override;
 };
 
 
@@ -393,7 +396,7 @@ public:
 
   PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                    BugReporterContext &BRC,
-                                   BugReport &R) override;
+                                   PathSensitiveBugReport &R) override;
 };
 
 } // namespace ento
index 6b5a2eb5a7e0020000e7b538a315068234229c00..289f6de97d215d783fed5ca44c575e5cdf6dc8f2 100644 (file)
@@ -282,8 +282,7 @@ public:
 
   /// Create a location corresponding to the next valid ExplodedNode as end
   /// of path location.
-  static PathDiagnosticLocation createEndOfPath(const ExplodedNode* N,
-                                                const SourceManager &SM);
+  static PathDiagnosticLocation createEndOfPath(const ExplodedNode* N);
 
   /// Convert the given location into a single kind location.
   static PathDiagnosticLocation createSingleLocation(
index e2966dcfc722e50a7405afd59d689e35143818bf..abf8329cddfb7b694f2093210c6dde975cc02da3 100644 (file)
@@ -36,8 +36,8 @@ void MainCallChecker::checkPreStmt(const CallExpr *CE,
     if (!BT)
       BT.reset(new BugType(this, "call to main", "example analyzer plugin"));
 
-    std::unique_ptr<BugReport> report =
-        std::make_unique<BugReport>(*BT, BT->getName(), N);
+    auto report =
+        std::make_unique<PathSensitiveBugReport>(*BT, BT->getName(), N);
     report->addRange(Callee->getSourceRange());
     C.emitReport(std::move(report));
   }
index 5292806ef8b301097e8ceb61f375ce1cfcc87123..8d4793e0802ffd8cc9a3aa65be897963eaef19ba 100644 (file)
@@ -75,7 +75,8 @@ void ArrayBoundChecker::checkLocation(SVal l, bool isLoad, const Stmt* LoadS,
     // reference is outside the range.
 
     // Generate a report for this bug.
-    auto report = std::make_unique<BugReport>(*BT, BT->getDescription(), N);
+    auto report =
+        std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N);
 
     report->addRange(LoadS->getSourceRange());
     C.emitReport(std::move(report));
index 8f9b2c60728630d772d04e169db778a5839a91fe..8f3bf138cae4a44559e3a99e24bac01edf3ff340 100644 (file)
@@ -256,7 +256,7 @@ void ArrayBoundCheckerV2::reportOOB(
     break;
   }
 
-  auto BR = std::make_unique<BugReport>(*BT, os.str(), errorNode);
+  auto BR = std::make_unique<PathSensitiveBugReport>(*BT, os.str(), errorNode);
   BR->addVisitor(std::move(Visitor));
   checkerContext.emitReport(std::move(BR));
 }
index c4f74cf610b040175a370b438b64663daa064daf..325952fe4ed4d0590a2032bce217fdc532319742 100644 (file)
@@ -211,7 +211,7 @@ void NilArgChecker::generateBugReport(ExplodedNode *N,
   if (!BT)
     BT.reset(new APIMisuse(this, "nil argument"));
 
-  auto R = std::make_unique<BugReport>(*BT, Msg, N);
+  auto R = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
   R->addRange(Range);
   bugreporter::trackExpressionValue(N, E, *R);
   C.emitReport(std::move(R));
@@ -520,7 +520,7 @@ void CFNumberChecker::checkPreStmt(const CallExpr *CE,
     if (!BT)
       BT.reset(new APIMisuse(this, "Bad use of CFNumber APIs"));
 
-    auto report = std::make_unique<BugReport>(*BT, os.str(), N);
+    auto report = std::make_unique<PathSensitiveBugReport>(*BT, os.str(), N);
     report->addRange(CE->getArg(2)->getSourceRange());
     C.emitReport(std::move(report));
   }
@@ -575,7 +575,7 @@ void CFRetainReleaseChecker::checkPreCall(const CallEvent &Call,
     OS << "Null pointer argument in call to "
        << cast<FunctionDecl>(Call.getDecl())->getName();
 
-    auto report = std::make_unique<BugReport>(BT, OS.str(), N);
+    auto report = std::make_unique<PathSensitiveBugReport>(BT, OS.str(), N);
     report->addRange(Call.getArgSourceRange(0));
     bugreporter::trackExpressionValue(N, Call.getArgExpr(0), *report);
     C.emitReport(std::move(report));
@@ -635,7 +635,7 @@ void ClassReleaseChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
           "of class '" << Class->getName()
        << "' and not the class directly";
 
-    auto report = std::make_unique<BugReport>(*BT, os.str(), N);
+    auto report = std::make_unique<PathSensitiveBugReport>(*BT, os.str(), N);
     report->addRange(msg.getSourceRange());
     C.emitReport(std::move(report));
   }
@@ -788,7 +788,8 @@ void VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
     ArgTy.print(os, C.getLangOpts());
     os << "'";
 
-    auto R = std::make_unique<BugReport>(*BT, os.str(), errorNode.getValue());
+    auto R = std::make_unique<PathSensitiveBugReport>(*BT, os.str(),
+                                                      errorNode.getValue());
     R->addRange(msg.getArgSourceRange(I));
     C.emitReport(std::move(R));
   }
index c3dcbf2b1100696a009c1e7a6549fccc0dfc48a1..e5b8a6b5ffe304e014ad9ab0fe7f164fd38a6bd7 100644 (file)
@@ -173,7 +173,8 @@ void BlockInCriticalSectionChecker::reportBlockInCritSection(
   llvm::raw_string_ostream os(msg);
   os << "Call to blocking function '" << Call.getCalleeIdentifier()->getName()
      << "' inside of critical section";
-  auto R = std::make_unique<BugReport>(*BlockInCritSectionBugType, os.str(), ErrNode);
+  auto R = std::make_unique<PathSensitiveBugReport>(*BlockInCritSectionBugType,
+                                                    os.str(), ErrNode);
   R->addRange(Call.getSourceRange());
   R->markInteresting(BlockDescSym);
   C.emitReport(std::move(R));
index 805c46a3809fe75db5f0e67009fbd0dd5326eac0..1423b9c39b266437485bd992cec364f745e91e72 100644 (file)
@@ -34,7 +34,9 @@ void BoolAssignmentChecker::emitReport(ProgramStateRef state,
   if (ExplodedNode *N = C.generateNonFatalErrorNode(state)) {
     if (!BT)
       BT.reset(new BuiltinBug(this, "Assignment of a non-Boolean value"));
-    C.emitReport(std::make_unique<BugReport>(*BT, BT->getDescription(), N));
+
+    C.emitReport(
+        std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N));
   }
 }
 
index 6f1b9c3979b54dc0f42c6493f8fd65c17506d942..ba790648deb5ed153aa9900ce66cd44a8d481c1c 100644 (file)
@@ -570,7 +570,7 @@ void CStringChecker::emitOverlapBug(CheckerContext &C, ProgramStateRef state,
                                  categories::UnixAPI, "Improper arguments"));
 
   // Generate a report for this bug.
-  auto report = std::make_unique<BugReport>(
+  auto report = std::make_unique<PathSensitiveBugReport>(
       *BT_Overlap, "Arguments must not be overlapping buffers", N);
   report->addRange(First->getSourceRange());
   report->addRange(Second->getSourceRange());
@@ -587,7 +587,7 @@ void CStringChecker::emitNullArgBug(CheckerContext &C, ProgramStateRef State,
           "Null pointer argument in call to byte string function"));
 
     BuiltinBug *BT = static_cast<BuiltinBug *>(BT_Null.get());
-    auto Report = std::make_unique<BugReport>(*BT, WarningMsg, N);
+    auto Report = std::make_unique<PathSensitiveBugReport>(*BT, WarningMsg, N);
     Report->addRange(S->getSourceRange());
     if (const auto *Ex = dyn_cast<Expr>(S))
       bugreporter::trackExpressionValue(N, Ex, *Report);
@@ -611,7 +611,7 @@ void CStringChecker::emitOutOfBoundsBug(CheckerContext &C,
     // FIXME: It would be nice to eventually make this diagnostic more clear,
     // e.g., by referencing the original declaration or by saying *why* this
     // reference is outside the range.
-    auto Report = std::make_unique<BugReport>(*BT, WarningMsg, N);
+    auto Report = std::make_unique<PathSensitiveBugReport>(*BT, WarningMsg, N);
     Report->addRange(S->getSourceRange());
     C.emitReport(std::move(Report));
   }
@@ -626,7 +626,8 @@ void CStringChecker::emitNotCStringBug(CheckerContext &C, ProgramStateRef State,
           Filter.CheckNameCStringNotNullTerm, categories::UnixAPI,
           "Argument is not a null-terminated string."));
 
-    auto Report = std::make_unique<BugReport>(*BT_NotCString, WarningMsg, N);
+    auto Report =
+        std::make_unique<PathSensitiveBugReport>(*BT_NotCString, WarningMsg, N);
 
     Report->addRange(S->getSourceRange());
     C.emitReport(std::move(Report));
@@ -648,7 +649,8 @@ void CStringChecker::emitAdditionOverflowBug(CheckerContext &C,
         "This expression will create a string whose length is too big to "
         "be represented as a size_t";
 
-    auto Report = std::make_unique<BugReport>(*BT_NotCString, WarningMsg, N);
+    auto Report =
+        std::make_unique<PathSensitiveBugReport>(*BT_NotCString, WarningMsg, N);
     C.emitReport(std::move(Report));
   }
 }
index 0da7bd227bb947a84ce0c589886464e48437402d..325d2f80a67dc0929b1c47253ca97763df47471b 100644 (file)
@@ -95,7 +95,7 @@ void CallAndMessageChecker::emitBadCall(BugType *BT, CheckerContext &C,
   if (!N)
     return;
 
-  auto R = std::make_unique<BugReport>(*BT, BT->getName(), N);
+  auto R = std::make_unique<PathSensitiveBugReport>(*BT, BT->getName(), N);
   if (BadE) {
     R->addRange(BadE->getSourceRange());
     if (BadE->isGLValue())
@@ -175,7 +175,7 @@ bool CallAndMessageChecker::uninitRefOrPointer(
     if (PSV.isUndef()) {
       if (ExplodedNode *N = C.generateErrorNode()) {
         LazyInit_BT(BD, BT);
-        auto R = std::make_unique<BugReport>(*BT, Os.str(), N);
+        auto R = std::make_unique<PathSensitiveBugReport>(*BT, Os.str(), N);
         R->addRange(ArgRange);
         if (ArgEx)
           bugreporter::trackExpressionValue(N, ArgEx, *R);
@@ -252,7 +252,7 @@ bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
       SmallString<200> Buf;
       llvm::raw_svector_ostream Os(Buf);
       describeUninitializedArgumentInCall(Call, ArgumentNumber, Os);
-      auto R = std::make_unique<BugReport>(*BT, Os.str(), N);
+      auto R = std::make_unique<PathSensitiveBugReport>(*BT, Os.str(), N);
 
       R->addRange(ArgRange);
       if (ArgEx)
@@ -295,7 +295,7 @@ bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
         }
 
         // Generate a report for this bug.
-        auto R = std::make_unique<BugReport>(*BT, os.str(), N);
+        auto R = std::make_unique<PathSensitiveBugReport>(*BT, os.str(), N);
         R->addRange(ArgRange);
 
         if (ArgEx)
@@ -358,7 +358,7 @@ void CallAndMessageChecker::checkPreStmt(const CXXDeleteExpr *DE,
     else
       Desc = "Argument to 'delete' is uninitialized";
     BugType *BT = BT_cxx_delete_undef.get();
-    auto R = std::make_unique<BugReport>(*BT, Desc, N);
+    auto R = std::make_unique<PathSensitiveBugReport>(*BT, Desc, N);
     bugreporter::trackExpressionValue(N, DE, *R);
     C.emitReport(std::move(R));
     return;
@@ -420,8 +420,8 @@ void CallAndMessageChecker::checkPreCall(const CallEvent &Call,
          << (Params == 1 ? "" : "s") << " is called with fewer ("
          << Call.getNumArgs() << ")";
 
-      C.emitReport(
-          std::make_unique<BugReport>(*BT_call_few_args, os.str(), N));
+      C.emitReport(std::make_unique<PathSensitiveBugReport>(*BT_call_few_args,
+                                                            os.str(), N));
     }
   }
 
@@ -482,7 +482,7 @@ void CallAndMessageChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
       }
       assert(BT && "Unknown message kind.");
 
-      auto R = std::make_unique<BugReport>(*BT, BT->getName(), N);
+      auto R = std::make_unique<PathSensitiveBugReport>(*BT, BT->getName(), N);
       const ObjCMessageExpr *ME = msg.getOriginExpr();
       R->addRange(ME->getReceiverRange());
 
@@ -525,7 +525,8 @@ void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
     os << "' that will be garbage";
   }
 
-  auto report = std::make_unique<BugReport>(*BT_msg_ret, os.str(), N);
+  auto report =
+      std::make_unique<PathSensitiveBugReport>(*BT_msg_ret, os.str(), N);
   report->addRange(ME->getReceiverRange());
   // FIXME: This won't track "self" in messages to super.
   if (const Expr *receiver = ME->getInstanceReceiver()) {
index f72fb5773c489a92db2e4b536482a2b6e34b83cf..51c1d4409929eadb42b2b7c891f6c7f2feb7e96c 100644 (file)
@@ -132,7 +132,8 @@ void CastSizeChecker::checkPreStmt(const CastExpr *CE,CheckerContext &C) const {
       BT.reset(new BuiltinBug(this, "Cast region with wrong size.",
                                     "Cast a region whose size is not a multiple"
                                     " of the destination type size."));
-    auto R = std::make_unique<BugReport>(*BT, BT->getDescription(), errorNode);
+    auto R = std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(),
+                                                      errorNode);
     R->addRange(CE->getSourceRange());
     C.emitReport(std::move(R));
   }
index a7ca814c8f9672881cb9492ae3597e7030fce14c..9a21de80fb0b673d496587a54ef4dbb58d134272 100644 (file)
@@ -576,9 +576,8 @@ void ObjCDeallocChecker::diagnoseMissingReleases(CheckerContext &C) const {
     OS << " by a synthesized property but not released"
           " before '[super dealloc]'";
 
-    std::unique_ptr<BugReport> BR(
-        new BugReport(*MissingReleaseBugType, OS.str(), ErrNode));
-
+    auto BR = std::make_unique<PathSensitiveBugReport>(*MissingReleaseBugType,
+                                                       OS.str(), ErrNode);
     C.emitReport(std::move(BR));
   }
 
@@ -699,8 +698,8 @@ bool ObjCDeallocChecker::diagnoseExtraRelease(SymbolRef ReleasedValue,
     OS <<  " property but was released in 'dealloc'";
   }
 
-  std::unique_ptr<BugReport> BR(
-      new BugReport(*ExtraReleaseBugType, OS.str(), ErrNode));
+  auto BR = std::make_unique<PathSensitiveBugReport>(*ExtraReleaseBugType,
+                                                     OS.str(), ErrNode);
   BR->addRange(M.getOriginExpr()->getSourceRange());
 
   C.emitReport(std::move(BR));
@@ -741,8 +740,8 @@ bool ObjCDeallocChecker::diagnoseMistakenDealloc(SymbolRef DeallocedValue,
   OS << "'" << *PropImpl->getPropertyIvarDecl()
      << "' should be released rather than deallocated";
 
-  std::unique_ptr<BugReport> BR(
-      new BugReport(*MistakenDeallocBugType, OS.str(), ErrNode));
+  auto BR = std::make_unique<PathSensitiveBugReport>(*MistakenDeallocBugType,
+                                                     OS.str(), ErrNode);
   BR->addRange(M.getOriginExpr()->getSourceRange());
 
   C.emitReport(std::move(BR));
index e1abfac799db9334888b14027d3b2cfabbf08e82..7a41a7b6b216e88f603cb2bbd1478155f79bb0bf 100644 (file)
@@ -127,7 +127,7 @@ void ChrootChecker::checkPreCall(const CallEvent &Call,
           BT_BreakJail.reset(new BuiltinBug(
               this, "Break out of jail", "No call of chdir(\"/\") immediately "
                                          "after chroot"));
-        C.emitReport(std::make_unique<BugReport>(
+        C.emitReport(std::make_unique<PathSensitiveBugReport>(
             *BT_BreakJail, BT_BreakJail->getDescription(), N));
       }
 }
index d0bab200c55cb13c381fc9c1795b50525c995e95..ce45b5be34c9f493e845a092f0588b6a264169ca 100644 (file)
@@ -114,8 +114,8 @@ void CloneChecker::reportClones(
   for (const CloneDetector::CloneGroup &Group : CloneGroups) {
     // We group the clones by printing the first as a warning and all others
     // as a note.
-    auto R = std::make_unique<BugReport>(*BT_Exact, "Duplicate code detected",
-                                          makeLocation(Group.front(), Mgr));
+    auto R = std::make_unique<BasicBugReport>(
+        *BT_Exact, "Duplicate code detected", makeLocation(Group.front(), Mgr));
     R->addRange(Group.front().getSourceRange());
 
     for (unsigned i = 1; i < Group.size(); ++i)
@@ -169,7 +169,7 @@ void CloneChecker::reportSuspiciousClones(
     // which may confuse the user.
     // Think how to perform more accurate suggestions?
 
-    auto R = std::make_unique<BugReport>(
+    auto R = std::make_unique<BasicBugReport>(
         *BT_Suspicious,
         "Potential copy-paste error; did you really mean to use '" +
             Pair.FirstCloneInfo.Variable->getNameAsString() + "' here?",
index 3b4f8a28241162cfb5ca7f5dadb4964032df89d5..8dd3132f07e2b1444093de9b0e138b052ab64d2a 100644 (file)
@@ -121,7 +121,7 @@ void ConversionChecker::reportBug(ExplodedNode *N, CheckerContext &C,
         new BuiltinBug(this, "Conversion", "Possible loss of sign/precision."));
 
   // Generate a report for this bug.
-  auto R = std::make_unique<BugReport>(*BT, Msg, N);
+  auto R = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
   C.emitReport(std::move(R));
 }
 
index fbf9efef665ee94c88630d25294e8289e8e92f2b..0cb4be2c7fdc375641b8365ddad8e098f80c319e 100644 (file)
@@ -333,7 +333,8 @@ public:
     if (!Node)
       return;
 
-    auto Report = std::make_unique<BugReport>(BT_stmtLoc, "Statement", Node);
+    auto Report =
+        std::make_unique<PathSensitiveBugReport>(BT_stmtLoc, "Statement", Node);
 
     C.emitReport(std::move(Report));
   }
index 4ec01158e88d6ab85ad902046c25c658dff3cb2c..89225d0bc772d17a230079c1052080d0dd639d6d 100644 (file)
@@ -47,7 +47,7 @@ class DeleteWithNonVirtualDtorChecker
     }
     PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                      BugReporterContext &BRC,
-                                     BugReport &BR) override;
+                                     PathSensitiveBugReport &BR) override;
 
   private:
     bool Satisfied;
@@ -92,7 +92,7 @@ void DeleteWithNonVirtualDtorChecker::checkPreStmt(const CXXDeleteExpr *DE,
                          "Logic error"));
 
   ExplodedNode *N = C.generateNonFatalErrorNode();
-  auto R = std::make_unique<BugReport>(*BT, BT->getName(), N);
+  auto R = std::make_unique<PathSensitiveBugReport>(*BT, BT->getName(), N);
 
   // Mark region of problematic base class for later use in the BugVisitor.
   R->markInteresting(BaseClassRegion);
@@ -102,7 +102,8 @@ void DeleteWithNonVirtualDtorChecker::checkPreStmt(const CXXDeleteExpr *DE,
 
 PathDiagnosticPieceRef
 DeleteWithNonVirtualDtorChecker::DeleteBugVisitor::VisitNode(
-    const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) {
+    const ExplodedNode *N, BugReporterContext &BRC,
+    PathSensitiveBugReport &BR) {
   // Stop traversal after the first conversion was found on a path.
   if (Satisfied)
     return nullptr;
index dc941b93af81a669bc8903e3606d16273ee079dc..e3de0b4f4a7ff32e81ab3e0e789f3c477e14fae6 100644 (file)
@@ -179,7 +179,7 @@ void DereferenceChecker::reportBug(ProgramStateRef State, const Stmt *S,
     break;
   }
 
-  auto report = std::make_unique<BugReport>(
+  auto report = std::make_unique<PathSensitiveBugReport>(
       *BT_null, buf.empty() ? BT_null->getDescription() : StringRef(buf), N);
 
   bugreporter::trackExpressionValue(N, bugreporter::getDerefExpr(S), *report);
@@ -200,8 +200,8 @@ void DereferenceChecker::checkLocation(SVal l, bool isLoad, const Stmt* S,
         BT_undef.reset(
             new BuiltinBug(this, "Dereference of undefined pointer value"));
 
-      auto report =
-          std::make_unique<BugReport>(*BT_undef, BT_undef->getDescription(), N);
+      auto report = std::make_unique<PathSensitiveBugReport>(
+          *BT_undef, BT_undef->getDescription(), N);
       bugreporter::trackExpressionValue(N, bugreporter::getDerefExpr(S), *report);
       C.emitReport(std::move(report));
     }
index 93d88e4df2a2efad6d930e14f056c7ed362e6e0f..8798bde88dcd60f3e283a1c883031703809f02d6 100644 (file)
@@ -47,7 +47,7 @@ void DivZeroChecker::reportBug(
     if (!BT)
       BT.reset(new BuiltinBug(this, "Division by zero"));
 
-    auto R = std::make_unique<BugReport>(*BT, Msg, N);
+    auto R = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
     R->addVisitor(std::move(Visitor));
     bugreporter::trackExpressionValue(N, getDenomExpr(N), *R);
     C.emitReport(std::move(R));
index c19e963ab2c78ed7ecc7fd651441c9644c23cf93..7693314f889d050d50778ac469a2a94841663fe0 100644 (file)
@@ -49,7 +49,7 @@ class DynamicTypeChecker : public Checker<check::PostStmt<ImplicitCastExpr>> {
 
     PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                      BugReporterContext &BRC,
-                                     BugReport &BR) override;
+                                     PathSensitiveBugReport &BR) override;
 
   private:
     // The tracked region.
@@ -80,8 +80,8 @@ void DynamicTypeChecker::reportTypeError(QualType DynamicType,
   QualType::print(StaticType.getTypePtr(), Qualifiers(), OS, C.getLangOpts(),
                   llvm::Twine());
   OS << "'";
-  std::unique_ptr<BugReport> R(
-      new BugReport(*BT, OS.str(), C.generateNonFatalErrorNode()));
+  auto R = std::make_unique<PathSensitiveBugReport>(
+      *BT, OS.str(), C.generateNonFatalErrorNode());
   R->markInteresting(Reg);
   R->addVisitor(std::make_unique<DynamicTypeBugVisitor>(Reg));
   R->addRange(ReportedNode->getSourceRange());
@@ -89,7 +89,7 @@ void DynamicTypeChecker::reportTypeError(QualType DynamicType,
 }
 
 PathDiagnosticPieceRef DynamicTypeChecker::DynamicTypeBugVisitor::VisitNode(
-    const ExplodedNode *N, BugReporterContext &BRC, BugReport &) {
+    const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &) {
   ProgramStateRef State = N->getState();
   ProgramStateRef StatePrev = N->getFirstPred()->getState();
 
index e1dcf2c1a18f2d6ad73bc1f1cf204c697bddee6e..f4ebc3d0d8b7bbd94645d7e84b6c65e762918fe9 100644 (file)
@@ -85,7 +85,7 @@ class DynamicTypePropagation:
 
     PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                      BugReporterContext &BRC,
-                                     BugReport &BR) override;
+                                     PathSensitiveBugReport &BR) override;
 
   private:
     // The tracked symbol.
@@ -911,8 +911,8 @@ void DynamicTypePropagation::reportGenericsBug(
   OS << "' to incompatible type '";
   QualType::print(To, Qualifiers(), OS, C.getLangOpts(), llvm::Twine());
   OS << "'";
-  std::unique_ptr<BugReport> R(
-      new BugReport(*ObjCGenericsBugType, OS.str(), N));
+  auto R = std::make_unique<PathSensitiveBugReport>(*ObjCGenericsBugType,
+                                                    OS.str(), N);
   R->markInteresting(Sym);
   R->addVisitor(std::make_unique<GenericsBugVisitor>(Sym));
   if (ReportedNode)
@@ -921,7 +921,8 @@ void DynamicTypePropagation::reportGenericsBug(
 }
 
 PathDiagnosticPieceRef DynamicTypePropagation::GenericsBugVisitor::VisitNode(
-    const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) {
+    const ExplodedNode *N, BugReporterContext &BRC,
+    PathSensitiveBugReport &BR) {
   ProgramStateRef state = N->getState();
   ProgramStateRef statePrev = N->getFirstPred()->getState();
 
index 021d440d3d05f5eb280a8d2d9e81e93946ff8a71..481a5685a71f637454153f45b06dfd67652456a6 100644 (file)
@@ -83,7 +83,7 @@ void EnumCastOutOfRangeChecker::reportWarning(CheckerContext &C) const {
           new BuiltinBug(this, "Enum cast out of range",
                          "The value provided to the cast expression is not in "
                          "the valid range of values for the enum"));
-    C.emitReport(std::make_unique<BugReport>(
+    C.emitReport(std::make_unique<PathSensitiveBugReport>(
         *EnumValueCastOutOfRange, EnumValueCastOutOfRange->getDescription(),
         N));
   }
index 5334204b7966b698337db6482b094a1cbc16978a..b32fa07b1a822a25a283512abc4c09715929a936 100644 (file)
@@ -148,7 +148,7 @@ ExplodedNode *ExprInspectionChecker::reportBug(llvm::StringRef Msg,
   if (!BT)
     BT.reset(new BugType(this, "Checking analyzer assumptions", "debug"));
 
-  BR.emitReport(std::make_unique<BugReport>(*BT, Msg, N));
+  BR.emitReport(std::make_unique<PathSensitiveBugReport>(*BT, Msg, N));
   return N;
 }
 
index 5c4c7a0ca076b75df3ac067242bb60e21e0ca22f..b315a845228594561d91e9d02928cdd929fac564 100644 (file)
@@ -55,7 +55,8 @@ void FixedAddressChecker::checkPreStmt(const BinaryOperator *B,
                          "Using a fixed address is not portable because that "
                          "address will probably not be valid in all "
                          "environments or platforms."));
-    auto R = std::make_unique<BugReport>(*BT, BT->getDescription(), N);
+    auto R =
+        std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N);
     R->addRange(B->getRHS()->getSourceRange());
     C.emitReport(std::move(R));
   }
index 161ce54ea4b0d7ff9685f0a6af9b677bb0af9e51..d442b26b3959432b0efcc9229995407f12676621 100644 (file)
@@ -736,7 +736,7 @@ bool GenericTaintChecker::generateReportIfTainted(const Expr *E, StringRef Msg,
   // Generate diagnostic.
   if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
     initBugType();
-    auto report = std::make_unique<BugReport>(*BT, Msg, N);
+    auto report = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
     report->addRange(E->getSourceRange());
     report->addVisitor(std::make_unique<TaintBugVisitor>(TaintedSVal));
     C.emitReport(std::move(report));
index 2a571aea4568074257fc05e290e04581f808f6f7..e8a2121e93d76b75cda28bf4aa1646e9279ae17c 100644 (file)
@@ -54,9 +54,9 @@ public:
       ID.AddPointer(getTag());
     }
 
-    virtual PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
-                                             BugReporterContext &BRC,
-                                             BugReport &BR) override;
+    virtual PathDiagnosticPieceRef
+    VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
+              PathSensitiveBugReport &BR) override;
 
     // FIXME: Scan the map once in the visitor's constructor and do a direct
     // lookup by region.
@@ -279,7 +279,7 @@ const MemRegion *getContainerObjRegion(ProgramStateRef State, SymbolRef Sym) {
 } // end namespace clang
 
 PathDiagnosticPieceRef InnerPointerChecker::InnerPointerBRVisitor::VisitNode(
-    const ExplodedNode *N, BugReporterContext &BRC, BugReport &) {
+    const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &) {
   if (!isSymbolTracked(N->getState(), PtrToBuf) ||
       isSymbolTracked(N->getFirstPred()->getState(), PtrToBuf))
     return nullptr;
index ee2ed43ec579612b95ea1c75e85544969a8d6b3b..b80f7618bf2d6ef720a27e29e1efdae6619293bc 100644 (file)
@@ -1590,7 +1590,8 @@ IteratorPosition IteratorChecker::advancePosition(CheckerContext &C,
 void IteratorChecker::reportOutOfRangeBug(const StringRef &Message,
                                           const SVal &Val, CheckerContext &C,
                                           ExplodedNode *ErrNode) const {
-  auto R = std::make_unique<BugReport>(*OutOfRangeBugType, Message, ErrNode);
+  auto R = std::make_unique<PathSensitiveBugReport>(*OutOfRangeBugType, Message,
+                                                    ErrNode);
   R->markInteresting(Val);
   C.emitReport(std::move(R));
 }
@@ -1599,7 +1600,8 @@ void IteratorChecker::reportMismatchedBug(const StringRef &Message,
                                           const SVal &Val1, const SVal &Val2,
                                           CheckerContext &C,
                                           ExplodedNode *ErrNode) const {
-  auto R = std::make_unique<BugReport>(*MismatchedBugType, Message, ErrNode);
+  auto R = std::make_unique<PathSensitiveBugReport>(*MismatchedBugType, Message,
+                                                    ErrNode);
   R->markInteresting(Val1);
   R->markInteresting(Val2);
   C.emitReport(std::move(R));
@@ -1609,7 +1611,8 @@ void IteratorChecker::reportMismatchedBug(const StringRef &Message,
                                           const SVal &Val, const MemRegion *Reg,
                                           CheckerContext &C,
                                           ExplodedNode *ErrNode) const {
-  auto R = std::make_unique<BugReport>(*MismatchedBugType, Message, ErrNode);
+  auto R = std::make_unique<PathSensitiveBugReport>(*MismatchedBugType, Message,
+                                                    ErrNode);
   R->markInteresting(Val);
   R->markInteresting(Reg);
   C.emitReport(std::move(R));
@@ -1618,7 +1621,8 @@ void IteratorChecker::reportMismatchedBug(const StringRef &Message,
 void IteratorChecker::reportInvalidatedBug(const StringRef &Message,
                                            const SVal &Val, CheckerContext &C,
                                            ExplodedNode *ErrNode) const {
-  auto R = std::make_unique<BugReport>(*InvalidatedBugType, Message, ErrNode);
+  auto R = std::make_unique<PathSensitiveBugReport>(*InvalidatedBugType,
+                                                    Message, ErrNode);
   R->markInteresting(Val);
   C.emitReport(std::move(R));
 }
index dd83b0b952e7f2baa32350aec9c76ace45ffa83b..a81015b6e524b78dcfc791f1f3b232a25e46d29e 100644 (file)
@@ -125,7 +125,7 @@ public:
 
   PathDiagnosticPieceRef VisitNode(const ExplodedNode *Succ,
                                    BugReporterContext &BRC,
-                                   BugReport &BR) override;
+                                   PathSensitiveBugReport &BR) override;
 
   void Profile(llvm::FoldingSetNodeID &ID) const override {
     ID.Add(NonLocalizedString);
@@ -761,8 +761,8 @@ void NonLocalizedStringChecker::reportLocalizationError(
     return;
 
   // Generate the bug report.
-  std::unique_ptr<BugReport> R(new BugReport(
-      *BT, "User-facing text should use localized string macro", ErrNode));
+  auto R = std::make_unique<PathSensitiveBugReport>(
+      *BT, "User-facing text should use localized string macro", ErrNode);
   if (argumentNumber) {
     R->addRange(M.getArgExpr(argumentNumber - 1)->getSourceRange());
   } else {
@@ -999,7 +999,8 @@ void NonLocalizedStringChecker::checkPostStmt(const ObjCStringLiteral *SL,
 
 PathDiagnosticPieceRef
 NonLocalizedStringBRVisitor::VisitNode(const ExplodedNode *Succ,
-                                       BugReporterContext &BRC, BugReport &BR) {
+                                       BugReporterContext &BRC,
+                                       PathSensitiveBugReport &BR) {
   if (Satisfied)
     return nullptr;
 
index f51ec4659ecf392a71ea3e90144f061b485f9464..d8fd125f4003de377563db4840c4790808f91495 100644 (file)
@@ -274,7 +274,7 @@ void MIGChecker::checkReturnAux(const ReturnStmt *RS, CheckerContext &C) const {
   if (!N)
     return;
 
-  auto R = std::make_unique<BugReport>(
+  auto R = std::make_unique<PathSensitiveBugReport>(
       BT,
       "MIG callback fails with error after deallocating argument value. "
       "This is a use-after-free vulnerability because the caller will try to "
index d87e30782b74744defab635ffc4c4e93fd0a9eca..bbf2ddec5762073bdf669ec94ef1ccec3155355e 100644 (file)
@@ -30,8 +30,8 @@ void MPIBugReporter::reportDoubleNonblocking(
   ErrorText = "Double nonblocking on request " +
               RequestRegion->getDescriptiveName() + ". ";
 
-  auto Report = std::make_unique<BugReport>(*DoubleNonblockingBugType,
-                                             ErrorText, ExplNode);
+  auto Report = std::make_unique<PathSensitiveBugReport>(
+      *DoubleNonblockingBugType, ErrorText, ExplNode);
 
   Report->addRange(MPICallEvent.getSourceRange());
   SourceRange Range = RequestRegion->sourceRange();
@@ -53,8 +53,8 @@ void MPIBugReporter::reportMissingWait(
   std::string ErrorText{"Request " + RequestRegion->getDescriptiveName() +
                         " has no matching wait. "};
 
-  auto Report =
-      std::make_unique<BugReport>(*MissingWaitBugType, ErrorText, ExplNode);
+  auto Report = std::make_unique<PathSensitiveBugReport>(*MissingWaitBugType,
+                                                         ErrorText, ExplNode);
 
   SourceRange Range = RequestRegion->sourceRange();
   if (Range.isValid())
@@ -73,8 +73,8 @@ void MPIBugReporter::reportUnmatchedWait(
   std::string ErrorText{"Request " + RequestRegion->getDescriptiveName() +
                         " has no matching nonblocking call. "};
 
-  auto Report =
-      std::make_unique<BugReport>(*UnmatchedWaitBugType, ErrorText, ExplNode);
+  auto Report = std::make_unique<PathSensitiveBugReport>(*UnmatchedWaitBugType,
+                                                         ErrorText, ExplNode);
 
   Report->addRange(CE.getSourceRange());
   SourceRange Range = RequestRegion->sourceRange();
@@ -84,8 +84,10 @@ void MPIBugReporter::reportUnmatchedWait(
   BReporter.emitReport(std::move(Report));
 }
 
-PathDiagnosticPieceRef MPIBugReporter::RequestNodeVisitor::VisitNode(
-    const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) {
+PathDiagnosticPieceRef
+MPIBugReporter::RequestNodeVisitor::VisitNode(const ExplodedNode *N,
+                                              BugReporterContext &BRC,
+                                              PathSensitiveBugReport &BR) {
 
   if (IsNodeFound)
     return nullptr;
index 66da02f76156eaf5e51317e69641a5512baa5b68..9871da026b042809cbdc718f56b6cd8b4804e378 100644 (file)
@@ -91,7 +91,7 @@ private:
 
     PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                      BugReporterContext &BRC,
-                                     BugReport &BR) override;
+                                     PathSensitiveBugReport &BR) override;
 
   private:
     const MemRegion *const RequestRegion;
index 07f99bee7f349eecbb4b450e4312725918c5a7bb..9947b57e276fcf11eeaa241064109f381b29d749 100644 (file)
@@ -117,7 +117,8 @@ private:
       const AllocationPair &AP, ExplodedNode *N, CheckerContext &C) const;
 
   /// Mark an AllocationPair interesting for diagnostic reporting.
-  void markInteresting(BugReport *R, const AllocationPair &AP) const {
+  void markInteresting(PathSensitiveBugReport *R,
+                       const AllocationPair &AP) const {
     R->markInteresting(AP.first);
     R->markInteresting(AP.second->Region);
   }
@@ -141,7 +142,7 @@ private:
 
     PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                      BugReporterContext &BRC,
-                                     BugReport &BR) override;
+                                     PathSensitiveBugReport &BR) override;
   };
 };
 }
@@ -236,7 +237,7 @@ void MacOSKeychainAPIChecker::
 
   os << "Deallocator doesn't match the allocator: '"
      << FunctionsToTrack[PDeallocIdx].Name << "' should be used.";
-  auto Report = std::make_unique<BugReport>(*BT, os.str(), N);
+  auto Report = std::make_unique<PathSensitiveBugReport>(*BT, os.str(), N);
   Report->addVisitor(std::make_unique<SecKeychainBugVisitor>(AP.first));
   Report->addRange(ArgExpr->getSourceRange());
   markInteresting(Report.get(), AP);
@@ -280,7 +281,8 @@ void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
             << "the allocator: missing a call to '"
             << FunctionsToTrack[DIdx].Name
             << "'.";
-        auto Report = std::make_unique<BugReport>(*BT, os.str(), N);
+        auto Report =
+            std::make_unique<PathSensitiveBugReport>(*BT, os.str(), N);
         Report->addVisitor(std::make_unique<SecKeychainBugVisitor>(V));
         Report->addRange(ArgExpr->getSourceRange());
         Report->markInteresting(AS->Region);
@@ -334,7 +336,7 @@ void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
     if (!N)
       return;
     initBugType();
-    auto Report = std::make_unique<BugReport>(
+    auto Report = std::make_unique<PathSensitiveBugReport>(
         *BT, "Trying to free data which has not been allocated.", N);
     Report->addRange(ArgExpr->getSourceRange());
     if (AS)
@@ -487,9 +489,9 @@ MacOSKeychainAPIChecker::generateAllocatedDataNotReleasedReport(
                                               C.getSourceManager(),
                                               AllocNode->getLocationContext());
 
-  auto Report =
-      std::make_unique<BugReport>(*BT, os.str(), N, LocUsedForUniqueing,
-                                  AllocNode->getLocationContext()->getDecl());
+  auto Report = std::make_unique<PathSensitiveBugReport>(
+      *BT, os.str(), N, LocUsedForUniqueing,
+      AllocNode->getLocationContext()->getDecl());
 
   Report->addVisitor(std::make_unique<SecKeychainBugVisitor>(AP.first));
   markInteresting(Report.get(), AP);
@@ -615,7 +617,8 @@ ProgramStateRef MacOSKeychainAPIChecker::checkPointerEscape(
 
 PathDiagnosticPieceRef
 MacOSKeychainAPIChecker::SecKeychainBugVisitor::VisitNode(
-    const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) {
+    const ExplodedNode *N, BugReporterContext &BRC,
+    PathSensitiveBugReport &BR) {
   const AllocationState *AS = N->getState()->get<AllocatedData>(Sym);
   if (!AS)
     return nullptr;
index aff4318f6b586da2c87cadfd097739dc3f7b82b2..d964a1668eaaabaf02062eef241a5334041f2c5f 100644 (file)
@@ -139,7 +139,8 @@ void MacOSXAPIChecker::CheckDispatchOnce(CheckerContext &C, const CallExpr *CE,
     BT_dispatchOnce.reset(new BugType(this, "Improper use of 'dispatch_once'",
                                       "API Misuse (Apple)"));
 
-  auto report = std::make_unique<BugReport>(*BT_dispatchOnce, os.str(), N);
+  auto report =
+      std::make_unique<PathSensitiveBugReport>(*BT_dispatchOnce, os.str(), N);
   report->addRange(CE->getArg(0)->getSourceRange());
   C.emitReport(std::move(report));
 }
index 8abd938c22168e14baaea0a91c63eda044407bd7..6d0673051ad8a1f75c63b40cceb37728182b93a6 100644 (file)
@@ -524,17 +524,16 @@ private:
 
     PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                      BugReporterContext &BRC,
-                                     BugReport &BR) override;
+                                     PathSensitiveBugReport &BR) override;
 
     PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC,
                                       const ExplodedNode *EndPathNode,
-                                      BugReport &BR) override {
+                                      PathSensitiveBugReport &BR) override {
       if (!IsLeak)
         return nullptr;
 
       PathDiagnosticLocation L =
-        PathDiagnosticLocation::createEndOfPath(EndPathNode,
-                                                BRC.getSourceManager());
+          PathDiagnosticLocation::createEndOfPath(EndPathNode);
       // Do not add the statement itself as a range in case of leak.
       return std::make_shared<PathDiagnosticEventPiece>(L, BR.getDescription(),
                                                          false);
@@ -1822,7 +1821,8 @@ void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal,
 
     printExpectedAllocName(os, C, DeallocExpr);
 
-    auto R = std::make_unique<BugReport>(*BT_BadFree[*CheckKind], os.str(), N);
+    auto R = std::make_unique<PathSensitiveBugReport>(*BT_BadFree[*CheckKind],
+                                                      os.str(), N);
     R->markInteresting(MR);
     R->addRange(Range);
     C.emitReport(std::move(R));
@@ -1846,7 +1846,7 @@ void MallocChecker::ReportFreeAlloca(CheckerContext &C, SVal ArgVal,
       BT_FreeAlloca[*CheckKind].reset(new BugType(
           CheckNames[*CheckKind], "Free alloca()", categories::MemoryError));
 
-    auto R = std::make_unique<BugReport>(
+    auto R = std::make_unique<PathSensitiveBugReport>(
         *BT_FreeAlloca[*CheckKind],
         "Memory allocated by alloca() should not be deallocated", N);
     R->markInteresting(ArgVal.getAsRegion());
@@ -1902,7 +1902,8 @@ void MallocChecker::ReportMismatchedDealloc(CheckerContext &C,
         os << ", not " << DeallocOs.str();
     }
 
-    auto R = std::make_unique<BugReport>(*BT_MismatchedDealloc, os.str(), N);
+    auto R = std::make_unique<PathSensitiveBugReport>(*BT_MismatchedDealloc,
+                                                      os.str(), N);
     R->markInteresting(Sym);
     R->addRange(Range);
     R->addVisitor(std::make_unique<MallocBugVisitor>(Sym));
@@ -1961,7 +1962,8 @@ void MallocChecker::ReportOffsetFree(CheckerContext &C, SVal ArgVal,
   else
     os << "allocated memory";
 
-  auto R = std::make_unique<BugReport>(*BT_OffsetFree[*CheckKind], os.str(), N);
+  auto R = std::make_unique<PathSensitiveBugReport>(*BT_OffsetFree[*CheckKind],
+                                                    os.str(), N);
   R->markInteresting(MR->getBaseRegion());
   R->addRange(Range);
   C.emitReport(std::move(R));
@@ -1987,10 +1989,11 @@ void MallocChecker::ReportUseAfterFree(CheckerContext &C, SourceRange Range,
     AllocationFamily AF =
         C.getState()->get<RegionState>(Sym)->getAllocationFamily();
 
-    auto R = std::make_unique<BugReport>(*BT_UseFree[*CheckKind],
+    auto R = std::make_unique<PathSensitiveBugReport>(
+        *BT_UseFree[*CheckKind],
         AF == AF_InnerBuffer
-              ? "Inner pointer of container used after re/deallocation"
-              : "Use of memory after it is freed",
+            ? "Inner pointer of container used after re/deallocation"
+            : "Use of memory after it is freed",
         N);
 
     R->markInteresting(Sym);
@@ -2021,7 +2024,7 @@ void MallocChecker::ReportDoubleFree(CheckerContext &C, SourceRange Range,
       BT_DoubleFree[*CheckKind].reset(new BugType(
           CheckNames[*CheckKind], "Double free", categories::MemoryError));
 
-    auto R = std::make_unique<BugReport>(
+    auto R = std::make_unique<PathSensitiveBugReport>(
         *BT_DoubleFree[*CheckKind],
         (Released ? "Attempt to free released memory"
                   : "Attempt to free non-owned memory"),
@@ -2050,7 +2053,7 @@ void MallocChecker::ReportDoubleDelete(CheckerContext &C, SymbolRef Sym) const {
                                         "Double delete",
                                         categories::MemoryError));
 
-    auto R = std::make_unique<BugReport>(
+    auto R = std::make_unique<PathSensitiveBugReport>(
         *BT_DoubleDelete, "Attempt to delete released memory", N);
 
     R->markInteresting(Sym);
@@ -2078,8 +2081,8 @@ void MallocChecker::ReportUseZeroAllocated(CheckerContext &C,
           new BugType(CheckNames[*CheckKind], "Use of zero allocated",
                       categories::MemoryError));
 
-    auto R = std::make_unique<BugReport>(*BT_UseZerroAllocated[*CheckKind],
-                                         "Use of zero-allocated memory", N);
+    auto R = std::make_unique<PathSensitiveBugReport>(
+        *BT_UseZerroAllocated[*CheckKind], "Use of zero-allocated memory", N);
 
     R->addRange(Range);
     if (Sym) {
@@ -2118,7 +2121,8 @@ void MallocChecker::ReportFunctionPointerFree(CheckerContext &C, SVal ArgVal,
 
     Os << " is a function pointer";
 
-    auto R = std::make_unique<BugReport>(*BT_BadFree[*CheckKind], Os.str(), N);
+    auto R = std::make_unique<PathSensitiveBugReport>(*BT_BadFree[*CheckKind],
+                                                      Os.str(), N);
     R->markInteresting(MR);
     R->addRange(Range);
     C.emitReport(std::move(R));
@@ -2343,7 +2347,7 @@ void MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N,
     os << "Potential memory leak";
   }
 
-  auto R = std::make_unique<BugReport>(
+  auto R = std::make_unique<PathSensitiveBugReport>(
       *BT_Leak[*CheckKind], os.str(), N, LocUsedForUniqueing,
       AllocNode->getLocationContext()->getDecl());
   R->markInteresting(Sym);
@@ -2905,8 +2909,10 @@ static bool isReferenceCountingPointerDestructor(const CXXDestructorDecl *DD) {
   return false;
 }
 
-PathDiagnosticPieceRef MallocChecker::MallocBugVisitor::VisitNode(
-    const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) {
+PathDiagnosticPieceRef
+MallocChecker::MallocBugVisitor::VisitNode(const ExplodedNode *N,
+                                           BugReporterContext &BRC,
+                                           PathSensitiveBugReport &BR) {
 
   ProgramStateRef state = N->getState();
   ProgramStateRef statePrev = N->getFirstPred()->getState();
index 22d166394a9084b40004c5de39fb4769d9648ac2..ceea62160545ef90cf324488d7fdd763a43cd07a 100644 (file)
@@ -67,7 +67,7 @@ void MmapWriteExecChecker::checkPreCall(const CallEvent &Call,
       if (!N)
         return;
 
-      auto Report = std::make_unique<BugReport>(
+      auto Report = std::make_unique<PathSensitiveBugReport>(
           *BT, "Both PROT_WRITE and PROT_EXEC flags are set. This can "
                "lead to exploitable memory regions, which could be overwritten "
                "with malicious code", N);
index 26102c57446339f1e8e4332595844d742439e4e6..a429123ddca9c1827aba37f0fa014a656ad19f01 100644 (file)
@@ -171,7 +171,7 @@ private:
 
     PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                      BugReporterContext &BRC,
-                                     BugReport &BR) override;
+                                     PathSensitiveBugReport &BR) override;
 
   private:
     const MoveChecker &Chk;
@@ -270,8 +270,10 @@ static const MemRegion *unwrapRValueReferenceIndirection(const MemRegion *MR) {
   return MR;
 }
 
-PathDiagnosticPieceRef MoveChecker::MovedBugVisitor::VisitNode(
-    const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) {
+PathDiagnosticPieceRef
+MoveChecker::MovedBugVisitor::VisitNode(const ExplodedNode *N,
+                                        BugReporterContext &BRC,
+                                        PathSensitiveBugReport &BR) {
   // We need only the last move of the reported object's region.
   // The visitor walks the ExplodedGraph backwards.
   if (Found)
@@ -427,9 +429,9 @@ ExplodedNode *MoveChecker::reportBug(const MemRegion *Region,
         break;
     }
 
-    auto R =
-        std::make_unique<BugReport>(*BT, OS.str(), N, LocUsedForUniqueing,
-                                     MoveNode->getLocationContext()->getDecl());
+    auto R = std::make_unique<PathSensitiveBugReport>(
+        *BT, OS.str(), N, LocUsedForUniqueing,
+        MoveNode->getLocationContext()->getDecl());
     R->addVisitor(std::make_unique<MovedBugVisitor>(*this, Region, RD, MK));
     C.emitReport(std::move(R));
     return N;
index 9325773cf81ea29004d4437b2b31f3b75181feb7..41b7fe5e43b6f30a1cf4aa14238722f8dff54223 100644 (file)
@@ -67,9 +67,11 @@ void NSAutoreleasePoolChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
     return;
   }
 
-  auto Report = std::make_unique<BugReport>(
-      *BT, "Use -drain instead of -release when using NSAutoreleasePool and "
-           "garbage collection", N);
+  auto Report = std::make_unique<PathSensitiveBugReport>(
+      *BT,
+      "Use -drain instead of -release when using NSAutoreleasePool and "
+      "garbage collection",
+      N);
   Report->addRange(msg.getSourceRange());
   C.emitReport(std::move(Report));
 }
index 96ad4983be01d25f827ff7da379a319a5f1b67e1..85370bf133cd714e99782b0d3a5045fd1fe8cbc7 100644 (file)
@@ -273,7 +273,8 @@ void NSOrCFErrorDerefChecker::checkEvent(ImplicitNullDerefEvent event) const {
       CFBT.reset(new CFErrorDerefBug(this));
     bug = CFBT.get();
   }
-  BR.emitReport(std::make_unique<BugReport>(*bug, os.str(), event.SinkNode));
+  BR.emitReport(
+      std::make_unique<PathSensitiveBugReport>(*bug, os.str(), event.SinkNode));
 }
 
 static bool IsNSError(QualType T, IdentifierInfo *II) {
index 74d54100bac2c718151098e98deeb70bec9cd4c8..0734272381b8aa26e1191b428a5bd34401e16711 100644 (file)
@@ -196,7 +196,8 @@ NonNullParamChecker::genReportNullAttrNonNull(const ExplodedNode *ErrorNode,
      << IdxOfArg << llvm::getOrdinalSuffix(IdxOfArg)
      << " parameter expecting 'nonnull'";
 
-  auto R = std::make_unique<BugReport>(*BTAttrNonNull, SBuf, ErrorNode);
+  auto R =
+      std::make_unique<PathSensitiveBugReport>(*BTAttrNonNull, SBuf, ErrorNode);
   if (ArgE)
     bugreporter::trackExpressionValue(ErrorNode, ArgE, *R);
 
@@ -208,7 +209,7 @@ std::unique_ptr<BugReport> NonNullParamChecker::genReportReferenceToNullPointer(
   if (!BTNullRefArg)
     BTNullRefArg.reset(new BuiltinBug(this, "Dereference of null pointer"));
 
-  auto R = std::make_unique<BugReport>(
+  auto R = std::make_unique<PathSensitiveBugReport>(
       *BTNullRefArg, "Forming reference to null pointer", ErrorNode);
   if (ArgE) {
     const Expr *ArgEDeref = bugreporter::getDerefExpr(ArgE);
index 5915fce10560da824fe9e7406c5d21b3a24bf3d4..f3a252cf4268fcb13e7618f7ff7fc2cc00762d75 100644 (file)
@@ -139,7 +139,7 @@ private:
 
     PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                      BugReporterContext &BRC,
-                                     BugReport &BR) override;
+                                     PathSensitiveBugReport &BR) override;
 
   private:
     // The tracked region.
@@ -163,7 +163,7 @@ private:
     if (!BT)
       BT.reset(new BugType(this, "Nullability", categories::MemoryError));
 
-    auto R = std::make_unique<BugReport>(*BT, Msg, N);
+    auto R = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
     if (Region) {
       R->markInteresting(Region);
       R->addVisitor(std::make_unique<NullabilityBugVisitor>(Region));
@@ -291,7 +291,8 @@ NullabilityChecker::getTrackRegion(SVal Val, bool CheckSuperRegion) const {
 }
 
 PathDiagnosticPieceRef NullabilityChecker::NullabilityBugVisitor::VisitNode(
-    const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) {
+    const ExplodedNode *N, BugReporterContext &BRC,
+    PathSensitiveBugReport &BR) {
   ProgramStateRef State = N->getState();
   ProgramStateRef StatePrev = N->getFirstPred()->getState();
 
index 3c810c53e7d1b5c0db5128681c0d2eddfdb305ca..0e25817c87932e62f2dd7508466d1ac07302b030 100644 (file)
@@ -46,8 +46,8 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
       if (!BT_undef)
         BT_undef.reset(new BuiltinBug(this, "Uninitialized value used as mutex "
                                             "for @synchronized"));
-      auto report =
-          std::make_unique<BugReport>(*BT_undef, BT_undef->getDescription(), N);
+      auto report = std::make_unique<PathSensitiveBugReport>(
+          *BT_undef, BT_undef->getDescription(), N);
       bugreporter::trackExpressionValue(N, Ex, *report);
       C.emitReport(std::move(report));
     }
@@ -70,8 +70,8 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S,
           BT_null.reset(new BuiltinBug(
               this, "Nil value used as mutex for @synchronized() "
                     "(no synchronization will occur)"));
-        auto report =
-            std::make_unique<BugReport>(*BT_null, BT_null->getDescription(), N);
+        auto report = std::make_unique<PathSensitiveBugReport>(
+            *BT_null, BT_null->getDescription(), N);
         bugreporter::trackExpressionValue(N, Ex, *report);
 
         C.emitReport(std::move(report));
index 95995fb2130c1331753d2f0a17d2f88901d636ec..8abb926d4862f12fe8eb158bd52c6eede296aa53 100644 (file)
@@ -144,7 +144,8 @@ void ObjCContainersChecker::checkPreStmt(const CallExpr *CE,
       if (!N)
         return;
       initBugType();
-      auto R = std::make_unique<BugReport>(*BT, "Index is out of bounds", N);
+      auto R = std::make_unique<PathSensitiveBugReport>(
+          *BT, "Index is out of bounds", N);
       R->addRange(IdxExpr->getSourceRange());
       bugreporter::trackExpressionValue(
           N, IdxExpr, *R, bugreporter::TrackingKind::Thorough, false);
index 0f2b8f564d717c3572599b664f118785d4c2b60a..344285750f0e8ebc6346370062f6051d5cf1834b 100644 (file)
@@ -159,7 +159,7 @@ void ObjCSelfInitChecker::checkForInvalidSelf(const Expr *E, CheckerContext &C,
   if (!BT)
     BT.reset(new BugType(this, "Missing \"self = [(super or self) init...]\"",
                          categories::CoreFoundationObjectiveC));
-  C.emitReport(std::make_unique<BugReport>(*BT, errorStr, N));
+  C.emitReport(std::make_unique<PathSensitiveBugReport>(*BT, errorStr, N));
 }
 
 void ObjCSelfInitChecker::checkPostObjCMessage(const ObjCMethodCall &Msg,
index d81d3723a7e8162f6120295adeec94fa7b496474..0575be8453743728c934145ebc814562fd754f78 100644 (file)
@@ -71,7 +71,7 @@ public:
 
   PathDiagnosticPieceRef VisitNode(const ExplodedNode *Succ,
                                    BugReporterContext &BRC,
-                                   BugReport &BR) override;
+                                   PathSensitiveBugReport &BR) override;
 
   void Profile(llvm::FoldingSetNodeID &ID) const override {
     ID.Add(ReceiverSymbol);
@@ -187,8 +187,8 @@ void ObjCSuperDeallocChecker::reportUseAfterDealloc(SymbolRef Sym,
     Desc = "Use of 'self' after it has been deallocated";
 
   // Generate the report.
-  std::unique_ptr<BugReport> BR(
-      new BugReport(*DoubleSuperDeallocBugType, Desc, ErrNode));
+  auto BR = std::make_unique<PathSensitiveBugReport>(*DoubleSuperDeallocBugType,
+                                                     Desc, ErrNode);
   BR->addRange(S->getSourceRange());
   BR->addVisitor(std::make_unique<SuperDeallocBRVisitor>(Sym));
   C.emitReport(std::move(BR));
@@ -244,7 +244,8 @@ ObjCSuperDeallocChecker::isSuperDeallocMessage(const ObjCMethodCall &M) const {
 
 PathDiagnosticPieceRef
 SuperDeallocBRVisitor::VisitNode(const ExplodedNode *Succ,
-                                 BugReporterContext &BRC, BugReport &) {
+                                 BugReporterContext &BRC,
+                                 PathSensitiveBugReport &) {
   if (Satisfied)
     return nullptr;
 
index e370682b979b26db7d87fcda7946188435c17b5a..4a3c2b8cd40e27f4833a3927044fb45364fc3407 100644 (file)
@@ -335,7 +335,8 @@ public:
 
     PathDiagnosticLocation CELoc =
         PathDiagnosticLocation::create(RD, BR->getSourceManager());
-    auto Report = std::make_unique<BugReport>(*PaddingBug, Os.str(), CELoc);
+    auto Report =
+        std::make_unique<BasicBugReport>(*PaddingBug, Os.str(), CELoc);
     Report->setDeclWithIssue(RD);
     Report->addRange(RD->getSourceRange());
     BR->emitReport(std::move(Report));
index 4ce82f225b94672f2d4d584baa47d690d02d83b8..259f23abdc958276ea19518d730fdccaeb627840 100644 (file)
@@ -173,8 +173,8 @@ void PointerArithChecker::reportPointerArithMisuse(const Expr *E,
             this, "Dangerous pointer arithmetic",
             "Pointer arithmetic on a pointer to base class is dangerous "
             "because derived and base class may have different size."));
-      auto R = std::make_unique<BugReport>(*BT_polyArray,
-                                            BT_polyArray->getDescription(), N);
+      auto R = std::make_unique<PathSensitiveBugReport>(
+          *BT_polyArray, BT_polyArray->getDescription(), N);
       R->addRange(E->getSourceRange());
       R->markInteresting(ArrayRegion);
       C.emitReport(std::move(R));
@@ -196,8 +196,8 @@ void PointerArithChecker::reportPointerArithMisuse(const Expr *E,
                                            "Pointer arithmetic on non-array "
                                            "variables relies on memory layout, "
                                            "which is dangerous."));
-    auto R = std::make_unique<BugReport>(*BT_pointerArith,
-                                          BT_pointerArith->getDescription(), N);
+    auto R = std::make_unique<PathSensitiveBugReport>(
+        *BT_pointerArith, BT_pointerArith->getDescription(), N);
     R->addRange(SR);
     R->markInteresting(Region);
     C.emitReport(std::move(R));
index a4d6a1904a578d24381ebababffd99559ce4f126..88d0eb2ae748407919202666a945dfd41e24339a 100644 (file)
@@ -63,7 +63,8 @@ void PointerSubChecker::checkPreStmt(const BinaryOperator *B,
           new BuiltinBug(this, "Pointer subtraction",
                          "Subtraction of two pointers that do not point to "
                          "the same memory chunk may cause incorrect result."));
-    auto R = std::make_unique<BugReport>(*BT, BT->getDescription(), N);
+    auto R =
+        std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N);
     R->addRange(B->getSourceRange());
     C.emitReport(std::move(R));
   }
index e98ad6ff38138e4ef71fb9dca8e76d0f2d356205..8649b8b96dd036f1906476b5d51d110445d369eb 100644 (file)
@@ -240,7 +240,7 @@ void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE,
       ExplodedNode *N = C.generateErrorNode();
       if (!N)
         return;
-      auto report = std::make_unique<BugReport>(
+      auto report = std::make_unique<PathSensitiveBugReport>(
           *BT_doublelock, "This lock has already been acquired", N);
       report->addRange(CE->getArg(0)->getSourceRange());
       C.emitReport(std::move(report));
@@ -305,7 +305,7 @@ void PthreadLockChecker::ReleaseLock(CheckerContext &C, const CallExpr *CE,
       ExplodedNode *N = C.generateErrorNode();
       if (!N)
         return;
-      auto Report = std::make_unique<BugReport>(
+      auto Report = std::make_unique<PathSensitiveBugReport>(
           *BT_doubleunlock, "This lock has already been unlocked", N);
       Report->addRange(CE->getArg(0)->getSourceRange());
       C.emitReport(std::move(Report));
@@ -328,7 +328,7 @@ void PthreadLockChecker::ReleaseLock(CheckerContext &C, const CallExpr *CE,
       ExplodedNode *N = C.generateErrorNode();
       if (!N)
         return;
-      auto report = std::make_unique<BugReport>(
+      auto report = std::make_unique<PathSensitiveBugReport>(
           *BT_lor, "This was not the most recently acquired lock. Possible "
                    "lock order reversal", N);
       report->addRange(CE->getArg(0)->getSourceRange());
@@ -399,7 +399,8 @@ void PthreadLockChecker::DestroyLock(CheckerContext &C, const CallExpr *CE,
   ExplodedNode *N = C.generateErrorNode();
   if (!N)
     return;
-  auto Report = std::make_unique<BugReport>(*BT_destroylock, Message, N);
+  auto Report =
+      std::make_unique<PathSensitiveBugReport>(*BT_destroylock, Message, N);
   Report->addRange(CE->getArg(0)->getSourceRange());
   C.emitReport(std::move(Report));
 }
@@ -438,7 +439,8 @@ void PthreadLockChecker::InitLock(CheckerContext &C, const CallExpr *CE,
   ExplodedNode *N = C.generateErrorNode();
   if (!N)
     return;
-  auto Report = std::make_unique<BugReport>(*BT_initlock, Message, N);
+  auto Report =
+      std::make_unique<PathSensitiveBugReport>(*BT_initlock, Message, N);
   Report->addRange(CE->getArg(0)->getSourceRange());
   C.emitReport(std::move(Report));
 }
@@ -451,7 +453,7 @@ void PthreadLockChecker::reportUseDestroyedBug(CheckerContext &C,
   ExplodedNode *N = C.generateErrorNode();
   if (!N)
     return;
-  auto Report = std::make_unique<BugReport>(
+  auto Report = std::make_unique<PathSensitiveBugReport>(
       *BT_destroylock, "This lock has already been destroyed", N);
   Report->addRange(CE->getArg(0)->getSourceRange());
   C.emitReport(std::move(Report));
index f67fb7eea7cb9d587b210834a69804fc76329437..d3c60112ab74da708d307a204985ef514dbd9d8a 100644 (file)
@@ -327,11 +327,11 @@ public:
 
   PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                    BugReporterContext &BRC,
-                                   BugReport &BR) override;
+                                   PathSensitiveBugReport &BR) override;
 
   PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC,
                                     const ExplodedNode *N,
-                                    BugReport &BR) override;
+                                    PathSensitiveBugReport &BR) override;
 };
 
 class RefLeakReportVisitor : public RefCountReportVisitor {
@@ -340,7 +340,7 @@ public:
 
   PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC,
                                     const ExplodedNode *N,
-                                    BugReport &BR) override;
+                                    PathSensitiveBugReport &BR) override;
 };
 
 } // end namespace retaincountchecker
@@ -448,9 +448,9 @@ annotateStartParameter(const ExplodedNode *N, SymbolRef Sym,
   return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
 }
 
-PathDiagnosticPieceRef RefCountReportVisitor::VisitNode(const ExplodedNode *N,
-                                                        BugReporterContext &BRC,
-                                                        BugReport &BR) {
+PathDiagnosticPieceRef
+RefCountReportVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
+                                 PathSensitiveBugReport &BR) {
 
   const auto &BT = static_cast<const RefCountBug&>(BR.getBugType());
   const auto *Checker =
@@ -715,14 +715,16 @@ static AllocationInfo GetAllocationSite(ProgramStateManager &StateMgr,
 
 PathDiagnosticPieceRef
 RefCountReportVisitor::getEndPath(BugReporterContext &BRC,
-                                  const ExplodedNode *EndN, BugReport &BR) {
+                                  const ExplodedNode *EndN,
+                                  PathSensitiveBugReport &BR) {
   BR.markInteresting(Sym);
   return BugReporterVisitor::getDefaultEndPath(BRC, EndN, BR);
 }
 
 PathDiagnosticPieceRef
 RefLeakReportVisitor::getEndPath(BugReporterContext &BRC,
-                                 const ExplodedNode *EndN, BugReport &BR) {
+                                 const ExplodedNode *EndN,
+                                 PathSensitiveBugReport &BR) {
 
   // Tell the BugReporterContext to report cases when the tracked symbol is
   // assigned to different variables, etc.
@@ -736,13 +738,11 @@ RefLeakReportVisitor::getEndPath(BugReporterContext &BRC,
   const MemRegion* FirstBinding = AllocI.R;
   BR.markInteresting(AllocI.InterestingMethodContext);
 
-  const SourceManager& SM = BRC.getSourceManager();
-
   // Compute an actual location for the leak.  Sometimes a leak doesn't
   // occur at an actual statement (e.g., transition between blocks; end
   // of function) so we need to walk the graph and compute a real location.
   const ExplodedNode *LeakN = EndN;
-  PathDiagnosticLocation L = PathDiagnosticLocation::createEndOfPath(LeakN, SM);
+  PathDiagnosticLocation L = PathDiagnosticLocation::createEndOfPath(LeakN);
 
   std::string sbuf;
   llvm::raw_string_ostream os(sbuf);
@@ -813,9 +813,9 @@ RefLeakReportVisitor::getEndPath(BugReporterContext &BRC,
 }
 
 RefCountReport::RefCountReport(const RefCountBug &D, const LangOptions &LOpts,
-                               ExplodedNode *n, SymbolRef sym,
-                               bool isLeak)
-    : BugReport(D, D.getDescription(), n), Sym(sym), isLeak(isLeak) {
+                               ExplodedNode *n, SymbolRef sym, bool isLeak)
+    : PathSensitiveBugReport(D, D.getDescription(), n), Sym(sym),
+      isLeak(isLeak) {
   if (!isLeak)
     addVisitor(std::make_unique<RefCountReportVisitor>(sym));
 }
@@ -823,7 +823,7 @@ RefCountReport::RefCountReport(const RefCountBug &D, const LangOptions &LOpts,
 RefCountReport::RefCountReport(const RefCountBug &D, const LangOptions &LOpts,
                                ExplodedNode *n, SymbolRef sym,
                                StringRef endText)
-    : BugReport(D, D.getDescription(), endText, n) {
+    : PathSensitiveBugReport(D, D.getDescription(), endText, n) {
 
   addVisitor(std::make_unique<RefCountReportVisitor>(sym));
 }
index 6e2a613aed629da48726d2c736358f7829166c67..323b50ad9f0487d729b72d92dd6dea8c9aa397c4 100644 (file)
@@ -53,7 +53,7 @@ private:
   static StringRef bugTypeToName(RefCountBugType BT);
 };
 
-class RefCountReport : public BugReport {
+class RefCountReport : public PathSensitiveBugReport {
 protected:
   SymbolRef Sym;
   bool isLeak = false;
@@ -67,16 +67,17 @@ public:
               ExplodedNode *n, SymbolRef sym,
               StringRef endText);
 
-  llvm::iterator_range<ranges_iterator> getRanges() const override {
+  ArrayRef<SourceRange> getRanges() const override {
     if (!isLeak)
-      return BugReport::getRanges();
-    return llvm::make_range(ranges_iterator(), ranges_iterator());
+      return PathSensitiveBugReport::getRanges();
+    return {};
   }
 };
 
 class RefLeakReport : public RefCountReport {
   const MemRegion* AllocBinding;
   const Stmt *AllocStmt;
+  PathDiagnosticLocation Location;
 
   // Finds the function declaration where a leak warning for the parameter
   // 'sym' should be raised.
@@ -90,7 +91,7 @@ public:
   RefLeakReport(const RefCountBug &D, const LangOptions &LOpts, ExplodedNode *n,
                 SymbolRef sym, CheckerContext &Ctx);
 
-  PathDiagnosticLocation getLocation(const SourceManager &SM) const override {
+  PathDiagnosticLocation getLocation() const override {
     assert(Location.isValid());
     return Location;
   }
index 46266b33efd9cbc9082e1db04993b37766605788..abd1a074b487172de04ff065f1ae091f3455563a 100644 (file)
@@ -79,7 +79,8 @@ void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS,
     // reference is outside the range.
 
     // Generate a report for this bug.
-    auto report = std::make_unique<BugReport>(*BT, BT->getDescription(), N);
+    auto report =
+        std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N);
 
     report->addRange(RetE->getSourceRange());
     C.emitReport(std::move(report));
index f1d2d96c2465684146262efb9035daef80f12eb5..fbd15d864424eab37da585167cd8c9498a368ff3 100644 (file)
@@ -83,7 +83,8 @@ static void emitBug(CheckerContext &C, BuiltinBug &BT, const Expr *RetE,
   if (!N)
     return;
 
-  auto Report = std::make_unique<BugReport>(BT, BT.getDescription(), N);
+  auto Report =
+      std::make_unique<PathSensitiveBugReport>(BT, BT.getDescription(), N);
 
   Report->addRange(RetE->getSourceRange());
   bugreporter::trackExpressionValue(N, TrackingE ? TrackingE : RetE, *Report);
index cb48791a1ae0bc3dd7e0f7bf679776e29a06158c..8193bcbef4cdfaa919f9d0a76cf539f12a1bef55 100644 (file)
@@ -206,8 +206,8 @@ void SimpleStreamChecker::reportDoubleClose(SymbolRef FileDescSym,
     return;
 
   // Generate the report.
-  auto R = std::make_unique<BugReport>(*DoubleCloseBugType,
-      "Closing a previously closed file stream", ErrNode);
+  auto R = std::make_unique<PathSensitiveBugReport>(
+      *DoubleCloseBugType, "Closing a previously closed file stream", ErrNode);
   R->addRange(Call.getSourceRange());
   R->markInteresting(FileDescSym);
   C.emitReport(std::move(R));
@@ -219,8 +219,9 @@ void SimpleStreamChecker::reportLeaks(ArrayRef<SymbolRef> LeakedStreams,
   // Attach bug reports to the leak node.
   // TODO: Identify the leaked file descriptor.
   for (SymbolRef LeakedStream : LeakedStreams) {
-    auto R = std::make_unique<BugReport>(*LeakBugType,
-        "Opened file is never closed; potential resource leak", ErrNode);
+    auto R = std::make_unique<PathSensitiveBugReport>(
+        *LeakBugType, "Opened file is never closed; potential resource leak",
+        ErrNode);
     R->markInteresting(LeakedStream);
     C.emitReport(std::move(R));
   }
index c4376c584f11fb0cccaf34e8e42603a19885905e..7285d27495a7c1ab39a4611b30bb238a0d35f780 100644 (file)
@@ -162,7 +162,8 @@ void StackAddrEscapeChecker::EmitStackError(CheckerContext &C,
   llvm::raw_svector_ostream os(buf);
   SourceRange range = genName(os, R, C.getASTContext());
   os << " returned to caller";
-  auto report = std::make_unique<BugReport>(*BT_returnstack, os.str(), N);
+  auto report =
+      std::make_unique<PathSensitiveBugReport>(*BT_returnstack, os.str(), N);
   report->addRange(RetE->getSourceRange());
   if (range.isValid())
     report->addRange(range);
@@ -199,8 +200,8 @@ void StackAddrEscapeChecker::checkAsyncExecutedBlockCaptures(
     llvm::raw_svector_ostream Out(Buf);
     SourceRange Range = genName(Out, Region, C.getASTContext());
     Out << " is captured by an asynchronously-executed block";
-    auto Report =
-        std::make_unique<BugReport>(*BT_capturedstackasync, Out.str(), N);
+    auto Report = std::make_unique<PathSensitiveBugReport>(
+        *BT_capturedstackasync, Out.str(), N);
     if (Range.isValid())
       Report->addRange(Range);
     C.emitReport(std::move(Report));
@@ -222,8 +223,8 @@ void StackAddrEscapeChecker::checkReturnedBlockCaptures(
     llvm::raw_svector_ostream Out(Buf);
     SourceRange Range = genName(Out, Region, C.getASTContext());
     Out << " is captured by a returned block";
-    auto Report =
-        std::make_unique<BugReport>(*BT_capturedstackret, Out.str(), N);
+    auto Report = std::make_unique<PathSensitiveBugReport>(*BT_capturedstackret,
+                                                           Out.str(), N);
     if (Range.isValid())
       Report->addRange(Range);
     C.emitReport(std::move(Report));
@@ -351,7 +352,8 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
     const VarRegion *VR = cast<VarRegion>(P.first->getBaseRegion());
     Out << *VR->getDecl()
         << "' upon returning to the caller.  This will be a dangling reference";
-    auto Report = std::make_unique<BugReport>(*BT_stackleak, Out.str(), N);
+    auto Report =
+        std::make_unique<PathSensitiveBugReport>(*BT_stackleak, Out.str(), N);
     if (Range.isValid())
       Report->addRange(Range);
 
index 377a03d19307b996801e25c8617530676a0f9149..c254408351c810be9661dcaf6e47b00cda73f81c 100644 (file)
@@ -277,7 +277,7 @@ void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) const {
           new BuiltinBug(this, "Illegal whence argument",
                          "The whence argument to fseek() should be "
                          "SEEK_SET, SEEK_END, or SEEK_CUR."));
-    C.emitReport(std::make_unique<BugReport>(
+    C.emitReport(std::make_unique<PathSensitiveBugReport>(
         *BT_illegalwhence, BT_illegalwhence->getDescription(), N));
   }
 }
@@ -345,7 +345,7 @@ ProgramStateRef StreamChecker::CheckNullStream(SVal SV, ProgramStateRef state,
       if (!BT_nullfp)
         BT_nullfp.reset(new BuiltinBug(this, "NULL stream pointer",
                                        "Stream pointer might be NULL."));
-      C.emitReport(std::make_unique<BugReport>(
+      C.emitReport(std::make_unique<PathSensitiveBugReport>(
           *BT_nullfp, BT_nullfp->getDescription(), N));
     }
     return nullptr;
@@ -375,7 +375,7 @@ ProgramStateRef StreamChecker::CheckDoubleClose(const CallExpr *CE,
         BT_doubleclose.reset(new BuiltinBug(
             this, "Double fclose", "Try to close a file Descriptor already"
                                    " closed. Cause undefined behaviour."));
-      C.emitReport(std::make_unique<BugReport>(
+      C.emitReport(std::make_unique<PathSensitiveBugReport>(
           *BT_doubleclose, BT_doubleclose->getDescription(), N));
     }
     return nullptr;
@@ -405,7 +405,7 @@ void StreamChecker::checkDeadSymbols(SymbolReaper &SymReaper,
       BT_ResourceLeak.reset(
           new BuiltinBug(this, "Resource Leak",
                          "Opened File never closed. Potential Resource leak."));
-    C.emitReport(std::make_unique<BugReport>(
+    C.emitReport(std::make_unique<PathSensitiveBugReport>(
         *BT_ResourceLeak, BT_ResourceLeak->getDescription(), N));
   }
 }
index cd8cab8f52e40ca682530fddb9c91791132b568d..2a9456dd84d5bbf8f4f4e165d6ccce2bea06afc6 100644 (file)
@@ -206,7 +206,7 @@ bool taint::isTainted(ProgramStateRef State, SymbolRef Sym, TaintTagType Kind) {
 
 PathDiagnosticPieceRef TaintBugVisitor::VisitNode(const ExplodedNode *N,
                                                   BugReporterContext &BRC,
-                                                  BugReport &BR) {
+                                                  PathSensitiveBugReport &BR) {
 
   // Find the ExplodedNode where the taint was first introduced
   if (!isTainted(N->getState(), V) ||
index 2c3b001b5f0a069b0dab173726353161b793a24b..8940916c19331e0e0a06f6fcc3b6e31a92091e25 100644 (file)
@@ -91,7 +91,7 @@ public:
 
   PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                    BugReporterContext &BRC,
-                                   BugReport &BR) override;
+                                   PathSensitiveBugReport &BR) override;
 };
 
 } // namespace taint
index 9aeb4ea94349335e69fb4ae9deb51f401663c3b2..f81705304f3abdf04ed3aff99825a3a03b0d446d 100644 (file)
@@ -52,7 +52,7 @@ void TaintTesterChecker::checkPostStmt(const Expr *E,
   if (isTainted(State, E, C.getLocationContext())) {
     if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
       initBugType();
-      auto report = std::make_unique<BugReport>(*BT, "tainted",N);
+      auto report = std::make_unique<PathSensitiveBugReport>(*BT, "tainted", N);
       report->addRange(E->getSourceRange());
       C.emitReport(std::move(report));
     }
index 79c55647734f1bdb5cce2b7dd04fa4aea900f6d7..3663b09636924849b67a28d08facafba1c780def 100644 (file)
@@ -71,7 +71,7 @@ public:
 
   PathDiagnosticPieceRef VisitNode(const ExplodedNode *Succ,
                                    BugReporterContext &BRC,
-                                   BugReport &BR) override;
+                                   PathSensitiveBugReport &BR) override;
 };
 
 class TestAfterDivZeroChecker
@@ -92,9 +92,9 @@ public:
 
 REGISTER_SET_WITH_PROGRAMSTATE(DivZeroMap, ZeroState)
 
-PathDiagnosticPieceRef DivisionBRVisitor::VisitNode(const ExplodedNode *Succ,
-                                                    BugReporterContext &BRC,
-                                                    BugReport &BR) {
+PathDiagnosticPieceRef
+DivisionBRVisitor::VisitNode(const ExplodedNode *Succ, BugReporterContext &BRC,
+                             PathSensitiveBugReport &BR) {
   if (Satisfied)
     return nullptr;
 
@@ -167,7 +167,7 @@ void TestAfterDivZeroChecker::reportBug(SVal Val, CheckerContext &C) const {
     if (!DivZeroBug)
       DivZeroBug.reset(new BuiltinBug(this, "Division by zero"));
 
-    auto R = std::make_unique<BugReport>(
+    auto R = std::make_unique<PathSensitiveBugReport>(
         *DivZeroBug, "Value being compared against zero has already been used "
                      "for division",
         N);
index 00044c160298832ba9263437a09e25a14d8d1325..247cba7dc9333f593d4272596160550970077a89 100644 (file)
@@ -96,7 +96,8 @@ void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
       Ex = FindIt.FindExpr(Ex);
 
       // Emit the bug report.
-      auto R = std::make_unique<BugReport>(*BT, BT->getDescription(), N);
+      auto R = std::make_unique<PathSensitiveBugReport>(
+          *BT, BT->getDescription(), N);
       bugreporter::trackExpressionValue(N, Ex, *R);
       R->addRange(Ex->getSourceRange());
 
index 79a9a16eccb02960bf1e0f6a2e52ee5a38bb112f..7b581bef39001fb0bf803317761e431640e7bee8 100644 (file)
@@ -83,7 +83,7 @@ UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE,
         os << "Variable '" << VD->getName()
            << "' is uninitialized when captured by block";
 
-        auto R = std::make_unique<BugReport>(*BT, os.str(), N);
+        auto R = std::make_unique<PathSensitiveBugReport>(*BT, os.str(), N);
         if (const Expr *Ex = FindBlockDeclRefExpr(BE->getBody(), VD))
           R->addRange(Ex->getSourceRange());
         R->addVisitor(std::make_unique<FindLastStoreBRVisitor>(
index 962e76651432495a19b7b2c2aa4ce91eefa8949b..a2f3e0da13fb06b5702f1944277469c6eb4f7c0a 100644 (file)
@@ -170,7 +170,7 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B,
            << "' expression is undefined";
       }
     }
-    auto report = std::make_unique<BugReport>(*BT, OS.str(), N);
+    auto report = std::make_unique<PathSensitiveBugReport>(*BT, OS.str(), N);
     if (Ex) {
       report->addRange(Ex->getSourceRange());
       bugreporter::trackExpressionValue(N, Ex, *report);
index 6e7cf89e4f9dcf1dd9bbc4e018bd633fa48383c3..0cd1c3f16fd840627002bea577faee5d6a24a21d 100644 (file)
@@ -52,7 +52,7 @@ UndefinedArraySubscriptChecker::checkPreStmt(const ArraySubscriptExpr *A,
     BT.reset(new BuiltinBug(this, "Array subscript is undefined"));
 
   // Generate a report for this bug.
-  auto R = std::make_unique<BugReport>(*BT, BT->getName(), N);
+  auto R = std::make_unique<PathSensitiveBugReport>(*BT, BT->getName(), N);
   R->addRange(A->getIdx()->getSourceRange());
   bugreporter::trackExpressionValue(N, A->getIdx(), *R);
   C.emitReport(std::move(R));
index f06d6b8c7175673132c434eb74ba3366c6cc402e..277a8a143328285dc2cac6c67f95eb67e1776a57 100644 (file)
@@ -108,7 +108,7 @@ void UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
   if (OS.str().empty())
     OS << DefaultMsg;
 
-  auto R = std::make_unique<BugReport>(*BT, OS.str(), N);
+  auto R = std::make_unique<PathSensitiveBugReport>(*BT, OS.str(), N);
   if (ex) {
     R->addRange(ex->getSourceRange());
     bugreporter::trackExpressionValue(N, ex, *R);
index de8c13605edd61d996eaf82ec4bfc17a9072c723..020df8a1bb8c779a324bea82c2ed0875d8e1948c 100644 (file)
@@ -187,7 +187,7 @@ void UninitializedObjectChecker::checkEndFunction(
   if (Opts.ShouldConvertNotesToWarnings) {
     for (const auto &Pair : UninitFields) {
 
-      auto Report = std::make_unique<BugReport>(
+      auto Report = std::make_unique<PathSensitiveBugReport>(
           *BT_uninitField, Pair.second, Node, LocUsedForUniqueing,
           Node->getLocationContext()->getDecl());
       Context.emitReport(std::move(Report));
@@ -201,7 +201,7 @@ void UninitializedObjectChecker::checkEndFunction(
             << (UninitFields.size() == 1 ? "" : "s")
             << " at the end of the constructor call";
 
-  auto Report = std::make_unique<BugReport>(
+  auto Report = std::make_unique<PathSensitiveBugReport>(
       *BT_uninitField, WarningOS.str(), Node, LocUsedForUniqueing,
       Node->getLocationContext()->getDecl());
 
index 16cc5807d3cdc67de6abbe0962d8a1e01e7033f1..f4e225d836f38b8887d3b40649a7254e6cdd6b34 100644 (file)
@@ -135,7 +135,7 @@ void UnixAPIMisuseChecker::ReportOpenBug(CheckerContext &C,
 
   LazyInitialize(this, BT_open, "Improper use of 'open'");
 
-  auto Report = std::make_unique<BugReport>(*BT_open, Msg, N);
+  auto Report = std::make_unique<PathSensitiveBugReport>(*BT_open, Msg, N);
   Report->addRange(SR);
   C.emitReport(std::move(Report));
 }
@@ -304,7 +304,8 @@ void UnixAPIMisuseChecker::CheckPthreadOnce(CheckerContext &C,
 
   LazyInitialize(this, BT_pthreadOnce, "Improper use of 'pthread_once'");
 
-  auto report = std::make_unique<BugReport>(*BT_pthreadOnce, os.str(), N);
+  auto report =
+      std::make_unique<PathSensitiveBugReport>(*BT_pthreadOnce, os.str(), N);
   report->addRange(CE->getArg(0)->getSourceRange());
   C.emitReport(std::move(report));
 }
@@ -347,7 +348,8 @@ bool UnixAPIPortabilityChecker::ReportZeroByteAllocation(
   SmallString<256> S;
   llvm::raw_svector_ostream os(S);
   os << "Call to '" << fn_name << "' has an allocation size of 0 bytes";
-  auto report = std::make_unique<BugReport>(*BT_mallocZero, os.str(), N);
+  auto report =
+      std::make_unique<PathSensitiveBugReport>(*BT_mallocZero, os.str(), N);
 
   report->addRange(arg->getSourceRange());
   bugreporter::trackExpressionValue(N, arg, *report);
index 36da59940c060fc1ab7ddd0d4698ef54ac3f2053..b92757312dc65864e9c3dc7d554b422a3a564723 100644 (file)
@@ -72,7 +72,7 @@ void VLASizeChecker::reportBug(
     break;
   }
 
-  auto report = std::make_unique<BugReport>(*BT, os.str(), N);
+  auto report = std::make_unique<PathSensitiveBugReport>(*BT, os.str(), N);
   report->addVisitor(std::move(Visitor));
   report->addRange(SizeE->getSourceRange());
   bugreporter::trackExpressionValue(N, SizeE, *report);
index 9f3b16a5a34b170d95b462bfb8ee7bc7fa739328..ca0091205e242ea16713456095083776f6137782 100644 (file)
@@ -79,19 +79,19 @@ private:
     }
     PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC,
                                       const ExplodedNode *EndPathNode,
-                                      BugReport &BR) override {
+                                      PathSensitiveBugReport &BR) override {
       if (!IsLeak)
         return nullptr;
 
-      PathDiagnosticLocation L = PathDiagnosticLocation::createEndOfPath(
-          EndPathNode, BRC.getSourceManager());
+      PathDiagnosticLocation L =
+          PathDiagnosticLocation::createEndOfPath(EndPathNode);
       // Do not add the statement itself as a range in case of leak.
       return std::make_shared<PathDiagnosticEventPiece>(L, BR.getDescription(),
                                                         false);
     }
     PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                      BugReporterContext &BRC,
-                                     BugReport &BR) override;
+                                     PathSensitiveBugReport &BR) override;
 
   private:
     const MemRegion *Reg;
@@ -256,7 +256,7 @@ void ValistChecker::reportUninitializedAccess(const MemRegion *VAList,
       BT_uninitaccess.reset(new BugType(CheckNames[CK_Uninitialized],
                                         "Uninitialized va_list",
                                         categories::MemoryError));
-    auto R = std::make_unique<BugReport>(*BT_uninitaccess, Msg, N);
+    auto R = std::make_unique<PathSensitiveBugReport>(*BT_uninitaccess, Msg, N);
     R->markInteresting(VAList);
     R->addVisitor(std::make_unique<ValistBugVisitor>(VAList));
     C.emitReport(std::move(R));
@@ -297,7 +297,7 @@ void ValistChecker::reportLeakedVALists(const RegionVector &LeakedVALists,
       OS << " " << VariableName;
     OS << Msg2;
 
-    auto R = std::make_unique<BugReport>(
+    auto R = std::make_unique<PathSensitiveBugReport>(
         *BT_leakedvalist, OS.str(), N, LocUsedForUniqueing,
         StartNode->getLocationContext()->getDecl());
     R->markInteresting(Reg);
@@ -377,7 +377,7 @@ void ValistChecker::checkVAListEndCall(const CallEvent &Call,
 }
 
 PathDiagnosticPieceRef ValistChecker::ValistBugVisitor::VisitNode(
-    const ExplodedNode *N, BugReporterContext &BRC, BugReport &) {
+    const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &) {
   ProgramStateRef State = N->getState();
   ProgramStateRef StatePrev = N->getFirstPred()->getState();
 
index 2a54cef177f1bc566e64009f57a23010bfa9225c..6724eead5072004c1008fab167e64621c506b220 100644 (file)
@@ -132,7 +132,7 @@ void VforkChecker::reportBug(const char *What, CheckerContext &C,
     if (Details)
       os << "; " << Details;
 
-    auto Report = std::make_unique<BugReport>(*BT, os.str(), N);
+    auto Report = std::make_unique<PathSensitiveBugReport>(*BT, os.str(), N);
     // TODO: mark vfork call in BugReportVisitor
     C.emitReport(std::move(Report));
   }
index a210128bab7a9c21b3c19021caee9fe73bd8dd14..3d0630e8031fcadab59b8b876a2c93636804a9c9 100644 (file)
@@ -146,7 +146,7 @@ void VirtualCallChecker::checkPreCall(const CallEvent &Call,
     return;
   }
 
-  auto Report = std::make_unique<BugReport>(*BT, OS.str(), N);
+  auto Report = std::make_unique<PathSensitiveBugReport>(*BT, OS.str(), N);
 
   if (ShowFixIts && !IsPure) {
     // FIXME: These hints are valid only when the virtual call is made
index f5d747c7fdde6c62fb82556c48209cda01c5f826..331d7379577a4877e2baae66b2bdf3dd183da90c 100644 (file)
@@ -71,6 +71,7 @@
 
 using namespace clang;
 using namespace ento;
+using namespace llvm;
 
 #define DEBUG_TYPE "BugReporter"
 
@@ -131,7 +132,8 @@ public:
 
 public:
   PathDiagnosticConstruct(const PathDiagnosticConsumer *PDC,
-                          const ExplodedNode *ErrorNode, const BugReport *R);
+                          const ExplodedNode *ErrorNode,
+                          const PathSensitiveBugReport *R);
 
   /// \returns the location context associated with the current position in the
   /// bug path.
@@ -202,7 +204,7 @@ class PathDiagnosticBuilder : public BugReporterContext {
   /// them being the last entities being able to modify it (for example,
   /// changing interestingness here would cause inconsistencies as to how this
   /// file and visitors construct diagnostics), hence its const.
-  const BugReport *R;
+  const PathSensitiveBugReport *R;
   /// The leaf of the bug path. This isn't the same as the bug reports error
   /// node, which refers to the *original* graph, not the bug path.
   const ExplodedNode *const ErrorNode;
@@ -215,12 +217,12 @@ public:
   /// a PathDiagnosticBuilder able to construct bug reports for different
   /// consumers. Returns None if no valid report is found.
   static Optional<PathDiagnosticBuilder>
-  findValidReport(ArrayRef<BugReport *> &bugReports,
+  findValidReport(ArrayRef<PathSensitiveBugReport *> &bugReports,
                   PathSensitiveBugReporter &Reporter);
 
   PathDiagnosticBuilder(
       BugReporterContext BRC, std::unique_ptr<ExplodedGraph> BugPath,
-      BugReport *r, const ExplodedNode *ErrorNode,
+      PathSensitiveBugReport *r, const ExplodedNode *ErrorNode,
       std::unique_ptr<VisitorsDiagnosticsTy> VisitorsDiagnostics);
 
   /// This function is responsible for generating diagnostic pieces that are
@@ -262,7 +264,7 @@ private:
   ExecutionContinues(llvm::raw_string_ostream &os,
                      const PathDiagnosticConstruct &C) const;
 
-  const BugReport *getBugReport() const { return R; }
+  const PathSensitiveBugReport *getBugReport() const { return R; }
 };
 
 } // namespace
@@ -369,7 +371,8 @@ static void removeRedundantMsgs(PathPieces &path) {
 /// that aren't needed.  Return true if afterwards the path contains
 /// "interesting stuff" which means it shouldn't be pruned from the parent path.
 static bool removeUnneededCalls(const PathDiagnosticConstruct &C,
-                                PathPieces &pieces, const BugReport *R,
+                                PathPieces &pieces,
+                                const PathSensitiveBugReport *R,
                                 bool IsInteresting = false) {
   bool containsSomethingInteresting = IsInteresting;
   const unsigned N = pieces.size();
@@ -1263,13 +1266,23 @@ void PathDiagnosticBuilder::generatePathDiagnosticsForNode(
 }
 
 static std::unique_ptr<PathDiagnostic>
-generateEmptyDiagnosticForReport(const BugReport *R, const SourceManager &SM) {
+generateDiagnosticForBasicReport(const BasicBugReport *R) {
   const BugType &BT = R->getBugType();
   return std::make_unique<PathDiagnostic>(
-      R->getBugType().getCheckName(), R->getDeclWithIssue(),
-      R->getBugType().getName(), R->getDescription(),
-      R->getShortDescription(/*UseFallback=*/false), BT.getCategory(),
-      R->getUniqueingLocation(), R->getUniqueingDecl(),
+      BT.getCheckName(), R->getDeclWithIssue(), BT.getName(),
+      R->getDescription(), R->getShortDescription(/*UseFallback=*/false),
+      BT.getCategory(), R->getUniqueingLocation(), R->getUniqueingDecl(),
+      std::make_unique<FilesToLineNumsMap>());
+}
+
+static std::unique_ptr<PathDiagnostic>
+generateEmptyDiagnosticForReport(const PathSensitiveBugReport *R,
+                                 const SourceManager &SM) {
+  const BugType &BT = R->getBugType();
+  return std::make_unique<PathDiagnostic>(
+      BT.getCheckName(), R->getDeclWithIssue(), BT.getName(),
+      R->getDescription(), R->getShortDescription(/*UseFallback=*/false),
+      BT.getCategory(), R->getUniqueingLocation(), R->getUniqueingDecl(),
       findExecutedLines(SM, R->getErrorNode()));
 }
 
@@ -1909,7 +1922,7 @@ static void updateExecutedLinesWithDiagnosticPieces(PathDiagnostic &PD) {
 
 PathDiagnosticConstruct::PathDiagnosticConstruct(
     const PathDiagnosticConsumer *PDC, const ExplodedNode *ErrorNode,
-    const BugReport *R)
+    const PathSensitiveBugReport *R)
     : Consumer(PDC), CurrentNode(ErrorNode),
       SM(CurrentNode->getCodeDecl().getASTContext().getSourceManager()),
       PD(generateEmptyDiagnosticForReport(R, getSourceManager())) {
@@ -1918,7 +1931,7 @@ PathDiagnosticConstruct::PathDiagnosticConstruct(
 
 PathDiagnosticBuilder::PathDiagnosticBuilder(
     BugReporterContext BRC, std::unique_ptr<ExplodedGraph> BugPath,
-    BugReport *r, const ExplodedNode *ErrorNode,
+    PathSensitiveBugReport *r, const ExplodedNode *ErrorNode,
     std::unique_ptr<VisitorsDiagnosticsTy> VisitorsDiagnostics)
     : BugReporterContext(BRC), BugPath(std::move(BugPath)), R(r),
       ErrorNode(ErrorNode),
@@ -1929,7 +1942,6 @@ PathDiagnosticBuilder::generate(const PathDiagnosticConsumer *PDC) const {
   PathDiagnosticConstruct Construct(PDC, ErrorNode, R);
 
   const SourceManager &SM = getSourceManager();
-  const BugReport *R = getBugReport();
   const AnalyzerOptions &Opts = getAnalyzerOptions();
   StringRef ErrorTag = ErrorNode->getLocation().getTag()->getTagDescription();
 
@@ -2050,7 +2062,8 @@ void BuiltinBug::anchor() {}
 // Methods for BugReport and subclasses.
 //===----------------------------------------------------------------------===//
 
-void BugReport::addVisitor(std::unique_ptr<BugReporterVisitor> visitor) {
+void PathSensitiveBugReport::addVisitor(
+    std::unique_ptr<BugReporterVisitor> visitor) {
   if (!visitor)
     return;
 
@@ -2065,14 +2078,11 @@ void BugReport::addVisitor(std::unique_ptr<BugReporterVisitor> visitor) {
   Callbacks.push_back(std::move(visitor));
 }
 
-void BugReport::clearVisitors() {
+void PathSensitiveBugReport::clearVisitors() {
   Callbacks.clear();
 }
 
-const Decl *BugReport::getDeclWithIssue() const {
-  if (DeclWithIssue)
-    return DeclWithIssue;
-
+const Decl *PathSensitiveBugReport::getDeclWithIssue() const {
   const ExplodedNode *N = getErrorNode();
   if (!N)
     return nullptr;
@@ -2081,14 +2091,28 @@ const Decl *BugReport::getDeclWithIssue() const {
   return LC->getStackFrame()->getDecl();
 }
 
-void BugReport::Profile(llvm::FoldingSetNodeID& hash) const {
+void BasicBugReport::Profile(llvm::FoldingSetNodeID& hash) const {
+  hash.AddInteger(static_cast<int>(getKind()));
+  hash.AddPointer(&BT);
+  hash.AddString(Description);
+  assert(Location.isValid());
+  Location.Profile(hash);
+
+  for (SourceRange range : Ranges) {
+    if (!range.isValid())
+      continue;
+    hash.AddInteger(range.getBegin().getRawEncoding());
+    hash.AddInteger(range.getEnd().getRawEncoding());
+  }
+}
+
+void PathSensitiveBugReport::Profile(llvm::FoldingSetNodeID &hash) const {
+  hash.AddInteger(static_cast<int>(getKind()));
   hash.AddPointer(&BT);
   hash.AddString(Description);
   PathDiagnosticLocation UL = getUniqueingLocation();
   if (UL.isValid()) {
     UL.Profile(hash);
-  } else if (Location.isValid()) {
-    Location.Profile(hash);
   } else {
     assert(ErrorNode);
     hash.AddPointer(GetCurrentOrPreviousStmt(ErrorNode));
@@ -2131,8 +2155,8 @@ static void insertToInterestingnessMap(
       "have, if it was already marked as interesting with a different kind!");
 }
 
-void BugReport::markInteresting(SymbolRef sym,
-                                bugreporter::TrackingKind TKind) {
+void PathSensitiveBugReport::markInteresting(SymbolRef sym,
+                                             bugreporter::TrackingKind TKind) {
   if (!sym)
     return;
 
@@ -2142,8 +2166,8 @@ void BugReport::markInteresting(SymbolRef sym,
     markInteresting(meta->getRegion(), TKind);
 }
 
-void BugReport::markInteresting(const MemRegion *R,
-                                bugreporter::TrackingKind TKind) {
+void PathSensitiveBugReport::markInteresting(const MemRegion *R,
+                                             bugreporter::TrackingKind TKind) {
   if (!R)
     return;
 
@@ -2154,19 +2178,20 @@ void BugReport::markInteresting(const MemRegion *R,
     markInteresting(SR->getSymbol(), TKind);
 }
 
-void BugReport::markInteresting(SVal V, bugreporter::TrackingKind TKind) {
+void PathSensitiveBugReport::markInteresting(SVal V,
+                                             bugreporter::TrackingKind TKind) {
   markInteresting(V.getAsRegion(), TKind);
   markInteresting(V.getAsSymbol(), TKind);
 }
 
-void BugReport::markInteresting(const LocationContext *LC) {
+void PathSensitiveBugReport::markInteresting(const LocationContext *LC) {
   if (!LC)
     return;
   InterestingLocationContexts.insert(LC);
 }
 
 Optional<bugreporter::TrackingKind>
-BugReport::getInterestingnessKind(SVal V) const {
+PathSensitiveBugReport::getInterestingnessKind(SVal V) const {
   auto RKind = getInterestingnessKind(V.getAsRegion());
   auto SKind = getInterestingnessKind(V.getAsSymbol());
   if (!RKind)
@@ -2191,7 +2216,7 @@ BugReport::getInterestingnessKind(SVal V) const {
 }
 
 Optional<bugreporter::TrackingKind>
-BugReport::getInterestingnessKind(SymbolRef sym) const {
+PathSensitiveBugReport::getInterestingnessKind(SymbolRef sym) const {
   if (!sym)
     return None;
   // We don't currently consider metadata symbols to be interesting
@@ -2203,7 +2228,7 @@ BugReport::getInterestingnessKind(SymbolRef sym) const {
 }
 
 Optional<bugreporter::TrackingKind>
-BugReport::getInterestingnessKind(const MemRegion *R) const {
+PathSensitiveBugReport::getInterestingnessKind(const MemRegion *R) const {
   if (!R)
     return None;
 
@@ -2217,25 +2242,25 @@ BugReport::getInterestingnessKind(const MemRegion *R) const {
   return None;
 }
 
-bool BugReport::isInteresting(SVal V) const {
+bool PathSensitiveBugReport::isInteresting(SVal V) const {
   return getInterestingnessKind(V).hasValue();
 }
 
-bool BugReport::isInteresting(SymbolRef sym) const {
+bool PathSensitiveBugReport::isInteresting(SymbolRef sym) const {
   return getInterestingnessKind(sym).hasValue();
 }
 
-bool BugReport::isInteresting(const MemRegion *R) const {
+bool PathSensitiveBugReport::isInteresting(const MemRegion *R) const {
   return getInterestingnessKind(R).hasValue();
 }
 
-bool BugReport::isInteresting(const LocationContext *LC)  const {
+bool PathSensitiveBugReport::isInteresting(const LocationContext *LC)  const {
   if (!LC)
     return false;
   return InterestingLocationContexts.count(LC);
 }
 
-const Stmt *BugReport::getStmt() const {
+const Stmt *PathSensitiveBugReport::getStmt() const {
   if (!ErrorNode)
     return nullptr;
 
@@ -2253,31 +2278,19 @@ const Stmt *BugReport::getStmt() const {
   return S;
 }
 
-llvm::iterator_range<BugReport::ranges_iterator> BugReport::getRanges() const {
+ArrayRef<SourceRange>
+PathSensitiveBugReport::getRanges() const {
   // If no custom ranges, add the range of the statement corresponding to
   // the error node.
-  if (Ranges.empty()) {
-    if (dyn_cast_or_null<Expr>(getStmt()))
-      return llvm::make_range(&ErrorNodeRange, &ErrorNodeRange + 1);
-    return llvm::make_range(ranges_iterator(), ranges_iterator());
-  }
+  if (Ranges.empty() && isa_and_nonnull<Expr>(getStmt()))
+      return ErrorNodeRange;
 
-  // User-specified absence of range info.
-  if (Ranges.size() == 1 && !Ranges.begin()->isValid())
-    return llvm::make_range(ranges_iterator(), ranges_iterator());
-
-  return llvm::make_range(Ranges.begin(), Ranges.end());
+  return Ranges;
 }
 
-PathDiagnosticLocation BugReport::getLocation(const SourceManager &SM) const {
-  if (ErrorNode) {
-    assert(!Location.isValid() &&
-     "Either Location or ErrorNode should be specified but not both.");
-    return PathDiagnosticLocation::createEndOfPath(ErrorNode, SM);
-  }
-
-  assert(Location.isValid());
-  return Location;
+PathDiagnosticLocation
+PathSensitiveBugReport::getLocation() const {
+  return PathDiagnosticLocation::createEndOfPath(ErrorNode);
 }
 
 //===----------------------------------------------------------------------===//
@@ -2326,7 +2339,7 @@ namespace {
 class BugPathInfo {
 public:
   std::unique_ptr<ExplodedGraph> BugPath;
-  BugReport *Report;
+  PathSensitiveBugReport *Report;
   const ExplodedNode *ErrorNode;
 };
 
@@ -2342,7 +2355,8 @@ class BugPathGetter {
 
   /// Since the getErrorNode() or BugReport refers to the original ExplodedGraph,
   /// we need to pair it to the error node of the constructed trimmed graph.
-  using ReportNewNodePair = std::pair<BugReport *, const ExplodedNode *>;
+  using ReportNewNodePair =
+      std::pair<PathSensitiveBugReport *, const ExplodedNode *>;
   SmallVector<ReportNewNodePair, 32> ReportNodes;
 
   BugPathInfo CurrentBugPath;
@@ -2377,7 +2391,7 @@ class BugPathGetter {
 
 public:
   BugPathGetter(const ExplodedGraph *OriginalGraph,
-                ArrayRef<BugReport *> &bugReports);
+                ArrayRef<PathSensitiveBugReport *> &bugReports);
 
   BugPathInfo *getNextBugPath();
 };
@@ -2385,7 +2399,7 @@ public:
 } // namespace
 
 BugPathGetter::BugPathGetter(const ExplodedGraph *OriginalGraph,
-                             ArrayRef<BugReport *> &bugReports) {
+                             ArrayRef<PathSensitiveBugReport *> &bugReports) {
   SmallVector<const ExplodedNode *, 32> Nodes;
   for (const auto I : bugReports) {
     assert(I->isValid() &&
@@ -2404,7 +2418,7 @@ BugPathGetter::BugPathGetter(const ExplodedGraph *OriginalGraph,
   // in the new graph.
   llvm::SmallPtrSet<const ExplodedNode *, 32> RemainingNodes;
 
-  for (BugReport *Report : bugReports) {
+  for (PathSensitiveBugReport *Report : bugReports) {
     const ExplodedNode *NewNode = ForwardMap.lookup(Report->getErrorNode());
     assert(NewNode &&
            "Failed to construct a trimmed graph that contains this error "
@@ -2592,11 +2606,12 @@ static void CompactMacroExpandedPieces(PathPieces &path,
 /// Notes associated with {@code ErrorNode} are generated using
 /// {@code getEndPath}, and the rest are generated with {@code VisitNode}.
 static std::unique_ptr<VisitorsDiagnosticsTy>
-generateVisitorsDiagnostics(BugReport *R, const ExplodedNode *ErrorNode,
+generateVisitorsDiagnostics(PathSensitiveBugReport *R,
+                            const ExplodedNode *ErrorNode,
                             BugReporterContext &BRC) {
   std::unique_ptr<VisitorsDiagnosticsTy> Notes =
       std::make_unique<VisitorsDiagnosticsTy>();
-  BugReport::VisitorList visitors;
+  PathSensitiveBugReport::VisitorList visitors;
 
   // Run visitors on all nodes starting from the node *before* the last one.
   // The last node is reserved for notes generated with {@code getEndPath}.
@@ -2646,15 +2661,15 @@ generateVisitorsDiagnostics(BugReport *R, const ExplodedNode *ErrorNode,
   return Notes;
 }
 
-Optional<PathDiagnosticBuilder>
-PathDiagnosticBuilder::findValidReport(ArrayRef<BugReport *> &bugReports,
-                                       PathSensitiveBugReporter &Reporter) {
+Optional<PathDiagnosticBuilder> PathDiagnosticBuilder::findValidReport(
+    ArrayRef<PathSensitiveBugReport *> &bugReports,
+    PathSensitiveBugReporter &Reporter) {
 
   BugPathGetter BugGraph(&Reporter.getGraph(), bugReports);
 
   while (BugPathInfo *BugPath = BugGraph.getNextBugPath()) {
     // Find the BugReport with the original location.
-    BugReport *R = BugPath->Report;
+    PathSensitiveBugReport *R = BugPath->Report;
     assert(R && "No original report found for sliced graph.");
     assert(R->isValid() && "Report selected by trimmed graph marked invalid.");
     const ExplodedNode *ErrorNode = BugPath->ErrorNode;
@@ -2700,7 +2715,7 @@ PathDiagnosticBuilder::findValidReport(ArrayRef<BugReport *> &bugReports,
 std::unique_ptr<DiagnosticForConsumerMapTy>
 PathSensitiveBugReporter::generatePathDiagnostics(
     ArrayRef<PathDiagnosticConsumer *> consumers,
-    ArrayRef<BugReport *> &bugReports) {
+    ArrayRef<PathSensitiveBugReport *> &bugReports) {
   assert(!bugReports.empty());
 
   auto Out = std::make_unique<DiagnosticForConsumerMapTy>();
@@ -2720,24 +2735,7 @@ PathSensitiveBugReporter::generatePathDiagnostics(
 }
 
 void BugReporter::emitReport(std::unique_ptr<BugReport> R) {
-  if (const ExplodedNode *E = R->getErrorNode()) {
-    // An error node must either be a sink or have a tag, otherwise
-    // it could get reclaimed before the path diagnostic is created.
-    assert((E->isSink() || E->getLocation().getTag()) &&
-            "Error node must either be a sink or have a tag");
-
-    const AnalysisDeclContext *DeclCtx =
-        E->getLocationContext()->getAnalysisDeclContext();
-    // The source of autosynthesized body can be handcrafted AST or a model
-    // file. The locations from handcrafted ASTs have no valid source locations
-    // and have to be discarded. Locations from model files should be preserved
-    // for processing and reporting.
-    if (DeclCtx->isBodyAutosynthesized() &&
-        !DeclCtx->isBodyAutosynthesizedFromModelFile())
-      return;
-  }
-
-  bool ValidSourceLoc = R->getLocation(getSourceManager()).isValid();
+  bool ValidSourceLoc = R->getLocation().isValid();
   assert(ValidSourceLoc);
   // If we mess up in a release build, we'd still prefer to just drop the bug
   // instead of trying to go on.
@@ -2760,6 +2758,28 @@ void BugReporter::emitReport(std::unique_ptr<BugReport> R) {
     EQ->AddReport(std::move(R));
 }
 
+void PathSensitiveBugReporter::emitReport(std::unique_ptr<BugReport> R) {
+  if (auto PR = dyn_cast<PathSensitiveBugReport>(R.get()))
+    if (const ExplodedNode *E = PR->getErrorNode()) {
+      // An error node must either be a sink or have a tag, otherwise
+      // it could get reclaimed before the path diagnostic is created.
+      assert((E->isSink() || E->getLocation().getTag()) &&
+             "Error node must either be a sink or have a tag");
+
+      const AnalysisDeclContext *DeclCtx =
+          E->getLocationContext()->getAnalysisDeclContext();
+      // The source of autosynthesized body can be handcrafted AST or a model
+      // file. The locations from handcrafted ASTs have no valid source
+      // locations and have to be discarded. Locations from model files should
+      // be preserved for processing and reporting.
+      if (DeclCtx->isBodyAutosynthesized() &&
+          !DeclCtx->isBodyAutosynthesizedFromModelFile())
+        return;
+    }
+
+  BugReporter::emitReport(std::move(R));
+}
+
 //===----------------------------------------------------------------------===//
 // Emitting reports in equivalence classes.
 //===----------------------------------------------------------------------===//
@@ -2776,9 +2796,8 @@ struct FRIEC_WLItem {
 
 } // namespace
 
-static BugReport *
-FindReportInEquivalenceClass(BugReportEquivClass& EQ,
-                             SmallVectorImpl<BugReport*> &bugReports) {
+BugReport *PathSensitiveBugReporter::findReportInEquivalenceClass(
+    BugReportEquivClass &EQ, SmallVectorImpl<BugReport *> &bugReports) {
   BugReportEquivClass::iterator I = EQ.begin(), E = EQ.end();
   assert(I != E);
   const BugType& BT = I->getBugType();
@@ -2789,10 +2808,9 @@ FindReportInEquivalenceClass(BugReportEquivClass& EQ,
   if (!BT.isSuppressOnSink()) {
     BugReport *R = &*I;
     for (auto &I : EQ) {
-      const ExplodedNode *N = I.getErrorNode();
-      if (N) {
-        R = &I;
-        bugReports.push_back(R);
+      if (auto *PR = dyn_cast<PathSensitiveBugReport>(&I)) {
+        R = PR;
+        bugReports.push_back(PR);
       }
     }
     return R;
@@ -2807,19 +2825,20 @@ FindReportInEquivalenceClass(BugReportEquivClass& EQ,
   BugReport *exampleReport = nullptr;
 
   for (; I != E; ++I) {
-    const ExplodedNode *errorNode = I->getErrorNode();
-
-    if (!errorNode)
+    auto *R = dyn_cast<PathSensitiveBugReport>(&*I);
+    if (!R)
       continue;
+
+    const ExplodedNode *errorNode = R->getErrorNode();
     if (errorNode->isSink()) {
       llvm_unreachable(
            "BugType::isSuppressSink() should not be 'true' for sink end nodes");
     }
     // No successors?  By definition this nodes isn't post-dominated by a sink.
     if (errorNode->succ_empty()) {
-      bugReports.push_back(&*I);
+      bugReports.push_back(R);
       if (!exampleReport)
-        exampleReport = &*I;
+        exampleReport = R;
       continue;
     }
 
@@ -2852,9 +2871,9 @@ FindReportInEquivalenceClass(BugReportEquivClass& EQ,
         if (Succ->succ_empty()) {
           // If we found an end-of-path node that is not a sink.
           if (!Succ->isSink()) {
-            bugReports.push_back(&*I);
+            bugReports.push_back(R);
             if (!exampleReport)
-              exampleReport = &*I;
+              exampleReport = R;
             WL.clear();
             break;
           }
@@ -2885,7 +2904,7 @@ FindReportInEquivalenceClass(BugReportEquivClass& EQ,
 
 void BugReporter::FlushReport(BugReportEquivClass& EQ) {
   SmallVector<BugReport*, 10> bugReports;
-  BugReport *report = FindReportInEquivalenceClass(EQ, bugReports);
+  BugReport *report = findReportInEquivalenceClass(EQ, bugReports);
   if (!report)
     return;
 
@@ -2900,7 +2919,7 @@ void BugReporter::FlushReport(BugReportEquivClass& EQ) {
     // If the path is empty, generate a single step path with the location
     // of the issue.
     if (PD->path.empty()) {
-      PathDiagnosticLocation L = report->getLocation(getSourceManager());
+      PathDiagnosticLocation L = report->getLocation();
       auto piece = std::make_unique<PathDiagnosticEventPiece>(
         L, report->getDescription());
       for (SourceRange Range : report->getRanges())
@@ -3015,16 +3034,24 @@ findExecutedLines(const SourceManager &SM, const ExplodedNode *N) {
 
 std::unique_ptr<DiagnosticForConsumerMapTy>
 BugReporter::generateDiagnosticForConsumerMap(
-    BugReport *report, ArrayRef<PathDiagnosticConsumer *> consumers,
+    BugReport *exampleReport, ArrayRef<PathDiagnosticConsumer *> consumers,
     ArrayRef<BugReport *> bugReports) {
+  auto *basicReport = cast<BasicBugReport>(exampleReport);
+  auto Out = std::make_unique<DiagnosticForConsumerMapTy>();
+  for (auto *Consumer : consumers)
+    (*Out)[Consumer] = generateDiagnosticForBasicReport(basicReport);
+  return Out;
+}
 
-  if (!report->isPathSensitive()) {
-    auto Out = std::make_unique<DiagnosticForConsumerMapTy>();
-    for (auto *Consumer : consumers)
-      (*Out)[Consumer] = generateEmptyDiagnosticForReport(report,
-                                                          getSourceManager());
-    return Out;
-  }
+std::unique_ptr<DiagnosticForConsumerMapTy>
+PathSensitiveBugReporter::generateDiagnosticForConsumerMap(
+    BugReport *exampleReport, ArrayRef<PathDiagnosticConsumer *> consumers,
+    ArrayRef<BugReport *> bugReports) {
+  std::vector<BasicBugReport *> BasicBugReports;
+  std::vector<PathSensitiveBugReport *> PathSensitiveBugReports;
+  if (isa<BasicBugReport>(exampleReport))
+    return BugReporter::generateDiagnosticForConsumerMap(exampleReport,
+                                                         consumers, bugReports);
 
   // Generate the full path sensitive diagnostic, using the generation scheme
   // specified by the PathDiagnosticConsumer. Note that we have to generate
@@ -3032,8 +3059,13 @@ BugReporter::generateDiagnosticForConsumerMap(
   // the BugReporterVisitors may mark this bug as a false positive.
   assert(!bugReports.empty());
   MaxBugClassSize.updateMax(bugReports.size());
-  std::unique_ptr<DiagnosticForConsumerMapTy> Out =
-    generatePathDiagnostics(consumers, bugReports);
+
+  // Avoid copying the whole array because there may be a lot of reports.
+  ArrayRef<PathSensitiveBugReport *> convertedArrayOfReports(
+      reinterpret_cast<PathSensitiveBugReport *const *>(&*bugReports.begin()),
+      reinterpret_cast<PathSensitiveBugReport *const *>(&*bugReports.end()));
+  std::unique_ptr<DiagnosticForConsumerMapTy> Out = generatePathDiagnostics(
+      consumers, convertedArrayOfReports);
 
   if (Out->empty())
     return Out;
@@ -3068,7 +3100,7 @@ void BugReporter::EmitBasicReport(const Decl *DeclWithIssue,
                                   ArrayRef<FixItHint> Fixits) {
   // 'BT' is owned by BugReporter.
   BugType *BT = getBugTypeForName(CheckName, name, category);
-  auto R = std::make_unique<BugReport>(*BT, str, Loc);
+  auto R = std::make_unique<BasicBugReport>(*BT, str, Loc);
   R->setDeclWithIssue(DeclWithIssue);
   for (const auto &SR : Ranges)
     R->addRange(SR);
index b223c6fb496b79c0155f67dc709421bdd715b78d..7b26b8fabb9c972213a0b37cfcb23d472bfd28a2 100644 (file)
@@ -215,7 +215,7 @@ getConcreteIntegerValue(const Expr *CondVarExpr, const ExplodedNode *N) {
 
 static bool isVarAnInterestingCondition(const Expr *CondVarExpr,
                                         const ExplodedNode *N,
-                                        const BugReport *B) {
+                                        const PathSensitiveBugReport *B) {
   // Even if this condition is marked as interesting, it isn't *that*
   // interesting if it didn't happen in a nested stackframe, the user could just
   // follow the arrows.
@@ -230,7 +230,7 @@ static bool isVarAnInterestingCondition(const Expr *CondVarExpr,
 }
 
 static bool isInterestingExpr(const Expr *E, const ExplodedNode *N,
-                              const BugReport *B) {
+                              const PathSensitiveBugReport *B) {
   if (Optional<SVal> V = getSValForVar(E, N))
     return B->getInterestingnessKind(*V).hasValue();
   return false;
@@ -296,19 +296,20 @@ static bool wasRegionOfInterestModifiedAt(const SubRegion *RegionOfInterest,
 
 PathDiagnosticPieceRef BugReporterVisitor::getEndPath(BugReporterContext &,
                                                       const ExplodedNode *,
-                                                      BugReport &) {
+                                                      PathSensitiveBugReport &) {
   return nullptr;
 }
 
 void BugReporterVisitor::finalizeVisitor(BugReporterContext &,
-                                         const ExplodedNode *, BugReport &) {}
+                                         const ExplodedNode *,
+                                         PathSensitiveBugReport &) {}
 
 PathDiagnosticPieceRef
 BugReporterVisitor::getDefaultEndPath(const BugReporterContext &BRC,
                                       const ExplodedNode *EndPathNode,
-                                      const BugReport &BR) {
-  PathDiagnosticLocation L = PathDiagnosticLocation::createEndOfPath(
-      EndPathNode, BRC.getSourceManager());
+                                      const PathSensitiveBugReport &BR) {
+  PathDiagnosticLocation L =
+      PathDiagnosticLocation::createEndOfPath(EndPathNode);
 
   const auto &Ranges = BR.getRanges();
 
@@ -376,7 +377,7 @@ public:
 
   PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                    BugReporterContext &BR,
-                                   BugReport &R) override;
+                                   PathSensitiveBugReport &R) override;
 
 private:
   /// Attempts to find the region of interest in a given record decl,
@@ -410,10 +411,10 @@ private:
   /// \return Diagnostics piece for region not modified in the current function,
   /// if it decides to emit one.
   PathDiagnosticPieceRef
-  maybeEmitNote(BugReport &R, const CallEvent &Call, const ExplodedNode *N,
-                const RegionVector &FieldChain, const MemRegion *MatchedRegion,
-                StringRef FirstElement, bool FirstIsReferenceType,
-                unsigned IndirectionLevel);
+  maybeEmitNote(PathSensitiveBugReport &R, const CallEvent &Call,
+                const ExplodedNode *N, const RegionVector &FieldChain,
+                const MemRegion *MatchedRegion, StringRef FirstElement,
+                bool FirstIsReferenceType, unsigned IndirectionLevel);
 
   /// Pretty-print region \p MatchedRegion to \p os.
   /// \return Whether printing succeeded.
@@ -542,9 +543,9 @@ NoStoreFuncVisitor::findRegionOfInterestInRecord(
   return None;
 }
 
-PathDiagnosticPieceRef NoStoreFuncVisitor::VisitNode(const ExplodedNode *N,
-                                                     BugReporterContext &BR,
-                                                     BugReport &R) {
+PathDiagnosticPieceRef
+NoStoreFuncVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BR,
+                              PathSensitiveBugReport &R) {
 
   const LocationContext *Ctx = N->getLocationContext();
   const StackFrameContext *SCtx = Ctx->getStackFrame();
@@ -656,7 +657,7 @@ static llvm::StringLiteral WillBeUsedForACondition =
     ", which participates in a condition later";
 
 PathDiagnosticPieceRef NoStoreFuncVisitor::maybeEmitNote(
-    BugReport &R, const CallEvent &Call, const ExplodedNode *N,
+    PathSensitiveBugReport &R, const CallEvent &Call, const ExplodedNode *N,
     const RegionVector &FieldChain, const MemRegion *MatchedRegion,
     StringRef FirstElement, bool FirstIsReferenceType,
     unsigned IndirectionLevel) {
@@ -803,7 +804,7 @@ public:
 
   PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                    BugReporterContext &BRC,
-                                   BugReport &BR) override {
+                                   PathSensitiveBugReport &BR) override {
     if (WasModified)
       return nullptr;
 
@@ -829,7 +830,7 @@ public:
 
   static void addMacroVisitorIfNecessary(
         const ExplodedNode *N, const MemRegion *R,
-        bool EnableNullFPSuppression, BugReport &BR,
+        bool EnableNullFPSuppression, PathSensitiveBugReport &BR,
         const SVal V) {
     AnalyzerOptions &Options = N->getState()->getAnalysisManager().options;
     if (EnableNullFPSuppression &&
@@ -923,7 +924,7 @@ public:
   /// the statement is a call that was inlined, we add the visitor to the
   /// bug report, so it can print a note later.
   static void addVisitorIfNecessary(const ExplodedNode *Node, const Stmt *S,
-                                    BugReport &BR,
+                                    PathSensitiveBugReport &BR,
                                     bool InEnableNullFPSuppression,
                                     bugreporter::TrackingKind TKind) {
     if (!CallEvent::isCallStmt(S))
@@ -1003,7 +1004,7 @@ public:
 
   PathDiagnosticPieceRef visitNodeInitial(const ExplodedNode *N,
                                           BugReporterContext &BRC,
-                                          BugReport &BR) {
+                                          PathSensitiveBugReport &BR) {
     // Only print a message at the interesting return statement.
     if (N->getLocationContext() != CalleeSFC)
       return nullptr;
@@ -1130,10 +1131,8 @@ public:
 
   PathDiagnosticPieceRef visitNodeMaybeUnsuppress(const ExplodedNode *N,
                                                   BugReporterContext &BRC,
-                                                  BugReport &BR) {
-#ifndef NDEBUG
+                                                  PathSensitiveBugReport &BR) {
     assert(Options.ShouldAvoidSuppressingNullArgumentPaths);
-#endif
 
     // Are we at the entry node for this call?
     Optional<CallEnter> CE = N->getLocationAs<CallEnter>();
@@ -1179,7 +1178,7 @@ public:
 
   PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                    BugReporterContext &BRC,
-                                   BugReport &BR) override {
+                                   PathSensitiveBugReport &BR) override {
     switch (Mode) {
     case Initial:
       return visitNodeInitial(N, BRC, BR);
@@ -1193,7 +1192,7 @@ public:
   }
 
   void finalizeVisitor(BugReporterContext &, const ExplodedNode *,
-                       BugReport &BR) override {
+                       PathSensitiveBugReport &BR) override {
     if (EnableNullFPSuppression && ShouldInvalidate)
       BR.markInvalid(ReturnVisitor::getTag(), CalleeSFC);
   }
@@ -1316,9 +1315,8 @@ static void showBRParamDiagnostics(llvm::raw_svector_ostream& os,
 }
 
 /// Show default diagnostics for storing bad region.
-static void showBRDefaultDiagnostics(llvm::raw_svector_ostream& os,
-    const MemRegion *R,
-    SVal V) {
+static void showBRDefaultDiagnostics(llvm::raw_svector_ostream &os,
+                                     const MemRegion *R, SVal V) {
   if (V.getAs<loc::ConcreteInt>()) {
     bool b = false;
     if (R->isBoundable()) {
@@ -1363,7 +1361,8 @@ static void showBRDefaultDiagnostics(llvm::raw_svector_ostream& os,
 
 PathDiagnosticPieceRef
 FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
-                                  BugReporterContext &BRC, BugReport &BR) {
+                                  BugReporterContext &BRC,
+                                  PathSensitiveBugReport &BR) {
   if (Satisfied)
     return nullptr;
 
@@ -1540,9 +1539,8 @@ bool TrackConstraintBRVisitor::isUnderconstrained(const ExplodedNode *N) const {
   return (bool)N->getState()->assume(Constraint, !Assumption);
 }
 
-PathDiagnosticPieceRef
-TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N,
-                                    BugReporterContext &BRC, BugReport &) {
+PathDiagnosticPieceRef TrackConstraintBRVisitor::VisitNode(
+    const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &) {
   const ExplodedNode *PrevN = N->getFirstPred();
   if (IsSatisfied)
     return nullptr;
@@ -1620,8 +1618,10 @@ const char *SuppressInlineDefensiveChecksVisitor::getTag() {
   return "IDCVisitor";
 }
 
-PathDiagnosticPieceRef SuppressInlineDefensiveChecksVisitor::VisitNode(
-    const ExplodedNode *Succ, BugReporterContext &BRC, BugReport &BR) {
+PathDiagnosticPieceRef
+SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *Succ,
+                                                BugReporterContext &BRC,
+                                                PathSensitiveBugReport &BR) {
   const ExplodedNode *Pred = Succ->getFirstPred();
   if (IsSatisfied)
     return nullptr;
@@ -1722,7 +1722,7 @@ public:
 
   PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
                                    BugReporterContext &BRC,
-                                   BugReport &BR) override;
+                                   PathSensitiveBugReport &BR) override;
 };
 } // end of anonymous namespace
 
@@ -1778,8 +1778,10 @@ static bool isAssertlikeBlock(const CFGBlock *B, ASTContext &Context) {
   return false;
 }
 
-PathDiagnosticPieceRef TrackControlDependencyCondBRVisitor::VisitNode(
-    const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) {
+PathDiagnosticPieceRef
+TrackControlDependencyCondBRVisitor::VisitNode(const ExplodedNode *N,
+                                               BugReporterContext &BRC,
+                                               PathSensitiveBugReport &BR) {
   // We can only reason about control dependencies within the same stack frame.
   if (Origin->getStackFrame() != N->getStackFrame())
     return nullptr;
@@ -1925,7 +1927,8 @@ static const ExplodedNode* findNodeForExpression(const ExplodedNode *N,
 }
 
 bool bugreporter::trackExpressionValue(const ExplodedNode *InputNode,
-                                       const Expr *E, BugReport &report,
+                                       const Expr *E,
+                                       PathSensitiveBugReport &report,
                                        bugreporter::TrackingKind TKind,
                                        bool EnableNullFPSuppression) {
 
@@ -2082,9 +2085,9 @@ const Expr *NilReceiverBRVisitor::getNilReceiver(const Stmt *S,
   return nullptr;
 }
 
-PathDiagnosticPieceRef NilReceiverBRVisitor::VisitNode(const ExplodedNode *N,
-                                                       BugReporterContext &BRC,
-                                                       BugReport &BR) {
+PathDiagnosticPieceRef
+NilReceiverBRVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
+                                PathSensitiveBugReport &BR) {
   Optional<PreStmt> P = N->getLocationAs<PreStmt>();
   if (!P)
     return nullptr;
@@ -2127,9 +2130,9 @@ PathDiagnosticPieceRef NilReceiverBRVisitor::VisitNode(const ExplodedNode *N,
 /// to make all PathDiagnosticPieces created by this visitor.
 const char *ConditionBRVisitor::getTag() { return "ConditionBRVisitor"; }
 
-PathDiagnosticPieceRef ConditionBRVisitor::VisitNode(const ExplodedNode *N,
-                                                     BugReporterContext &BRC,
-                                                     BugReport &BR) {
+PathDiagnosticPieceRef
+ConditionBRVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
+                              PathSensitiveBugReport &BR) {
   auto piece = VisitNodeImpl(N, BRC, BR);
   if (piece) {
     piece->setTag(getTag());
@@ -2141,7 +2144,8 @@ PathDiagnosticPieceRef ConditionBRVisitor::VisitNode(const ExplodedNode *N,
 
 PathDiagnosticPieceRef
 ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N,
-                                  BugReporterContext &BRC, BugReport &BR) {
+                                  BugReporterContext &BRC,
+                                  PathSensitiveBugReport &BR) {
   ProgramPoint ProgPoint = N->getLocation();
   const std::pair<const ProgramPointTag *, const ProgramPointTag *> &Tags =
       ExprEngine::geteagerlyAssumeBinOpBifurcationTags();
@@ -2179,7 +2183,8 @@ ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N,
 
 PathDiagnosticPieceRef ConditionBRVisitor::VisitTerminator(
     const Stmt *Term, const ExplodedNode *N, const CFGBlock *srcBlk,
-    const CFGBlock *dstBlk, BugReport &R, BugReporterContext &BRC) {
+    const CFGBlock *dstBlk, PathSensitiveBugReport &R,
+    BugReporterContext &BRC) {
   const Expr *Cond = nullptr;
 
   // In the code below, Term is a CFG terminator and Cond is a branch condition
@@ -2236,8 +2241,8 @@ PathDiagnosticPieceRef ConditionBRVisitor::VisitTerminator(
 
 PathDiagnosticPieceRef
 ConditionBRVisitor::VisitTrueTest(const Expr *Cond, BugReporterContext &BRC,
-                                  BugReport &R, const ExplodedNode *N,
-                                  bool TookTrue) {
+                                  PathSensitiveBugReport &R,
+                                  const ExplodedNode *N, bool TookTrue) {
   ProgramStateRef CurrentState = N->getState();
   ProgramStateRef PrevState = N->getFirstPred()->getState();
   const LocationContext *LCtx = N->getLocationContext();
@@ -2307,7 +2312,7 @@ bool ConditionBRVisitor::patternMatch(const Expr *Ex,
                                       const Expr *ParentEx,
                                       raw_ostream &Out,
                                       BugReporterContext &BRC,
-                                      BugReport &report,
+                                      PathSensitiveBugReport &report,
                                       const ExplodedNode *N,
                                       Optional<bool> &prunable,
                                       bool IsSameFieldName) {
@@ -2392,7 +2397,8 @@ bool ConditionBRVisitor::patternMatch(const Expr *Ex,
 
 PathDiagnosticPieceRef ConditionBRVisitor::VisitTrueTest(
     const Expr *Cond, const BinaryOperator *BExpr, BugReporterContext &BRC,
-    BugReport &R, const ExplodedNode *N, bool TookTrue, bool IsAssuming) {
+    PathSensitiveBugReport &R, const ExplodedNode *N, bool TookTrue,
+    bool IsAssuming) {
   bool shouldInvert = false;
   Optional<bool> shouldPrune;
 
@@ -2511,7 +2517,7 @@ PathDiagnosticPieceRef ConditionBRVisitor::VisitTrueTest(
 
 PathDiagnosticPieceRef ConditionBRVisitor::VisitConditionVariable(
     StringRef LhsString, const Expr *CondVarExpr, BugReporterContext &BRC,
-    BugReport &report, const ExplodedNode *N, bool TookTrue) {
+    PathSensitiveBugReport &report, const ExplodedNode *N, bool TookTrue) {
   // FIXME: If there's already a constraint tracker for this variable,
   // we shouldn't emit anything here (c.f. the double note in
   // test/Analysis/inlining/path-notes.c)
@@ -2538,7 +2544,8 @@ PathDiagnosticPieceRef ConditionBRVisitor::VisitConditionVariable(
 
 PathDiagnosticPieceRef ConditionBRVisitor::VisitTrueTest(
     const Expr *Cond, const DeclRefExpr *DRE, BugReporterContext &BRC,
-    BugReport &report, const ExplodedNode *N, bool TookTrue, bool IsAssuming) {
+    PathSensitiveBugReport &report, const ExplodedNode *N, bool TookTrue,
+    bool IsAssuming) {
   const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
   if (!VD)
     return nullptr;
@@ -2573,7 +2580,8 @@ PathDiagnosticPieceRef ConditionBRVisitor::VisitTrueTest(
 
 PathDiagnosticPieceRef ConditionBRVisitor::VisitTrueTest(
     const Expr *Cond, const MemberExpr *ME, BugReporterContext &BRC,
-    BugReport &report, const ExplodedNode *N, bool TookTrue, bool IsAssuming) {
+    PathSensitiveBugReport &report, const ExplodedNode *N, bool TookTrue,
+    bool IsAssuming) {
   SmallString<256> Buf;
   llvm::raw_svector_ostream Out(Buf);
 
@@ -2659,7 +2667,8 @@ bool ConditionBRVisitor::isPieceMessageGeneric(
 //===----------------------------------------------------------------------===//
 
 void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor(
-    BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR) {
+    BugReporterContext &BRC, const ExplodedNode *N,
+    PathSensitiveBugReport &BR) {
   // Here we suppress false positives coming from system headers. This list is
   // based on known issues.
   const AnalyzerOptions &Options = BRC.getAnalyzerOptions();
@@ -2730,7 +2739,7 @@ void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor(
   // Skip reports within the sys/queue.h macros as we do not have the ability to
   // reason about data structure shapes.
   const SourceManager &SM = BRC.getSourceManager();
-  FullSourceLoc Loc = BR.getLocation(SM).asLocation();
+  FullSourceLoc Loc = BR.getLocation().asLocation();
   while (Loc.isMacroID()) {
     Loc = Loc.getSpellingLoc();
     if (SM.getFilename(Loc).endswith("sys/queue.h")) {
@@ -2744,9 +2753,9 @@ void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor(
 // Implementation of UndefOrNullArgVisitor.
 //===----------------------------------------------------------------------===//
 
-PathDiagnosticPieceRef UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N,
-                                                        BugReporterContext &BRC,
-                                                        BugReport &BR) {
+PathDiagnosticPieceRef
+UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
+                                 PathSensitiveBugReport &BR) {
   ProgramStateRef State = N->getState();
   ProgramPoint ProgLoc = N->getLocation();
 
@@ -2802,7 +2811,8 @@ FalsePositiveRefutationBRVisitor::FalsePositiveRefutationBRVisitor()
     : Constraints(ConstraintRangeTy::Factory().getEmptyMap()) {}
 
 void FalsePositiveRefutationBRVisitor::finalizeVisitor(
-    BugReporterContext &BRC, const ExplodedNode *EndPathNode, BugReport &BR) {
+    BugReporterContext &BRC, const ExplodedNode *EndPathNode,
+    PathSensitiveBugReport &BR) {
   // Collect new constraints
   VisitNode(EndPathNode, BRC, BR);
 
@@ -2837,9 +2847,8 @@ void FalsePositiveRefutationBRVisitor::finalizeVisitor(
     BR.markInvalid("Infeasible constraints", EndPathNode->getLocationContext());
 }
 
-PathDiagnosticPieceRef
-FalsePositiveRefutationBRVisitor::VisitNode(const ExplodedNode *N,
-                                            BugReporterContext &, BugReport &) {
+PathDiagnosticPieceRef FalsePositiveRefutationBRVisitor::VisitNode(
+    const ExplodedNode *N, BugReporterContext &, PathSensitiveBugReport &) {
   // Collect new constraints
   const ConstraintRangeTy &NewCs = N->getState()->get<ConstraintRange>();
   ConstraintRangeTy::Factory &CF =
@@ -2875,7 +2884,7 @@ void TagVisitor::Profile(llvm::FoldingSetNodeID &ID) const {
 
 PathDiagnosticPieceRef TagVisitor::VisitNode(const ExplodedNode *N,
                                              BugReporterContext &BRC,
-                                             BugReport &R) {
+                                             PathSensitiveBugReport &R) {
   ProgramPoint PP = N->getLocation();
   const NoteTag *T = dyn_cast_or_null<NoteTag>(PP.getTag());
   if (!T)
index c5a1f9b857e09c93f6f5e11fdd96d3847fc2a3e6..de23a3ca75f5f8e05ca1c36485829cbb7e4f5406 100644 (file)
@@ -3004,9 +3004,13 @@ struct DOTGraphTraits<ExplodedGraph*> : public DefaultDOTGraphTraits {
         llvm::make_range(BR.EQClasses_begin(), BR.EQClasses_end());
 
     for (const auto &EQ : EQClasses) {
-      for (const BugReport &Report : EQ) {
-        if (Report.getErrorNode()->getState() == N->getState() &&
-            Report.getErrorNode()->getLocation() == N->getLocation())
+      for (const BugReport &R : EQ) {
+        const auto *PR = dyn_cast<PathSensitiveBugReport>(&R);
+        if (!PR)
+          continue;
+        const ExplodedNode *EN = PR->getErrorNode();
+        if (EN->getState() == N->getState() &&
+            EN->getLocation() == N->getLocation())
           return true;
       }
     }
@@ -3131,8 +3135,11 @@ std::string ExprEngine::DumpGraph(bool trim, StringRef Filename) {
     // Iterate through the reports and get their nodes.
     for (BugReporter::EQClasses_iterator
            EI = BR.EQClasses_begin(), EE = BR.EQClasses_end(); EI != EE; ++EI) {
-      const auto *N = const_cast<ExplodedNode *>(EI->begin()->getErrorNode());
-      if (N) Src.push_back(N);
+      const auto *R = dyn_cast<PathSensitiveBugReport>(&*EI->begin());
+      if (!R)
+        continue;
+      const auto *N = const_cast<ExplodedNode *>(R->getErrorNode());
+      Src.push_back(N);
     }
     return DumpGraph(Src, Filename);
   } else {
index 2d3b50082c7dc3ce2bebb24aef6d85e96e116b17..f049a1c4120b431eef0c3eb611521a8aa5bd8d9f 100644 (file)
@@ -850,11 +850,12 @@ const Stmt *PathDiagnosticLocation::getNextStmt(const ExplodedNode *N) {
 }
 
 PathDiagnosticLocation
-  PathDiagnosticLocation::createEndOfPath(const ExplodedNode *N,
-                                          const SourceManager &SM) {
+PathDiagnosticLocation::createEndOfPath(const ExplodedNode *N) {
   assert(N && "Cannot create a location with a null node.");
   const Stmt *S = getStmt(N);
   const LocationContext *LC = N->getLocationContext();
+  SourceManager &SM =
+      N->getState()->getStateManager().getContext().getSourceManager();
 
   if (!S) {
     // If this is an implicit call, return the implicit call point location.