From a6cf169646c9794495f75f02b6f2d3e8dd390d9f Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Thu, 2 Jun 2016 11:21:30 +0300 Subject: [PATCH] Fix for KT-12582: "VerifyError: Bad local variable type" caused by explicit loop variable type #KT-12582 Fixed --- .../kotlin/codegen/ExpressionCodegen.java | 57 ++++++++++++------- .../progressionExpression.kt | 12 ++++ .../nullableLoopParameter/rangeExpression.kt | 12 ++++ .../nullableLoopParameter/rangeLiteral.kt | 11 ++++ .../codegen/BlackBoxCodegenTestGenerated.java | 27 +++++++++ 5 files changed, 98 insertions(+), 21 deletions(-) create mode 100644 compiler/testData/codegen/box/ranges/nullableLoopParameter/progressionExpression.kt create mode 100644 compiler/testData/codegen/box/ranges/nullableLoopParameter/rangeExpression.kt create mode 100644 compiler/testData/codegen/box/ranges/nullableLoopParameter/rangeLiteral.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index d9231cafe65..0d06fbb0a8e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -766,9 +766,15 @@ public class ExpressionCodegen extends KtVisitor impleme // This method consumes range/progression from stack // The result is stored to local variable - protected void generateRangeOrProgressionProperty(Type loopRangeType, String getterName, Type elementType, int varToStore) { - v.invokevirtual(loopRangeType.getInternalName(), getterName, "()" + elementType.getDescriptor(), false); - v.store(varToStore, elementType); + protected void generateRangeOrProgressionProperty( + @NotNull Type loopRangeType, + @NotNull String getterName, + @NotNull Type getterReturnType, + @NotNull Type varType, + int varToStore + ) { + v.invokevirtual(loopRangeType.getInternalName(), getterName, "()" + getterReturnType.getDescriptor(), false); + StackValue.local(varToStore, varType).store(StackValue.onStack(getterReturnType), v); } } @@ -923,6 +929,8 @@ public class ExpressionCodegen extends KtVisitor impleme private abstract class AbstractForInProgressionOrRangeLoopGenerator extends AbstractForLoopGenerator { protected int endVar; + private StackValue loopParameter; + private AbstractForInProgressionOrRangeLoopGenerator(@NotNull KtForExpression forExpression) { super(forExpression); @@ -949,8 +957,7 @@ public class ExpressionCodegen extends KtVisitor impleme protected void checkPostCondition(@NotNull Label loopExit) { assert endVar != -1 : "endVar must be allocated, endVar = " + endVar; - - v.load(loopParameterVar, asmElementType); + loopParameter().put(asmElementType, v); v.load(endVar, asmElementType); if (asmElementType.getSort() == Type.LONG) { v.lcmp(); @@ -964,6 +971,14 @@ public class ExpressionCodegen extends KtVisitor impleme @Override public void checkPreCondition(@NotNull Label loopExit) { } + + @NotNull + protected StackValue loopParameter() { + if (loopParameter == null) { + loopParameter = StackValue.local(loopParameterVar, loopParameterType); + } + return loopParameter; + } } private abstract class AbstractForInRangeLoopGenerator extends AbstractForInProgressionOrRangeLoopGenerator { @@ -982,8 +997,7 @@ public class ExpressionCodegen extends KtVisitor impleme @Override public void checkEmptyLoop(@NotNull Label loopExit) { - - v.load(loopParameterVar, asmElementType); + loopParameter().put(asmElementType, v); v.load(endVar, asmElementType); if (asmElementType.getSort() == Type.LONG) { v.lcmp(); @@ -1002,13 +1016,14 @@ public class ExpressionCodegen extends KtVisitor impleme protected void increment(@NotNull Label loopExit) { checkPostCondition(loopExit); - if (asmElementType == Type.INT_TYPE) { + if (loopParameterType == Type.INT_TYPE) { v.iinc(loopParameterVar, 1); } else { - v.load(loopParameterVar, asmElementType); + StackValue loopParameter = loopParameter(); + loopParameter.put(asmElementType, v); genIncrement(asmElementType, 1, v); - v.store(loopParameterVar, asmElementType); + loopParameter.store(StackValue.onStack(asmElementType), v); } } } @@ -1026,8 +1041,8 @@ public class ExpressionCodegen extends KtVisitor impleme @Override protected void storeRangeStartAndEnd() { - gen(rangeCall.left, asmElementType); - v.store(loopParameterVar, asmElementType); + gen(rangeCall.left, loopParameterType); + v.store(loopParameterVar, loopParameterType); gen(rangeCall.right, asmElementType); v.store(endVar, asmElementType); @@ -1048,8 +1063,8 @@ public class ExpressionCodegen extends KtVisitor impleme v.dup(); // ranges inherit first and last from corresponding progressions - generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterVar); - generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, endVar); + generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterType, loopParameterVar); + generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, asmElementType, endVar); } } @@ -1080,15 +1095,14 @@ public class ExpressionCodegen extends KtVisitor impleme v.dup(); v.dup(); - generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterVar); - generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, endVar); - generateRangeOrProgressionProperty(asmLoopRangeType, "getStep", incrementType, incrementVar); + generateRangeOrProgressionProperty(asmLoopRangeType, "getFirst", asmElementType, loopParameterType, loopParameterVar); + generateRangeOrProgressionProperty(asmLoopRangeType, "getLast", asmElementType, asmElementType, endVar); + generateRangeOrProgressionProperty(asmLoopRangeType, "getStep", incrementType, incrementType, incrementVar); } @Override public void checkEmptyLoop(@NotNull Label loopExit) { - - v.load(loopParameterVar, asmElementType); + loopParameter().put(asmElementType, v); v.load(endVar, asmElementType); v.load(incrementVar, incrementType); @@ -1133,7 +1147,8 @@ public class ExpressionCodegen extends KtVisitor impleme protected void increment(@NotNull Label loopExit) { checkPostCondition(loopExit); - v.load(loopParameterVar, asmElementType); + StackValue loopParameter = loopParameter(); + loopParameter.put(asmElementType, v); v.load(incrementVar, asmElementType); v.add(asmElementType); @@ -1141,7 +1156,7 @@ public class ExpressionCodegen extends KtVisitor impleme StackValue.coerce(Type.INT_TYPE, asmElementType, v); } - v.store(loopParameterVar, asmElementType); + loopParameter.store(StackValue.onStack(asmElementType), v); } } diff --git a/compiler/testData/codegen/box/ranges/nullableLoopParameter/progressionExpression.kt b/compiler/testData/codegen/box/ranges/nullableLoopParameter/progressionExpression.kt new file mode 100644 index 00000000000..2caf1a33808 --- /dev/null +++ b/compiler/testData/codegen/box/ranges/nullableLoopParameter/progressionExpression.kt @@ -0,0 +1,12 @@ +fun box(): String { + var result = 0 + val intRange: IntProgression = 1..3 + for (i: Int? in intRange) { + result = sum(result, i) + } + return if (result == 6) "OK" else "fail: $result" +} + +fun sum(i: Int, z: Int?): Int { + return i + z!! +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/ranges/nullableLoopParameter/rangeExpression.kt b/compiler/testData/codegen/box/ranges/nullableLoopParameter/rangeExpression.kt new file mode 100644 index 00000000000..7cc906c09d2 --- /dev/null +++ b/compiler/testData/codegen/box/ranges/nullableLoopParameter/rangeExpression.kt @@ -0,0 +1,12 @@ +fun box(): String { + var result = 0 + val intRange = 1..3 + for (i: Int? in intRange) { + result = sum(result, i) + } + return if (result == 6) "OK" else "fail: $result" +} + +fun sum(i: Int, z: Int?): Int { + return i + z!! +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/ranges/nullableLoopParameter/rangeLiteral.kt b/compiler/testData/codegen/box/ranges/nullableLoopParameter/rangeLiteral.kt new file mode 100644 index 00000000000..52713ad8bf7 --- /dev/null +++ b/compiler/testData/codegen/box/ranges/nullableLoopParameter/rangeLiteral.kt @@ -0,0 +1,11 @@ +fun box(): String { + var result = 0 + for (i: Int? in 1..3) { + result = sum(result, i) + } + return if (result == 6) "OK" else "fail: $result" +} + +fun sum(i: Int, z: Int?): Int { + return i + z!! +} \ 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 808893086f2..cc65cdedb9e 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -10668,6 +10668,33 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } } + + @TestMetadata("compiler/testData/codegen/box/ranges/nullableLoopParameter") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class NullableLoopParameter extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInNullableLoopParameter() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/ranges/nullableLoopParameter"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("progressionExpression.kt") + public void testProgressionExpression() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/nullableLoopParameter/progressionExpression.kt"); + doTest(fileName); + } + + @TestMetadata("rangeExpression.kt") + public void testRangeExpression() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/nullableLoopParameter/rangeExpression.kt"); + doTest(fileName); + } + + @TestMetadata("rangeLiteral.kt") + public void testRangeLiteral() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/ranges/nullableLoopParameter/rangeLiteral.kt"); + doTest(fileName); + } + } } @TestMetadata("compiler/testData/codegen/box/reflection")