]> granicus.if.org Git - clang/commitdiff
[analyzer] Convert VisitUnaryOperator to use short lived Node builders
authorAnna Zaks <ganna@apple.com>
Mon, 24 Oct 2011 18:26:03 +0000 (18:26 +0000)
committerAnna Zaks <ganna@apple.com>
Mon, 24 Oct 2011 18:26:03 +0000 (18:26 +0000)
To convert iteratively, we take the nodes the local builder will
process from the from the global builder and add the generated nodes
after the short lived builder is done. PureStmtNodeBuilder is the
one we should eventually use everywhere. Added Stmt index and Builder
context as ExprEngine globals. To avoid passing them around.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142828 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
lib/StaticAnalyzer/Core/ExprEngine.cpp
lib/StaticAnalyzer/Core/ExprEngineC.cpp

index f31cdc986da9ffd5d03cf5aba3be3a81733cbf03..f304d82786ea76ec77099b33a540f318431b6286 100644 (file)
@@ -222,18 +222,16 @@ public:
   NodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
               const NodeBuilderContext &Ctx, bool F = true)
     : C(Ctx), Finalized(F), HasGeneratedNodes(false), Frontier(DstSet) {
-    assert(DstSet.empty());
+  //  assert(DstSet.empty());
     Frontier.Add(SrcNode);
   }
 
   NodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet,
               const NodeBuilderContext &Ctx, bool F = true)
     : C(Ctx), Finalized(F), HasGeneratedNodes(false), Frontier(DstSet) {
-    assert(DstSet.empty());
+    //assert(DstSet.empty());
     //assert(!SrcSet.empty());
-
     Frontier.insert(SrcSet);
-
     assert(haveNoSinksInFrontier());
   }
 
@@ -297,7 +295,31 @@ protected:
 };
 
 
-class StmtNodeBuilder: public NodeBuilder {
+class PureStmtNodeBuilder: public NodeBuilder {
+public:
+  PureStmtNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
+                      const NodeBuilderContext &Ctx)
+    : NodeBuilder(SrcNode, DstSet, Ctx) {}
+
+  ExplodedNode *generateNode(const Stmt *S,
+                             ExplodedNode *Pred,
+                             const ProgramState *St,
+                             ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
+                             bool MarkAsSink = false,
+                             const ProgramPointTag *tag = 0,
+                             bool Purging = false) {
+    if (Purging) {
+      assert(K == ProgramPoint::PostStmtKind);
+      K = ProgramPoint::PostPurgeDeadSymbolsKind;
+    }
+
+    const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
+                                  Pred->getLocationContext(), tag);
+    return generateNodeImpl(L, St, Pred, MarkAsSink);
+  }
+};
+
+class StmtNodeBuilder : public NodeBuilder {
   const unsigned Idx;
 
 public:
@@ -310,15 +332,14 @@ public:
 
   void GenerateAutoTransition(ExplodedNode *N);
 
-public:
   StmtNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
                   unsigned idx, const NodeBuilderContext &Ctx)
     : NodeBuilder(SrcNode, DstSet, Ctx), Idx(idx),
       PurgingDeadSymbols(false), BuildSinks(false), hasGeneratedNode(false),
       PointKind(ProgramPoint::PostStmtKind), Tag(0) {}
 
-  ~StmtNodeBuilder();
-  
+  virtual ~StmtNodeBuilder();
+
   ExplodedNode *generateNode(const Stmt *S,
                              const ProgramState *St,
                              ExplodedNode *Pred,
@@ -395,7 +416,6 @@ public:
   void addNodes(ExplodedNode *N) {
     Frontier.Add(N);
   }
-
 };
 
 class BranchNodeBuilder: public NodeBuilder {
index f18b04b8b8a6080a54a1db71bfe8f68878b22267..a593fac99a5ced864796103945912b85de2f86f7 100644 (file)
@@ -69,6 +69,8 @@ class ExprEngine : public SubEngine {
 
   /// currentStmt - The current block-level statement.
   const Stmt *currentStmt;
+  unsigned int currentStmtIdx;
+  const NodeBuilderContext *currentBuilderContext;
 
   /// Obj-C Class Identifiers.
   IdentifierInfo* NSExceptionII;
@@ -343,6 +345,11 @@ public:
   void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode *Pred, 
                           ExplodedNodeSet &Dst);
 
+  /// Handle ++ and -- (both pre- and post-increment).
+  void VisitIncrementDecrementOperator(const UnaryOperator* U,
+                                       ExplodedNode *Pred,
+                                       ExplodedNodeSet &Dst);
+
   void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 
                         ExplodedNodeSet & Dst);
 
index eaba5eedb5fa91958bed7a5bbe04c3fca12514fb..f141392cbd048050ee26992fb50719f926cd4240 100644 (file)
@@ -62,7 +62,8 @@ ExprEngine::ExprEngine(AnalysisManager &mgr, bool gcEnabled)
              *this),
     SymMgr(StateMgr.getSymbolManager()),
     svalBuilder(StateMgr.getSValBuilder()),
