Ejemplo n.º 1
0
void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
                                              BranchNodeBuilder &Builder,
                                              ExprEngine &Eng) const {
  const GRState *state = Builder.getState();
  SVal X = state->getSVal(Condition);
  if (X.isUndef()) {
    ExplodedNode *N = Builder.generateNode(state, true);
    if (N) {
      N->markAsSink();
      if (!BT)
        BT.reset(
               new BuiltinBug("Branch condition evaluates to a garbage value"));

      // What's going on here: we want to highlight the subexpression of the
      // condition that is the most likely source of the "uninitialized
      // branch condition."  We do a recursive walk of the condition's
      // subexpressions and roughly look for the most nested subexpression
      // that binds to Undefined.  We then highlight that expression's range.
      BlockEdge B = cast<BlockEdge>(N->getLocation());
      const Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
      assert (Ex && "Block must have a terminator.");

      // Get the predecessor node and check if is a PostStmt with the Stmt
      // being the terminator condition.  We want to inspect the state
      // of that node instead because it will contain main information about
      // the subexpressions.
      assert (!N->pred_empty());

      // Note: any predecessor will do.  They should have identical state,
      // since all the BlockEdge did was act as an error sink since the value
      // had to already be undefined.
      ExplodedNode *PrevN = *N->pred_begin();
      ProgramPoint P = PrevN->getLocation();
      const GRState* St = N->getState();

      if (PostStmt* PS = dyn_cast<PostStmt>(&P))
        if (PS->getStmt() == Ex)
          St = PrevN->getState();

      FindUndefExpr FindIt(Eng.getStateManager(), St);
      Ex = FindIt.FindExpr(Ex);

      // Emit the bug report.
      EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getDescription(),N);
      R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex);
      R->addRange(Ex->getSourceRange());

      Eng.getBugReporter().EmitReport(R);
    }

    Builder.markInfeasible(true);
    Builder.markInfeasible(false);
  }
}
Ejemplo n.º 2
0
void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
                                              CheckerContext &Ctx) const {
  SVal X = Ctx.getState()->getSVal(Condition, Ctx.getLocationContext());
  if (X.isUndef()) {
    // Generate a sink node, which implicitly marks both outgoing branches as
    // infeasible.
    ExplodedNode *N = Ctx.generateSink();
    if (N) {
      if (!BT)
        BT.reset(new BuiltinBug(
            this, "Branch condition evaluates to a garbage value"));

      // What's going on here: we want to highlight the subexpression of the
      // condition that is the most likely source of the "uninitialized
      // branch condition."  We do a recursive walk of the condition's
      // subexpressions and roughly look for the most nested subexpression
      // that binds to Undefined.  We then highlight that expression's range.

      // Get the predecessor node and check if is a PostStmt with the Stmt
      // being the terminator condition.  We want to inspect the state
      // of that node instead because it will contain main information about
      // the subexpressions.

      // Note: any predecessor will do.  They should have identical state,
      // since all the BlockEdge did was act as an error sink since the value
      // had to already be undefined.
      assert (!N->pred_empty());
      const Expr *Ex = cast<Expr>(Condition);
      ExplodedNode *PrevN = *N->pred_begin();
      ProgramPoint P = PrevN->getLocation();
      ProgramStateRef St = N->getState();

      if (Optional<PostStmt> PS = P.getAs<PostStmt>())
        if (PS->getStmt() == Ex)
          St = PrevN->getState();

      FindUndefExpr FindIt(St, Ctx.getLocationContext());
      Ex = FindIt.FindExpr(Ex);

      // Emit the bug report.
      BugReport *R = new BugReport(*BT, BT->getDescription(), N);
      bugreporter::trackNullOrUndefValue(N, Ex, *R);
      R->addRange(Ex->getSourceRange());

      Ctx.emitReport(R);
    }
  }
}
Ejemplo n.º 3
0
static const char *getArgumentValueString(const CallExpr *CE,
                                          CheckerContext &C) {
  if (CE->getNumArgs() == 0)
    return "Missing assertion argument";

  ExplodedNode *N = C.getPredecessor();
  const LocationContext *LC = N->getLocationContext();
  ProgramStateRef State = N->getState();

  const Expr *Assertion = CE->getArg(0);
  SVal AssertionVal = State->getSVal(Assertion, LC);

  if (AssertionVal.isUndef())
    return "UNDEFINED";

  ProgramStateRef StTrue, StFalse;
  llvm::tie(StTrue, StFalse) =
    State->assume(cast<DefinedOrUnknownSVal>(AssertionVal));

  if (StTrue) {
    if (StFalse)
      return "UNKNOWN";
    else
      return "TRUE";
  } else {
    if (StFalse)
      return "FALSE";
    else
      llvm_unreachable("Invalid constraint; neither true or false.");
  }
}
Ejemplo n.º 4
0
void MPIChecker::checkDoubleNonblocking(const CallEvent &PreCallEvent,
                                        CheckerContext &Ctx) const {
  if (!FuncClassifier->isNonBlockingType(PreCallEvent.getCalleeIdentifier())) {
    return;
  }
  const MemRegion *const MR =
      PreCallEvent.getArgSVal(PreCallEvent.getNumArgs() - 1).getAsRegion();
  if (!MR)
    return;
  const ElementRegion *const ER = dyn_cast<ElementRegion>(MR);

  // The region must be typed, in order to reason about it.
  if (!isa<TypedRegion>(MR) || (ER && !isa<TypedRegion>(ER->getSuperRegion())))
    return;

  ProgramStateRef State = Ctx.getState();
  const Request *const Req = State->get<RequestMap>(MR);

  // double nonblocking detected
  if (Req && Req->CurrentState == Request::State::Nonblocking) {
    ExplodedNode *ErrorNode = Ctx.generateNonFatalErrorNode();
    BReporter.reportDoubleNonblocking(PreCallEvent, *Req, MR, ErrorNode,
                                      Ctx.getBugReporter());
    Ctx.addTransition(ErrorNode->getState(), ErrorNode);
  }
  // no error
  else {
    State = State->set<RequestMap>(MR, Request::State::Nonblocking);
    Ctx.addTransition(State);
  }
}
Ejemplo n.º 5
0
void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
                               ExplodedNodeSet &Dst) {
  
  // FIXME: static variables may have an initializer, but the second
  //  time a function is called those values may not be current.
  //  This may need to be reflected in the CFG.
  
  // Assumption: The CFG has one DeclStmt per Decl.
  const Decl *D = *DS->decl_begin();
  
  if (!D || !isa<VarDecl>(D)) {
    //TODO:AZ: remove explicit insertion after refactoring is done.
    Dst.insert(Pred);
    return;
  }
  
  // FIXME: all pre/post visits should eventually be handled by ::Visit().
  ExplodedNodeSet dstPreVisit;
  getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, DS, *this);
  
  StmtNodeBuilder B(dstPreVisit, Dst, *currentBuilderContext);
  const VarDecl *VD = dyn_cast<VarDecl>(D);
  for (ExplodedNodeSet::iterator I = dstPreVisit.begin(), E = dstPreVisit.end();
       I!=E; ++I) {
    ExplodedNode *N = *I;
    const ProgramState *state = N->getState();
    
    // Decls without InitExpr are not initialized explicitly.
    const LocationContext *LC = N->getLocationContext();
    
    if (const Expr *InitEx = VD->getInit()) {
      SVal InitVal = state->getSVal(InitEx, Pred->getLocationContext());
      
      // We bound the temp obj region to the CXXConstructExpr. Now recover
      // the lazy compound value when the variable is not a reference.
      if (AMgr.getLangOptions().CPlusPlus && VD->getType()->isRecordType() && 
          !VD->getType()->isReferenceType() && isa<loc::MemRegionVal>(InitVal)){
        InitVal = state->getSVal(cast<loc::MemRegionVal>(InitVal).getRegion());
        assert(isa<nonloc::LazyCompoundVal>(InitVal));
      }
      
      // Recover some path-sensitivity if a scalar value evaluated to
      // UnknownVal.
      if (InitVal.isUnknown()) {
        InitVal = svalBuilder.getConjuredSymbolVal(NULL, InitEx,
                                 currentBuilderContext->getCurrentBlockCount());
      }
      B.takeNodes(N);
      ExplodedNodeSet Dst2;
      evalBind(Dst2, DS, N, state->getLValue(VD, LC), InitVal, true);
      B.addNodes(Dst2);
    }
    else {
      B.generateNode(DS, N,state->bindDeclWithNoInit(state->getRegion(VD, LC)));
    }
  }
}
Ejemplo n.º 6
0
void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
                                  ExplodedNodeSet &Dst) {
  assert(B->getOpcode() == BO_LAnd ||
         B->getOpcode() == BO_LOr);

  StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
  ProgramStateRef state = Pred->getState();

  ExplodedNode *N = Pred;
  while (!isa<BlockEntrance>(N->getLocation())) {
    ProgramPoint P = N->getLocation();
    assert(isa<PreStmt>(P)|| isa<PreStmtPurgeDeadSymbols>(P));
    (void) P;
    assert(N->pred_size() == 1);
    N = *N->pred_begin();
  }
  assert(N->pred_size() == 1);
  N = *N->pred_begin();
  BlockEdge BE = cast<BlockEdge>(N->getLocation());
  SVal X;

  // Determine the value of the expression by introspecting how we
  // got this location in the CFG.  This requires looking at the previous
  // block we were in and what kind of control-flow transfer was involved.
  const CFGBlock *SrcBlock = BE.getSrc();
  // The only terminator (if there is one) that makes sense is a logical op.
  CFGTerminator T = SrcBlock->getTerminator();
  if (const BinaryOperator *Term = cast_or_null<BinaryOperator>(T.getStmt())) {
    (void) Term;
    assert(Term->isLogicalOp());
    assert(SrcBlock->succ_size() == 2);
    // Did we take the true or false branch?
    unsigned constant = (*SrcBlock->succ_begin() == BE.getDst()) ? 1 : 0;
    X = svalBuilder.makeIntVal(constant, B->getType());
  }
  else {
    // If there is no terminator, by construction the last statement
    // in SrcBlock is the value of the enclosing expression.
    assert(!SrcBlock->empty());
    CFGStmt Elem = cast<CFGStmt>(*SrcBlock->rbegin());
    const Stmt *S = Elem.getStmt();
    X = N->getState()->getSVal(S, Pred->getLocationContext());
  }

  Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getLocationContext(), X));
}
Ejemplo n.º 7
0
bool OSAtomicChecker::evalOSAtomicCompareAndSwap(CheckerContext &C, 
                                                 const CallExpr *CE) {
  // Not enough arguments to match OSAtomicCompareAndSwap?
  if (CE->getNumArgs() != 3)
    return false;

  ASTContext &Ctx = C.getASTContext();
  const Expr *oldValueExpr = CE->getArg(0);
  QualType oldValueType = Ctx.getCanonicalType(oldValueExpr->getType());

  const Expr *newValueExpr = CE->getArg(1);
  QualType newValueType = Ctx.getCanonicalType(newValueExpr->getType());

  // Do the types of 'oldValue' and 'newValue' match?
  if (oldValueType != newValueType)
    return false;

  const Expr *theValueExpr = CE->getArg(2);
  const PointerType *theValueType=theValueExpr->getType()->getAs<PointerType>();

  // theValueType not a pointer?
  if (!theValueType)
    return false;

  QualType theValueTypePointee =
    Ctx.getCanonicalType(theValueType->getPointeeType()).getUnqualifiedType();

  // The pointee must match newValueType and oldValueType.
  if (theValueTypePointee != newValueType)
    return false;

  static SimpleProgramPointTag OSAtomicLoadTag("OSAtomicChecker : Load");
  static SimpleProgramPointTag OSAtomicStoreTag("OSAtomicChecker : Store");
  
  // Load 'theValue'.
  ExprEngine &Engine = C.getEngine();
  const ProgramState *state = C.getState();
  ExplodedNodeSet Tmp;
  SVal location = state->getSVal(theValueExpr);
  // Here we should use the value type of the region as the load type, because
  // we are simulating the semantics of the function, not the semantics of 
  // passing argument. So the type of theValue expr is not we are loading.
  // But usually the type of the varregion is not the type we want either,
  // we still need to do a CastRetrievedVal in store manager. So actually this
  // LoadTy specifying can be omitted. But we put it here to emphasize the 
  // semantics.
  QualType LoadTy;
  if (const TypedValueRegion *TR =
      dyn_cast_or_null<TypedValueRegion>(location.getAsRegion())) {
    LoadTy = TR->getValueType();
  }
  Engine.evalLoad(Tmp, theValueExpr, C.getPredecessor(), 
                  state, location, &OSAtomicLoadTag, LoadTy);

  if (Tmp.empty()) {
    // If no nodes were generated, other checkers must generated sinks. But 
    // since the builder state was restored, we set it manually to prevent 
    // auto transition.
    // FIXME: there should be a better approach.
    C.getNodeBuilder().BuildSinks = true;
    return true;
  }
 
  for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end();
       I != E; ++I) {

    ExplodedNode *N = *I;
    const ProgramState *stateLoad = N->getState();

    // Use direct bindings from the environment since we are forcing a load
    // from a location that the Environment would typically not be used
    // to bind a value.
    SVal theValueVal_untested = stateLoad->getSVal(theValueExpr, true);

    SVal oldValueVal_untested = stateLoad->getSVal(oldValueExpr);

    // FIXME: Issue an error.
    if (theValueVal_untested.isUndef() || oldValueVal_untested.isUndef()) {
      return false;
    }
    
    DefinedOrUnknownSVal theValueVal =
      cast<DefinedOrUnknownSVal>(theValueVal_untested);
    DefinedOrUnknownSVal oldValueVal =
      cast<DefinedOrUnknownSVal>(oldValueVal_untested);

    SValBuilder &svalBuilder = Engine.getSValBuilder();

    // Perform the comparison.
    DefinedOrUnknownSVal Cmp =
      svalBuilder.evalEQ(stateLoad,theValueVal,oldValueVal);

    const ProgramState *stateEqual = stateLoad->assume(Cmp, true);

    // Were they equal?
    if (stateEqual) {
      // Perform the store.
      ExplodedNodeSet TmpStore;
      SVal val = stateEqual->getSVal(newValueExpr);

      // Handle implicit value casts.
      if (const TypedValueRegion *R =
          dyn_cast_or_null<TypedValueRegion>(location.getAsRegion())) {
        val = svalBuilder.evalCast(val,R->getValueType(), newValueExpr->getType());
      }

      Engine.evalStore(TmpStore, NULL, theValueExpr, N, 
                       stateEqual, location, val, &OSAtomicStoreTag);

      if (TmpStore.empty()) {
        // If no nodes were generated, other checkers must generated sinks. But 
        // since the builder state was restored, we set it manually to prevent 
        // auto transition.
        // FIXME: there should be a better approach.
        C.getNodeBuilder().BuildSinks = true;
        return true;
      }

      // Now bind the result of the comparison.
      for (ExplodedNodeSet::iterator I2 = TmpStore.begin(),
           E2 = TmpStore.end(); I2 != E2; ++I2) {
        ExplodedNode *predNew = *I2;
        const ProgramState *stateNew = predNew->getState();
        // Check for 'void' return type if we have a bogus function prototype.
        SVal Res = UnknownVal();
        QualType T = CE->getType();
        if (!T->isVoidType())
          Res = Engine.getSValBuilder().makeTruthVal(true, T);
        C.generateNode(stateNew->BindExpr(CE, Res), predNew);
      }
    }

    // Were they not equal?
    if (const ProgramState *stateNotEqual = stateLoad->assume(Cmp, false)) {
      // Check for 'void' return type if we have a bogus function prototype.
      SVal Res = UnknownVal();
      QualType T = CE->getType();
      if (!T->isVoidType())
        Res = Engine.getSValBuilder().makeTruthVal(false, CE->getType());
      C.generateNode(stateNotEqual->BindExpr(CE, Res), N);
    }
  }

  return true;
}
Ejemplo n.º 8
0
void ExplodedGraph::reclaimRecentlyAllocatedNodes() {
  if (!recentlyAllocatedNodes)
    return;
  NodeList &nl = *getNodeList(recentlyAllocatedNodes);
 
  // Reclaimn all nodes that match *all* the following criteria:
  //
  // (1) 1 predecessor (that has one successor)
  // (2) 1 successor (that has one predecessor)
  // (3) The ProgramPoint is for a PostStmt.
  // (4) There is no 'tag' for the ProgramPoint.
  // (5) The 'store' is the same as the predecessor.
  // (6) The 'GDM' is the same as the predecessor.
  // (7) The LocationContext is the same as the predecessor.
  // (8) The PostStmt is for a non-CFGElement expression.
  
  for (NodeList::iterator i = nl.begin(), e = nl.end() ; i != e; ++i) {
    ExplodedNode *node = *i;
    
    // Conditions 1 and 2.
    if (node->pred_size() != 1 || node->succ_size() != 1)
      continue;

    ExplodedNode *pred = *(node->pred_begin());
    if (pred->succ_size() != 1)
      continue;

    ExplodedNode *succ = *(node->succ_begin());
    if (succ->pred_size() != 1)
      continue;

    // Condition 3.
    ProgramPoint progPoint = node->getLocation();
    if (!isa<PostStmt>(progPoint))
      continue;
    // Condition 4.
    PostStmt ps = cast<PostStmt>(progPoint);
    if (ps.getTag())
      continue;

    if (isa<BinaryOperator>(ps.getStmt()))
      continue;

    // Conditions 5, 6, and 7.
    const ProgramState *state = node->getState();
    const ProgramState *pred_state = pred->getState();    
    if (state->store != pred_state->store || state->GDM != pred_state->GDM ||
        progPoint.getLocationContext() != pred->getLocationContext())
      continue;

    // Condition 8.
    if (node->getCFG().isBlkExpr(ps.getStmt()))
      continue;
    
    // If we reach here, we can remove the node.  This means:
    // (a) changing the predecessors successor to the successor of this node
    // (b) changing the successors predecessor to the predecessor of this node
    // (c) Putting 'node' onto freeNodes.
    pred->replaceSuccessor(succ);
    succ->replacePredecessor(pred);
    if (!freeNodes)
      freeNodes = new NodeList();
    getNodeList(freeNodes)->push_back(node);
    Nodes.RemoveNode(node);
    --NumNodes;
    node->~ExplodedNode();
  }
  
  nl.clear();
}
Ejemplo n.º 9
0
void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
                                  ExplodedNodeSet &Dst) {
  assert(B->getOpcode() == BO_LAnd ||
         B->getOpcode() == BO_LOr);

  StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
  ProgramStateRef state = Pred->getState();

  ExplodedNode *N = Pred;
  while (!N->getLocation().getAs<BlockEntrance>()) {
    ProgramPoint P = N->getLocation();
    assert(P.getAs<PreStmt>()|| P.getAs<PreStmtPurgeDeadSymbols>());
    (void) P;
    assert(N->pred_size() == 1);
    N = *N->pred_begin();
  }
  assert(N->pred_size() == 1);
  N = *N->pred_begin();
  BlockEdge BE = N->getLocation().castAs<BlockEdge>();
  SVal X;

  // Determine the value of the expression by introspecting how we
  // got this location in the CFG.  This requires looking at the previous
  // block we were in and what kind of control-flow transfer was involved.
  const CFGBlock *SrcBlock = BE.getSrc();
  // The only terminator (if there is one) that makes sense is a logical op.
  CFGTerminator T = SrcBlock->getTerminator();
  if (const BinaryOperator *Term = cast_or_null<BinaryOperator>(T.getStmt())) {
    (void) Term;
    assert(Term->isLogicalOp());
    assert(SrcBlock->succ_size() == 2);
    // Did we take the true or false branch?
    unsigned constant = (*SrcBlock->succ_begin() == BE.getDst()) ? 1 : 0;
    X = svalBuilder.makeIntVal(constant, B->getType());
  }
  else {
    // If there is no terminator, by construction the last statement
    // in SrcBlock is the value of the enclosing expression.
    // However, we still need to constrain that value to be 0 or 1.
    assert(!SrcBlock->empty());
    CFGStmt Elem = SrcBlock->rbegin()->castAs<CFGStmt>();
    const Expr *RHS = cast<Expr>(Elem.getStmt());
    SVal RHSVal = N->getState()->getSVal(RHS, Pred->getLocationContext());

    if (RHSVal.isUndef()) {
      X = RHSVal;
    } else {
      DefinedOrUnknownSVal DefinedRHS = RHSVal.castAs<DefinedOrUnknownSVal>();
      ProgramStateRef StTrue, StFalse;
      llvm::tie(StTrue, StFalse) = N->getState()->assume(DefinedRHS);
      if (StTrue) {
        if (StFalse) {
          // We can't constrain the value to 0 or 1.
          // The best we can do is a cast.
          X = getSValBuilder().evalCast(RHSVal, B->getType(), RHS->getType());
        } else {
          // The value is known to be true.
          X = getSValBuilder().makeIntVal(1, B->getType());
        }
      } else {
        // The value is known to be false.
        assert(StFalse && "Infeasible path!");
        X = getSValBuilder().makeIntVal(0, B->getType());
      }
    }
  }
  Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getLocationContext(), X));
}
Ejemplo n.º 10
0
void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
                               ExplodedNodeSet &Dst) {
  // Assumption: The CFG has one DeclStmt per Decl.
  const VarDecl *VD = dyn_cast_or_null<VarDecl>(*DS->decl_begin());

  if (!VD) {
    //TODO:AZ: remove explicit insertion after refactoring is done.
    Dst.insert(Pred);
    return;
  }
  
  // FIXME: all pre/post visits should eventually be handled by ::Visit().
  ExplodedNodeSet dstPreVisit;
  getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, DS, *this);
  
  StmtNodeBuilder B(dstPreVisit, Dst, *currBldrCtx);
  for (ExplodedNodeSet::iterator I = dstPreVisit.begin(), E = dstPreVisit.end();
       I!=E; ++I) {
    ExplodedNode *N = *I;
    ProgramStateRef state = N->getState();
    const LocationContext *LC = N->getLocationContext();

    // Decls without InitExpr are not initialized explicitly.
    if (const Expr *InitEx = VD->getInit()) {

      // Note in the state that the initialization has occurred.
      ExplodedNode *UpdatedN = N;
      SVal InitVal = state->getSVal(InitEx, LC);

      if (isa<CXXConstructExpr>(InitEx->IgnoreImplicit())) {
        // We constructed the object directly in the variable.
        // No need to bind anything.
        B.generateNode(DS, UpdatedN, state);
      } else {
        // We bound the temp obj region to the CXXConstructExpr. Now recover
        // the lazy compound value when the variable is not a reference.
        if (AMgr.getLangOpts().CPlusPlus && VD->getType()->isRecordType() &&
            !VD->getType()->isReferenceType()) {
          if (Optional<loc::MemRegionVal> M =
                  InitVal.getAs<loc::MemRegionVal>()) {
            InitVal = state->getSVal(M->getRegion());
            assert(InitVal.getAs<nonloc::LazyCompoundVal>());
          }
        }
        
        // Recover some path-sensitivity if a scalar value evaluated to
        // UnknownVal.
        if (InitVal.isUnknown()) {
          QualType Ty = InitEx->getType();
          if (InitEx->isGLValue()) {
            Ty = getContext().getPointerType(Ty);
          }

          InitVal = svalBuilder.conjureSymbolVal(0, InitEx, LC, Ty,
                                                 currBldrCtx->blockCount());
        }


        B.takeNodes(UpdatedN);
        ExplodedNodeSet Dst2;
        evalBind(Dst2, DS, UpdatedN, state->getLValue(VD, LC), InitVal, true);
        B.addNodes(Dst2);
      }
    }
    else {
      B.generateNode(DS, N, state);
    }
  }
}
Ejemplo n.º 11
0
void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, 
                           ExplodedNode *Pred, ExplodedNodeSet &Dst) {
  
  ExplodedNodeSet dstPreStmt;
  getCheckerManager().runCheckersForPreStmt(dstPreStmt, Pred, CastE, *this);
  
  if (CastE->getCastKind() == CK_LValueToRValue) {
    for (ExplodedNodeSet::iterator I = dstPreStmt.begin(), E = dstPreStmt.end();
         I!=E; ++I) {
      ExplodedNode *subExprNode = *I;
      ProgramStateRef state = subExprNode->getState();
      const LocationContext *LCtx = subExprNode->getLocationContext();
      evalLoad(Dst, CastE, CastE, subExprNode, state, state->getSVal(Ex, LCtx));
    }
    return;
  }
  
  // All other casts.  
  QualType T = CastE->getType();
  QualType ExTy = Ex->getType();
  
  if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(CastE))
    T = ExCast->getTypeAsWritten();
  
  StmtNodeBuilder Bldr(dstPreStmt, Dst, *currBldrCtx);
  for (ExplodedNodeSet::iterator I = dstPreStmt.begin(), E = dstPreStmt.end();
       I != E; ++I) {
    
    Pred = *I;
    ProgramStateRef state = Pred->getState();
    const LocationContext *LCtx = Pred->getLocationContext();

    switch (CastE->getCastKind()) {
      case CK_LValueToRValue:
        llvm_unreachable("LValueToRValue casts handled earlier.");
      case CK_ToVoid:
        continue;
        // The analyzer doesn't do anything special with these casts,
        // since it understands retain/release semantics already.
      case CK_ARCProduceObject:
      case CK_ARCConsumeObject:
      case CK_ARCReclaimReturnedObject:
      case CK_ARCExtendBlockObject: // Fall-through.
      case CK_CopyAndAutoreleaseBlockObject:
        // The analyser can ignore atomic casts for now, although some future
        // checkers may want to make certain that you're not modifying the same
        // value through atomic and nonatomic pointers.
      case CK_AtomicToNonAtomic:
      case CK_NonAtomicToAtomic:
        // True no-ops.
      case CK_NoOp:
      case CK_ConstructorConversion:
      case CK_UserDefinedConversion:
      case CK_FunctionToPointerDecay:
      case CK_BuiltinFnToFnPtr: {
        // Copy the SVal of Ex to CastE.
        ProgramStateRef state = Pred->getState();
        const LocationContext *LCtx = Pred->getLocationContext();
        SVal V = state->getSVal(Ex, LCtx);
        state = state->BindExpr(CastE, LCtx, V);
        Bldr.generateNode(CastE, Pred, state);
        continue;
      }
      case CK_MemberPointerToBoolean:
        // FIXME: For now, member pointers are represented by void *.
        // FALLTHROUGH
      case CK_Dependent:
      case CK_ArrayToPointerDecay:
      case CK_BitCast:
      case CK_IntegralCast:
      case CK_NullToPointer:
      case CK_IntegralToPointer:
      case CK_PointerToIntegral:
      case CK_PointerToBoolean:
      case CK_IntegralToBoolean:
      case CK_IntegralToFloating:
      case CK_FloatingToIntegral:
      case CK_FloatingToBoolean:
      case CK_FloatingCast:
      case CK_FloatingRealToComplex:
      case CK_FloatingComplexToReal:
      case CK_FloatingComplexToBoolean:
      case CK_FloatingComplexCast:
      case CK_FloatingComplexToIntegralComplex:
      case CK_IntegralRealToComplex:
      case CK_IntegralComplexToReal:
      case CK_IntegralComplexToBoolean:
      case CK_IntegralComplexCast:
      case CK_IntegralComplexToFloatingComplex:
      case CK_CPointerToObjCPointerCast:
      case CK_BlockPointerToObjCPointerCast:
      case CK_AnyPointerToBlockPointerCast:  
      case CK_ObjCObjectLValueCast: 
      case CK_ZeroToOCLEvent: {
        // Delegate to SValBuilder to process.
        SVal V = state->getSVal(Ex, LCtx);
        V = svalBuilder.evalCast(V, T, ExTy);
        state = state->BindExpr(CastE, LCtx, V);
        Bldr.generateNode(CastE, Pred, state);
        continue;
      }
      case CK_DerivedToBase:
      case CK_UncheckedDerivedToBase: {
        // For DerivedToBase cast, delegate to the store manager.
        SVal val = state->getSVal(Ex, LCtx);
        val = getStoreManager().evalDerivedToBase(val, CastE);
        state = state->BindExpr(CastE, LCtx, val);
        Bldr.generateNode(CastE, Pred, state);
        continue;
      }
      // Handle C++ dyn_cast.
      case CK_Dynamic: {
        SVal val = state->getSVal(Ex, LCtx);

        // Compute the type of the result.
        QualType resultType = CastE->getType();
        if (CastE->isGLValue())
          resultType = getContext().getPointerType(resultType);

        bool Failed = false;

        // Check if the value being cast evaluates to 0.
        if (val.isZeroConstant())
          Failed = true;
        // Else, evaluate the cast.
        else
          val = getStoreManager().evalDynamicCast(val, T, Failed);

        if (Failed) {
          if (T->isReferenceType()) {
            // A bad_cast exception is thrown if input value is a reference.
            // Currently, we model this, by generating a sink.
            Bldr.generateSink(CastE, Pred, state);
            continue;
          } else {
            // If the cast fails on a pointer, bind to 0.
            state = state->BindExpr(CastE, LCtx, svalBuilder.makeNull());
          }
        } else {
          // If we don't know if the cast succeeded, conjure a new symbol.
          if (val.isUnknown()) {
            DefinedOrUnknownSVal NewSym =
              svalBuilder.conjureSymbolVal(0, CastE, LCtx, resultType,
                                           currBldrCtx->blockCount());
            state = state->BindExpr(CastE, LCtx, NewSym);
          } else 
            // Else, bind to the derived region value.
            state = state->BindExpr(CastE, LCtx, val);
        }
        Bldr.generateNode(CastE, Pred, state);
        continue;
      }
      case CK_NullToMemberPointer: {
        // FIXME: For now, member pointers are represented by void *.
        SVal V = svalBuilder.makeIntValWithPtrWidth(0, true);
        state = state->BindExpr(CastE, LCtx, V);
        Bldr.generateNode(CastE, Pred, state);
        continue;
      }
      // Various C++ casts that are not handled yet.
      case CK_ToUnion:
      case CK_BaseToDerived:
      case CK_BaseToDerivedMemberPointer:
      case CK_DerivedToBaseMemberPointer:
      case CK_ReinterpretMemberPointer:
      case CK_VectorSplat:
      case CK_LValueBitCast: {
        // Recover some path-sensitivty by conjuring a new value.
        QualType resultType = CastE->getType();
        if (CastE->isGLValue())
          resultType = getContext().getPointerType(resultType);
        SVal result = svalBuilder.conjureSymbolVal(0, CastE, LCtx,
                                                   resultType,
                                                   currBldrCtx->blockCount());
        state = state->BindExpr(CastE, LCtx, result);
        Bldr.generateNode(CastE, Pred, state);
        continue;
      }
    }
  }
}
Ejemplo n.º 12
0
void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
                                  ExplodedNodeSet &Dst) {
  assert(B->getOpcode() == BO_LAnd ||
         B->getOpcode() == BO_LOr);

  StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
  ProgramStateRef state = Pred->getState();

  if (B->getType()->isVectorType()) {
    // FIXME: We do not model vector arithmetic yet. When adding support for
    // that, note that the CFG-based reasoning below does not apply, because
    // logical operators on vectors are not short-circuit. Currently they are
    // modeled as short-circuit in Clang CFG but this is incorrect.
    // Do not set the value for the expression. It'd be UnknownVal by default.
    Bldr.generateNode(B, Pred, state);
    return;
  }

  ExplodedNode *N = Pred;
  while (!N->getLocation().getAs<BlockEntrance>()) {
    ProgramPoint P = N->getLocation();
    assert(P.getAs<PreStmt>()|| P.getAs<PreStmtPurgeDeadSymbols>());
    (void) P;
    assert(N->pred_size() == 1);
    N = *N->pred_begin();
  }
  assert(N->pred_size() == 1);
  N = *N->pred_begin();
  BlockEdge BE = N->getLocation().castAs<BlockEdge>();
  SVal X;

  // Determine the value of the expression by introspecting how we
  // got this location in the CFG.  This requires looking at the previous
  // block we were in and what kind of control-flow transfer was involved.
  const CFGBlock *SrcBlock = BE.getSrc();
  // The only terminator (if there is one) that makes sense is a logical op.
  CFGTerminator T = SrcBlock->getTerminator();
  if (const BinaryOperator *Term = cast_or_null<BinaryOperator>(T.getStmt())) {
    (void) Term;
    assert(Term->isLogicalOp());
    assert(SrcBlock->succ_size() == 2);
    // Did we take the true or false branch?
    unsigned constant = (*SrcBlock->succ_begin() == BE.getDst()) ? 1 : 0;
    X = svalBuilder.makeIntVal(constant, B->getType());
  }
  else {
    // If there is no terminator, by construction the last statement
    // in SrcBlock is the value of the enclosing expression.
    // However, we still need to constrain that value to be 0 or 1.
    assert(!SrcBlock->empty());
    CFGStmt Elem = SrcBlock->rbegin()->castAs<CFGStmt>();
    const Expr *RHS = cast<Expr>(Elem.getStmt());
    SVal RHSVal = N->getState()->getSVal(RHS, Pred->getLocationContext());

    if (RHSVal.isUndef()) {
      X = RHSVal;
    } else {
      // We evaluate "RHSVal != 0" expression which result in 0 if the value is
      // known to be false, 1 if the value is known to be true and a new symbol
      // when the assumption is unknown.
      nonloc::ConcreteInt Zero(getBasicVals().getValue(0, B->getType()));
      X = evalBinOp(N->getState(), BO_NE, 
                    svalBuilder.evalCast(RHSVal, B->getType(), RHS->getType()),
                    Zero, B->getType());
    }
  }
  Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getLocationContext(), X));
}
Ejemplo n.º 13
0
void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, 
                                       const MemRegion *Dest,
                                       ExplodedNode *Pred,
                                       ExplodedNodeSet &destNodes) {

  const CXXConstructorDecl *CD = E->getConstructor();
  assert(CD);
  
#if 0
  if (!(CD->doesThisDeclarationHaveABody() && AMgr.shouldInlineCall()))
    // FIXME: invalidate the object.
    return;
#endif
  
  // Evaluate other arguments.
  ExplodedNodeSet argsEvaluated;
  const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
  evalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, argsEvaluated);

