SVal GRSimpleVals::EvalEquality(GRExprEngine& Eng, Loc L, Loc R, bool isEqual) { BasicValueFactory& BasicVals = Eng.getBasicVals(); switch (L.getSubKind()) { default: assert(false && "EQ/NE not implemented for this Loc."); return UnknownVal(); case loc::ConcreteIntKind: if (isa<loc::ConcreteInt>(R)) { bool b = cast<loc::ConcreteInt>(L).getValue() == cast<loc::ConcreteInt>(R).getValue(); // Are we computing '!='? Flip the result. if (!isEqual) b = !b; return NonLoc::MakeIntTruthVal(BasicVals, b); } else if (SymbolRef Sym = R.getAsSymbol()) { const SymIntExpr * SE = Eng.getSymbolManager().getSymIntExpr(Sym, isEqual ? BinaryOperator::EQ : BinaryOperator::NE, cast<loc::ConcreteInt>(L).getValue(), Eng.getContext().IntTy); return nonloc::SymExprVal(SE); } break; case loc::MemRegionKind: { if (SymbolRef LSym = L.getAsLocSymbol()) { if (isa<loc::ConcreteInt>(R)) { const SymIntExpr *SE = Eng.getSymbolManager().getSymIntExpr(LSym, isEqual ? BinaryOperator::EQ : BinaryOperator::NE, cast<loc::ConcreteInt>(R).getValue(), Eng.getContext().IntTy); return nonloc::SymExprVal(SE); } } } // Fall-through. case loc::GotoLabelKind: return NonLoc::MakeIntTruthVal(BasicVals, isEqual ? L == R : L != R); } return NonLoc::MakeIntTruthVal(BasicVals, isEqual ? false : true); }
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(); } } }