summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
authorDavid Bolvansky <david.bolvansky@gmail.com>2018-11-14 14:24:33 +0000
committerDavid Bolvansky <david.bolvansky@gmail.com>2018-11-14 14:24:33 +0000
commitf137da261070a9ece08a9ff74e52aa278a428d13 (patch)
tree3e1fcfabe22dc5a5a0f157be3a575e62920ae8b2 /lib/Sema/SemaChecking.cpp
parent15f792eb0f51d2fa8189a31b9c71dc45e4fb02fa (diff)
downloadclang-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.cpp48
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);