[cfe-commits] r46581 - in /cfe/trunk: Analysis/GRConstants.cpp Analysis/GREngine.cpp include/clang/Analysis/PathSensitive/ExplodedGraph.h include/clang/Analysis/PathSensitive/GREngine.h

Ted Kremenek kremenek at apple.com
Wed Jan 30 15:03:39 PST 2008


Author: kremenek
Date: Wed Jan 30 17:03:39 2008
New Revision: 46581

URL: http://llvm.org/viewvc/llvm-project?rev=46581&view=rev
Log:
Implemented some branch pruning in GRConstants using != and == for
constant integers.

Modified:
    cfe/trunk/Analysis/GRConstants.cpp
    cfe/trunk/Analysis/GREngine.cpp
    cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h
    cfe/trunk/include/clang/Analysis/PathSensitive/GREngine.h

Modified: cfe/trunk/Analysis/GRConstants.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/GRConstants.cpp?rev=46581&r1=46580&r2=46581&view=diff

==============================================================================
--- cfe/trunk/Analysis/GRConstants.cpp (original)
+++ cfe/trunk/Analysis/GRConstants.cpp Wed Jan 30 17:03:39 2008
@@ -26,6 +26,7 @@
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/ImmutableMap.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Streams.h"
@@ -722,8 +723,18 @@
   };
 }
 
+typedef ValueMapTy StateTy;
+
 //===----------------------------------------------------------------------===//
 // The Checker.
+//
+//  FIXME: This checker logic should be eventually broken into two components.
+//         The first is the "meta"-level checking logic; the code that
+//         does the Stmt visitation, fetching values from the map, etc.
+//         The second part does the actual state manipulation.  This way we
+//         get more of a separate of concerns of these two pieces, with the
+//         latter potentially being refactored back into the main checking
+//         logic.
 //===----------------------------------------------------------------------===//
 
 namespace {
@@ -743,9 +754,9 @@
   public:
     
     NodeSet() {}
-    NodeSet(NodeTy* N) { assert (N && !N->isInfeasible()); Impl.push_back(N); }
+    NodeSet(NodeTy* N) { assert (N && !N->isSink()); Impl.push_back(N); }
     
-    void Add(NodeTy* N) { if (N && !N->isInfeasible()) Impl.push_back(N); }
+    void Add(NodeTy* N) { if (N && !N->isSink()) Impl.push_back(N); }
     
     typedef ImplTy::iterator       iterator;
     typedef ImplTy::const_iterator const_iterator;
@@ -787,6 +798,11 @@
   /// CurrentStmt - The current block-level statement.
   Stmt* CurrentStmt;
   
+  /// UninitBranches - Nodes in the ExplodedGraph that result from
+  ///  taking a branch based on an uninitialized value.
+  typedef llvm::SmallPtrSet<NodeTy*,5> UninitBranchesTy;
+  UninitBranchesTy UninitBranches;
+  
   bool StateCleaned;
   
   ASTContext& getContext() const { return G.getContext(); }
@@ -856,6 +872,19 @@
   
   RValue GetValue(const StateTy& St, const LValue& LV);
   LValue GetLValue(const StateTy& St, Stmt* S);
+    
+  /// Assume - Create new state by assuming that a given expression
+  ///  is true or false.
+  inline StateTy Assume(StateTy St, RValue Cond, bool Assumption, 
+                        bool& isFeasible) {
+    if (isa<LValue>(Cond))
+      return Assume(St, cast<LValue>(Cond), Assumption, isFeasible);
+    else
+      return Assume(St, cast<NonLValue>(Cond), Assumption, isFeasible);
+  }
+  
+  StateTy Assume(StateTy St, LValue Cond, bool Assumption, bool& isFeasible);
+  StateTy Assume(StateTy St, NonLValue Cond, bool Assumption, bool& isFeasible);
   
   void Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, StateTy St);
   
@@ -880,8 +909,54 @@
 
 void GRConstants::ProcessBranch(Stmt* Condition, Stmt* Term,
                                 BranchNodeBuilder& builder) {
+
+  StateTy PrevState = builder.getState();
+  
+  // Remove old bindings for subexpressions.  
+  for (StateTy::iterator I=PrevState.begin(), E=PrevState.end(); I!=E; ++I)
+    if (I.getKey().isSubExpr())
+      PrevState = StateMgr.Remove(PrevState, I.getKey());
+  
+  RValue V = GetValue(PrevState, Condition);
+  
+  switch (V.getBaseKind()) {
+    default:
+      break;
+
+    case RValue::InvalidKind:
+      builder.generateNode(PrevState, true);
+      builder.generateNode(PrevState, false);
+      return;
+      
+    case RValue::UninitializedKind: {      
+      NodeTy* N = builder.generateNode(PrevState, true);
+
+      if (N) {
+        N->markAsSink();
+        UninitBranches.insert(N);
+      }
+      
+      builder.markInfeasible(false);
+      return;
+    }      
+  }
+
+  // Process the true branch.
+  bool isFeasible = true;
+  StateTy St = Assume(PrevState, V, true, isFeasible);
+
+  if (isFeasible) builder.generateNode(St, true);
+  else {
+    builder.markInfeasible(true);
+    isFeasible = true;
+  }
   
+  // Process the false branch.  
+  St = Assume(PrevState, V, false, isFeasible);
   
+  if (isFeasible) builder.generateNode(St, false);
+  else builder.markInfeasible(false);
+
 }
 
 void GRConstants::ProcessStmt(Stmt* S, StmtNodeBuilder& builder) {
@@ -1369,6 +1444,32 @@
 }
 
 //===----------------------------------------------------------------------===//
+// "Assume" logic.
+//===----------------------------------------------------------------------===//
+
+StateTy GRConstants::Assume(StateTy St, LValue Cond, bool Assumption, 
+                            bool& isFeasible) {    
+  return St;
+}
+
+StateTy GRConstants::Assume(StateTy St, NonLValue Cond, bool Assumption, 
+                            bool& isFeasible) {
+  
+  switch (Cond.getSubKind()) {
+    default:
+      assert (false && "'Assume' not implemented for this NonLValue.");
+      return St;
+      
+    case ConcreteIntKind: {
+      bool b = cast<ConcreteInt>(Cond).getValue() != 0;
+      isFeasible = b ? Assumption : !Assumption;      
+      return St;
+    }
+  }
+}
+
+
+//===----------------------------------------------------------------------===//
 // Driver.
 //===----------------------------------------------------------------------===//
 
@@ -1447,6 +1548,24 @@
         const BlockEdge& E = cast<BlockEdge>(Loc);
         Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
             << E.getDst()->getBlockID()  << ')';
+        
+        if (Stmt* T = E.getSrc()->getTerminator()) {
+          Out << "\\|Terminator: ";
+          E.getSrc()->printTerminator(Out);
+          
+          if (isa<SwitchStmt>(T)) {
+            // FIXME
+          }
+          else {
+            Out << "\\lCondition: ";
+            if (*E.getSrc()->succ_begin() == E.getDst())
+              Out << "true";
+            else
+              Out << "false";                        
+          }
+          
+          Out << "\\l";
+        }
       }
     }
     

Modified: cfe/trunk/Analysis/GREngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/GREngine.cpp?rev=46581&r1=46580&r2=46581&view=diff

==============================================================================
--- cfe/trunk/Analysis/GREngine.cpp (original)
+++ cfe/trunk/Analysis/GREngine.cpp Wed Jan 30 17:03:39 2008
@@ -243,12 +243,12 @@
 
 GRStmtNodeBuilderImpl::~GRStmtNodeBuilderImpl() {
   for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
-    if (!(*I)->isInfeasible())
+    if (!(*I)->isSink())
       GenerateAutoTransition(*I);
 }
 
 void GRStmtNodeBuilderImpl::GenerateAutoTransition(ExplodedNodeImpl* N) {
-  assert (!N->isInfeasible());
+  assert (!N->isSink());
   
   PostStmt Loc(getStmt());
   
@@ -287,7 +287,8 @@
   return NULL;  
 }
 
