IR: add an emptiness check to all unsigned until loops

Unlike signed integers, a larger unsigned type does not mean a lower
minimum value, so `x - 1` can overflow even if `x` is casted to a larger
type.

 #KT-42186 Fixed
This commit is contained in:
pyos
2020-10-05 15:20:57 +02:00
committed by Alexander Udalov
parent 4a03006162
commit adcbfc7b4c
10 changed files with 283 additions and 86 deletions
@@ -4,27 +4,89 @@
val MinI = Int.MIN_VALUE
val MinB = Byte.MIN_VALUE
val MinS = Short.MIN_VALUE
val MinL = Long.MIN_VALUE
fun box(): String {
val list1 = ArrayList<Int>()
val range1 = 0..MinI step 3
val range1 = 0.toByte()..MinB step 3
for (i in range1) {
list1.add(i)
if (list1.size > 23) break
}
if (list1 != listOf<Int>()) {
return "Wrong elements for 0..MinI step 3: $list1"
return "Wrong elements for 0.toByte()..MinB step 3: $list1"
}
val list2 = ArrayList<Long>()
val range2 = 0L..MinL step 3
val list2 = ArrayList<Int>()
val range2 = 0.toShort()..MinS step 3
for (i in range2) {
list2.add(i)
if (list2.size > 23) break
}
if (list2 != listOf<Long>()) {
return "Wrong elements for 0L..MinL step 3: $list2"
if (list2 != listOf<Int>()) {
return "Wrong elements for 0.toShort()..MinS step 3: $list2"
}
val list3 = ArrayList<Int>()
val range3 = 0..MinI step 3
for (i in range3) {
list3.add(i)
if (list3.size > 23) break
}
if (list3 != listOf<Int>()) {
return "Wrong elements for 0..MinI step 3: $list3"
}
val list4 = ArrayList<Long>()
val range4 = 0L..MinL step 3
for (i in range4) {
list4.add(i)
if (list4.size > 23) break
}
if (list4 != listOf<Long>()) {
return "Wrong elements for 0L..MinL step 3: $list4"
}
val list5 = ArrayList<Int>()
val range5 = 0.toByte() until MinB step 3
for (i in range5) {
list5.add(i)
if (list5.size > 23) break
}
if (list5 != listOf<Int>()) {
return "Wrong elements for 0.toByte() until MinB step 3: $list5"
}
val list6 = ArrayList<Int>()
val range6 = 0.toShort() until MinS step 3
for (i in range6) {
list6.add(i)
if (list6.size > 23) break
}
if (list6 != listOf<Int>()) {
return "Wrong elements for 0.toShort() until MinS step 3: $list6"
}
val list7 = ArrayList<Int>()
val range7 = 0 until MinI step 3
for (i in range7) {
list7.add(i)
if (list7.size > 23) break
}
if (list7 != listOf<Int>()) {
return "Wrong elements for 0 until MinI step 3: $list7"
}
val list8 = ArrayList<Long>()
val range8 = 0L until MinL step 3
for (i in range8) {
list8.add(i)
if (list8.size > 23) break
}
if (list8 != listOf<Long>()) {
return "Wrong elements for 0L until MinL step 3: $list8"
}
return "OK"
@@ -4,25 +4,81 @@
val MinI = Int.MIN_VALUE
val MinB = Byte.MIN_VALUE
val MinS = Short.MIN_VALUE
val MinL = Long.MIN_VALUE
fun box(): String {
val list1 = ArrayList<Int>()
for (i in 0..MinI step 3) {
for (i in 0.toByte()..MinB step 3) {
list1.add(i)
if (list1.size > 23) break
}
if (list1 != listOf<Int>()) {
return "Wrong elements for 0..MinI step 3: $list1"
return "Wrong elements for 0.toByte()..MinB step 3: $list1"
}
val list2 = ArrayList<Long>()
for (i in 0L..MinL step 3) {
val list2 = ArrayList<Int>()
for (i in 0.toShort()..MinS step 3) {
list2.add(i)
if (list2.size > 23) break
}
if (list2 != listOf<Long>()) {
return "Wrong elements for 0L..MinL step 3: $list2"
if (list2 != listOf<Int>()) {
return "Wrong elements for 0.toShort()..MinS step 3: $list2"
}
val list3 = ArrayList<Int>()
for (i in 0..MinI step 3) {
list3.add(i)
if (list3.size > 23) break
}
if (list3 != listOf<Int>()) {
return "Wrong elements for 0..MinI step 3: $list3"
}
val list4 = ArrayList<Long>()
for (i in 0L..MinL step 3) {
list4.add(i)
if (list4.size > 23) break
}
if (list4 != listOf<Long>()) {
return "Wrong elements for 0L..MinL step 3: $list4"
}
val list5 = ArrayList<Int>()
for (i in 0.toByte() until MinB step 3) {
list5.add(i)
if (list5.size > 23) break
}
if (list5 != listOf<Int>()) {
return "Wrong elements for 0.toByte() until MinB step 3: $list5"
}
val list6 = ArrayList<Int>()
for (i in 0.toShort() until MinS step 3) {
list6.add(i)
if (list6.size > 23) break
}
if (list6 != listOf<Int>()) {
return "Wrong elements for 0.toShort() until MinS step 3: $list6"
}
val list7 = ArrayList<Int>()
for (i in 0 until MinI step 3) {
list7.add(i)
if (list7.size > 23) break
}
if (list7 != listOf<Int>()) {
return "Wrong elements for 0 until MinI step 3: $list7"
}
val list8 = ArrayList<Long>()
for (i in 0L until MinL step 3) {
list8.add(i)
if (list8.size > 23) break
}
if (list8 != listOf<Long>()) {
return "Wrong elements for 0L until MinL step 3: $list8"
}
return "OK"
@@ -4,27 +4,89 @@
val MinUI = UInt.MIN_VALUE
val MinUB = UByte.MIN_VALUE
val MinUS = UShort.MIN_VALUE
val MinUL = ULong.MIN_VALUE
fun box(): String {
val list1 = ArrayList<UInt>()
val range1 = 1u..MinUI step 3
val range1 = 1u.toUByte()..MinUB step 3
for (i in range1) {
list1.add(i)
if (list1.size > 23) break
}
if (list1 != listOf<UInt>()) {
return "Wrong elements for 1u..MinUI step 3: $list1"
return "Wrong elements for 1u.toUByte()..MinUB step 3: $list1"
}
val list2 = ArrayList<ULong>()
val range2 = 1uL..MinUL step 3
val list2 = ArrayList<UInt>()
val range2 = 1u.toUShort()..MinUS step 3
for (i in range2) {
list2.add(i)
if (list2.size > 23) break
}
if (list2 != listOf<ULong>()) {
return "Wrong elements for 1uL..MinUL step 3: $list2"
if (list2 != listOf<UInt>()) {
return "Wrong elements for 1u.toUShort()..MinUS step 3: $list2"
}
val list3 = ArrayList<UInt>()
val range3 = 1u..MinUI step 3
for (i in range3) {
list3.add(i)
if (list3.size > 23) break
}
if (list3 != listOf<UInt>()) {
return "Wrong elements for 1u..MinUI step 3: $list3"
}
val list4 = ArrayList<ULong>()
val range4 = 1uL..MinUL step 3
for (i in range4) {
list4.add(i)
if (list4.size > 23) break
}
if (list4 != listOf<ULong>()) {
return "Wrong elements for 1uL..MinUL step 3: $list4"
}
val list5 = ArrayList<UInt>()
val range5 = 1u.toUByte() until MinUB step 3
for (i in range5) {
list5.add(i)
if (list5.size > 23) break
}
if (list5 != listOf<UInt>()) {
return "Wrong elements for 1u.toUByte() until MinUB step 3: $list5"
}
val list6 = ArrayList<UInt>()
val range6 = 1u.toUShort() until MinUS step 3
for (i in range6) {
list6.add(i)
if (list6.size > 23) break
}
if (list6 != listOf<UInt>()) {
return "Wrong elements for 1u.toUShort() until MinUS step 3: $list6"
}
val list7 = ArrayList<UInt>()
val range7 = 1u until MinUI step 3
for (i in range7) {
list7.add(i)
if (list7.size > 23) break
}
if (list7 != listOf<UInt>()) {
return "Wrong elements for 1u until MinUI step 3: $list7"
}
val list8 = ArrayList<ULong>()
val range8 = 1uL until MinUL step 3
for (i in range8) {
list8.add(i)
if (list8.size > 23) break
}
if (list8 != listOf<ULong>()) {
return "Wrong elements for 1uL until MinUL step 3: $list8"
}
return "OK"
@@ -4,25 +4,81 @@
val MinUI = UInt.MIN_VALUE
val MinUB = UByte.MIN_VALUE
val MinUS = UShort.MIN_VALUE
val MinUL = ULong.MIN_VALUE
fun box(): String {
val list1 = ArrayList<UInt>()
for (i in 1u..MinUI step 3) {
for (i in 1u.toUByte()..MinUB step 3) {
list1.add(i)
if (list1.size > 23) break
}
if (list1 != listOf<UInt>()) {
return "Wrong elements for 1u..MinUI step 3: $list1"
return "Wrong elements for 1u.toUByte()..MinUB step 3: $list1"
}
val list2 = ArrayList<ULong>()
for (i in 1uL..MinUL step 3) {
val list2 = ArrayList<UInt>()
for (i in 1u.toUShort()..MinUS step 3) {
list2.add(i)
if (list2.size > 23) break
}
if (list2 != listOf<ULong>()) {
return "Wrong elements for 1uL..MinUL step 3: $list2"
if (list2 != listOf<UInt>()) {
return "Wrong elements for 1u.toUShort()..MinUS step 3: $list2"
}
val list3 = ArrayList<UInt>()
for (i in 1u..MinUI step 3) {
list3.add(i)
if (list3.size > 23) break
}
if (list3 != listOf<UInt>()) {
return "Wrong elements for 1u..MinUI step 3: $list3"
}
val list4 = ArrayList<ULong>()
for (i in 1uL..MinUL step 3) {
list4.add(i)
if (list4.size > 23) break
}
if (list4 != listOf<ULong>()) {
return "Wrong elements for 1uL..MinUL step 3: $list4"
}
val list5 = ArrayList<UInt>()
for (i in 1u.toUByte() until MinUB step 3) {
list5.add(i)
if (list5.size > 23) break
}
if (list5 != listOf<UInt>()) {
return "Wrong elements for 1u.toUByte() until MinUB step 3: $list5"
}
val list6 = ArrayList<UInt>()
for (i in 1u.toUShort() until MinUS step 3) {
list6.add(i)
if (list6.size > 23) break
}
if (list6 != listOf<UInt>()) {
return "Wrong elements for 1u.toUShort() until MinUS step 3: $list6"
}
val list7 = ArrayList<UInt>()
for (i in 1u until MinUI step 3) {
list7.add(i)
if (list7.size > 23) break
}
if (list7 != listOf<UInt>()) {
return "Wrong elements for 1u until MinUI step 3: $list7"
}
val list8 = ArrayList<ULong>()
for (i in 1uL until MinUL step 3) {
list8.add(i)
if (list8.size > 23) break
}
if (list8 != listOf<ULong>()) {
return "Wrong elements for 1uL until MinUL step 3: $list8"
}
return "OK"
@@ -1,36 +0,0 @@
// TARGET_BACKEND: JVM_IR
// WITH_RUNTIME
fun testUByteUntilUByte(a: UByte, b: UByte): Int {
var sum = 0
for (i in a until b) {
sum += i.toInt()
}
return sum
}
fun testUShortUntilUShort(a: UShort, b: UShort): Int {
var sum = 0
for (i in a until b) {
sum += i.toInt()
}
return sum
}
// For "until" progressions in JVM IR, there is typically a check that the range is not empty: upper bound != MIN_VALUE.
// However, this check is not needed when the upper bound is smaller than the range element type.
// Here are the available `until` extension functions with mixed bounds that return UIntRange:
//
// infix fun UByte.until(to: UByte): UIntRange // NO bound check needed
// infix fun UShort.until(to: UShort): UIntRange // NO bound check needed
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 0 getStep
// 2 IFGT
// 2 IFLE
// 4 IF
// 0 INVOKESTATIC kotlin/UInt.constructor-impl
// 0 INVOKE\w+ kotlin/UInt.(un)?box-impl