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

Ted Kremenek kremenek at apple.com
Tue Feb 12 16:24:46 PST 2008


Author: kremenek
Date: Tue Feb 12 18:24:44 2008
New Revision: 47038

URL: http://llvm.org/viewvc/llvm-project?rev=47038&view=rev
Log:
Added support to GREngine/GRConstants for handling computed gotos.

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
    cfe/trunk/include/clang/Analysis/ProgramPoint.h

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

==============================================================================
--- cfe/trunk/Analysis/GRConstants.cpp (original)
+++ cfe/trunk/Analysis/GRConstants.cpp Tue Feb 12 18:24:44 2008
@@ -67,6 +67,7 @@
   typedef ValueStateManager::StateTy StateTy;
   typedef GRStmtNodeBuilder<GRConstants> StmtNodeBuilder;
   typedef GRBranchNodeBuilder<GRConstants> BranchNodeBuilder;
+  typedef GRIndirectGotoNodeBuilder<GRConstants> IndirectGotoNodeBuilder;
   typedef ExplodedGraph<GRConstants> GraphTy;
   typedef GraphTy::NodeTy NodeTy;
   
@@ -192,6 +193,10 @@
   ///  nodes by processing the 'effects' of a branch condition.
   void ProcessBranch(Expr* Condition, Stmt* Term, BranchNodeBuilder& builder);
 
+  /// ProcessIndirectGoto - Called by GREngine.  Used to generate successor
+  ///  nodes by processing the 'effects' of a computed goto jump.
+  void ProcessIndirectGoto(IndirectGotoNodeBuilder& builder);
+  
   /// RemoveDeadBindings - Return a new state that is the same as 'St' except
   ///  that all subexpression mappings are removed and that any
   ///  block-level expressions that are not live at 'S' also have their
@@ -424,6 +429,52 @@
     builder.markInfeasible(false);
 }
 
