Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -124,10 +124,6 @@ SVal evalCast(ProgramStateRef State, SVal V, QualType CastTy, QualType OriginalTy = QualType{}); - // Handles casts of type CK_IntegralCast. - SVal evalIntegralCast(ProgramStateRef state, SVal val, QualType castTy, - QualType originalType); - virtual SVal evalMinus(NonLoc val) = 0; virtual SVal evalComplement(NonLoc val) = 0; Index: clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -431,7 +431,7 @@ case CK_IntegralCast: { // Delegate to SValBuilder to process. SVal V = state->getSVal(Ex, LCtx); - V = svalBuilder.evalIntegralCast(state, V, T, ExTy); + V = svalBuilder.evalCast(state, V, T, ExTy); state = state->BindExpr(CastE, LCtx, V); Bldr.generateNode(CastE, Pred, state); continue; Index: clang/lib/StaticAnalyzer/Core/SValBuilder.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ clang/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -493,44 +493,6 @@ return true; } -// Handles casts of type CK_IntegralCast. -// At the moment, this function will redirect to evalCast, except when the range -// of the original value is known to be greater than the max of the target type. -SVal SValBuilder::evalIntegralCast(ProgramStateRef state, SVal val, - QualType castTy, QualType originalTy) { - // No truncations if target type is big enough. - if (getContext().getTypeSize(castTy) >= getContext().getTypeSize(originalTy)) - return evalCast(state, val, castTy, originalTy); - - SymbolRef se = val.getAsSymbol(); - if (!se) // Let evalCast handle non symbolic expressions. - return evalCast(state, val, castTy, originalTy); - - // Find the maximum value of the target type. - APSIntType ToType(getContext().getTypeSize(castTy), - castTy->isUnsignedIntegerType()); - llvm::APSInt ToTypeMax = ToType.getMaxValue(); - NonLoc ToTypeMaxVal = - makeIntVal(ToTypeMax.isUnsigned() ? ToTypeMax.getZExtValue() - : ToTypeMax.getSExtValue(), - castTy) - .castAs(); - // Check the range of the symbol being casted against the maximum value of the - // target type. - NonLoc FromVal = val.castAs(); - QualType CmpTy = getConditionType(); - NonLoc CompVal = - evalBinOpNN(state, BO_LE, FromVal, ToTypeMaxVal, CmpTy).castAs(); - ProgramStateRef IsNotTruncated, IsTruncated; - std::tie(IsNotTruncated, IsTruncated) = state->assume(CompVal); - if (!IsNotTruncated && IsTruncated) { - // Symbol is truncated so we evaluate it as a cast. - NonLoc CastVal = makeNonLoc(se, originalTy, castTy); - return CastVal; - } - return evalCast(state, val, castTy, originalTy); -} - //===----------------------------------------------------------------------===// // Cast methods. // `evalCast` is the main method @@ -915,6 +877,31 @@ return makeNonLoc(SE, BO_NE, BVF.getValue(0, SE->getType()), CastTy); } } else { + + if (!OriginalTy.isNull() && CastTy->isIntegralOrEnumerationType() && + OriginalTy->isIntegralOrEnumerationType() && + getContext().getTypeSize(CastTy) < + getContext().getTypeSize(OriginalTy)) { + // Find the maximum value of the target type. + llvm::APSInt ToTypeMax = llvm::APSInt::getMaxValue( + getContext().getTypeSize(CastTy), CastTy->isUnsignedIntegerType()); + NonLoc ToTypeMaxVal = + makeIntVal(ToTypeMax.getExtValue(), CastTy).castAs(); + // Check the range of the symbol being casted against the maximum value of + // the target type. + NonLoc FromVal = V.castAs(); + QualType CmpTy = getConditionType(); + NonLoc CompVal = evalBinOpNN(State, BO_LE, FromVal, ToTypeMaxVal, CmpTy) + .castAs(); + ProgramStateRef IsNotTruncated, IsTruncated; + std::tie(IsNotTruncated, IsTruncated) = State->assume(CompVal); + if (!IsNotTruncated && IsTruncated) { + // Symbol is truncated so we evaluate it as a cast. + NonLoc CastVal = makeNonLoc(SE, OriginalTy, CastTy); + return CastVal; + } + } + // Symbol to integer, float. QualType T = Context.getCanonicalType(SE->getType()); // If types are the same or both are integers, ignore the cast.