r366972 - [Sema] Enable -Wimplicit-float-conversion for integral to floating point precision loss
Ziang Wan via cfe-commits
cfe-commits at lists.llvm.org
Wed Jul 24 17:32:50 PDT 2019
Author: ziangwan725
Date: Wed Jul 24 17:32:50 2019
New Revision: 366972
URL: http://llvm.org/viewvc/llvm-project?rev=366972&view=rev
Log:
[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
Added:
cfe/trunk/test/Sema/implicit-int-float-conversion.c
Modified:
cfe/trunk/include/clang/Basic/DiagnosticGroups.td
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaChecking.cpp
cfe/trunk/test/Sema/conversion.c
cfe/trunk/test/Sema/ext_vector_casts.c
Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=366972&r1=366971&r2=366972&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Wed Jul 24 17:32:50 2019
@@ -62,7 +62,8 @@ def BoolConversion : DiagGroup<"bool-con
def IntConversion : DiagGroup<"int-conversion">;
def EnumConversion : DiagGroup<"enum-conversion">;
def ImplicitIntConversion : DiagGroup<"implicit-int-conversion">;
-def ImplicitFloatConversion : DiagGroup<"implicit-float-conversion">;
+def ImplicitIntFloatConversion : DiagGroup<"implicit-int-float-conversion">;
+def ImplicitFloatConversion : DiagGroup<"implicit-float-conversion", [ImplicitIntFloatConversion]>;
def ImplicitFixedPointConversion : DiagGroup<"implicit-fixed-point-conversion">;
def FloatOverflowConversion : DiagGroup<"float-overflow-conversion">;
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=366972&r1=366971&r2=366972&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Jul 24 17:32:50 2019
@@ -3271,6 +3271,14 @@ def warn_impcast_float_integer : Warning
"implicit conversion turns floating-point number into integer: %0 to %1">,
InGroup<FloatConversion>, DefaultIgnore;
+// Implicit int -> float conversion precision loss warnings.
+def warn_impcast_integer_float_precision : Warning<
+ "implicit conversion from %0 to %1 may lose precision">,
+ InGroup<ImplicitIntFloatConversion>, DefaultIgnore;
+def warn_impcast_integer_float_precision_constant : Warning<
+ "implicit conversion from %2 to %3 changes value from %0 to %1">,
+ InGroup<ImplicitIntFloatConversion>;
+
def warn_impcast_float_to_integer : Warning<
"implicit conversion from %0 to %1 changes value from %2 to %3">,
InGroup<FloatOverflowConversion>, DefaultIgnore;
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=366972&r1=366971&r2=366972&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Wed Jul 24 17:32:50 2019
@@ -11400,6 +11400,55 @@ CheckImplicitConversion(Sema &S, Expr *E
}
}
+ // 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);
Modified: cfe/trunk/test/Sema/conversion.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/conversion.c?rev=366972&r1=366971&r2=366972&view=diff
==============================================================================
--- cfe/trunk/test/Sema/conversion.c (original)
+++ cfe/trunk/test/Sema/conversion.c Wed Jul 24 17:32:50 2019
@@ -233,7 +233,7 @@ void test8(int v) {
takes_int(v);
takes_long(v);
takes_longlong(v);
- takes_float(v);
+ takes_float(v); // expected-warning {{implicit conversion from 'int' to 'float' may lose precision}}
takes_double(v);
takes_longdouble(v);
}
@@ -244,8 +244,8 @@ void test9(long v) {
takes_int(v); // expected-warning {{implicit conversion loses integer precision}}
takes_long(v);
takes_longlong(v);
- takes_float(v);
- takes_double(v);
+ takes_float(v); // expected-warning {{implicit conversion from 'long' to 'float' may lose precision}}
+ takes_double(v); // expected-warning {{implicit conversion from 'long' to 'double' may lose precision}}
takes_longdouble(v);
}
@@ -255,8 +255,8 @@ void test10(long long v) {
takes_int(v); // expected-warning {{implicit conversion loses integer precision}}
takes_long(v);
takes_longlong(v);
- takes_float(v);
- takes_double(v);
+ takes_float(v); // expected-warning {{implicit conversion from 'long long' to 'float' may lose precision}}
+ takes_double(v); // expected-warning {{implicit conversion from 'long long' to 'double' may lose precision}}
takes_longdouble(v);
}
Modified: cfe/trunk/test/Sema/ext_vector_casts.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/ext_vector_casts.c?rev=366972&r1=366971&r2=366972&view=diff
==============================================================================
--- cfe/trunk/test/Sema/ext_vector_casts.c (original)
+++ cfe/trunk/test/Sema/ext_vector_casts.c Wed Jul 24 17:32:50 2019
@@ -115,12 +115,12 @@ static void splats(int i, long l, __uint
vl = vl + t; // expected-warning {{implicit conversion loses integer precision}}
vf = 1 + vf;
- vf = l + vf;
+ vf = l + vf; // expected-warning {{implicit conversion from 'long' to 'float2' (vector of 2 'float' values) may lose precision}}
vf = 2.0 + vf;
vf = d + vf; // expected-warning {{implicit conversion loses floating-point precision}}
- vf = vf + 0xffffffff;
+ vf = vf + 0xffffffff; // expected-warning {{implicit conversion from 'unsigned int' to 'float2' (vector of 2 'float' values) changes value from 4294967295 to 4294967296}}
vf = vf + 2.1; // expected-warning {{implicit conversion loses floating-point precision}}
- vd = l + vd;
- vd = vd + t;
+ vd = l + vd; // expected-warning {{implicit conversion from 'long' to 'double2' (vector of 2 'double' values) may lose precision}}
+ vd = vd + t; // expected-warning {{implicit conversion from '__uint128_t' (aka 'unsigned __int128') to 'double2' (vector of 2 'double' values) may lose precision}}
}
Added: cfe/trunk/test/Sema/implicit-int-float-conversion.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/implicit-int-float-conversion.c?rev=366972&view=auto
==============================================================================
--- cfe/trunk/test/Sema/implicit-int-float-conversion.c (added)
+++ cfe/trunk/test/Sema/implicit-int-float-conversion.c Wed Jul 24 17:32:50 2019
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 %s -verify -Wno-conversion -Wimplicit-int-float-conversion
+
+long testReturn(long a, float b) {
+ return a + b; // expected-warning {{implicit conversion from 'long' to 'float' may lose precision}}
+}
+
+void testAssignment() {
+ float f = 222222;
+ double b = 222222222222L;
+
+ float ff = 222222222222L; // expected-warning {{implicit conversion from 'long' to 'float' changes value from 222222222222 to 222222221312}}
+ float ffff = 222222222222UL; // expected-warning {{implicit conversion from 'unsigned long' to 'float' changes value from 222222222222 to 222222221312}}
+
+ long l = 222222222222L;
+ float fff = l; // expected-warning {{implicit conversion from 'long' to 'float' may lose precision}}
+}
+
+void testExpression() {
+ float a = 0.0f;
+ float b = 222222222222L + a; // expected-warning {{implicit conversion from 'long' to 'float' changes value from 222222222222 to 222222221312}}
+
+ float g = 22222222 + 22222222;
+ float c = 22222222 + 22222223; // expected-warning {{implicit conversion from 'int' to 'float' changes value from 44444445 to 44444444}}
+
+ int i = 0;
+ float d = i + a; // expected-warning {{implicit conversion from 'int' to 'float' may lose precision}}
+
+ double e = 0.0;
+ double f = i + e;
+}
More information about the cfe-commits
mailing list