+/// ProcessIndirectGoto - Called by GREngine.  Used to generate successor
+///  nodes by processing the 'effects' of a computed goto jump.
+void GRConstants::ProcessIndirectGoto(IndirectGotoNodeBuilder& builder) {
+
+  StateTy St = builder.getState();  
+  LValue V = cast<LValue>(GetValue(St, builder.getTarget()));
+  
+  // Three possibilities:
+  //
+  //   (1) We know the computed label.
+  //   (2) The label is NULL (or some other constant), or Uninitialized.
+  //   (3) We have no clue about the label.  Dispatch to all targets.
+  //
+  
+  typedef IndirectGotoNodeBuilder::iterator iterator;
+
+  if (isa<lval::GotoLabel>(V)) {
+    LabelStmt* L = cast<lval::GotoLabel>(V).getLabel();
+    
+    for (iterator I=builder.begin(), E=builder.end(); I != E; ++I) {
+      IndirectGotoNodeBuilder::Destination D = *I;
+      
+      if (D.getLabel() == L) {
+        builder.generateNode(D, St);
+        return;
+      }
+    }
+    
+    assert (false && "No block with label.");
+    return;
+  }
+
+  if (isa<lval::ConcreteInt>(V) || isa<UninitializedVal>(V)) {
+    // Dispatch to the first target and mark it as a sink.
+    NodeTy* N = builder.generateNode(*builder.begin(), St, true);
+    UninitBranches.insert(N);
+    return;
+  }
+  
+  // This is really a catch-all.  We don't support symbolics yet.
+  
+  assert (isa<UnknownVal>(V));
+  
+  for (iterator I=builder.begin(), E=builder.end(); I != E; ++I)
+    builder.generateNode(*I, St);
+}
 
 void GRConstants::VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred,
                                    NodeSet& Dst) {
@@ -1305,7 +1356,7 @@
           Out << "\\|Terminator: ";
           E.getSrc()->printTerminator(Out);
           
-          if (isa<SwitchStmt>(T)) {
+          if (isa<SwitchStmt>(T) || isa<IndirectGotoStmt>(T)) {
             // FIXME
           }
           else {

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

==============================================================================
--- cfe/trunk/Analysis/GREngine.cpp (original)
+++ cfe/trunk/Analysis/GREngine.cpp Tue Feb 12 18:24:44 2008
@@ -198,6 +198,18 @@
       case Stmt::IfStmtClass:
         HandleBranch(cast<IfStmt>(Term)->getCond(), Term, B, Pred);
         return;
+               
+      case Stmt::IndirectGotoStmtClass: {
+        // Only 1 successor: the indirect goto dispatch block.
+        assert (B->succ_size() == 1);
+        
+        GRIndirectGotoNodeBuilderImpl
+           builder(Pred, B, cast<IndirectGotoStmt>(Term)->getTarget(),
+                   *(B->succ_begin()), this);
+        
+        ProcessIndirectGoto(builder);
+        return;
+      }
         
       case Stmt::WhileStmtClass:
         HandleBranch(cast<WhileStmt>(Term)->getCond(), Term, B, Pred);
@@ -346,3 +358,46 @@
   for (DeferredTy::iterator I=Deferred.begin(), E=Deferred.end(); I!=E; ++I)
     if (!(*I)->isSink()) Eng.WList->Enqueue(*I);
 }
+
+GRIndirectGotoNodeBuilderImpl::Destination
+GRIndirectGotoNodeBuilderImpl::Iterator::operator*() {
+  CFGBlock* B = *I;
+  assert (!B->empty());      
+  LabelStmt* L = cast<LabelStmt>(B->getLabel());
+  return Destination(L, *I);
+}
+
+GRIndirectGotoNodeBuilderImpl::Iterator
+GRIndirectGotoNodeBuilderImpl::begin() {
+  return Iterator(DispatchBlock.succ_begin());
+}
+
+GRIndirectGotoNodeBuilderImpl::Iterator
+GRIndirectGotoNodeBuilderImpl::end() {
+  return Iterator(DispatchBlock.succ_end());
+}
+
+ExplodedNodeImpl*
+GRIndirectGotoNodeBuilderImpl::generateNodeImpl(const Destination& D,
+                                                void* St,
+                                                bool isSink) {
+  bool IsNew;
+  
+  ExplodedNodeImpl* Succ =
+    Eng.G->getNodeImpl(BlockEdge(Eng.getCFG(), Src, D.getBlock(), true),
+                       St, &IsNew);
+              
+  Succ->addPredecessor(Pred);
+  
+  if (IsNew) {
+    
+    if (isSink)
+      Succ->markAsSink();
+    else
+      Eng.WList->Enqueue(Succ);
+    
+    return Succ;
+  }
+                       
+  return NULL;
+}

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=47038&r1=47037&r2=47038&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/ExplodedGraph.h Tue Feb 12 18:24:44 2008
@@ -30,6 +30,7 @@
 class ExplodedNodeImpl;
 class GRStmtNodeBuilderImpl;
 class GRBranchNodeBuilderImpl;
+class GRIndirectGotoNodeBuilderImpl;
 class CFG;
 class ASTContext;
 class FunctionDecl;
@@ -41,6 +42,7 @@
   friend class GREngineImpl;
   friend class GRStmtNodeBuilderImpl;
   friend class GRBranchNodeBuilderImpl;
+  friend class GRIndirectGotoNodeBuilderImpl;
   
   class NodeGroup {
     enum { Size1 = 0x0, SizeOther = 0x1, AuxFlag = 0x2, Mask = 0x3 };
@@ -195,6 +197,7 @@
   friend class GREngineImpl;
   friend class GRStmtNodeBuilderImpl;
   friend class GRBranchNodeBuilderImpl;
+  friend class GRIndirectGotoNodeBuilderImpl;
   
   // Type definitions.
   typedef llvm::DenseMap<ProgramPoint,void*>        EdgeNodeSetMap;

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=47038&r1=47037&r2=47038&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GREngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GREngine.h Tue Feb 12 18:24:44 2008
@@ -24,12 +24,15 @@
   
 class GRStmtNodeBuilderImpl;
 class GRBranchNodeBuilderImpl;
+class GRIndirectGotoNodeBuilderImpl;
 class GRWorkList;
+class LabelStmt;
   
 class GREngineImpl {
 protected:
   friend class GRStmtNodeBuilderImpl;
   friend class GRBranchNodeBuilderImpl;
+  friend class GRIndirectGotoNodeBuilderImpl;
   
   typedef llvm::DenseMap<Stmt*,Stmt*> ParentMapTy;
     
@@ -78,6 +81,7 @@
   virtual void  ProcessBranch(Expr* Condition, Stmt* Terminator,
                               GRBranchNodeBuilderImpl& Builder) = 0;
 
+  virtual void ProcessIndirectGoto(GRIndirectGotoNodeBuilderImpl& Builder) = 0;
 
 private:
   GREngineImpl(const GREngineImpl&); // Do not implement.
@@ -246,6 +250,87 @@
   }
 };
   
+class GRIndirectGotoNodeBuilderImpl {
+  GREngineImpl& Eng;
+  CFGBlock* Src;
+  CFGBlock& DispatchBlock;
+  Expr* E;
+  ExplodedNodeImpl* Pred;  
+public:
+  GRIndirectGotoNodeBuilderImpl(ExplodedNodeImpl* pred, CFGBlock* src,
+                                Expr* e, CFGBlock* dispatch,
+                                GREngineImpl* eng)
+  : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {}
+  
+  class Iterator;
+  
+  class Destination {
+    LabelStmt* L;
+    CFGBlock* B;
+
+    friend class Iterator;
+    Destination(LabelStmt* l, CFGBlock* b) : L(l), B(b) {}
+    
+  public:    
+    CFGBlock*  getBlock() const { return B; }
+    LabelStmt* getLabel() const { return L; }
+  };
+  
+  class Iterator {
+    CFGBlock::succ_iterator I;
+    
+    friend class GRIndirectGotoNodeBuilderImpl;    
+    Iterator(CFGBlock::succ_iterator i) : I(i) {}    
+  public:
+    
+    Iterator& operator++() { ++I; return *this; }
+    bool operator!=(const Iterator& X) const { return I != X.I; }
+    
+    Destination operator*();
+  };
+  
+  Iterator begin();
+  Iterator end();
+  
+  ExplodedNodeImpl* generateNodeImpl(const Destination& D, void* State,
+                                     bool isSink);
+  
+  inline Expr* getTarget() const { return E; }
+  inline void* getState() const { return Pred->State; }
+};
+  
+template<typename CHECKER>
+class GRIndirectGotoNodeBuilder {
+  typedef CHECKER                                CheckerTy; 
+  typedef typename CheckerTy::StateTy            StateTy;
+  typedef ExplodedGraph<CheckerTy>               GraphTy;
+  typedef typename GraphTy::NodeTy               NodeTy;
+
+  GRIndirectGotoNodeBuilderImpl& NB;
+
+public:
+  GRIndirectGotoNodeBuilder(GRIndirectGotoNodeBuilderImpl& nb) : NB(nb) {}
+  
+  typedef GRIndirectGotoNodeBuilderImpl::Iterator     iterator;
+  typedef GRIndirectGotoNodeBuilderImpl::Destination  Destination;
+
+  inline iterator begin() { return NB.begin(); }
+  inline iterator end() { return NB.end(); }
+  
+  inline Expr* getTarget() const { return NB.getTarget(); }
+  
+  inline NodeTy* generateNode(const Destination& D, StateTy St,
+                              bool isSink = false) {
+    
+    void *state = GRTrait<StateTy>::toPtr(St);        
+    return static_cast<NodeTy*>(NB.generateNodeImpl(D, state, isSink));
+  }
+  
+  inline StateTy getState() const {
+    return GRTrait<StateTy>::toState(NB.getState());
+  }    
+};
+
   
 template<typename CHECKER>
 class GREngine : public GREngineImpl {
@@ -274,13 +359,16 @@
     Checker->ProcessStmt(S, Builder);
   }
 
-
   virtual void ProcessBranch(Expr* Condition, Stmt* Terminator,
                              GRBranchNodeBuilderImpl& BuilderImpl) {
     GRBranchNodeBuilder<CHECKER> Builder(BuilderImpl);
     Checker->ProcessBranch(Condition, Terminator, Builder);    
   }
   
+  virtual void ProcessIndirectGoto(GRIndirectGotoNodeBuilderImpl& BuilderImpl) {
+    GRIndirectGotoNodeBuilder<CHECKER> Builder(BuilderImpl);
+    Checker->ProcessIndirectGoto(Builder);
+  }
   
 public:  
   /// Construct a GREngine object to analyze the provided CFG using

Modified: cfe/trunk/include/clang/Analysis/ProgramPoint.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/ProgramPoint.h?rev=47038&r1=47037&r2=47038&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/ProgramPoint.h (original)
+++ cfe/trunk/include/clang/Analysis/ProgramPoint.h Tue Feb 12 18:24:44 2008
@@ -104,6 +104,15 @@
   typedef std::pair<CFGBlock*,CFGBlock*> BPair;
 public:
   BlockEdge(CFG& cfg, const CFGBlock* B1, const CFGBlock* B2);
+  
+  /// This ctor forces the BlockEdge to be constructed using an explicitly
+  ///  allocated pair object that is stored in the CFG.  This is usually
+  ///  used to construct edges representing jumps using computed gotos.
+  BlockEdge(CFG& cfg, const CFGBlock* B1, const CFGBlock* B2, bool) {
+    Data = reinterpret_cast<uintptr_t>(cfg.getBlockEdgeImpl(B1, B2))
+           | BlockEdgeAuxKind;
+  }
+
 
   CFGBlock* getSrc() const;
   CFGBlock* getDst() const;





More information about the cfe-commits mailing list