]> granicus.if.org Git - clang/commitdiff
[analyzer] Modularize builder use in processBranch.
authorAnna Zaks <ganna@apple.com>
Tue, 18 Oct 2011 23:06:21 +0000 (23:06 +0000)
committerAnna Zaks <ganna@apple.com>
Tue, 18 Oct 2011 23:06:21 +0000 (23:06 +0000)
Take advantage of the new builders for branch processing. As part of this change pass generic NodeBuilder (instead of BranchNodeBuilder) to the BranchCondition callback and remove the unused methods form BranchBuilder.

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

include/clang/StaticAnalyzer/Core/Checker.h
include/clang/StaticAnalyzer/Core/CheckerManager.h
include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp
lib/StaticAnalyzer/Core/CheckerManager.cpp
lib/StaticAnalyzer/Core/CoreEngine.cpp
lib/StaticAnalyzer/Core/ExprEngine.cpp

index 1e4edeb0c7ae4c5d6de8a57f4e51a7b7b3d2c344..51533489e5fbecf30572a5df2978c440c3b005df 100644 (file)
@@ -215,7 +215,7 @@ public:
 class BranchCondition {
   template <typename CHECKER>
   static void _checkBranchCondition(void *checker, const Stmt *condition,
-                                    BranchNodeBuilder &B, ExprEngine &Eng) {
+                                    NodeBuilder &B, ExprEngine &Eng) {
     ((const CHECKER *)checker)->checkBranchCondition(condition, B, Eng);
   }
 
index e3e4c49f71e11c3c97c087f86719e3288337292f..6026aec643aa42ff2264e4c287b1ad6db4f77252 100644 (file)
@@ -39,7 +39,7 @@ namespace ento {
   class ExplodedGraph;
   class ProgramState;
   class EndOfFunctionNodeBuilder;
-  class BranchNodeBuilder;
+  class NodeBuilder;
   class MemRegion;
   class SymbolReaper;
 
@@ -232,7 +232,7 @@ public:
 
   /// \brief Run checkers for branch condition.
   void runCheckersForBranchCondition(const Stmt *condition,
-                                     BranchNodeBuilder &B, ExprEngine &Eng);
+                                     NodeBuilder &B, ExprEngine &Eng);
 
   /// \brief Run checkers for live symbols.
   ///
@@ -334,7 +334,7 @@ public:
   typedef CheckerFn<void (EndOfFunctionNodeBuilder &, ExprEngine &)>
       CheckEndPathFunc;
   
-  typedef CheckerFn<void (const Stmt *, BranchNodeBuilder &, ExprEngine &)>
+  typedef CheckerFn<void (const Stmt *, NodeBuilder &, ExprEngine &)>
       CheckBranchConditionFunc;
   
   typedef CheckerFn<void (SymbolReaper &, CheckerContext &)>
index e366b065c0bf13fcc57b6ec89b199b31750a0365..1bbc66ced708772a1b0badcbc1dfac4792050967 100644 (file)
@@ -51,7 +51,7 @@ public:
       ST(st),
       size(Dst.size()),
       Ctx(builder.Eng, builder.getBlock()),
-      NB(Ctx, pred),
+      NB(pred, Ctx),
       respondsToCallback(respondsToCB) {
     assert(!(ST && ST != Pred->getState()));
   }
index 7629ac4a67f3586cf766d6472582c34d86c238a7..ac174c4b39cce5ba1edb378e9af756d8d835b2b7 100644 (file)
@@ -181,7 +181,7 @@ protected:
   friend class StmtNodeBuilder;
 
   ExplodedNode *BuilderPred;
-  NodeBuilderContext &C;
+  const NodeBuilderContext &C;
   bool Finalized;
 
   /// \brief The frontier set - a set of nodes which need to be propagated after
@@ -212,12 +212,19 @@ protected:
                                  bool MarkAsSink = false);
 
 public:
-  NodeBuilder(NodeBuilderContext &Ctx, ExplodedNode *N)
+  NodeBuilder(ExplodedNode *N, NodeBuilderContext &Ctx)
     : BuilderPred(N), C(Ctx), Finalized(false) {
     assert(!N->isSink());
     Deferred.insert(N);
   }
 
+  /// Create a new builder using the parent builder's context.
+  NodeBuilder(ExplodedNode *N, const NodeBuilder &ParentBldr)
+    : BuilderPred(N), C(ParentBldr.C), Finalized(false) {
+    assert(!N->isSink());
+    Deferred.insert(N);
+  }
+
   virtual ~NodeBuilder() {}
 
   /// \brief Generates a node in the ExplodedGraph.
@@ -258,7 +265,11 @@ public:
                          C.Block->getBlockID());
   }
 
+  // \brief Get the builder's predecessor - the parent to all the other nodes.
   ExplodedNode *getPredecessor() const { return BuilderPred; }
