ProgramStateRef SimpleConstraintManager::assumeInclusiveRange( ProgramStateRef State, NonLoc Value, const llvm::APSInt &From, const llvm::APSInt &To, bool InRange) { assert(From.isUnsigned() == To.isUnsigned() && From.getBitWidth() == To.getBitWidth() && "Values should have same types!"); if (!canReasonAbout(Value)) { // Just add the constraint to the expression without trying to simplify. SymbolRef Sym = Value.getAsSymExpr(); assert(Sym); return assumeSymWithinInclusiveRange(State, Sym, From, To, InRange); } switch (Value.getSubKind()) { default: llvm_unreachable("'assumeInclusiveRange' is not implemented" "for this NonLoc"); case nonloc::LocAsIntegerKind: case nonloc::SymbolValKind: { if (SymbolRef Sym = Value.getAsSymbol()) return assumeSymWithinInclusiveRange(State, Sym, From, To, InRange); return State; } // end switch case nonloc::ConcreteIntKind: { const llvm::APSInt &IntVal = Value.castAs<nonloc::ConcreteInt>().getValue(); bool IsInRange = IntVal >= From && IntVal <= To; bool isFeasible = (IsInRange == InRange); return isFeasible ? State : nullptr; } } // end switch }
ProgramStateRef BasicConstraintManager::assumeSymLE(ProgramStateRef state, SymbolRef sym, const llvm::APSInt &V, const llvm::APSInt &Adjustment) { // Reject a path if the value of sym is a constant X and !(X+Adj <= V). if (const llvm::APSInt* X = getSymVal(state, sym)) { bool isFeasible = (*X <= V-Adjustment); return isFeasible ? state : NULL; } // Sym is not a constant, but it is worth looking to see if V is the // minimum integer value. if (V == llvm::APSInt::getMinValue(V.getBitWidth(), V.isUnsigned())) { llvm::APSInt Adjusted = V-Adjustment; // If we know that sym != V (after adjustment), then this condition // is infeasible since there is no other value less than V. bool isFeasible = !isNotEqual(state, sym, Adjusted); // If the path is still feasible then as a consequence we know that // 'sym+Adjustment == V' because there are no smaller values. // Add this constraint. return isFeasible ? AddEQ(state, sym, Adjusted) : NULL; } return state; }
ProgramStateRef BasicConstraintManager::assumeSymGT(ProgramStateRef state, SymbolRef sym, const llvm::APSInt &V, const llvm::APSInt &Adjustment) { // Is 'V' the largest possible value? if (V == llvm::APSInt::getMaxValue(V.getBitWidth(), V.isUnsigned())) { // sym cannot be any value greater than 'V'. This path is infeasible. return NULL; } // FIXME: For now have assuming x > y be the same as assuming sym != V; return assumeSymNE(state, sym, V, Adjustment); }
TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type) { Integer.Kind = Integral; // Copy the APSInt value into our decomposed form. Integer.BitWidth = Value.getBitWidth(); Integer.IsUnsigned = Value.isUnsigned(); // If the value is large, we have to get additional memory from the ASTContext unsigned NumWords = Value.getNumWords(); if (NumWords > 1) { void *Mem = Ctx.Allocate(NumWords * sizeof(uint64_t)); std::memcpy(Mem, Value.getRawData(), NumWords * sizeof(uint64_t)); Integer.pVal = static_cast<uint64_t *>(Mem); } else { Integer.VAL = Value.getZExtValue(); } Integer.Type = Type.getAsOpaquePtr(); }
/// \brief Determine if two APSInts have the same value, zero- or sign-extending /// as needed. static bool IsSameValue(const llvm::APSInt &I1, const llvm::APSInt &I2) { if (I1.getBitWidth() == I2.getBitWidth() && I1.isSigned() == I2.isSigned()) return I1 == I2; // Check for a bit-width mismatch. if (I1.getBitWidth() > I2.getBitWidth()) return IsSameValue(I1, I2.extend(I1.getBitWidth())); else if (I2.getBitWidth() > I1.getBitWidth()) return IsSameValue(I1.extend(I2.getBitWidth()), I2); // We have a signedness mismatch. Turn the signed value into an unsigned // value. if (I1.isSigned()) { if (I1.isNegative()) return false; return llvm::APSInt(I1, true) == I2; } if (I2.isNegative()) return false; return I1 == llvm::APSInt(I2, true); }
SVal SimpleSValBuilder::MakeSymIntVal(const SymExpr *LHS, BinaryOperator::Opcode op, const llvm::APSInt &RHS, QualType resultTy) { bool isIdempotent = false; // Check for a few special cases with known reductions first. switch (op) { default: // We can't reduce this case; just treat it normally. break; case BO_Mul: // a*0 and a*1 if (RHS == 0) return makeIntVal(0, resultTy); else if (RHS == 1) isIdempotent = true; break; case BO_Div: // a/0 and a/1 if (RHS == 0) // This is also handled elsewhere. return UndefinedVal(); else if (RHS == 1) isIdempotent = true; break; case BO_Rem: // a%0 and a%1 if (RHS == 0) // This is also handled elsewhere. return UndefinedVal(); else if (RHS == 1) return makeIntVal(0, resultTy); break; case BO_Add: case BO_Sub: case BO_Shl: case BO_Shr: case BO_Xor: // a+0, a-0, a<<0, a>>0, a^0 if (RHS == 0) isIdempotent = true; break; case BO_And: // a&0 and a&(~0) if (RHS == 0) return makeIntVal(0, resultTy); else if (RHS.isAllOnesValue()) isIdempotent = true; break; case BO_Or: // a|0 and a|(~0) if (RHS == 0) isIdempotent = true; else if (RHS.isAllOnesValue()) { const llvm::APSInt &Result = BasicVals.Convert(resultTy, RHS); return nonloc::ConcreteInt(Result); } break; } // Idempotent ops (like a*1) can still change the type of an expression. // Wrap the LHS up in a NonLoc again and let evalCastFromNonLoc do the // dirty work. if (isIdempotent) return evalCastFromNonLoc(nonloc::SymbolVal(LHS), resultTy); // If we reach this point, the expression cannot be simplified. // Make a SymbolVal for the entire expression, after converting the RHS. const llvm::APSInt *ConvertedRHS = &RHS; if (BinaryOperator::isComparisonOp(op)) { // We're looking for a type big enough to compare the symbolic value // with the given constant. // FIXME: This is an approximation of Sema::UsualArithmeticConversions. ASTContext &Ctx = getContext(); QualType SymbolType = LHS->getType(); uint64_t ValWidth = RHS.getBitWidth(); uint64_t TypeWidth = Ctx.getTypeSize(SymbolType); if (ValWidth < TypeWidth) { // If the value is too small, extend it. ConvertedRHS = &BasicVals.Convert(SymbolType, RHS); } else if (ValWidth == TypeWidth) { // If the value is signed but the symbol is unsigned, do the comparison // in unsigned space. [C99 6.3.1.8] // (For the opposite case, the value is already unsigned.) if (RHS.isSigned() && !SymbolType->isSignedIntegerOrEnumerationType()) ConvertedRHS = &BasicVals.Convert(SymbolType, RHS); } } else ConvertedRHS = &BasicVals.Convert(resultTy, RHS); return makeNonLoc(LHS, op, *ConvertedRHS, resultTy); }
unsigned getBitWidth() const { return Val.getBitWidth(); }