Skip to content

Commit 2b25e05

Browse files
Merge pull request #23184 from ravikandhadai/swift-5.1-rdar48605307-cherrypick
[SIL Diagnostics] Fix undefined behavior due to bit shifting in ConstantFolding.cpp
2 parents 825d241 + 8f0ca34 commit 2b25e05

File tree

3 files changed

+26
-2
lines changed

3 files changed

+26
-2
lines changed

lib/SILOptimizer/Utils/ConstantFolding.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -993,11 +993,14 @@ bool isLossyUnderflow(int srcExponent, uint64_t srcSignificand,
993993
: srcSignificand;
994994

995995
// Compute the significand bits lost due to subnormal form. Note that the
996-
// integer part: 1 will use up a significand bit in denormal form.
996+
// integer part: 1 will use up a significand bit in subnormal form.
997997
unsigned additionalLoss = destSem.minExponent - srcExponent + 1;
998+
// Lost bits cannot exceed Double.minExponent - Double.significandWidth = 53.
999+
// This can happen when truncating from Float80 to Double.
1000+
assert(additionalLoss <= 53);
9981001

9991002
// Check whether a set LSB is lost due to subnormal representation.
1000-
unsigned lostLSBBitMask = (1 << additionalLoss) - 1;
1003+
uint64_t lostLSBBitMask = ((uint64_t)1 << additionalLoss) - 1;
10011004
return (truncSignificand & lostLSBBitMask);
10021005
}
10031006

test/SILOptimizer/diagnostic_constant_propagation_floats.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,14 @@ func testHexFloatImprecision() {
171171
// Smallest non-zero number representable in Double.
172172
let d2: Double = 0x0.0000000000001p-1022
173173
_blackHole(d2)
174+
let d3: Double = 0x1p-1074
175+
_blackHole(d3)
176+
177+
// Test the case where conversion results in subnormality in the destination.
178+
let d4: Float = 0x1p-149
179+
_blackHole(d4)
180+
let d5: Float = 0x1.8p-149 // expected-warning {{'0x1.8p-149' loses precision during conversion to 'Float}}
181+
_blackHole(d5)
174182

175183
// All warnings are disabled during explict conversions.
176184
_blackHole(Float(0x1.000002p-126))

test/SILOptimizer/diagnostic_constant_propagation_floats_x86.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,24 @@ func testFloatConvertUnderflow() {
7070
let d4: Double = 5E-324
7171
_blackHole(d4)
7272

73+
let e4: Float80 = 0x1p-16445
74+
_blackHole(e4)
75+
7376
// FIXME: if a number is so tiny that it underflows even Float80,
7477
// nothing is reported
7578
let e1: Float80 = 0x1p-16446
7679
_blackHole(e1)
7780

81+
// Test the case where conversion results in subnormality in the destination.
82+
let e2: Double = 0x1p-1074
83+
_blackHole(e2)
84+
// FIXME: there should be a warning in the following line but it is suppressed
85+
// conservatively as ConstantFolder thinks that the truncation here is
86+
// explicitly requested in the code. A future enhancement to the AST may
87+
// produce a warning here.
88+
let e3: Double = 0x11p-1074
89+
_blackHole(e3)
90+
7891
// All warnings are disabled during explict conversions
7992
_blackHole(Float(1E-400))
8093
_blackHole(Double(1E-309))

0 commit comments

Comments
 (0)