[cfe-commits] r123217 - in /cfe/trunk: include/clang/StaticAnalyzer/PathSensitive/CoreEngine.h include/clang/StaticAnalyzer/PathSensitive/ExprEngine.h include/clang/StaticAnalyzer/PathSensitive/SubEngine.h lib/StaticAnalyzer/Checkers/ExprEngine.cpp lib/StaticAnalyzer/CoreEngine.cpp test/Analysis/retain-release-region-store.m

Ted Kremenek kremenek at apple.com
Mon Jan 10 22:37:47 PST 2011


Author: kremenek
Date: Tue Jan 11 00:37:47 2011
New Revision: 123217

URL: http://llvm.org/viewvc/llvm-project?rev=123217&view=rev
Log:
Rework ExprEngine::processCFGBlockEntrance()
to use a node builder.  This paves the way
for Checkers to interpose (via a "visit" method)
at the entrance to blocks.

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/CoreEngine.h
    cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/ExprEngine.h
    cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/SubEngine.h
    cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
    cfe/trunk/lib/StaticAnalyzer/CoreEngine.cpp
    cfe/trunk/test/Analysis/retain-release-region-store.m

Modified: cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/CoreEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/CoreEngine.h?rev=123217&r1=123216&r2=123217&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/CoreEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/CoreEngine.h Tue Jan 11 00:37:47 2011
@@ -37,6 +37,7 @@
 ///   any transfer function logic and the sub-expression level (if any).
 class CoreEngine {
   friend class StmtNodeBuilder;
+  friend class GenericNodeBuilderImpl;
   friend class BranchNodeBuilder;
   friend class IndirectGotoNodeBuilder;
   friend class SwitchNodeBuilder;
@@ -397,6 +398,50 @@
   const GRState* getState() const { return Pred->State; }
 };
 
