Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -3140,6 +3140,9 @@ def warn_impcast_literal_float_to_integer : Warning< "implicit conversion from %0 to %1 changes value from %2 to %3">, InGroup; +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; def warn_impcast_float_integer : Warning< "implicit conversion turns floating-point number into integer: %0 to %1">, InGroup, DefaultIgnore; @@ -3148,6 +3151,9 @@ "implicit conversion of out of range value from %0 to %1 changes value " "from %2 to %3">, InGroup, 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, DefaultIgnore; def warn_impcast_float_to_integer_zero : Warning< "implicit conversion from %0 to %1 changes non-zero value from %2 to %3">, InGroup, DefaultIgnore; Index: lib/Sema/SemaChecking.cpp =================================================================== --- lib/Sema/SemaChecking.cpp +++ lib/Sema/SemaChecking.cpp @@ -9429,6 +9429,16 @@ 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 @@ 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; Index: test/SemaCXX/coroutines.cpp =================================================================== --- test/SemaCXX/coroutines.cpp +++ test/SemaCXX/coroutines.cpp @@ -157,7 +157,7 @@ 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}} Index: test/SemaCXX/warn-float-conversion.cpp =================================================================== --- test/SemaCXX/warn-float-conversion.cpp +++ test/SemaCXX/warn-float-conversion.cpp @@ -81,9 +81,9 @@ 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 Index: test/SemaCXX/warn-literal-conversion.cpp =================================================================== --- test/SemaCXX/warn-literal-conversion.cpp +++ test/SemaCXX/warn-literal-conversion.cpp @@ -48,4 +48,11 @@ // 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}} }