diff options
author | David Bolvansky <david.bolvansky@gmail.com> | 2018-11-14 14:24:33 +0000 |
---|---|---|
committer | David Bolvansky <david.bolvansky@gmail.com> | 2018-11-14 14:24:33 +0000 |
commit | f137da261070a9ece08a9ff74e52aa278a428d13 (patch) | |
tree | 3e1fcfabe22dc5a5a0f157be3a575e62920ae8b2 /lib/Sema/SemaChecking.cpp | |
parent | 15f792eb0f51d2fa8189a31b9c71dc45e4fb02fa (diff) | |
download | clang-f137da261070a9ece08a9ff74e52aa278a428d13.tar.gz |
[Diagnostics] Check integer to floating point number implicit conversions
Summary:
GCC already catches these situations so we should handle it too.
GCC warns in C++ mode only (does anybody know why?). I think it is useful in C mode too.
Reviewers: rsmith, erichkeane, aaron.ballman, efriedma, xbolva00
Reviewed By: xbolva00
Subscribers: efriedma, craig.topper, scanon, cfe-commits
Differential Revision: https://reviews.llvm.org/D52835
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@346865 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaChecking.cpp')
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 48 |
1 files changed, 40 insertions, 8 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index a45d4fdfd7..183e0a5860 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -105,6 +105,19 @@ SourceLocation Sema::getLocationOfStringLiteralByte(const StringLiteral *SL, Context.getTargetInfo()); } +// FIXME: Force the precision of the source value down so we don't print +// digits which are usually useless (we don't really care here if we +// truncate a digit by accident in edge cases). Ideally, APFloat::toString +// would automatically print the shortest representation, but it's a bit +// tricky to implement. +static void PrettyPrintFloat(const llvm::APFloat &floatValue, + const llvm::fltSemantics &floatSem, + SmallVectorImpl<char> &prettyFloatValue) { + unsigned precision = llvm::APFloat::semanticsPrecision(floatSem); + precision = llvm::divideCeil(precision * 59, 196); + floatValue.toString(prettyFloatValue, precision); +} + /// Checks that a call expression's argument count is the desired number. /// This is useful when doing custom type-checking. Returns true on error. static bool checkArgCount(Sema &S, CallExpr *call, unsigned desiredArgCount) { @@ -10473,15 +10486,8 @@ static void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T, DiagID = diag::warn_impcast_float_to_integer; } - // FIXME: Force the precision of the source value down so we don't print - // digits which are usually useless (we don't really care here if we - // truncate a digit by accident in edge cases). Ideally, APFloat::toString - // would automatically print the shortest representation, but it's a bit - // tricky to implement. SmallString<16> PrettySourceValue; - unsigned precision = llvm::APFloat::semanticsPrecision(Value.getSemantics()); - precision = (precision * 59 + 195) / 196; - Value.toString(PrettySourceValue, precision); + PrettyPrintFloat(Value, Value.getSemantics(), PrettySourceValue); SmallString<16> PrettyTargetValue; if (IsBool) @@ -10914,6 +10920,32 @@ CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC, return; } + if (Source->isIntegerType() && TargetBT && TargetBT->isFloatingType()) { + llvm::APSInt IntValue; + if (E->EvaluateAsInt(IntValue, S.Context, Expr::SE_AllowSideEffects)) { + if (S.SourceMgr.isInSystemMacro(CC)) + return; + const llvm::fltSemantics &FloatSemantics = + S.Context.getFloatTypeSemantics(QualType(TargetBT, 0)); + llvm::APFloat FloatValue(FloatSemantics); + if (FloatValue.convertFromAPInt(IntValue, Source->isSignedIntegerType(), + llvm::APFloat::rmNearestTiesToEven) != + llvm::APFloat::opOK) { + SmallString<16> PrettyTargetValue; + SmallString<16> PrettySourceValue; + PrettyPrintFloat(FloatValue, FloatSemantics, PrettyTargetValue); + IntValue.toString(PrettySourceValue); + + S.DiagRuntimeBehavior( + E->getExprLoc(), E, + S.PDiag(diag::warn_impcast_precision_float_to_integer) + << E->getType() << T << PrettySourceValue << PrettyTargetValue + << E->getSourceRange() << clang::SourceRange(CC)); + return; + } + } + } + DiagnoseNullConversion(S, E, T, CC); S.DiscardMisalignedMemberAddress(Target, E); |