+class GenericNodeBuilderImpl {
+protected:
+  CoreEngine &engine;
+  ExplodedNode *pred;
+  bool HasGeneratedNode;
+  ProgramPoint pp;
+  llvm::SmallVector<ExplodedNode*, 2> sinksGenerated;  
+
+  ExplodedNode *generateNodeImpl(const GRState *state, ExplodedNode *pred,
+                                 ProgramPoint programPoint, bool asSink);
+
+  GenericNodeBuilderImpl(CoreEngine &eng, ExplodedNode *pr, ProgramPoint p)
+    : engine(eng), pred(pr), HasGeneratedNode(false), pp(p) {}
+
+public:
+  bool hasGeneratedNode() const { return HasGeneratedNode; }
+  
+  WorkList &getWorkList() { return *engine.WList; }
+  
+  ExplodedNode* getPredecessor() const { return pred; }
+  
+  BlockCounter getBlockCounter() const {
+    return engine.WList->getBlockCounter();
+  }
+  
+  const llvm::SmallVectorImpl<ExplodedNode*> &sinks() const {
+    return sinksGenerated;
+  }
+};
+
+template <typename PP>
+class GenericNodeBuilder : public GenericNodeBuilderImpl {
+public:
+  GenericNodeBuilder(CoreEngine &eng, ExplodedNode *pr, const PP &p)
+    : GenericNodeBuilderImpl(eng, pr, p) {}
+
+  ExplodedNode *generateNode(const GRState *state, ExplodedNode *pred,
+                             PP programPoint, bool asSink) {
+    return generateNodeImpl(state, pred, programPoint, asSink);
+  }
+  
+  const PP &getProgramPoint() const { return cast<PP>(pp); }
+};
+
 class EndOfFunctionNodeBuilder {
   CoreEngine &Eng;
   const CFGBlock& B;

Modified: cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/ExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/ExprEngine.h?rev=123217&r1=123216&r2=123217&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/ExprEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/ExprEngine.h Tue Jan 11 00:37:47 2011
@@ -193,12 +193,10 @@
   void ProcessTemporaryDtor(const CFGTemporaryDtor D, 
                             StmtNodeBuilder &builder);
 
-  /// processCFGBlockEntrance - Called by CoreEngine when start processing
-  ///  a CFGBlock.  This method returns true if the analysis should continue
-  ///  exploring the given path, and false otherwise.
-  bool processCFGBlockEntrance(const CFGBlock* B, const ExplodedNode *Pred,
-                            BlockCounter BC);
-
+  /// Called by CoreEngine when processing the entrance of a CFGBlock.
+  virtual void processCFGBlockEntrance(ExplodedNodeSet &dstNodes,
+                                GenericNodeBuilder<BlockEntrance> &nodeBuilder);
+  
   /// ProcessBranch - Called by CoreEngine.  Used to generate successor
   ///  nodes by processing the 'effects' of a branch condition.
   void processBranch(const Stmt* Condition, const Stmt* Term, 

Modified: cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/SubEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/SubEngine.h?rev=123217&r1=123216&r2=123217&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/SubEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/PathSensitive/SubEngine.h Tue Jan 11 00:37:47 2011
@@ -13,6 +13,7 @@
 #ifndef LLVM_CLANG_GR_SUBENGINE_H
 #define LLVM_CLANG_GR_SUBENGINE_H
 
+#include "clang/Analysis/ProgramPoint.h"
 #include "clang/StaticAnalyzer/PathSensitive/SVals.h"
 
 namespace clang {
@@ -23,8 +24,10 @@
 class Stmt;
 
 namespace ento {
-
+  
+template <typename PP> class GenericNodeBuilder;
 class AnalysisManager;
+class ExplodedNodeSet;
 class ExplodedNode;
 class GRState;
 class GRStateManager;
@@ -52,12 +55,11 @@
   /// nodes by processing the 'effects' of a block-level statement.
   virtual void processCFGElement(const CFGElement E, StmtNodeBuilder& builder)=0;
 
-  /// Called by CoreEngine when start processing
-  /// a CFGBlock.  This method returns true if the analysis should continue
-  /// exploring the given path, and false otherwise.
-  virtual bool processCFGBlockEntrance(const CFGBlock* B,
-                                       const ExplodedNode *Pred,
-                                       BlockCounter BC) = 0;
+  /// Called by CoreEngine when it starts processing a CFGBlock.  The
+  /// SubEngine is expected to populate dstNodes with new nodes representing
+  /// updated analysis state, or generate no nodes at all if it doesn't.
+  virtual void processCFGBlockEntrance(ExplodedNodeSet &dstNodes,
+                            GenericNodeBuilder<BlockEntrance> &nodeBuilder) = 0;
 
   /// Called by CoreEngine.  Used to generate successor
   ///  nodes by processing the 'effects' of a branch condition.

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp?rev=123217&r1=123216&r2=123217&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ExprEngine.cpp Tue Jan 11 00:37:47 2011
@@ -1077,11 +1077,22 @@
 // Block entrance.  (Update counters).
 //===----------------------------------------------------------------------===//
 
-bool ExprEngine::processCFGBlockEntrance(const CFGBlock* B, 
-                                        const ExplodedNode *Pred,
-                                        BlockCounter BC) {
-  return BC.getNumVisited(Pred->getLocationContext()->getCurrentStackFrame(), 
-                          B->getBlockID()) < AMgr.getMaxVisit();
+void ExprEngine::processCFGBlockEntrance(ExplodedNodeSet &dstNodes,
+                               GenericNodeBuilder<BlockEntrance> &nodeBuilder){
+  
+  // FIXME: Refactor this into a checker.
+  const CFGBlock *block = nodeBuilder.getProgramPoint().getBlock();
+  ExplodedNode *pred = nodeBuilder.getPredecessor();
+  
+  if (nodeBuilder.getBlockCounter().getNumVisited(
+                       pred->getLocationContext()->getCurrentStackFrame(), 
+                       block->getBlockID()) >= AMgr.getMaxVisit()) {
+
+    static int tag = 0;
+    const BlockEntrance &BE = nodeBuilder.getProgramPoint();
+    BlockEntrance BE_tagged(BE.getBlock(), BE.getLocationContext(), &tag);
+    nodeBuilder.generateNode(pred->getState(), pred, BE_tagged, true);
+  }
 }
 
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/StaticAnalyzer/CoreEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/CoreEngine.cpp?rev=123217&r1=123216&r2=123217&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/CoreEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/CoreEngine.cpp Tue Jan 11 00:37:47 2011
@@ -288,13 +288,29 @@
     return;
   }
 
-  // FIXME: Should we allow processCFGBlockEntrance to also manipulate state?
-
-  if (SubEng.processCFGBlockEntrance(Blk, Pred, WList->getBlockCounter()))
-    generateNode(BlockEntrance(Blk, Pred->getLocationContext()),
-                 Pred->State, Pred);
+  // Call into the subengine to process entering the CFGBlock.
+  ExplodedNodeSet dstNodes;
+  BlockEntrance BE(Blk, Pred->getLocationContext());
+  GenericNodeBuilder<BlockEntrance> nodeBuilder(*this, Pred, BE);
+  SubEng.processCFGBlockEntrance(dstNodes, nodeBuilder);
+
+  if (dstNodes.empty()) {
+    if (!nodeBuilder.hasGeneratedNode()) {
+      // Auto-generate a node and enqueue it to the worklist.
+      generateNode(BE, Pred->State, Pred);    
+    }
+  }
   else {
-    blocksAborted.push_back(std::make_pair(L, Pred));
+    for (ExplodedNodeSet::iterator I = dstNodes.begin(), E = dstNodes.end();
+         I != E; ++I) {
+      WList->enqueue(*I);
+    }
+  }
+
+  for (llvm::SmallVectorImpl<ExplodedNode*>::const_iterator
+       I = nodeBuilder.sinks().begin(), E = nodeBuilder.sinks().end();
+       I != E; ++I) {
+    blocksAborted.push_back(std::make_pair(L, *I));
   }
 }
 
@@ -446,6 +462,27 @@
   if (IsNew) WList->enqueue(Node);
 }
 
+ExplodedNode *
+GenericNodeBuilderImpl::generateNodeImpl(const GRState *state,
+                                         ExplodedNode *pred,
+                                         ProgramPoint programPoint,
+                                         bool asSink) {
+  
+  HasGeneratedNode = true;
+  bool isNew;
+  ExplodedNode *node = engine.getGraph().getNode(programPoint, state, &isNew);
+  if (pred)
+    node->addPredecessor(pred, engine.getGraph());
+  if (isNew) {
+    if (asSink) {
+      node->markAsSink();
+      sinksGenerated.push_back(node);
+    }
+    return node;
+  }
+  return 0;
+}
+
 StmtNodeBuilder::StmtNodeBuilder(const CFGBlock* b, unsigned idx,
                                      ExplodedNode* N, CoreEngine* e,
                                      GRStateManager &mgr)

Modified: cfe/trunk/test/Analysis/retain-release-region-store.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/retain-release-region-store.m?rev=123217&r1=123216&r2=123217&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/retain-release-region-store.m (original)
+++ cfe/trunk/test/Analysis/retain-release-region-store.m Tue Jan 11 00:37:47 2011
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=region -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-store=region -analyzer-max-loop 6 -verify %s
 
 //===----------------------------------------------------------------------===//
 // The following code is reduced using delta-debugging from





More information about the cfe-commits mailing list