[cfe-commits] r138462 - /cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp

Jordy Rose jediknil at belkadan.com
Wed Aug 24 11:56:32 PDT 2011


Author: jrose
Date: Wed Aug 24 13:56:32 2011
New Revision: 138462

URL: http://llvm.org/viewvc/llvm-project?rev=138462&view=rev
Log:
[analyzer] Slightly clean up the fix in 138432, so that it doesn't depend on the relative ordering of path-sensitive and path-insensitive checks. Still not ideal, but I think a real fix would require infrastructure that doesn't exist yet.

Modified:
    cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp?rev=138462&r1=138461&r2=138462&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CFRefCount.cpp Wed Aug 24 13:56:32 2011
@@ -2619,9 +2619,9 @@
 
 namespace {
 class RetainReleaseChecker
-  : public Checker< check::ASTCodeBody,
-                    check::Bind,
+  : public Checker< check::Bind,
                     check::DeadSymbols,
+                    check::EndAnalysis,
                     check::EndPath,
                     check::PostStmt<BlockExpr>,
                     check::PostStmt<CastExpr>,
@@ -2637,37 +2637,52 @@
   // This map is only used to ensure proper deletion of any allocated tags.
   mutable SymbolTagMap DeadSymbolTags;
 
-  mutable SummaryLogTy SummaryLog;
   mutable ARCounts::Factory ARCountFactory;
 
+  mutable SummaryLogTy SummaryLog;
+  mutable bool ShouldResetSummaryLog;
+
 public:  
+  RetainReleaseChecker() : ShouldResetSummaryLog(false) {}
 
   virtual ~RetainReleaseChecker() {
     DeleteContainerSeconds(DeadSymbolTags);
   }
 
-  void checkASTCodeBody(const Decl *D, AnalysisManager &mgr,
-                        BugReporter &BR) const {
-    // FIXME: This is a horrible hack which makes the checker stateful --
-    // exactly what being const was supposed to prevent, or at least discourage.
-    // Why? Because a checker's lifetime is tied to a translation unit, but an
-    // ExplodedGraph's lifetime is just a code body. Once in a blue moon, a new
-    // ExplodedNode will have the same address as an old one with an associated
-    // summary, and the bug report visitor will get very confused.
-    // (To make things worse, the summary lifetime is currently also tied to a
-    // code body, so we get a crash instead of incorrect results.)
-    // This fix wipes the summary log at the start of a code body.
+  void checkEndAnalysis(ExplodedGraph &G, BugReporter &BR,
+                        ExprEngine &Eng) const {
+    // FIXME: This is a hack to make sure the summary log gets cleared between
+    // analyses of different code bodies.
+    //
+    // Why is this necessary? Because a checker's lifetime is tied to a
+    // translation unit, but an ExplodedGraph's lifetime is just a code body.
+    // Once in a blue moon, a new ExplodedNode will have the same address as an
+    // old one with an associated summary, and the bug report visitor gets very
+    // confused. (To make things worse, the summary lifetime is currently also
+    // tied to a code body, so we get a crash instead of incorrect results.)
     //
     // Why is this a bad solution? Because if the lifetime of the ExplodedGraph
     // changes, things will start going wrong again. Really the lifetime of this
     // log needs to be tied to either the specific nodes in it or the entire
     // ExplodedGraph, not to a specific part of the code being analyzed.
     //
-    // Oh, and it has to happen at the BEGINNING of the code body instead of the
-    // end because the summary log has to be live when emitting bug reports.
+    // (Also, having stateful local data means that the same checker can't be
+    // used from multiple threads, but a lot of checkers have incorrect
+    // assumptions about that anyway. So that wasn't a priority at the time of
+    // this fix.)
     //
-    // This took forever to track down. A better fix is (hopefully) forthcoming.
-    SummaryLog.clear();
+    // This happens at the end of analysis, but bug reports are emitted /after/
+    // this point. So we can't just clear the summary log now. Instead, we mark
+    // that the next time we access the summary log, it should be cleared.
+
+    // If we never reset the summary log during /this/ code body analysis,
+    // there were no new summaries. There might still have been summaries from
+    // the /last/ analysis, so clear them out to make sure the bug report
+    // visitors don't get confused.
+    if (ShouldResetSummaryLog)
+      SummaryLog.clear();
+
+    ShouldResetSummaryLog = !SummaryLog.empty();
   }
 
   void checkBind(SVal loc, SVal val, CheckerContext &C) const;
@@ -3088,9 +3103,15 @@
     NewNode = C.generateNode(state);
   }
 
-  // Annotate the edge with summary we used.
-  if (NewNode)
+  // Annotate the node with summary we used.
+  if (NewNode) {
+    // FIXME: This is ugly. See checkEndAnalysis for why it's necessary.
+    if (ShouldResetSummaryLog) {
+      SummaryLog.clear();
+      ShouldResetSummaryLog = false;
+    }
     SummaryLog[NewNode] = &Summ;
+  }
 }
 
 





More information about the cfe-commits mailing list