#if 0
  // Is the constructor elidable?
  if (E->isElidable()) {
    VisitAggExpr(E->getArg(0), destNodes, Pred, Dst);
    // FIXME: this is here to force propagation if VisitAggExpr doesn't
    if (destNodes.empty())
      destNodes.Add(Pred);
    return;
  }
#endif
  
  // Perform the previsit of the constructor.
  ExplodedNodeSet destPreVisit;
  getCheckerManager().runCheckersForPreStmt(destPreVisit, argsEvaluated, E, 
                                            *this);
  
  // Evaluate the constructor.  Currently we don't now allow checker-specific
  // implementations of specific constructors (as we do with ordinary
  // function calls.  We can re-evaluate this in the future.
  
#if 0
  // Inlining currently isn't fully implemented.

  if (AMgr.shouldInlineCall()) {
    if (!Dest)
      Dest =
        svalBuilder.getRegionManager().getCXXTempObjectRegion(E,
                                                  Pred->getLocationContext());

    // The callee stack frame context used to create the 'this'
    // parameter region.
    const StackFrameContext *SFC = 
      AMgr.getStackFrame(CD, Pred->getLocationContext(),
                         E, currentBuilderContext->getBlock(),
                         currentStmtIdx);

    // Create the 'this' region.
    const CXXThisRegion *ThisR =
      getCXXThisRegion(E->getConstructor()->getParent(), SFC);

    CallEnter Loc(E, SFC, Pred->getLocationContext());

    StmtNodeBuilder Bldr(argsEvaluated, destNodes, *currentBuilderContext);
    for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(),
                                  NE = argsEvaluated.end(); NI != NE; ++NI) {
      const ProgramState *state = (*NI)->getState();
      // Setup 'this' region, so that the ctor is evaluated on the object pointed
      // by 'Dest'.
      state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
      Bldr.generateNode(Loc, *NI, state);
    }
  }
