From 1ac07340c9c6803bae078290088c9192f8d64c05 Mon Sep 17 00:00:00 2001 From: Vsevolod Date: Sat, 24 Sep 2016 00:41:22 +0300 Subject: [PATCH] KT-13931 generate IntRange#contains with respect to side-effects on argument loading, test added --- .../kotlin/codegen/ExpressionCodegen.java | 23 ++++++++--------- .../testData/codegen/box/ranges/inIntRange.kt | 25 +++++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 +++++ 3 files changed, 41 insertions(+), 13 deletions(-) create mode 100644 compiler/testData/codegen/box/ranges/inIntRange.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 56f184861c3..5f904238fdb 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -3470,38 +3470,35 @@ public class ExpressionCodegen extends KtVisitor 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) { diff --git a/compiler/testData/codegen/box/ranges/inIntRange.kt b/compiler/testData/codegen/box/ranges/inIntRange.kt new file mode 100644 index 00000000000..67fc02b6570 --- /dev/null +++ b/compiler/testData/codegen/box/ranges/inIntRange.kt @@ -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 +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index b974114a9c4..fe00143b978 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -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");