+
+  // \brief Returns state of the predecessor.
+  const ProgramState *getState() const { return BuilderPred->getState(); }
 };
 
 class CommonNodeBuilder {
@@ -409,19 +420,19 @@ class BranchNodeBuilder: public NodeBuilder {
   }
 
 public:
-  BranchNodeBuilder(NodeBuilderContext &C, ExplodedNode *Pred,
+  BranchNodeBuilder(ExplodedNode *Pred, NodeBuilderContext &C,
                     const CFGBlock *dstT, const CFGBlock *dstF)
-  : NodeBuilder(C, Pred), DstT(dstT), DstF(dstF),
+  : NodeBuilder(Pred, C), DstT(dstT), DstF(dstF),
     GeneratedTrue(false), GeneratedFalse(false),
     InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {
   }
 
-  /// This function generate a new ExplodedNode but not a new
-  /// branch(block edge). Creates a transition from the Builder's top
-  /// predecessor.
-  ExplodedNode *generateNode(const Stmt *Condition, const ProgramState *State,
-                             const ProgramPointTag *Tag = 0,
-                             bool MarkAsSink = false);
+  /// Create a new builder using the parent builder's context.
+  BranchNodeBuilder(ExplodedNode *Pred, BranchNodeBuilder &ParentBldr)
+  : NodeBuilder(Pred, ParentBldr), DstT(ParentBldr.DstT), DstF(ParentBldr.DstF),
+    GeneratedTrue(false), GeneratedFalse(false),
+    InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {
+  }
 
   ExplodedNode *generateNode(const ProgramState *State, bool branch,
                              ExplodedNode *Pred = 0);
@@ -440,10 +451,6 @@ public:
   bool isFeasible(bool branch) {
     return branch ? !InFeasibleTrue : !InFeasibleFalse;
   }
-
-  const ProgramState *getState() const {
-    return getPredecessor()->getState();
-  }
 };
 
 class IndirectGotoNodeBuilder {
index 8663893f2eddfaa1cdbe78df49101b1e03df9416..451fa91b3aba8100bd0923424aefa2d3f325901d 100644 (file)
@@ -49,20 +49,27 @@ class UndefBranchChecker : public Checker<check::BranchCondition> {
   };
 
 public:
-  void checkBranchCondition(const Stmt *Condition, BranchNodeBuilder &Builder,
+  void checkBranchCondition(const Stmt *Condition, NodeBuilder &Builder,
                             ExprEngine &Eng) const;
 };
 
 }
 
 void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
-                                              BranchNodeBuilder &Builder,
+                                              NodeBuilder &Builder,
                                               ExprEngine &Eng) const {
   const ProgramState *state = Builder.getState();
   SVal X = state->getSVal(Condition);
   if (X.isUndef()) {
-    // Generate a sink node.
-    ExplodedNode *N = Builder.generateNode(Condition, state, 0, true);
+    // TODO: The PP will be generated with the correct tag by the CheckerManager
+    // after we migrate the callback to CheckerContext.
+    const ProgramPointTag *Tag = 0;
+    ProgramPoint PP = PostCondition(Condition,
+                        Builder.getPredecessor()->getLocationContext(), Tag);
+    // Generate a sink node, which implicitly marks both outgoing branches as
+    // infeasible.
+    ExplodedNode *N = Builder.generateNode(PP, state,
+                                           Builder.getPredecessor(), true);
     if (N) {
       if (!BT)
         BT.reset(
@@ -102,9 +109,6 @@ void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
 
       Eng.getBugReporter().EmitReport(R);
     }
-
-    Builder.markInfeasible(true);
-    Builder.markInfeasible(false);
   }
 }
 
index acacfb0e18c63dbc21a0d0295e759d7cebba56f7..d47033a70e7380d6d9f082adabac77d307dc8685 100644 (file)
@@ -297,7 +297,7 @@ void CheckerManager::runCheckersForEndPath(EndOfFunctionNodeBuilder &B,
 
 /// \brief Run checkers for branch condition.
 void CheckerManager::runCheckersForBranchCondition(const Stmt *condition,
-                                                   BranchNodeBuilder &B,
+                                                   NodeBuilder &B,
                                                    ExprEngine &Eng) {
   for (unsigned i = 0, e = BranchConditionCheckers.size(); i != e; ++i) {
     CheckBranchConditionFunc fn = BranchConditionCheckers[i];
index d1c1e39d59c8c1161c92aec6d182fdee79cc43fe..91aa9a567c98f6e84eaacdac1cd71f7e8745e837 100644 (file)
@@ -602,21 +602,6 @@ StmtNodeBuilder::generateNodeInternal(const ProgramPoint &Loc,
   return NULL;
 }
 
-// This function generate a new ExplodedNode but not a new branch(block edge).
-// Creates a transition from the Builder's top predecessor.
-ExplodedNode *BranchNodeBuilder::generateNode(const Stmt *Condition,
-                                              const ProgramState *State,
-                                              const ProgramPointTag *Tag,
-                                              bool MarkAsSink) {
-  ProgramPoint PP = PostCondition(Condition,
-                                  BuilderPred->getLocationContext(), Tag);
-  ExplodedNode *N = generateNodeImpl(PP, State, BuilderPred, MarkAsSink);
-  assert(N);
-  // TODO: This needs to go - we should not change Pred!!!
-  BuilderPred = N;
-  return N;
-}
-
 ExplodedNode *BranchNodeBuilder::generateNode(const ProgramState *State,
                                               bool branch,
                                               ExplodedNode *NodePred) {
index dba1ce10bd37d20622c39c46ff893b8637380991..70142c8fc1c105d7e8b58689f2c1ef789090fcfe 100644 (file)
@@ -945,11 +945,9 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
                                const CFGBlock *DstT,
                                const CFGBlock *DstF) {
 
-  BranchNodeBuilder builder(BldCtx, Pred, DstT, DstF);
-
   // Check for NULL conditions; e.g. "for(;;)"
   if (!Condition) {
-    BranchNodeBuilder NullCondBldr(BldCtx, Pred, DstT, DstF);
+    BranchNodeBuilder NullCondBldr(Pred, BldCtx, DstT, DstF);
     NullCondBldr.markInfeasible(false);
     Engine.enqueue(NullCondBldr);
     return;
@@ -959,27 +957,36 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
                                 Condition->getLocStart(),
                                 "Error evaluating branch");
 
-  //TODO: This should take the NodeBuiolder.
-  getCheckerManager().runCheckersForBranchCondition(Condition, builder,
+  NodeBuilder CheckerBldr(Pred, BldCtx);
+  getCheckerManager().runCheckersForBranchCondition(Condition, CheckerBldr,
                                                     *this);
 
-  const ProgramState *PrevState = builder.getState();
-  SVal X = PrevState->getSVal(Condition);
-
-  if (X.isUnknownOrUndef()) {
-    // Give it a chance to recover from unknown.
-    if (const Expr *Ex = dyn_cast<Expr>(Condition)) {
-      if (Ex->getType()->isIntegerType()) {
-        // Try to recover some path-sensitivity.  Right now casts of symbolic
-        // integers that promote their values are currently not tracked well.
-        // If 'Condition' is such an expression, try and recover the
-        // underlying value and use that instead.
-        SVal recovered = RecoverCastedSymbol(getStateManager(),
-                                             builder.getState(), Condition,
-                                             getContext());
-
-        if (!recovered.isUnknown()) {
-          X = recovered;
+  for (NodeBuilder::iterator I = CheckerBldr.results_begin(),
+                             E = CheckerBldr.results_end(); E != I; ++I) {
+    ExplodedNode *PredI = *I;
+
+    if (PredI->isSink())
+      continue;
+
+    BranchNodeBuilder builder(PredI, BldCtx, DstT, DstF);
+    const ProgramState *PrevState = builder.getState();
+    SVal X = PrevState->getSVal(Condition);
+
+    if (X.isUnknownOrUndef()) {
+      // Give it a chance to recover from unknown.
+      if (const Expr *Ex = dyn_cast<Expr>(Condition)) {
+        if (Ex->getType()->isIntegerType()) {
+          // Try to recover some path-sensitivity.  Right now casts of symbolic
+          // integers that promote their values are currently not tracked well.
+          // If 'Condition' is such an expression, try and recover the
+          // underlying value and use that instead.
+          SVal recovered = RecoverCastedSymbol(getStateManager(),
+                                               PrevState, Condition,
+                                               getContext());
+
+          if (!recovered.isUnknown()) {
+            X = recovered;
+          }
         }
       }
     }
@@ -989,30 +996,30 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
       builder.generateNode(MarkBranch(PrevState, Term, false), false);
       // Enqueue the results into the work list.
       Engine.enqueue(builder);
-      return;
+      continue;
     }
-  }
 
-  DefinedSVal V = cast<DefinedSVal>(X);
+    DefinedSVal V = cast<DefinedSVal>(X);
 
-  // Process the true branch.
-  if (builder.isFeasible(true)) {
-    if (const ProgramState *state = PrevState->assume(V, true))
-      builder.generateNode(MarkBranch(state, Term, true), true);
-    else
-      builder.markInfeasible(true);
-  }
+    // Process the true branch.
+    if (builder.isFeasible(true)) {
+      if (const ProgramState *state = PrevState->assume(V, true))
+        builder.generateNode(MarkBranch(state, Term, true), true);
+      else
+        builder.markInfeasible(true);
+    }
 
-  // Process the false branch.
-  if (builder.isFeasible(false)) {
-    if (const ProgramState *state = PrevState->assume(V, false))
-      builder.generateNode(MarkBranch(state, Term, false), false);
-    else
-      builder.markInfeasible(false);
-  }
+    // Process the false branch.
+    if (builder.isFeasible(false)) {
+      if (const ProgramState *state = PrevState->assume(V, false))
+        builder.generateNode(MarkBranch(state, Term, false), false);
+      else
+        builder.markInfeasible(false);
+    }
 
-  // Enqueue the results into the work list.
-  Engine.enqueue(builder);
+    // Enqueue the results into the work list.
+    Engine.enqueue(builder);
+  }
 }
 
 /// processIndirectGoto - Called by CoreEngine.  Used to generate successor