diff options
author | Ziang Wan <ziangw2@illinois.edu> | 2019-07-25 00:32:50 +0000 |
---|---|---|
committer | Ziang Wan <ziangw2@illinois.edu> | 2019-07-25 00:32:50 +0000 |
commit | 2028d97d09b8abb7f47c4ad4ed6ffe7a1f6486ea (patch) | |
tree | c312b19bf7b42e736d4a24db44cb413932b7254e /clang/lib/Sema/SemaChecking.cpp | |
parent | 5aee1c6b102fcc4890a5fa73e320f850328024b3 (diff) | |
download | bcm5719-llvm-2028d97d09b8abb7f47c4ad4ed6ffe7a1f6486ea.tar.gz bcm5719-llvm-2028d97d09b8abb7f47c4ad4ed6ffe7a1f6486ea.zip |
[Sema] Enable -Wimplicit-float-conversion for integral to floating point precision loss
Issue an warning when the code tries to do an implicit int -> float
conversion, where the float type ha a narrower significant than the
float type.
The new warning is controlled by flag -Wimplicit-int-float-conversion,
under -Wimplicit-float-conversion and -Wconversion.
Differential Revision: https://reviews.llvm.org/D64666
llvm-svn: 366972
Diffstat (limited to 'clang/lib/Sema/SemaChecking.cpp')
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index f9f82cdeef4..2b0d8c903b4 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -11400,6 +11400,55 @@ CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC, } } + // If we are casting an integer type to a floating point type, we might + // lose accuracy if the floating point type has a narrower significand + // than the integer type. Issue warnings for that accuracy loss. + if (SourceBT && TargetBT && SourceBT->isIntegerType() && + TargetBT->isFloatingType()) { + // Determine the number of precision bits in the source integer type. + IntRange SourceRange = GetExprRange(S.Context, E, S.isConstantEvaluated()); + unsigned int SourcePrecision = SourceRange.Width; + + // Determine the number of precision bits in the + // target floating point type. + unsigned int TargetPrecision = llvm::APFloatBase::semanticsPrecision( + S.Context.getFloatTypeSemantics(QualType(TargetBT, 0))); + + if (SourcePrecision > 0 && TargetPrecision > 0 && + SourcePrecision > TargetPrecision) { + + llvm::APSInt SourceInt; + if (E->isIntegerConstantExpr(SourceInt, S.Context)) { + // If the source integer is a constant, convert it to the target + // floating point type. Issue a warning if the value changes + // during the whole conversion. + llvm::APFloat TargetFloatValue( + S.Context.getFloatTypeSemantics(QualType(TargetBT, 0))); + llvm::APFloat::opStatus ConversionStatus = + TargetFloatValue.convertFromAPInt(SourceInt, + SourceBT->isSignedInteger(), llvm::APFloat::rmNearestTiesToEven); + + if (ConversionStatus != llvm::APFloat::opOK) { + std::string PrettySourceValue = SourceInt.toString(10); + SmallString<32> PrettyTargetValue; + TargetFloatValue.toString(PrettyTargetValue, + TargetPrecision); + + S.DiagRuntimeBehavior( + E->getExprLoc(), E, + S.PDiag(diag::warn_impcast_integer_float_precision_constant) + << PrettySourceValue << PrettyTargetValue + << E->getType() << T + << E->getSourceRange() << clang::SourceRange(CC)); + } + } else { + // Otherwise, the implicit conversion may lose precision. + DiagnoseImpCast(S, E, T, CC, + diag::warn_impcast_integer_float_precision); + } + } + } + DiagnoseNullConversion(S, E, T, CC); S.DiscardMisalignedMemberAddress(Target, E); |