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:
Generated
-5
@@ -2746,11 +2746,6 @@ public class FirBytecodeTextTestGenerated extends AbstractFirBytecodeTextTest {
|
|||||||
runTest("compiler/testData/codegen/bytecodeText/forLoop/unsigned/forInUntilULongMinValue.kt");
|
runTest("compiler/testData/codegen/bytecodeText/forLoop/unsigned/forInUntilULongMinValue.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("forInUntilWithMixedTypeBoundsNoBoundCheckNeededForUIntRangeIR.kt")
|
|
||||||
public void testForInUntilWithMixedTypeBoundsNoBoundCheckNeededForUIntRangeIR() throws Exception {
|
|
||||||
runTest("compiler/testData/codegen/bytecodeText/forLoop/unsigned/forInUntilWithMixedTypeBoundsNoBoundCheckNeededForUIntRangeIR.kt");
|
|
||||||
}
|
|
||||||
|
|
||||||
@TestMetadata("illegalStepConst.kt")
|
@TestMetadata("illegalStepConst.kt")
|
||||||
public void testIllegalStepConst() throws Exception {
|
public void testIllegalStepConst() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeText/forLoop/unsigned/illegalStepConst.kt");
|
runTest("compiler/testData/codegen/bytecodeText/forLoop/unsigned/illegalStepConst.kt");
|
||||||
|
|||||||
+4
-8
@@ -45,14 +45,10 @@ internal sealed class ProgressionType(
|
|||||||
irType.isSubtypeOfClass(symbols.charProgression) -> CharProgressionType(symbols)
|
irType.isSubtypeOfClass(symbols.charProgression) -> CharProgressionType(symbols)
|
||||||
irType.isSubtypeOfClass(symbols.intProgression) -> IntProgressionType(symbols)
|
irType.isSubtypeOfClass(symbols.intProgression) -> IntProgressionType(symbols)
|
||||||
irType.isSubtypeOfClass(symbols.longProgression) -> LongProgressionType(symbols)
|
irType.isSubtypeOfClass(symbols.longProgression) -> LongProgressionType(symbols)
|
||||||
symbols.uIntProgression != null && irType.isSubtypeOfClass(symbols.uIntProgression) -> UIntProgressionType(
|
symbols.uIntProgression != null && irType.isSubtypeOfClass(symbols.uIntProgression) ->
|
||||||
symbols,
|
UIntProgressionType(symbols, allowUnsignedBounds)
|
||||||
allowUnsignedBounds
|
symbols.uLongProgression != null && irType.isSubtypeOfClass(symbols.uLongProgression) ->
|
||||||
)
|
ULongProgressionType(symbols, allowUnsignedBounds)
|
||||||
symbols.uLongProgression != null && irType.isSubtypeOfClass(symbols.uLongProgression) -> ULongProgressionType(
|
|
||||||
symbols,
|
|
||||||
allowUnsignedBounds
|
|
||||||
)
|
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-8
@@ -153,9 +153,8 @@ internal class UntilHandler(private val context: CommonBackendContext) :
|
|||||||
// infix fun UInt.until(to: UInt): UIntRange
|
// infix fun UInt.until(to: UInt): UIntRange
|
||||||
// infix fun ULong.until(to: ULong): ULongRange
|
// infix fun ULong.until(to: ULong): ULongRange
|
||||||
//
|
//
|
||||||
// The combinations where the range element type is strictly larger than the argument type do NOT need the additional condition.
|
// The additional condition is only needed when the argument casted to the range element type and then decremented can produce
|
||||||
// In such combinations, there is no possibility of underflow when the argument (casted to the range element type) is decremented.
|
// negative overflow - in other words, if the minimum value of `to` is the same as the minimum value for the progression type.
|
||||||
// For unexpected combinations that currently don't exist (e.g., Int until Char), we assume the check is needed to be safe.
|
|
||||||
return with(context.irBuiltIns) {
|
return with(context.irBuiltIns) {
|
||||||
when (receiverType) {
|
when (receiverType) {
|
||||||
charType -> true
|
charType -> true
|
||||||
@@ -167,11 +166,9 @@ internal class UntilHandler(private val context: CommonBackendContext) :
|
|||||||
byteType, shortType, intType -> false
|
byteType, shortType, intType -> false
|
||||||
else -> true
|
else -> true
|
||||||
}
|
}
|
||||||
uByteType -> false
|
// 1. All unsigned types regardless of size "bottom out" at 0, so they all need the check.
|
||||||
uShortType -> false
|
// 2. In case new types are added to stdlib, conservatively add a check as well.
|
||||||
uIntType -> true
|
else -> true
|
||||||
uLongType -> true
|
|
||||||
else -> true // Default in case a new `until` overload is added to stdlib and this function was not updated.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,27 +4,89 @@
|
|||||||
|
|
||||||
|
|
||||||
val MinI = Int.MIN_VALUE
|
val MinI = Int.MIN_VALUE
|
||||||
|
val MinB = Byte.MIN_VALUE
|
||||||
|
val MinS = Short.MIN_VALUE
|
||||||
val MinL = Long.MIN_VALUE
|
val MinL = Long.MIN_VALUE
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
val list1 = ArrayList<Int>()
|
val list1 = ArrayList<Int>()
|
||||||
val range1 = 0..MinI step 3
|
val range1 = 0.toByte()..MinB step 3
|
||||||
for (i in range1) {
|
for (i in range1) {
|
||||||
list1.add(i)
|
list1.add(i)
|
||||||
if (list1.size > 23) break
|
if (list1.size > 23) break
|
||||||
}
|
}
|
||||||
if (list1 != listOf<Int>()) {
|
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 list2 = ArrayList<Int>()
|
||||||
val range2 = 0L..MinL step 3
|
val range2 = 0.toShort()..MinS step 3
|
||||||
for (i in range2) {
|
for (i in range2) {
|
||||||
list2.add(i)
|
list2.add(i)
|
||||||
if (list2.size > 23) break
|
if (list2.size > 23) break
|
||||||
}
|
}
|
||||||
if (list2 != listOf<Long>()) {
|
if (list2 != listOf<Int>()) {
|
||||||
return "Wrong elements for 0L..MinL step 3: $list2"
|
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"
|
return "OK"
|
||||||
|
|||||||
@@ -4,25 +4,81 @@
|
|||||||
|
|
||||||
|
|
||||||
val MinI = Int.MIN_VALUE
|
val MinI = Int.MIN_VALUE
|
||||||
|
val MinB = Byte.MIN_VALUE
|
||||||
|
val MinS = Short.MIN_VALUE
|
||||||
val MinL = Long.MIN_VALUE
|
val MinL = Long.MIN_VALUE
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
val list1 = ArrayList<Int>()
|
val list1 = ArrayList<Int>()
|
||||||
for (i in 0..MinI step 3) {
|
for (i in 0.toByte()..MinB step 3) {
|
||||||
list1.add(i)
|
list1.add(i)
|
||||||
if (list1.size > 23) break
|
if (list1.size > 23) break
|
||||||
}
|
}
|
||||||
if (list1 != listOf<Int>()) {
|
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 list2 = ArrayList<Int>()
|
||||||
for (i in 0L..MinL step 3) {
|
for (i in 0.toShort()..MinS step 3) {
|
||||||
list2.add(i)
|
list2.add(i)
|
||||||
if (list2.size > 23) break
|
if (list2.size > 23) break
|
||||||
}
|
}
|
||||||
if (list2 != listOf<Long>()) {
|
if (list2 != listOf<Int>()) {
|
||||||
return "Wrong elements for 0L..MinL step 3: $list2"
|
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"
|
return "OK"
|
||||||
|
|||||||
+68
-6
@@ -4,27 +4,89 @@
|
|||||||
|
|
||||||
|
|
||||||
val MinUI = UInt.MIN_VALUE
|
val MinUI = UInt.MIN_VALUE
|
||||||
|
val MinUB = UByte.MIN_VALUE
|
||||||
|
val MinUS = UShort.MIN_VALUE
|
||||||
val MinUL = ULong.MIN_VALUE
|
val MinUL = ULong.MIN_VALUE
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
val list1 = ArrayList<UInt>()
|
val list1 = ArrayList<UInt>()
|
||||||
val range1 = 1u..MinUI step 3
|
val range1 = 1u.toUByte()..MinUB step 3
|
||||||
for (i in range1) {
|
for (i in range1) {
|
||||||
list1.add(i)
|
list1.add(i)
|
||||||
if (list1.size > 23) break
|
if (list1.size > 23) break
|
||||||
}
|
}
|
||||||
if (list1 != listOf<UInt>()) {
|
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 list2 = ArrayList<UInt>()
|
||||||
val range2 = 1uL..MinUL step 3
|
val range2 = 1u.toUShort()..MinUS step 3
|
||||||
for (i in range2) {
|
for (i in range2) {
|
||||||
list2.add(i)
|
list2.add(i)
|
||||||
if (list2.size > 23) break
|
if (list2.size > 23) break
|
||||||
}
|
}
|
||||||
if (list2 != listOf<ULong>()) {
|
if (list2 != listOf<UInt>()) {
|
||||||
return "Wrong elements for 1uL..MinUL step 3: $list2"
|
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"
|
return "OK"
|
||||||
|
|||||||
+62
-6
@@ -4,25 +4,81 @@
|
|||||||
|
|
||||||
|
|
||||||
val MinUI = UInt.MIN_VALUE
|
val MinUI = UInt.MIN_VALUE
|
||||||
|
val MinUB = UByte.MIN_VALUE
|
||||||
|
val MinUS = UShort.MIN_VALUE
|
||||||
val MinUL = ULong.MIN_VALUE
|
val MinUL = ULong.MIN_VALUE
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
val list1 = ArrayList<UInt>()
|
val list1 = ArrayList<UInt>()
|
||||||
for (i in 1u..MinUI step 3) {
|
for (i in 1u.toUByte()..MinUB step 3) {
|
||||||
list1.add(i)
|
list1.add(i)
|
||||||
if (list1.size > 23) break
|
if (list1.size > 23) break
|
||||||
}
|
}
|
||||||
if (list1 != listOf<UInt>()) {
|
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 list2 = ArrayList<UInt>()
|
||||||
for (i in 1uL..MinUL step 3) {
|
for (i in 1u.toUShort()..MinUS step 3) {
|
||||||
list2.add(i)
|
list2.add(i)
|
||||||
if (list2.size > 23) break
|
if (list2.size > 23) break
|
||||||
}
|
}
|
||||||
if (list2 != listOf<ULong>()) {
|
if (list2 != listOf<UInt>()) {
|
||||||
return "Wrong elements for 1uL..MinUL step 3: $list2"
|
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"
|
return "OK"
|
||||||
|
|||||||
-36
@@ -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
|
|
||||||
-5
@@ -2746,11 +2746,6 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
|
|||||||
runTest("compiler/testData/codegen/bytecodeText/forLoop/unsigned/forInUntilULongMinValue.kt");
|
runTest("compiler/testData/codegen/bytecodeText/forLoop/unsigned/forInUntilULongMinValue.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("forInUntilWithMixedTypeBoundsNoBoundCheckNeededForUIntRangeIR.kt")
|
|
||||||
public void testForInUntilWithMixedTypeBoundsNoBoundCheckNeededForUIntRangeIR() throws Exception {
|
|
||||||
runTest("compiler/testData/codegen/bytecodeText/forLoop/unsigned/forInUntilWithMixedTypeBoundsNoBoundCheckNeededForUIntRangeIR.kt");
|
|
||||||
}
|
|
||||||
|
|
||||||
@TestMetadata("illegalStepConst.kt")
|
@TestMetadata("illegalStepConst.kt")
|
||||||
public void testIllegalStepConst() throws Exception {
|
public void testIllegalStepConst() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeText/forLoop/unsigned/illegalStepConst.kt");
|
runTest("compiler/testData/codegen/bytecodeText/forLoop/unsigned/illegalStepConst.kt");
|
||||||
|
|||||||
@@ -467,12 +467,26 @@ public class RangeIterationTest : RangeIterationTestBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test fun overflowZeroToMinValue() {
|
@Test fun overflowZeroToMinValue() {
|
||||||
|
doTest(0.toByte()..MinB step 3, 0, MinB.toInt(), 3, listOf())
|
||||||
|
doTest(0.toShort()..MinS step 3, 0, MinS.toInt(), 3, listOf())
|
||||||
doTest(0..MinI step 3, 0, MinI, 3, listOf())
|
doTest(0..MinI step 3, 0, MinI, 3, listOf())
|
||||||
doTest(0L..MinL step 3, 0, MinL, 3L, listOf())
|
doTest(0L..MinL step 3, 0, MinL, 3L, listOf())
|
||||||
|
|
||||||
|
doTest(0.toByte() until MinB step 3, 0, MinB.toInt() - 1, 3, listOf())
|
||||||
|
doTest(0.toShort() until MinS step 3, 0, MinS.toInt() - 1, 3, listOf())
|
||||||
|
doTest(0 until MinI step 3, 1, 0, 3, listOf())
|
||||||
|
doTest(0L until MinL step 3, 1L, 0L, 3L, listOf())
|
||||||
|
|
||||||
// 1u as used as a start since min value is 0u for unsigned types
|
// 1u as used as a start since min value is 0u for unsigned types
|
||||||
|
doTest(1u.toUByte()..MinUB step 3, 1u, MinUB.toUInt(), 3, listOf())
|
||||||
|
doTest(1u.toUShort()..MinUS step 3, 1u, MinUS.toUInt(), 3, listOf())
|
||||||
doTest(1u..MinUI step 3, 1u, MinUI, 3, listOf())
|
doTest(1u..MinUI step 3, 1u, MinUI, 3, listOf())
|
||||||
doTest(1uL..MinUL step 3, 1u, MinUL, 3L, listOf())
|
doTest(1uL..MinUL step 3, 1u, MinUL, 3L, listOf())
|
||||||
|
|
||||||
|
doTest(1u.toUByte() until MinUB step 3, MaxUI, MinUI, 3, listOf())
|
||||||
|
doTest(1u.toUShort() until MinUS step 3, MaxUI, MinUI, 3, listOf())
|
||||||
|
doTest(1u until MinUI step 3, MaxUI, MinUI, 3, listOf())
|
||||||
|
doTest(1uL until MinUL step 3, MaxUL, MinUL, 3L, listOf())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test fun progressionDownToMinValue() {
|
@Test fun progressionDownToMinValue() {
|
||||||
|
|||||||
Reference in New Issue
Block a user