APSIntType::RangeTestResultKind APSIntType::testInRange(const llvm::APSInt &Value, bool AllowSignConversions) const { // Negative numbers cannot be losslessly converted to unsigned type. if (IsUnsigned && !AllowSignConversions && Value.isSigned() && Value.isNegative()) return RTR_Below; unsigned MinBits; if (AllowSignConversions) { if (Value.isSigned() && !IsUnsigned) MinBits = Value.getMinSignedBits(); else MinBits = Value.getActiveBits(); } else { // Signed integers can be converted to signed integers of the same width // or (if positive) unsigned integers with one fewer bit. // Unsigned integers can be converted to unsigned integers of the same width // or signed integers with one more bit. if (Value.isSigned()) MinBits = Value.getMinSignedBits() - IsUnsigned; else MinBits = Value.getActiveBits() + !IsUnsigned; } if (MinBits <= BitWidth) return RTR_Within; if (Value.isSigned() && Value.isNegative()) return RTR_Below; else return RTR_Above; }
/// \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); }
bool LiteralAnalyser::checkRange(QualType TLeft, const Expr* Right, clang::SourceLocation Loc, llvm::APSInt Result) { // TODO refactor with check() const QualType QT = TLeft.getCanonicalType(); int availableWidth = 0; if (QT.isBuiltinType()) { const BuiltinType* TL = cast<BuiltinType>(QT); if (!TL->isInteger()) { // TODO floats return false; } availableWidth = TL->getIntegerWidth(); } else { QT.dump(); assert(0 && "todo"); } const Limit* L = getLimit(availableWidth); assert(Result.isSigned() && "TEMP FOR NOW"); int64_t value = Result.getSExtValue(); bool overflow = false; if (Result.isNegative()) { const int64_t limit = L->minVal; if (value < limit) overflow = true; } else { const int64_t limit = (int64_t)L->maxVal; if (value > limit) overflow = true; } //fprintf(stderr, "VAL=%lld width=%d signed=%d\n", value, availableWidth, Result.isSigned()); if (overflow) { SmallString<20> ss; Result.toString(ss, 10, true); StringBuilder buf1; TLeft->DiagName(buf1); if (Right) { Diags.Report(Right->getLocStart(), diag::err_literal_outofbounds) << buf1 << L->minStr << L->maxStr << ss << Right->getSourceRange(); } else { Diags.Report(Loc, diag::err_literal_outofbounds) << buf1 << L->minStr << L->maxStr << ss; } return false; } return 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); }