NoQ created this revision.
NoQ added reviewers: dcoughlin, xazax.hun, a_sidorin, rnkovacs, Szelethus, 
baloghadamsoftware, Charusso.
Herald added subscribers: cfe-commits, dkrupp, donat.nagy, mikhail.ramalho, 
a.sidorin, szepet.
Herald added a project: clang.

I'm slowly cleaning up `BugReporter` as a preparation for porting clang-tidy to 
use it exclusively as discussed in 
http://lists.llvm.org/pipermail/cfe-dev/2019-August/063092.html . Basically, 
we'll need to make a `BugReport` and a `BugReporter` that both can be compiled 
with `CLANG_ENABLE_STATIC_ANALYZER=OFF`: no "error nodes", no nothing. So we'll 
most likely make a clear separation between a basic bug report(er) and a 
path-sensitive bug report(er), having them inherit from common bug report(er) 
classes.

While figuring out which field/method goes where, i already made a couple of 
trivial commits (rC369319 <https://reviews.llvm.org/rC369319>, rC369320 
<https://reviews.llvm.org/rC369320>). This one, however, is relatively 
interesting.

The `BugTypes` field is basically unused, and it definitely doesn't need to be 
implemented as an //immutable// set (if at all). But once i removed it i 
started noticing a bunch of null dereferences in 
`generateDiagnosticForConsumerMap()`:

  3060    std::unique_ptr<DiagnosticForConsumerMapTy> Out =
  3061        generatePathDiagnostics(consumers, bugReports);
  3062   
  3063    if (Out->empty())   // <== crash: Out is null!
  3064      return Out;

This was fun to debug because it's obvious by looking at 
`PathSensitiveBugReporter::generatePathDiagnostics()` that it never returns 
null:

  2643 std::unique_ptr<DiagnosticForConsumerMapTy>
  2644 PathSensitiveBugReporter::generatePathDiagnostics(...) {
  ...
  2649   auto Out = llvm::make_unique<DiagnosticForConsumerMapTy>();
  ...
  2658   return Out;
  2659 }

The debugger was also sure that we're dealing with a path-sensitive bug 
reporter here. The answer turned out to be related to this tiny discussion 
<https://reviews.llvm.org/D63227?id=204353#inline-562789>. Or, rather, here's a 
report that's worth a thousand words:

F9827911: report-f2e935.html <https://reviews.llvm.org/F9827911>

So i decided to avoid the destructor minefield entirely, even if it means 
calling flush manually.

Also, ugh, why is CloneChecker subscribed to `check::EndOfTranslationUnit` 
which is a path-sensitive callback? :/


Repository:
  rC Clang

https://reviews.llvm.org/D66460

Files:
  clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
  clang/lib/StaticAnalyzer/Core/BugReporter.cpp
  clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp

Index: clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -609,6 +609,7 @@
   // After all decls handled, run checkers on the entire TranslationUnit.
   checkerMgr->runCheckersOnEndOfTranslationUnit(TU, *Mgr, BR);
 
+  BR.FlushReports();
   RecVisitorBR = nullptr;
 }
 
@@ -766,6 +767,9 @@
     if (SyntaxCheckTimer)
       SyntaxCheckTimer->stopTimer();
   }
+
+  BR.FlushReports();
+
   if ((Mode & AM_Path) && checkerMgr->hasPathSensitiveCheckers()) {
     RunPathSensitiveChecks(D, IMode, VisitedCallees);
     if (IMode != ExprEngine::Inline_Minimal)
Index: clang/lib/StaticAnalyzer/Core/BugReporter.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -2221,7 +2221,9 @@
 }
 
 BugReporter::~BugReporter() {
-  FlushReports();
+  // Make sure reports are flushed.
+  assert(StrBugTypes.empty() &&
+         "Destroying BugReporter before diagnostics are emitted!");
 
   // Free the bug reports we are tracking.
   for (const auto I : EQClassesVector)
@@ -2229,9 +2231,6 @@
 }
 
 void BugReporter::FlushReports() {
-  if (BugTypes.isEmpty())
-    return;
-
   // We need to flush reports in deterministic order to ensure the order
   // of the reports is consistent between runs.
   for (const auto EQ : EQClassesVector)
@@ -2242,9 +2241,6 @@
   // FIXME: There are leaks from checkers that assume that the BugTypes they
   // create will be destroyed by the BugReporter.
   llvm::DeleteContainerSeconds(StrBugTypes);
-
-  // Remove all references to the BugType objects.
-  BugTypes = F.getEmptySet();
 }
 
 //===----------------------------------------------------------------------===//
@@ -2658,10 +2654,6 @@
   return Out;
 }
 
-void BugReporter::Register(const BugType *BT) {
-  BugTypes = F.add(BugTypes, BT);
-}
-
 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
@@ -2692,8 +2684,6 @@
   R->Profile(ID);
 
   // Lookup the equivance class.  If there isn't one, create it.
-  const BugType& BT = R->getBugType();
-  Register(&BT);
   void *InsertPos;
   BugReportEquivClass* EQ = EQClasses.FindNodeOrInsertPos(ID, InsertPos);
 
Index: clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
@@ -406,11 +406,6 @@
   enum Kind { BasicBRKind, PathSensitiveBRKind };
 
 private:
-  using BugTypesTy = llvm::ImmutableSet<BugType *>;
-
-  BugTypesTy::Factory F;
-  BugTypesTy BugTypes;
-
   const Kind kind;
   BugReporterData& D;
 
@@ -431,11 +426,10 @@
 
 protected:
   BugReporter(BugReporterData& d, Kind k)
-      : BugTypes(F.getEmptySet()), kind(k), D(d) {}
+      : kind(k), D(d) {}
 
 public:
-  BugReporter(BugReporterData& d)
-      : BugTypes(F.getEmptySet()), kind(BasicBRKind), D(d) {}
+  BugReporter(BugReporterData &d) : kind(BasicBRKind), D(d) {}
   virtual ~BugReporter();
 
   /// Generate and flush diagnostics for all bug reports.
@@ -451,11 +445,6 @@
     return D.getPathDiagnosticConsumers();
   }
 
-  /// Iterator over the set of BugTypes tracked by the BugReporter.
-  using iterator = BugTypesTy::iterator;
-  iterator begin() { return BugTypes.begin(); }
-  iterator end() { return BugTypes.end(); }
-
   /// Iterator over the set of BugReports tracked by the BugReporter.
   using EQClasses_iterator = llvm::FoldingSet<BugReportEquivClass>::iterator;
   EQClasses_iterator EQClasses_begin() { return EQClasses.begin(); }
@@ -473,8 +462,6 @@
     return {};
   }
 
-  void Register(const BugType *BT);
-
   /// Add the given report to the set of reports tracked by BugReporter.
   ///
   /// The reports are usually generated by the checkers. Further, they are
@@ -509,8 +496,6 @@
   PathSensitiveBugReporter(BugReporterData& d, ExprEngine& eng)
       : BugReporter(d, PathSensitiveBRKind), Eng(eng) {}
 
-  ~PathSensitiveBugReporter() override = default;
-
   /// getGraph - Get the exploded graph created by the analysis engine
   ///  for the analyzed method or function.
   const ExplodedGraph &getGraph() const;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to