KT-13931 generate IntRange#contains with respect to side-effects on argument loading, test added

This commit is contained in:
Vsevolod
2016-09-24 00:41:22 +03:00
committed by Dmitry Petrov
parent 1f9b148a5d
commit 1ac07340c9
3 changed files with 41 additions and 13 deletions
@@ -3470,38 +3470,35 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
}
/*
* Translates x in a..b (for int and char ranges only)
* to a <= x && x >= b same way as javac 1.8.0_91 does.
* Translates x in a..b (for int and char ranges only) to a <= x && x <= b
*/
private void genInIntRange(StackValue leftValue, KtBinaryExpression rangeExpression) {
int localVarIndex = myFrameMap.enterTemp(Type.INT_TYPE);
// Load left bound
gen(rangeExpression.getLeft(), Type.INT_TYPE);
// Load argument
// Load x into local variable to avoid StackValue#put side-effects
leftValue.put(Type.INT_TYPE, v);
v.store(localVarIndex, Type.INT_TYPE);
v.load(localVarIndex, Type.INT_TYPE);
// If (left > arg) goto L1 (return)
// If (x < left) goto L1
Label l1 = new Label();
v.ificmpgt(l1);
// Load argument again
leftValue.put(Type.INT_TYPE, v);
// Load right bound
// If (x > right) goto L1
v.load(localVarIndex, Type.INT_TYPE);
gen(rangeExpression.getRight(), Type.INT_TYPE);
// If (x > right) goto L1 (return)
v.ificmpgt(l1);
Label l2 = new Label();
// Push 'true'
v.iconst(1);
// Goto return
v.goTo(l2);
// L1: push 'false'
v.mark(l1);
v.iconst(0);
// L2: implicit ireturn
v.mark(l2);
myFrameMap.leaveTemp(Type.INT_TYPE);
}
private StackValue generateBooleanAnd(KtBinaryExpression expression) {
+25
View File
@@ -0,0 +1,25 @@
// WITH_RUNTIME
fun box(): String {
for (x in 1..10) {
assert(x in 1..10)
assert(x + 10 !in 1..10)
}
var x = 0
assert(0 !in 1..2)
assert(++x in 1..1)
assert(++x !in 1..1)
assert(sideEffect(x) in 2..3)
return "OK"
}
var invocationCounter = 0
fun sideEffect(x: Int): Int {
++invocationCounter
assert(invocationCounter == 1)
return x
}
@@ -11128,6 +11128,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("inIntRange.kt")
public void testInIntRange() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/inIntRange.kt");
doTest(fileName);
}
@TestMetadata("multiAssignmentIterationOverIntRange.kt")
public void testMultiAssignmentIterationOverIntRange() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/multiAssignmentIterationOverIntRange.kt");