-    EntryNode(NULL), currentStmt(NULL),
+    EntryNode(NULL),
+    currentStmt(NULL), currentStmtIdx(0), currentBuilderContext(0),
     NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL),
     RaiseSel(GetNullarySelector("raise", getContext())),
     ObjCGCEnabled(gcEnabled), BR(mgr, *this) {
@@ -229,6 +230,9 @@ void ExprEngine::ProcessStmt(const CFGStmt S, StmtNodeBuilder& builder,
   StateMgr.recycleUnusedStates();
   
   currentStmt = S.getStmt();
+  currentStmtIdx = builder.getIndex();
+  currentBuilderContext = &builder.getContext();
+
   PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
                                 currentStmt->getLocStart(),
                                 "Error evaluating statement");
@@ -432,7 +436,7 @@ void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D,
 }
 
 void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, 
-                         ExplodedNodeSet &Dst) {
+                       ExplodedNodeSet &Dst) {
   PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
                                 S->getLocStart(),
                                 "Error evaluating statement");
index 68ccc59ac952c0e7d367ba014b6a1b707dd309af..eeb6b44ef2b464892309b97283915d6425569776 100644 (file)
@@ -530,9 +530,15 @@ VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex,
 
 void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, 
                                     ExplodedNode *Pred,
-                                    ExplodedNodeSet &Dst) {  
+                                    ExplodedNodeSet &Dst) {
+  Builder->takeNodes(Pred);
+  PureStmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
+  bool IncDec = false;
   switch (U->getOpcode()) {
     default:
+      Builder->addNodes(Pred);
+      IncDec = true;
+      VisitIncrementDecrementOperator(U, Pred, Dst);
       break;
     case UO_Real: {
       const Expr *Ex = U->getSubExpr()->IgnoreParens();
@@ -544,17 +550,16 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
         // FIXME: We don't have complex SValues yet.
         if (Ex->getType()->isAnyComplexType()) {
           // Just report "Unknown."
-          Dst.Add(*I);
           continue;
         }
         
         // For all other types, UO_Real is an identity operation.
         assert (U->getType() == Ex->getType());
         const ProgramState *state = (*I)->getState();
-        MakeNode(Dst, U, *I, state->BindExpr(U, state->getSVal(Ex)));
+        Bldr.generateNode(U, *I, state->BindExpr(U, state->getSVal(Ex)));
       }
       
-      return;
+      break;
     }
       
     case UO_Imag: {
@@ -567,17 +572,16 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
         // FIXME: We don't have complex SValues yet.
         if (Ex->getType()->isAnyComplexType()) {
           // Just report "Unknown."
-          Dst.Add(*I);
           continue;
         }
         
         // For all other types, UO_Imag returns 0.
         const ProgramState *state = (*I)->getState();
         SVal X = svalBuilder.makeZeroVal(Ex->getType());
-        MakeNode(Dst, U, *I, state->BindExpr(U, X));
+        Bldr.generateNode(U, *I, state->BindExpr(U, X));
       }
       
-      return;
+      break;
     }
       
     case UO_Plus:
@@ -598,10 +602,10 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
       
       for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
         const ProgramState *state = (*I)->getState();
-        MakeNode(Dst, U, *I, state->BindExpr(U, state->getSVal(Ex)));
+        Bldr.generateNode(U, *I, state->BindExpr(U, state->getSVal(Ex)));
       }
       
-      return;
+      break;
     }
       
     case UO_LNot:
@@ -619,7 +623,7 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
         SVal V = state->getSVal(Ex);
         
         if (V.isUnknownOrUndef()) {
-          MakeNode(Dst, U, *I, state->BindExpr(U, V));
+          Bldr.generateNode(U, *I, state->BindExpr(U, V));
           continue;
         }
         
@@ -660,14 +664,19 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
             
             break;
         }
-        
-        MakeNode(Dst, U, *I, state);
+        Bldr.generateNode(U, *I, state);
       }
-      
-      return;
+      break;
     }
   }
-  
+
+  if (!IncDec)
+    Builder->addNodes(Dst);
+}
+
+void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
+                                                 ExplodedNode *Pred,
+                                                 ExplodedNodeSet &Dst) {
   // Handle ++ and -- (both pre- and post-increment).
   assert (U->isIncrementDecrementOp());
   ExplodedNodeSet Tmp;
@@ -729,7 +738,7 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U,
             // It isn't feasible for the original value to be null.
             // Propagate this constraint.
             Constraint = svalBuilder.evalEQ(state, SymVal,
-                                            svalBuilder.makeZeroVal(U->getType()));
+                                         svalBuilder.makeZeroVal(U->getType()));
             
             
             state = state->assume(Constraint, false);