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; }