Multiple fixes for try-catch-finally codegen
#KT-2259 Fixed #KT-2577 Fixed
This commit is contained in:
@@ -2717,8 +2717,10 @@ The "returned" value of try expression with no finally is either the last expres
|
|||||||
(or blocks).
|
(or blocks).
|
||||||
*/
|
*/
|
||||||
JetFinallySection finallyBlock = expression.getFinallyBlock();
|
JetFinallySection finallyBlock = expression.getFinallyBlock();
|
||||||
|
FinallyBlockStackElement finallyBlockStackElement = null;
|
||||||
if (finallyBlock != null) {
|
if (finallyBlock != null) {
|
||||||
blockStackElements.push(new FinallyBlockStackElement(expression));
|
finallyBlockStackElement = new FinallyBlockStackElement(expression);
|
||||||
|
blockStackElements.push(finallyBlockStackElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression);
|
JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression);
|
||||||
@@ -2727,15 +2729,26 @@ The "returned" value of try expression with no finally is either the last expres
|
|||||||
Label tryStart = new Label();
|
Label tryStart = new Label();
|
||||||
v.mark(tryStart);
|
v.mark(tryStart);
|
||||||
v.nop(); // prevent verify error on empty try
|
v.nop(); // prevent verify error on empty try
|
||||||
|
|
||||||
gen(expression.getTryBlock(), expectedAsmType);
|
gen(expression.getTryBlock(), expectedAsmType);
|
||||||
|
|
||||||
|
int savedValue = myFrameMap.enterTemp(expectedAsmType.getSize());
|
||||||
|
v.store(savedValue, expectedAsmType);
|
||||||
|
|
||||||
Label tryEnd = new Label();
|
Label tryEnd = new Label();
|
||||||
v.mark(tryEnd);
|
v.mark(tryEnd);
|
||||||
if (finallyBlock != null) {
|
if (finallyBlock != null) {
|
||||||
|
blockStackElements.pop();
|
||||||
gen(finallyBlock.getFinalExpression(), Type.VOID_TYPE);
|
gen(finallyBlock.getFinalExpression(), Type.VOID_TYPE);
|
||||||
|
blockStackElements.push(finallyBlockStackElement);
|
||||||
}
|
}
|
||||||
Label end = new Label();
|
Label end = new Label();
|
||||||
v.goTo(end); // TODO don't generate goto if there's no code following try/catch
|
v.goTo(end);
|
||||||
for (JetCatchClause clause : expression.getCatchClauses()) {
|
|
||||||
|
List<JetCatchClause> clauses = expression.getCatchClauses();
|
||||||
|
for (int i = 0, size = clauses.size(); i < size; i++) {
|
||||||
|
JetCatchClause clause = clauses.get(i);
|
||||||
|
|
||||||
Label clauseStart = new Label();
|
Label clauseStart = new Label();
|
||||||
v.mark(clauseStart);
|
v.mark(clauseStart);
|
||||||
|
|
||||||
@@ -2748,28 +2761,45 @@ The "returned" value of try expression with no finally is either the last expres
|
|||||||
|
|
||||||
gen(clause.getCatchBody(), expectedAsmType);
|
gen(clause.getCatchBody(), expectedAsmType);
|
||||||
|
|
||||||
|
v.store(savedValue, expectedAsmType);
|
||||||
|
|
||||||
myFrameMap.leave(descriptor);
|
myFrameMap.leave(descriptor);
|
||||||
|
|
||||||
if (finallyBlock != null) {
|
if (finallyBlock != null) {
|
||||||
|
blockStackElements.pop();
|
||||||
gen(finallyBlock.getFinalExpression(), Type.VOID_TYPE);
|
gen(finallyBlock.getFinalExpression(), Type.VOID_TYPE);
|
||||||
|
blockStackElements.push(finallyBlockStackElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
v.goTo(end); // TODO don't generate goto if there's no code following try/catch
|
if (i != size - 1 || finallyBlock != null) {
|
||||||
|
v.goTo(end);
|
||||||
|
}
|
||||||
|
|
||||||
v.visitTryCatchBlock(tryStart, tryEnd, clauseStart, descriptorType.getInternalName());
|
v.visitTryCatchBlock(tryStart, tryEnd, clauseStart, descriptorType.getInternalName());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (finallyBlock != null) {
|
if (finallyBlock != null) {
|
||||||
Label finallyStart = new Label();
|
Label finallyStart = new Label();
|
||||||
v.mark(finallyStart);
|
v.mark(finallyStart);
|
||||||
|
|
||||||
|
int savedException = myFrameMap.enterTemp();
|
||||||
|
v.store(savedException, TYPE_THROWABLE);
|
||||||
|
|
||||||
|
blockStackElements.pop();
|
||||||
gen(finallyBlock.getFinalExpression(), Type.VOID_TYPE);
|
gen(finallyBlock.getFinalExpression(), Type.VOID_TYPE);
|
||||||
|
blockStackElements.push(finallyBlockStackElement);
|
||||||
|
|
||||||
|
v.load(savedException, TYPE_THROWABLE);
|
||||||
|
myFrameMap.leaveTemp();
|
||||||
|
|
||||||
v.athrow();
|
v.athrow();
|
||||||
|
|
||||||
v.visitTryCatchBlock(tryStart, tryEnd, finallyStart, null);
|
v.visitTryCatchBlock(tryStart, tryEnd, finallyStart, null);
|
||||||
}
|
}
|
||||||
v.mark(end);
|
v.mark(end);
|
||||||
v.nop();
|
|
||||||
|
v.load(savedValue, expectedAsmType);
|
||||||
|
myFrameMap.leaveTemp(expectedAsmType.getSize());
|
||||||
|
|
||||||
if (finallyBlock != null) {
|
if (finallyBlock != null) {
|
||||||
blockStackElements.pop();
|
blockStackElements.pop();
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
fun box() : String {
|
||||||
|
try {
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
} finally {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
try {
|
||||||
|
} catch (f: Exception) {
|
||||||
|
} finally {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
fun main(args: Array<String>) {
|
||||||
|
try {
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box() = "OK"
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
fun foo(): Int {
|
||||||
|
try {
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
return 1
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box() = if (foo() == 1) "OK" else "Fail"
|
||||||
@@ -376,4 +376,19 @@ public class ControlStructuresTest extends CodegenTestCase {
|
|||||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||||
blackBoxFile("regressions/kt2291.kt");
|
blackBoxFile("regressions/kt2291.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testKt2259() {
|
||||||
|
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||||
|
blackBoxFile("regressions/kt2259.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testKt2577() {
|
||||||
|
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||||
|
blackBoxFile("regressions/kt2577.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testTryCatchFinallyChain() {
|
||||||
|
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||||
|
blackBoxFile("controlStructures/tryCatchFinallyChain.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user