bool ConversionChecker::isLossOfPrecision(const ImplicitCastExpr *Cast, QualType DestType, CheckerContext &C) const { // Don't warn about explicit loss of precision. if (Cast->isEvaluatable(C.getASTContext())) return false; QualType SubType = Cast->IgnoreParenImpCasts()->getType(); if (!DestType->isRealType() || !SubType->isIntegerType()) return false; const bool isFloat = DestType->isFloatingType(); const auto &AC = C.getASTContext(); // We will find the largest RepresentsUntilExp value such that the DestType // can exactly represent all nonnegative integers below 2^RepresentsUntilExp. unsigned RepresentsUntilExp; if (isFloat) { const llvm::fltSemantics &Sema = AC.getFloatTypeSemantics(DestType); RepresentsUntilExp = llvm::APFloat::semanticsPrecision(Sema); } else { RepresentsUntilExp = AC.getIntWidth(DestType); if (RepresentsUntilExp == 1) { // This is just casting a number to bool, probably not a bug. return false; } if (DestType->isSignedIntegerType()) RepresentsUntilExp--; } if (RepresentsUntilExp >= sizeof(unsigned long long) * CHAR_BIT) { // Avoid overflow in our later calculations. return false; } unsigned CorrectedSrcWidth = AC.getIntWidth(SubType); if (SubType->isSignedIntegerType()) CorrectedSrcWidth--; if (RepresentsUntilExp >= CorrectedSrcWidth) { // Simple case: the destination can store all values of the source type. return false; } unsigned long long MaxVal = 1ULL << RepresentsUntilExp; if (isFloat) { // If this is a floating point type, it can also represent MaxVal exactly. MaxVal++; } return C.isGreaterOrEqual(Cast->getSubExpr(), MaxVal); // TODO: maybe also check negative values with too large magnitude. }