void GRSimpleVals::EvalCall(ExplodedNodeSet<GRState>& Dst, GRExprEngine& Eng, GRStmtNodeBuilder<GRState>& Builder, CallExpr* CE, SVal L, ExplodedNode<GRState>* Pred) { GRStateManager& StateMgr = Eng.getStateManager(); const GRState* St = Builder.GetState(Pred); // Invalidate all arguments passed in by reference (Locs). for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) { SVal V = StateMgr.GetSVal(St, *I); if (isa<loc::MemRegionVal>(V)) St = StateMgr.BindLoc(St, cast<Loc>(V), UnknownVal()); else if (isa<nonloc::LocAsInteger>(V)) St = StateMgr.BindLoc(St, cast<nonloc::LocAsInteger>(V).getLoc(), UnknownVal()); } // Make up a symbol for the return value of this function. // FIXME: We eventually should handle structs and other compound types // that are returned by value. QualType T = CE->getType(); if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())) { unsigned Count = Builder.getCurrentBlockCount(); SVal X = Eng.getValueManager().getConjuredSymbolVal(CE, Count); St = StateMgr.BindExpr(St, CE, X, Eng.getCFG().isBlkExpr(CE), false); } Builder.MakeNode(Dst, CE, Pred, St); }
SVal GRSimpleVals::DetermEvalBinOpNN(GRExprEngine& Eng, BinaryOperator::Opcode Op, NonLoc L, NonLoc R, QualType T) { BasicValueFactory& BasicVals = Eng.getBasicVals(); unsigned subkind = L.getSubKind(); while (1) { switch (subkind) { default: return UnknownVal(); case nonloc::LocAsIntegerKind: { Loc LL = cast<nonloc::LocAsInteger>(L).getLoc(); switch (R.getSubKind()) { case nonloc::LocAsIntegerKind: return EvalBinOp(Eng, Op, LL, cast<nonloc::LocAsInteger>(R).getLoc()); case nonloc::ConcreteIntKind: { // Transform the integer into a location and compare. ASTContext& Ctx = Eng.getContext(); llvm::APSInt V = cast<nonloc::ConcreteInt>(R).getValue(); V.setIsUnsigned(true); V.extOrTrunc(Ctx.getTypeSize(Ctx.VoidPtrTy)); return EvalBinOp(Eng, Op, LL, loc::ConcreteInt(BasicVals.getValue(V))); } default: switch (Op) { case BinaryOperator::EQ: return NonLoc::MakeIntTruthVal(BasicVals, false); case BinaryOperator::NE: return NonLoc::MakeIntTruthVal(BasicVals, true); default: // This case also handles pointer arithmetic. return UnknownVal(); } } } case nonloc::SymExprValKind: { // Logical not? if (!(Op == BinaryOperator::EQ && R.isZeroConstant())) return UnknownVal(); const SymExpr &SE=*cast<nonloc::SymExprVal>(L).getSymbolicExpression(); // Only handle ($sym op constant) for now. if (const SymIntExpr *E = dyn_cast<SymIntExpr>(&SE)) { BinaryOperator::Opcode Opc = E->getOpcode(); if (Opc < BinaryOperator::LT || Opc > BinaryOperator::NE) return UnknownVal(); // For comparison operators, translate the constraint by // changing the opcode. int idx = (unsigned) Opc - (unsigned) BinaryOperator::LT; assert (idx >= 0 && (unsigned) idx < sizeof(LNotOpMap)/sizeof(unsigned char)); Opc = (BinaryOperator::Opcode) LNotOpMap[idx]; assert(E->getType(Eng.getContext()) == T); E = Eng.getSymbolManager().getSymIntExpr(E->getLHS(), Opc, E->getRHS(), T); return nonloc::SymExprVal(E); } return UnknownVal(); } case nonloc::ConcreteIntKind: if (isa<nonloc::ConcreteInt>(R)) { const nonloc::ConcreteInt& L_CI = cast<nonloc::ConcreteInt>(L); const nonloc::ConcreteInt& R_CI = cast<nonloc::ConcreteInt>(R); return L_CI.EvalBinOp(BasicVals, Op, R_CI); } else { subkind = R.getSubKind(); NonLoc tmp = R; R = L; L = tmp; // Swap the operators. switch (Op) { case BinaryOperator::LT: Op = BinaryOperator::GT; break; case BinaryOperator::GT: Op = BinaryOperator::LT; break; case BinaryOperator::LE: Op = BinaryOperator::GE; break; case BinaryOperator::GE: Op = BinaryOperator::LE; break; default: break; } continue; } case nonloc::SymbolValKind: if (isa<nonloc::ConcreteInt>(R)) { ValueManager &ValMgr = Eng.getValueManager(); return ValMgr.makeNonLoc(cast<nonloc::SymbolVal>(L).getSymbol(), Op, cast<nonloc::ConcreteInt>(R).getValue(), T); } else return UnknownVal(); } } }