-void GRBranchNodeBuilderImpl::generateNodeImpl(void* State, bool branch) {  
+ExplodedNodeImpl* GRBranchNodeBuilderImpl::generateNodeImpl(void* State,
+                                                            bool branch) {  
   bool IsNew;
   
   ExplodedNodeImpl* Succ =
@@ -299,8 +300,12 @@
   if (branch) GeneratedTrue = true;
   else GeneratedFalse = true;  
   
-  if (IsNew)
+  if (IsNew) {
     Eng.WList->Enqueue(GRWorkListUnit(Succ));
+    return Succ;
+  }
+  
+  return NULL;
 }
 
 GRBranchNodeBuilderImpl::~GRBranchNodeBuilderImpl() {

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h?rev=46581&r1=46580&r2=46581&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h Wed Jan 30 17:03:39 2008
@@ -43,15 +43,15 @@
   friend class GRBranchNodeBuilderImpl;
   
   class NodeGroup {
-    enum { Size1 = 0x0, SizeOther = 0x1, Infeasible = 0x2, Flags = 0x3 };
+    enum { Size1 = 0x0, SizeOther = 0x1, AuxFlag = 0x2, Mask = 0x3 };
     uintptr_t P;
     
     unsigned getKind() const {
-      return P & Flags;
+      return P & Mask;
     }
     
     void* getPtr() const {
-      return reinterpret_cast<void*>(P & ~Flags);
+      return reinterpret_cast<void*>(P & ~Mask);
     }
 
     ExplodedNodeImpl* getNode() const {
@@ -73,15 +73,14 @@
     
     void addNode(ExplodedNodeImpl* N);
     
-    void setInfeasibleFlag() {
-      P |= Infeasible;
+    void setFlag() {
+      P |= AuxFlag;
     }
     
-    bool getInfeasibleFlag() const {
-      return P & Infeasible ? true : false;
+    bool getFlag() const {
+      return P & AuxFlag ? true : false;
     }
-  };
-  
+  };  
   
   /// Location - The program location (within a function body) associated
   ///  with this node.
@@ -105,7 +104,7 @@
   /// addPredeccessor - Adds a predecessor to the current node, and 
   ///  in tandem add this node as a successor of the other node.
   void addPredecessor(ExplodedNodeImpl* V) {
-    assert (!V->isInfeasible());
+    assert (!V->isSink());
     Preds.addNode(V);
     V->Succs.addNode(this);
   }
@@ -129,8 +128,8 @@
   bool succ_empty() const { return Succs.empty(); }
   bool pred_empty() const { return Preds.size(); }
   
-  bool isInfeasible() const { return Preds.getInfeasibleFlag(); }
-  void setInfeasible() { Preds.setInfeasibleFlag(); }  
+  bool isSink() const { return Preds.getFlag(); }
+  void markAsSink() { Preds.setFlag(); }  
 };
 
 

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GREngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GREngine.h?rev=46581&r1=46580&r2=46581&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GREngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GREngine.h Wed Jan 30 17:03:39 2008
@@ -112,7 +112,7 @@
   const ExplodedGraphImpl& getGraph() const { return *Eng.G; }
   
   inline ExplodedNodeImpl* getLastNode() {
-    return LastNode ? (LastNode->isInfeasible() ? NULL : LastNode) : NULL;
+    return LastNode ? (LastNode->isSink() ? NULL : LastNode) : NULL;
   }
   
   ExplodedNodeImpl* generateNodeImpl(Stmt* S, void* State,
@@ -178,9 +178,10 @@
   
   ~GRBranchNodeBuilderImpl();
   
+  ExplodedNodeImpl* getPredecessor() const { return Pred; }
   const ExplodedGraphImpl& getGraph() const { return *Eng.G; }
     
-  void generateNodeImpl(void* State, bool branch);  
+  ExplodedNodeImpl* generateNodeImpl(void* State, bool branch);  
   
   void markInfeasible(bool branch) {
     if (branch) GeneratedTrue = true;
@@ -203,10 +204,18 @@
   const GraphTy& getGraph() const {
     return static_cast<const GraphTy&>(NB.getGraph());
   }
+  
+  NodeTy* getPredecessor() const {
+    return static_cast<NodeTy*>(NB.getPredecessor());
+  }
+  
+  StateTy getState() const {
+    return getPredecessor()->getState();
+  }
 
-  inline void generateNode(StateTy State, bool branch) {
+  inline NodeTy* generateNode(StateTy State, bool branch) {
     void *state = GRTrait<StateTy>::toPtr(State);        
-    NB.generateNodeImpl(state, branch);
+    return static_cast<NodeTy*>(NB.generateNodeImpl(state, branch));
   }
   
   inline void markInfeasible(bool branch) {





More information about the cfe-commits mailing list