Author: erichkeane Date: Mon May 7 13:52:56 2018 New Revision: 331673 URL: http://llvm.org/viewvc/llvm-project?rev=331673&view=rev Log: Correct warning on Float->Integer conversions.
As identified and briefly discussed here: https://bugs.llvm.org/show_bug.cgi?id=37305 Converting a floating point number to an integer type when the integral part is out of the range of the integer type is undefined behavior in C. Additionally, CodeGen emits an undef in this situation. HOWEVER, we've been giving a warning that says that the value is changed. This patch corrects the warning to list that it is actually undefined behavior. Differential Revision: https://reviews.llvm.org/D46535 Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaChecking.cpp cfe/trunk/test/SemaCXX/coroutines.cpp cfe/trunk/test/SemaCXX/warn-float-conversion.cpp cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=331673&r1=331672&r2=331673&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon May 7 13:52:56 2018 @@ -3140,6 +3140,9 @@ def warn_impcast_bitfield_precision_cons def warn_impcast_literal_float_to_integer : Warning< "implicit conversion from %0 to %1 changes value from %2 to %3">, InGroup<LiteralConversion>; +def warn_impcast_literal_float_to_integer_out_of_range : Warning< + "implicit conversion of out of range value from %0 to %1 is undefined">, + InGroup<LiteralConversion>; def warn_impcast_float_integer : Warning< "implicit conversion turns floating-point number into integer: %0 to %1">, InGroup<FloatConversion>, DefaultIgnore; @@ -3148,6 +3151,9 @@ def warn_impcast_float_to_integer : Warn "implicit conversion of out of range value from %0 to %1 changes value " "from %2 to %3">, InGroup<FloatOverflowConversion>, DefaultIgnore; +def warn_impcast_float_to_integer_out_of_range : Warning< + "implicit conversion of out of range value from %0 to %1 is undefined">, + InGroup<FloatOverflowConversion>, DefaultIgnore; def warn_impcast_float_to_integer_zero : Warning< "implicit conversion from %0 to %1 changes non-zero value from %2 to %3">, InGroup<FloatZeroConversion>, DefaultIgnore; Modified: cfe/trunk/lib/Sema/SemaChecking.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=331673&r1=331672&r2=331673&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) +++ cfe/trunk/lib/Sema/SemaChecking.cpp Mon May 7 13:52:56 2018 @@ -9429,6 +9429,16 @@ static void DiagnoseFloatingImpCast(Sema unsigned DiagID = 0; if (IsLiteral) { + // Conversion of a floating-point value to a non-bool integer where the + // integral part cannot be represented by the integer type is undefined. + if (!IsBool && + ((IntegerValue.isSigned() && (IntegerValue.isMaxSignedValue() || + IntegerValue.isMinSignedValue())) || + (IntegerValue.isUnsigned() && + (IntegerValue.isMaxValue() || IntegerValue.isMinValue())))) + return DiagnoseImpCast( + S, E, T, CContext, + diag::warn_impcast_literal_float_to_integer_out_of_range); // Warn on floating point literal to integer. DiagID = diag::warn_impcast_literal_float_to_integer; } else if (IntegerValue == 0) { @@ -9444,12 +9454,19 @@ static void DiagnoseFloatingImpCast(Sema return DiagnoseImpCast(S, E, T, CContext, diag::warn_impcast_float_integer, PruneWarnings); } + if (!IsBool && (IntegerValue.isMaxValue() || IntegerValue.isMinValue())) + return DiagnoseImpCast(S, E, T, CContext, + diag::warn_impcast_float_to_integer_out_of_range, + PruneWarnings); } else { // IntegerValue.isSigned() if (!IntegerValue.isMaxSignedValue() && !IntegerValue.isMinSignedValue()) { return DiagnoseImpCast(S, E, T, CContext, diag::warn_impcast_float_integer, PruneWarnings); } + return DiagnoseImpCast(S, E, T, CContext, + diag::warn_impcast_float_to_integer_out_of_range, + PruneWarnings); } // Warn on evaluatable floating point expression to integer conversion. DiagID = diag::warn_impcast_float_to_integer; Modified: cfe/trunk/test/SemaCXX/coroutines.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/coroutines.cpp?rev=331673&r1=331672&r2=331673&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/coroutines.cpp (original) +++ cfe/trunk/test/SemaCXX/coroutines.cpp Mon May 7 13:52:56 2018 @@ -157,7 +157,7 @@ struct coroutine_handle<void> { void yield() { co_yield 0; co_yield {"foo", 1, 2}; - co_yield {1e100}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{changes value}} expected-warning {{braces around scalar}} + co_yield {1e100}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{implicit conversion}} expected-warning {{braces around scalar}} co_yield {"foo", __LONG_LONG_MAX__}; // expected-error {{cannot be narrowed}} expected-note {{explicit cast}} expected-warning {{changes value}} co_yield {"foo"}; co_yield "foo"; // expected-error {{no matching}} Modified: cfe/trunk/test/SemaCXX/warn-float-conversion.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-float-conversion.cpp?rev=331673&r1=331672&r2=331673&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/warn-float-conversion.cpp (original) +++ cfe/trunk/test/SemaCXX/warn-float-conversion.cpp Mon May 7 13:52:56 2018 @@ -81,9 +81,9 @@ void TestOverflow() { char b = -500.0; // caught by -Wliteral-conversion const float LargeNumber = 1024; - char c = LargeNumber; // expected-warning{{implicit conversion of out of range value from 'const float' to 'char' changes value from 1024 to 127}} - char d = 400.0 + 400.0; // expected-warning{{implicit conversion of out of range value from 'double' to 'char' changes value from 800 to 127}} + char c = LargeNumber; // expected-warning{{implicit conversion of out of range value from 'const float' to 'char' is undefined}} + char d = 400.0 + 400.0; // expected-warning{{implicit conversion of out of range value from 'double' to 'char' is undefined}} - char e = 1.0 / 0.0; // expected-warning{{implicit conversion of out of range value from 'double' to 'char' changes value from +Inf to 127}} + char e = 1.0 / 0.0; // expected-warning{{implicit conversion of out of range value from 'double' to 'char' is undefined}} } #endif // OVERFLOW Modified: cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp?rev=331673&r1=331672&r2=331673&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp (original) +++ cfe/trunk/test/SemaCXX/warn-literal-conversion.cpp Mon May 7 13:52:56 2018 @@ -48,4 +48,11 @@ void test1() { // values. bool b3 = 0.0f; bool b4 = 0.0; + + // These all warn because they overflow the target type. + short s = 32768.0; // expected-warning{{implicit conversion of out of range value from 'double' to 'short' is undefined}} + unsigned short us = 65536.0; // expected-warning{{implicit conversion of out of range value from 'double' to 'unsigned short' is undefined}} + + short s2 = -32769.0; // expected-warning{{implicit conversion of out of range value from 'double' to 'short' is undefined}} + unsigned short us2 = -65537.0; // expected-warning{{implicit conversion of out of range value from 'double' to 'unsigned short' is undefined}} } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits