forked from OSchip/llvm-project
[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
This commit is contained in:
parent
5aee1c6b10
commit
2028d97d09
|
@ -62,7 +62,8 @@ def BoolConversion : DiagGroup<"bool-conversion", [PointerBoolConversion,
|
|||
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">;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -115,12 +115,12 @@ static void splats(int i, long l, __uint128_t t, float f, double d) {
|
|||
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}}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue