diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index dffff7dcf64..6ebefad845f 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -3092,7 +3092,6 @@ public class ExpressionCodegen extends JetVisitor implem } if (isPrimitiveNumberClassDescriptor(cls)) { - receiver.put(receiver.type, v); JetExpression operand = expression.getBaseExpression(); if (operand instanceof JetReferenceExpression && asmType == Type.INT_TYPE) { int index = indexOfLocal((JetReferenceExpression) operand); @@ -3100,8 +3099,16 @@ public class ExpressionCodegen extends JetVisitor implem return StackValue.postIncrement(index, increment); } } - gen(operand, asmType); // old value - generateIncrement(increment, asmType, operand, receiver); // increment in-place + StackValue value = gen(expression.getBaseExpression()); + value.dupReceiver(v); + + Type type = expressionType(expression.getBaseExpression()); + value.put(type, v); + + pushReceiverAndValueViaDup(value, type); + + genIncrement(asmType, increment, v); + value.store(asmType, v); return StackValue.onStack(asmType); // old value } else { @@ -3117,32 +3124,7 @@ public class ExpressionCodegen extends JetVisitor implem Type type = expressionType(expression.getBaseExpression()); value.put(type, v); - switch (value.receiverSize()) { - case 0: - dup(v, type); - break; - - case 1: - if (type.getSize() == 2) { - v.dup2X1(); - } - else { - v.dupX1(); - } - break; - - case 2: - if (type.getSize() == 2) { - v.dup2X2(); - } - else { - v.dupX2(); - } - break; - - case -1: - throw new UnsupportedOperationException(); - } + pushReceiverAndValueViaDup(value, type); CallableMethod callableMethod = (CallableMethod) callable; callableMethod.invokeWithNotNullAssertion(v, state, resolvedCall); @@ -3152,12 +3134,33 @@ public class ExpressionCodegen extends JetVisitor implem } } - private void generateIncrement(int increment, Type asmType, JetExpression operand, StackValue receiver) { - StackValue value = genQualified(receiver, operand); - value.dupReceiver(v); - value.put(asmType, v); - genIncrement(asmType, increment, v); - value.store(asmType, v); + private void pushReceiverAndValueViaDup(StackValue value, Type type) { + switch (value.receiverSize()) { + case 0: + dup(v, type); + break; + + case 1: + if (type.getSize() == 2) { + v.dup2X1(); + } + else { + v.dupX1(); + } + break; + + case 2: + if (type.getSize() == 2) { + v.dup2X2(); + } + else { + v.dupX2(); + } + break; + + case -1: + throw new UnsupportedOperationException(); + } } @Override diff --git a/compiler/testData/codegen/box/intrinsics/prefixIncDec.kt b/compiler/testData/codegen/box/intrinsics/prefixIncDec.kt new file mode 100644 index 00000000000..7ee85ce1319 --- /dev/null +++ b/compiler/testData/codegen/box/intrinsics/prefixIncDec.kt @@ -0,0 +1,29 @@ +public var inc: Int = 0; + +public var propInc: Int = 0 + get() {++inc; return $propInc} + set(a: Int) { + ++inc + $propInc = a + } + +public var dec: Int = 0; + +public var propDec: Int = 0; + get() { --dec; return $propDec} + set(a: Int) { + --dec + $propDec = a + } + +fun box(): String { + ++propInc + if (inc != 3) return "fail in prefix increment: ${inc} != 3" + if (propInc != 1) return "fail in prefix increment: ${propInc} != 1" + + --propDec + if (dec != -3) return "fail in prefix decrement: ${dec} != -3" + if (propDec != -1) return "fail in prefix decrement: ${propDec} != -1" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/operatorConventions/incDecOnObject.kt b/compiler/testData/codegen/box/operatorConventions/incDecOnObject.kt new file mode 100644 index 00000000000..db16fa3f081 --- /dev/null +++ b/compiler/testData/codegen/box/operatorConventions/incDecOnObject.kt @@ -0,0 +1,41 @@ +class X(var value: Long) + +fun X.inc(): X { + this.value++ + return this +} + +fun X.dec(): X { + this.value-- + return this +} + +class Z { + + public var counter: Int = 0; + + public var prop: X = X(0) + get() { + counter++; return $prop + } + set(a: X) { + counter++ + $prop = a; + } +} + +fun box(): String { + var z = Z() + z.prop++ + + if (z.counter != 2) return "fail in postfix increment: ${z.counter} != 2" + if (z.prop.value != 1.toLong()) return "fail in postfix increment: ${z.prop.value} != 1" + + z = Z() + z.prop-- + + if (z.counter != 2) return "fail in postfix decrement: ${z.counter} != 2" + if (z.prop.value != -1.toLong()) return "fail in postfix decrement: ${z.prop.value} != -1" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/operatorConventions/kt4152.kt b/compiler/testData/codegen/box/operatorConventions/kt4152.kt new file mode 100644 index 00000000000..4fcb8df0470 --- /dev/null +++ b/compiler/testData/codegen/box/operatorConventions/kt4152.kt @@ -0,0 +1,29 @@ +public var inc: Int = 0; + +public var propInc: Int = 0 + get() {inc++; return $propInc} + set(a: Int) { + inc++ + $propInc = a + } + +public var dec: Int = 0; + +public var propDec: Int = 0; + get() { dec--; return $propDec} + set(a: Int) { + dec-- + $propDec = a + } + +fun box(): String { + propInc++ + if (inc != 2) return "fail in postfix increment: ${inc} != 2" + if (propInc != 1) return "fail in postfix increment: ${propInc} != 1" + + propDec-- + if (dec != -2) return "fail in postfix decrement: ${dec} != -2" + if (propDec != -1) return "fail in postfix decrement: ${propDec} != -1" + + return "OK" +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java index 18b5fcb2acb..f9419f97ff1 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -2704,6 +2704,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest("compiler/testData/codegen/box/intrinsics/longRangeWithExplicitDot.kt"); } + @TestMetadata("prefixIncDec.kt") + public void testPrefixIncDec() throws Exception { + doTest("compiler/testData/codegen/box/intrinsics/prefixIncDec.kt"); + } + @TestMetadata("rangeFromCollection.kt") public void testRangeFromCollection() throws Exception { doTest("compiler/testData/codegen/box/intrinsics/rangeFromCollection.kt"); @@ -3550,6 +3555,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest("compiler/testData/codegen/box/operatorConventions/assignmentOperations.kt"); } + @TestMetadata("incDecOnObject.kt") + public void testIncDecOnObject() throws Exception { + doTest("compiler/testData/codegen/box/operatorConventions/incDecOnObject.kt"); + } + + @TestMetadata("kt4152.kt") + public void testKt4152() throws Exception { + doTest("compiler/testData/codegen/box/operatorConventions/kt4152.kt"); + } + @TestMetadata("compiler/testData/codegen/box/operatorConventions/compareTo") public static class CompareTo extends AbstractBlackBoxCodegenTest { public void testAllFilesPresentInCompareTo() throws Exception {