#endif
  
  // Default semantics: invalidate all regions passed as arguments.
  ExplodedNodeSet destCall;
  {
    StmtNodeBuilder Bldr(destPreVisit, destCall, *currentBuilderContext);
    for (ExplodedNodeSet::iterator
        i = destPreVisit.begin(), e = destPreVisit.end();
        i != e; ++i)
    {
      ExplodedNode *Pred = *i;
      const LocationContext *LC = Pred->getLocationContext();
      const ProgramState *state = Pred->getState();

      state = invalidateArguments(state, CallOrObjCMessage(E, state, LC), LC);
      Bldr.generateNode(E, Pred, state);
    }
  }
  // Do the post visit.
  getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this);  
}
Ejemplo n.º 14
0
void ExprEngine::VisitObjCMessage(const ObjCMessageExpr *ME,
                                  ExplodedNode *Pred,
                                  ExplodedNodeSet &Dst) {
  CallEventManager &CEMgr = getStateManager().getCallEventManager();
  CallEventRef<ObjCMethodCall> Msg =
    CEMgr.getObjCMethodCall(ME, Pred->getState(), Pred->getLocationContext());

  // Handle the previsits checks.
  ExplodedNodeSet dstPrevisit;
  getCheckerManager().runCheckersForPreObjCMessage(dstPrevisit, Pred,
                                                   *Msg, *this);
  ExplodedNodeSet dstGenericPrevisit;
  getCheckerManager().runCheckersForPreCall(dstGenericPrevisit, dstPrevisit,
                                            *Msg, *this);

  // Proceed with evaluate the message expression.
  ExplodedNodeSet dstEval;
  StmtNodeBuilder Bldr(dstGenericPrevisit, dstEval, *currentBuilderContext);

  for (ExplodedNodeSet::iterator DI = dstGenericPrevisit.begin(),
       DE = dstGenericPrevisit.end(); DI != DE; ++DI) {
    ExplodedNode *Pred = *DI;
    ProgramStateRef State = Pred->getState();
    CallEventRef<ObjCMethodCall> UpdatedMsg = Msg.cloneWithState(State);
    
    if (UpdatedMsg->isInstanceMessage()) {
      SVal recVal = UpdatedMsg->getReceiverSVal();
      if (!recVal.isUndef()) {
        // Bifurcate the state into nil and non-nil ones.
        DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal);
        
        ProgramStateRef notNilState, nilState;
        llvm::tie(notNilState, nilState) = State->assume(receiverVal);
        
        // There are three cases: can be nil or non-nil, must be nil, must be
        // non-nil. We ignore must be nil, and merge the rest two into non-nil.
        // FIXME: This ignores many potential bugs (<rdar://problem/11733396>).
        // Revisit once we have lazier constraints.
        if (nilState && !notNilState) {
          continue;
        }
        
        // Check if the "raise" message was sent.
        assert(notNilState);
        if (Msg->getSelector() == RaiseSel) {
          // If we raise an exception, for now treat it as a sink.
          // Eventually we will want to handle exceptions properly.
          Bldr.generateNode(currentStmt, Pred, State, true);
          continue;
        }
        
        // Generate a transition to non-Nil state.
        if (notNilState != State)
          Pred = Bldr.generateNode(currentStmt, Pred, notNilState);
      }
    } else {
      // Check for special class methods.
      if (const ObjCInterfaceDecl *Iface = Msg->getReceiverInterface()) {
        if (!NSExceptionII) {
          ASTContext &Ctx = getContext();
          NSExceptionII = &Ctx.Idents.get("NSException");
        }
        
        if (isSubclass(Iface, NSExceptionII)) {
          enum { NUM_RAISE_SELECTORS = 2 };
          
          // Lazily create a cache of the selectors.
          if (!NSExceptionInstanceRaiseSelectors) {
            ASTContext &Ctx = getContext();
            NSExceptionInstanceRaiseSelectors =
              new Selector[NUM_RAISE_SELECTORS];
            SmallVector<IdentifierInfo*, NUM_RAISE_SELECTORS> II;
            unsigned idx = 0;
            
            // raise:format:
            II.push_back(&Ctx.Idents.get("raise"));
            II.push_back(&Ctx.Idents.get("format"));
            NSExceptionInstanceRaiseSelectors[idx++] =
              Ctx.Selectors.getSelector(II.size(), &II[0]);
            
            // raise:format:arguments:
            II.push_back(&Ctx.Idents.get("arguments"));
            NSExceptionInstanceRaiseSelectors[idx++] =
              Ctx.Selectors.getSelector(II.size(), &II[0]);
          }
          
          Selector S = Msg->getSelector();
          bool RaisesException = false;
          for (unsigned i = 0; i < NUM_RAISE_SELECTORS; ++i) {
            if (S == NSExceptionInstanceRaiseSelectors[i]) {
              RaisesException = true;
              break;
            }
          }
          if (RaisesException) {
            // If we raise an exception, for now treat it as a sink.
            // Eventually we will want to handle exceptions properly.
            Bldr.generateNode(currentStmt, Pred, Pred->getState(), true);
            continue;
          }

        }
      }
    }

    // Evaluate the call.
    defaultEvalCall(Bldr, Pred, *UpdatedMsg);
  }
  
  ExplodedNodeSet dstPostvisit;
  getCheckerManager().runCheckersForPostCall(dstPostvisit, dstEval,
                                             *Msg, *this);

  // Finally, perform the post-condition check of the ObjCMessageExpr and store
  // the created nodes in 'Dst'.
  getCheckerManager().runCheckersForPostObjCMessage(Dst, dstPostvisit,
                                                    *Msg, *this);
}
Ejemplo n.º 15
0
void ExprEngine::VisitObjCMessage(const ObjCMessageExpr *ME,
                                  ExplodedNode *Pred,
                                  ExplodedNodeSet &Dst) {
  CallEventManager &CEMgr = getStateManager().getCallEventManager();
  CallEventRef<ObjCMethodCall> Msg =
    CEMgr.getObjCMethodCall(ME, Pred->getState(), Pred->getLocationContext());

  // Handle the previsits checks.
  ExplodedNodeSet dstPrevisit;
  getCheckerManager().runCheckersForPreObjCMessage(dstPrevisit, Pred,
                                                   *Msg, *this);
  ExplodedNodeSet dstGenericPrevisit;
  getCheckerManager().runCheckersForPreCall(dstGenericPrevisit, dstPrevisit,
                                            *Msg, *this);

  // Proceed with evaluate the message expression.
  ExplodedNodeSet dstEval;
  StmtNodeBuilder Bldr(dstGenericPrevisit, dstEval, *currBldrCtx);

  for (ExplodedNodeSet::iterator DI = dstGenericPrevisit.begin(),
       DE = dstGenericPrevisit.end(); DI != DE; ++DI) {
    ExplodedNode *Pred = *DI;
    ProgramStateRef State = Pred->getState();
    CallEventRef<ObjCMethodCall> UpdatedMsg = Msg.cloneWithState(State);
    
    if (UpdatedMsg->isInstanceMessage()) {
      SVal recVal = UpdatedMsg->getReceiverSVal();
      if (!recVal.isUndef()) {
        // Bifurcate the state into nil and non-nil ones.
        DefinedOrUnknownSVal receiverVal =
            recVal.castAs<DefinedOrUnknownSVal>();

        ProgramStateRef notNilState, nilState;
        std::tie(notNilState, nilState) = State->assume(receiverVal);
        
        // There are three cases: can be nil or non-nil, must be nil, must be
        // non-nil. We ignore must be nil, and merge the rest two into non-nil.
        // FIXME: This ignores many potential bugs (<rdar://problem/11733396>).
        // Revisit once we have lazier constraints.
        if (nilState && !notNilState) {
          continue;
        }
        
        // Check if the "raise" message was sent.
        assert(notNilState);
        if (ObjCNoRet.isImplicitNoReturn(ME)) {
          // If we raise an exception, for now treat it as a sink.
          // Eventually we will want to handle exceptions properly.
          Bldr.generateSink(ME, Pred, State);
          continue;
        }
        
        // Generate a transition to non-Nil state.
        if (notNilState != State) {
          Pred = Bldr.generateNode(ME, Pred, notNilState);
          assert(Pred && "Should have cached out already!");
        }
      }
    } else {
      // Check for special class methods that are known to not return
      // and that we should treat as a sink.
      if (ObjCNoRet.isImplicitNoReturn(ME)) {
        // If we raise an exception, for now treat it as a sink.
        // Eventually we will want to handle exceptions properly.
        Bldr.generateSink(ME, Pred, Pred->getState());
        continue;
      }
    }

    defaultEvalCall(Bldr, Pred, *UpdatedMsg);
  }
  
  ExplodedNodeSet dstPostvisit;
  getCheckerManager().runCheckersForPostCall(dstPostvisit, dstEval,
                                             *Msg, *this);

  // Finally, perform the post-condition check of the ObjCMessageExpr and store
  // the created nodes in 'Dst'.
  getCheckerManager().runCheckersForPostObjCMessage(Dst, dstPostvisit,
                                                    *Msg, *this);
}
Ejemplo n.º 16
0
void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, 
                           ExplodedNode *Pred, ExplodedNodeSet &Dst) {
  
  ExplodedNodeSet dstPreStmt;
  getCheckerManager().runCheckersForPreStmt(dstPreStmt, Pred, CastE, *this);
  
  if (CastE->getCastKind() == CK_LValueToRValue) {
    for (ExplodedNodeSet::iterator I = dstPreStmt.begin(), E = dstPreStmt.end();
         I!=E; ++I) {
      ExplodedNode *subExprNode = *I;
      const ProgramState *state = subExprNode->getState();
      const LocationContext *LCtx = subExprNode->getLocationContext();
      evalLoad(Dst, CastE, subExprNode, state, state->getSVal(Ex, LCtx));
    }
    return;
  }
  
  // All other casts.  
  QualType T = CastE->getType();
  QualType ExTy = Ex->getType();
  
  if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(CastE))
    T = ExCast->getTypeAsWritten();
  
  StmtNodeBuilder Bldr(dstPreStmt, Dst, *currentBuilderContext);
  for (ExplodedNodeSet::iterator I = dstPreStmt.begin(), E = dstPreStmt.end();
       I != E; ++I) {
    
    Pred = *I;
    
    switch (CastE->getCastKind()) {
      case CK_LValueToRValue:
        llvm_unreachable("LValueToRValue casts handled earlier.");
      case CK_ToVoid:
        continue;
        // The analyzer doesn't do anything special with these casts,
        // since it understands retain/release semantics already.
      case CK_ARCProduceObject:
      case CK_ARCConsumeObject:
      case CK_ARCReclaimReturnedObject:
      case CK_ARCExtendBlockObject: // Fall-through.
        // The analyser can ignore atomic casts for now, although some future
        // checkers may want to make certain that you're not modifying the same
        // value through atomic and nonatomic pointers.
      case CK_AtomicToNonAtomic:
      case CK_NonAtomicToAtomic:
        // True no-ops.
      case CK_NoOp:
      case CK_FunctionToPointerDecay: {
        // Copy the SVal of Ex to CastE.
        const ProgramState *state = Pred->getState();
        const LocationContext *LCtx = Pred->getLocationContext();
        SVal V = state->getSVal(Ex, LCtx);
        state = state->BindExpr(CastE, LCtx, V);
        Bldr.generateNode(CastE, Pred, state);
        continue;
      }
      case CK_Dependent:
      case CK_ArrayToPointerDecay:
      case CK_BitCast:
      case CK_LValueBitCast:
      case CK_IntegralCast:
      case CK_NullToPointer:
      case CK_IntegralToPointer:
      case CK_PointerToIntegral:
      case CK_PointerToBoolean:
      case CK_IntegralToBoolean:
      case CK_IntegralToFloating:
      case CK_FloatingToIntegral:
      case CK_FloatingToBoolean:
      case CK_FloatingCast:
      case CK_FloatingRealToComplex:
      case CK_FloatingComplexToReal:
      case CK_FloatingComplexToBoolean:
      case CK_FloatingComplexCast:
      case CK_FloatingComplexToIntegralComplex:
      case CK_IntegralRealToComplex:
      case CK_IntegralComplexToReal:
      case CK_IntegralComplexToBoolean:
      case CK_IntegralComplexCast:
      case CK_IntegralComplexToFloatingComplex:
      case CK_CPointerToObjCPointerCast:
      case CK_BlockPointerToObjCPointerCast:
      case CK_AnyPointerToBlockPointerCast:  
      case CK_ObjCObjectLValueCast: {
        // Delegate to SValBuilder to process.
        const ProgramState *state = Pred->getState();
        const LocationContext *LCtx = Pred->getLocationContext();
        SVal V = state->getSVal(Ex, LCtx);
        V = svalBuilder.evalCast(V, T, ExTy);
        state = state->BindExpr(CastE, LCtx, V);
        Bldr.generateNode(CastE, Pred, state);
        continue;
      }
      case CK_DerivedToBase:
      case CK_UncheckedDerivedToBase: {
        // For DerivedToBase cast, delegate to the store manager.
        const ProgramState *state = Pred->getState();
        const LocationContext *LCtx = Pred->getLocationContext();
        SVal val = state->getSVal(Ex, LCtx);
        val = getStoreManager().evalDerivedToBase(val, T);
        state = state->BindExpr(CastE, LCtx, val);
        Bldr.generateNode(CastE, Pred, state);
        continue;
      }
        // Various C++ casts that are not handled yet.
      case CK_Dynamic:
      case CK_ToUnion:
      case CK_BaseToDerived:
      case CK_NullToMemberPointer:
      case CK_BaseToDerivedMemberPointer:
      case CK_DerivedToBaseMemberPointer:
      case CK_UserDefinedConversion:
      case CK_ConstructorConversion:
      case CK_VectorSplat:
      case CK_MemberPointerToBoolean: {
        // Recover some path-sensitivty by conjuring a new value.
        QualType resultType = CastE->getType();
        if (CastE->isLValue())
          resultType = getContext().getPointerType(resultType);
        
        SVal result =
        svalBuilder.getConjuredSymbolVal(NULL, CastE, resultType,
                               currentBuilderContext->getCurrentBlockCount());
        
        const LocationContext *LCtx = Pred->getLocationContext();
        const ProgramState *state = Pred->getState()->BindExpr(CastE, LCtx,
                                                               result);
        Bldr.generateNode(CastE, Pred, state);
        continue;
      }
    }
  }
}