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) * Translates x in a..b (for int and char ranges only) to a <= x && x <= b
* to a <= x && x >= b same way as javac 1.8.0_91 does.
*/ */
private void genInIntRange(StackValue leftValue, KtBinaryExpression rangeExpression) { private void genInIntRange(StackValue leftValue, KtBinaryExpression rangeExpression) {
int localVarIndex = myFrameMap.enterTemp(Type.INT_TYPE);
// Load left bound // Load left bound
gen(rangeExpression.getLeft(), Type.INT_TYPE); 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); 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(); Label l1 = new Label();
v.ificmpgt(l1); v.ificmpgt(l1);
// Load argument again // If (x > right) goto L1
leftValue.put(Type.INT_TYPE, v); v.load(localVarIndex, Type.INT_TYPE);
// Load right bound
gen(rangeExpression.getRight(), Type.INT_TYPE); gen(rangeExpression.getRight(), Type.INT_TYPE);
// If (x > right) goto L1 (return)
v.ificmpgt(l1); v.ificmpgt(l1);
Label l2 = new Label(); Label l2 = new Label();
// Push 'true'
v.iconst(1); v.iconst(1);
// Goto return
v.goTo(l2); v.goTo(l2);
// L1: push 'false'
v.mark(l1); v.mark(l1);
v.iconst(0); v.iconst(0);
// L2: implicit ireturn
v.mark(l2); v.mark(l2);
myFrameMap.leaveTemp(Type.INT_TYPE);
} }
private StackValue generateBooleanAnd(KtBinaryExpression expression) { 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); 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") @TestMetadata("multiAssignmentIterationOverIntRange.kt")
public void testMultiAssignmentIterationOverIntRange() throws Exception { public void testMultiAssignmentIterationOverIntRange() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/multiAssignmentIterationOverIntRange.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/multiAssignmentIterationOverIntRange.kt");