| // RUN: %target-swift-frontend -emit-sil -primary-file %s -o /dev/null -verify |
| // |
| // These are tests for diagnostics produced by constant propagation pass |
| // on floating-point operations. |
| |
| import StdlibUnittest |
| |
| func testFPToIntConversion() { |
| _blackHole(Int8(-1.28E2)) |
| _blackHole(Int8(-128.5)) // the result is -128 and is not an overflow |
| _blackHole(Int8(1.27E2)) |
| _blackHole(Int8(-0)) |
| _blackHole(Int8(3.33333)) |
| _blackHole(Int8(-2E2)) // expected-error {{invalid conversion: '-2E2' overflows 'Int8'}} |
| |
| _blackHole(UInt8(2E2)) |
| _blackHole(UInt8(3E2)) // expected-error {{invalid conversion: '3E2' overflows 'UInt8'}} |
| _blackHole(UInt8(-0E0)) |
| _blackHole(UInt8(-2E2)) // expected-error {{negative literal '-2E2' cannot be converted to 'UInt8'}} |
| |
| _blackHole(Int8(1E6000)) // expected-error {{invalid conversion: '1E6000' overflows 'Int8'}} |
| // expected-warning@-1 {{'1E6000' overflows to inf because its magnitude exceeds the limits of a float literal}} |
| |
| _blackHole(UInt8(1E6000)) // expected-error {{invalid conversion: '1E6000' overflows 'UInt8'}} |
| // expected-warning@-1 {{'1E6000' overflows to inf because its magnitude exceeds the limits of a float literal}} |
| |
| _blackHole(Int16(3.2767E4)) |
| _blackHole(Int16(3.2768E4)) // expected-error {{invalid conversion: '3.2768E4' overflows 'Int16'}} |
| _blackHole(Int16(-4E4)) // expected-error {{invalid conversion: '-4E4' overflows 'Int16'}} |
| |
| _blackHole(UInt16(6.5535E4)) |
| _blackHole(UInt16(6.5536E4)) // expected-error {{invalid conversion: '6.5536E4' overflows 'UInt16'}} |
| _blackHole(UInt16(7E4)) // expected-error {{invalid conversion: '7E4' overflows 'UInt16'}} |
| _blackHole(UInt16(-0E0)) |
| _blackHole(UInt16(-2E2)) // expected-error {{negative literal '-2E2' cannot be converted to 'UInt16'}} |
| |
| _blackHole(Int32(-2.147483648E9)) |
| _blackHole(Int32(-2.147483649E9)) // expected-error {{invalid conversion: '-2.147483649E9' overflows 'Int32'}} |
| _blackHole(Int32(3E9)) // expected-error {{invalid conversion: '3E9' overflows 'Int32'}} |
| |
| _blackHole(UInt32(4.294967295E9)) |
| _blackHole(UInt32(4.294967296E9)) // expected-error {{invalid conversion: '4.294967296E9' overflows 'UInt32'}} |
| _blackHole(UInt32(5E9)) // expected-error {{invalid conversion: '5E9' overflows 'UInt32'}} |
| _blackHole(UInt32(-0E0)) |
| _blackHole(UInt32(-2E2)) // expected-error {{negative literal '-2E2' cannot be converted to 'UInt32'}} |
| |
| _blackHole(Int64(9.223372036854775E18)) |
| |
| // A case where the imprecision due to the implicit conversion of |
| // float literals to 'Double' results in an overflow. |
| _blackHole(Int64(9.223372036854775807E18)) // expected-error {{invalid conversion: '9.223372036854775807E18' overflows 'Int64'}} |
| |
| // A case where implicit conversion of the float literal to 'Double' |
| // elides an overflow that one would expect during conversion to 'Int64'. |
| _blackHole(Int64(-9.223372036854775809E18)) |
| |
| // Cases of definite overflow. |
| _blackHole(Int64(9.223372036854775808E18)) // expected-error {{invalid conversion: '9.223372036854775808E18' overflows 'Int64'}} |
| _blackHole(Int64(1E19)) // expected-error {{invalid conversion: '1E19' overflows 'Int64'}} |
| |
| // A case where implicit conversion of the float literal to 'Double' |
| // results in an overflow during conversion to 'UInt64''. |
| _blackHole(UInt64(1.844674407370955E19)) |
| _blackHole(UInt64(1.8446744073709551615E19)) // expected-error {{invalid conversion: '1.8446744073709551615E19' overflows 'UInt64'}} |
| |
| _blackHole(UInt64(2E19)) // expected-error {{invalid conversion: '2E19' overflows 'UInt64'}} |
| _blackHole(UInt64(-0E0)) |
| _blackHole(UInt64(-2E2)) // expected-error {{negative literal '-2E2' cannot be converted to 'UInt64'}} |
| |
| _blackHole(Int64(1E6000)) // expected-error {{invalid conversion: '1E6000' overflows 'Int64'}} |
| // expected-warning@-1 {{'1E6000' overflows to inf because its magnitude exceeds the limits of a float literal}} |
| |
| _blackHole(UInt64(1E6000)) // expected-error {{invalid conversion: '1E6000' overflows 'UInt64'}} |
| // expected-warning@-1 {{'1E6000' overflows to inf because its magnitude exceeds the limits of a float literal}} |
| } |
| |
| func testFloatConvertOverflow() { |
| let f1: Float = 1E38 |
| _blackHole(f1) |
| let f2: Float = 1E39 // expected-warning {{'1E39' overflows to inf during conversion to 'Float'}} |
| _blackHole(f2) |
| let f3: Float = 1234567891012345678912345671234561234512.0 // expected-warning {{'1234567891012345678912345671234561234512.0' overflows to inf during conversion to 'Float'}} |
| _blackHole(f3) |
| let f4: Float = 0.1234567891012345678912345671234561234512 |
| _blackHole(f4) |
| let f5: Float32 = -3.4028236E+38 // expected-warning {{'-3.4028236E+38' overflows to -inf during conversion to 'Float32' (aka 'Float')}} |
| _blackHole(f5) |
| |
| // Diagnositcs for Double truncations have architecture dependent |
| // messages. See _nonx86 and _x86 test files. |
| let d1: Double = 1E308 |
| _blackHole(d1) |
| let d2: Double = 1234567891012345678912345671234561234512.0 |
| _blackHole(d2) |
| |
| // All warnings are disabled during explicit conversions. |
| // Except when the number is so large that it wouldn't even fit into largest |
| // FP type available. |
| _blackHole(Float(1E38)) |
| _blackHole(Float(1E39)) |
| _blackHole(Float(100000000000000000000000000000000000000000000000.0)) |
| _blackHole(Double(1E308)) |
| _blackHole(Float(1E6000)) // expected-warning {{'1E6000' overflows to inf because its magnitude exceeds the limits of a float literal}} |
| _blackHole(Float(-1E6000)) // expected-warning {{'-1E6000' overflows to -inf because its magnitude exceeds the limits of a float literal}} |
| _blackHole(Double(1E6000)) // expected-warning {{'1E6000' overflows to inf because its magnitude exceeds the limits of a float literal}} |
| } |
| |
| func testFloatConvertUnderflow() { |
| let f0: Float = 0.500000006364665322827 |
| _blackHole(f0) |
| let f1: Float = 1E-37 |
| _blackHole(f1) |
| let f2: Float = 1E-39 // expected-warning {{'1E-39' underflows and loses precision during conversion to 'Float'}} |
| _blackHole(f2) |
| let f3: Float = 1E-45 // expected-warning {{'1E-45' underflows and loses precision during conversion to 'Float'}} |
| _blackHole(f3) |
| |
| // A number close to 2^-150 (smaller than least non-zero float: 2^-149) |
| let f6: Float = 7.0064923E-46 // expected-warning {{'7.0064923E-46' underflows and loses precision during conversion to 'Float'}} |
| _blackHole(f6) |
| |
| // Some cases where tininess doesn't cause extra imprecision. |
| |
| // A number so close to 2^-130 that 2^-130 is its best approximation |
| // even in Float80. |
| let f4: Float = 7.3468396926392969248E-40 |
| _blackHole(f4) |
| // A number very close to 2^-149. |
| let f5: Float = 1.4012984821624085566E-45 |
| _blackHole(f5) |
| |
| let f7: Float = 1.1754943E-38 // expected-warning {{'1.1754943E-38' underflows and loses precision during conversion to 'Float'}} |
| _blackHole(f7) |
| let f8: Float = 1.17549428E-38 // expected-warning {{'1.17549428E-38' underflows and loses precision during conversion to 'Float'}} |
| _blackHole(f8) |
| |
| let d1: Double = 1E-307 |
| _blackHole(d1) |
| |
| // All warnings are disabled during explict conversions. |
| _blackHole(Float(1E-37)) |
| _blackHole(Float(1E-39)) |
| _blackHole(Float(1E-45)) |
| _blackHole(Double(1E-307)) |
| } |
| |
| func testHexFloatImprecision() { |
| let f1: Float = 0x0.800000p-126 |
| _blackHole(f1) |
| // Smallest Float subnormal number. |
| let f2: Float = 0x0.000002p-126 |
| _blackHole(f2) |
| let f3: Float = 0x1.000002p-127 // expected-warning {{'0x1.000002p-127' loses precision during conversion to 'Float'}} |
| _blackHole(f3) |
| let f4: Float = 0x1.000001p-127 // expected-warning {{'0x1.000001p-127' loses precision during conversion to 'Float'}} |
| _blackHole(f4) |
| let f5: Float = 0x1.0000002p-126 // expected-warning {{'0x1.0000002p-126' loses precision during conversion to 'Float'}} |
| _blackHole(f5) |
| |
| // In the following cases, the literal is truncated to a Float through a |
| // (lossless) conversion to Double. There should be no warnings here. |
| let t1: Double = 0x1.0000002p-126 |
| _blackHole(Float(t1)) |
| let t2: Double = 0x1.000001p-126 |
| _blackHole(Float(t2)) |
| let t3 = 0x1.000000fp25 |
| _blackHole(Float(t3)) |
| |
| let d1: Double = 0x0.8p-1022 |
| _blackHole(d1) |
| // Smallest non-zero number representable in Double. |
| let d2: Double = 0x0.0000000000001p-1022 |
| _blackHole(d2) |
| |
| // All warnings are disabled during explict conversions. |
| _blackHole(Float(0x1.000002p-126)) |
| _blackHole(Float(0x1.0000002p-126)) |
| _blackHole(Float(0x1.000002p-127)) |
| _blackHole(Float(0x1.000001p-127)) |
| _blackHole(Float(Double(0x1.000000fp25))) |
| _blackHole(Double(0x1p-1074)) |
| } |
| |
| func testFloatArithmetic() { |
| // Ignore inf and Nan during arithmetic operations. |
| // This may become a warning in the future. |
| let infV: Float = 3.0 / 0.0 |
| _blackHole(infV) |
| |
| let a: Float = 1E38 |
| let b: Float = 10.0 |
| _blackHole(a * b) |
| } |
| |
| func testIntToFloatConversion() { |
| let f1: Float = 16777216 |
| _blackHole(f1) |
| |
| let f2: Float = 1_000_000_000_000 // expected-warning {{'1000000000000' is not exactly representable as 'Float'; it becomes '999999995904'}} |
| _blackHole(f2) |
| |
| // First positive integer that cannot be precisely represented in Float: 2^24 + 1 |
| let f3: Float = 16777217 // expected-warning {{'16777217' is not exactly representable as 'Float'; it becomes '16777216'}} |
| _blackHole(f3) |
| |
| let d1: Double = 9_007_199_254_740_992 // This value is 2^53 |
| _blackHole(d1) |
| |
| // FIXME: False Negative: no warning is produced here since we do not |
| // distinguish between implicit Double conversion that are within the |
| // context of an explicit conversion from others. |
| let d2: Double = 9_007_199_254_740_993 |
| _blackHole(d2) |
| |
| // No warnings are emitted for conversion through explicit constructor calls. |
| _blackHole(Float(16777217)) |
| _blackHole(Double(2_147_483_647)) |
| } |