From ae03e2983d122ac4e7e1ec06a4650f3f04e3db66 Mon Sep 17 00:00:00 2001 From: Mads Ager Date: Mon, 14 Jun 2021 13:16:41 +0200 Subject: [PATCH] [JVM_IR] Keep track of catch variable gaps. This ensures that catch variables are not visible in duplicated finally blocks generated at an exit within the catch variable scope. ^KT-46449 Fixed --- .../kotlin/backend/jvm/codegen/ExpressionCodegen.kt | 11 +++++------ .../testData/debug/localVariables/tryFinally11.kt | 4 ++-- .../testData/debug/localVariables/tryFinally12.kt | 5 ++--- .../testData/debug/localVariables/tryFinally13.kt | 9 ++++----- compiler/testData/debug/localVariables/tryFinally7.kt | 4 ++-- 5 files changed, 15 insertions(+), 18 deletions(-) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index 67596f49b1c..4fccb9f3858 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -1159,18 +1159,17 @@ class ExpressionCodegen( val afterStore = markNewLabel() val catchBody = clause.result - val catchResult = catchBody.accept(this, data) + var catchBlockInfo = BlockInfo(data) + catchBlockInfo.variables.add(VariableInfo(parameter, index, descriptorType, afterStore)) + + val catchResult = catchBody.accept(this, catchBlockInfo) if (savedValue != null) { catchResult.materializeAt(tryAsmType, aTry.type, true) mv.store(savedValue, tryAsmType) } else { catchResult.discard() } - - frameMap.leave(clause.catchParameter) - - val clauseEnd = markNewLabel() - mv.visitLocalVariable(parameter.name.asString(), descriptorType.descriptor, null, afterStore, clauseEnd, index) + writeLocalVariablesInTable(catchBlockInfo, markNewLabel()) if (tryInfo is TryWithFinallyInfo) { data.handleBlock { genFinallyBlock(tryInfo, tryCatchBlockEnd, null, data) } diff --git a/compiler/testData/debug/localVariables/tryFinally11.kt b/compiler/testData/debug/localVariables/tryFinally11.kt index 6da45dc425f..399c556413a 100644 --- a/compiler/testData/debug/localVariables/tryFinally11.kt +++ b/compiler/testData/debug/localVariables/tryFinally11.kt @@ -11,7 +11,7 @@ fun box(): String { val z = "z" break // TODO: why does the break not have a line number so we can stop on it? } finally { - throw RuntimeException("$i") // TODO: `e` should not be visible here + throw RuntimeException("$i") } } } finally { @@ -32,5 +32,5 @@ fun box(): String { // test.kt:9 box: i:int=0:int // test.kt:10 box: i:int=0:int, e:java.lang.Exception=java.lang.RuntimeException // test.kt:11 box: i:int=0:int, e:java.lang.Exception=java.lang.RuntimeException, y:java.lang.String="y":java.lang.String -// test.kt:14 box: i:int=0:int, e:java.lang.Exception=java.lang.RuntimeException +// test.kt:14 box: i:int=0:int // test.kt:18 box: diff --git a/compiler/testData/debug/localVariables/tryFinally12.kt b/compiler/testData/debug/localVariables/tryFinally12.kt index 6d3ad7335bd..fab3272af13 100644 --- a/compiler/testData/debug/localVariables/tryFinally12.kt +++ b/compiler/testData/debug/localVariables/tryFinally12.kt @@ -11,7 +11,7 @@ fun box(): String { val z = "z" continue // TODO: why does the continue not have a line number so we stop here? } finally { - throw RuntimeException("$i") // TODO: `e` should not be visible here + throw RuntimeException("$i") } } } finally { @@ -32,6 +32,5 @@ fun box(): String { // test.kt:9 box: i:int=0:int // test.kt:10 box: i:int=0:int, e:java.lang.Exception=java.lang.RuntimeException // test.kt:11 box: i:int=0:int, e:java.lang.Exception=java.lang.RuntimeException, y:java.lang.String="y":java.lang.String -// test.kt:14 box: i:int=0:int, e:java.lang.Exception=java.lang.RuntimeException +// test.kt:14 box: i:int=0:int // test.kt:18 box: - diff --git a/compiler/testData/debug/localVariables/tryFinally13.kt b/compiler/testData/debug/localVariables/tryFinally13.kt index 770dc03e4f9..91e0a46ada9 100644 --- a/compiler/testData/debug/localVariables/tryFinally13.kt +++ b/compiler/testData/debug/localVariables/tryFinally13.kt @@ -10,11 +10,11 @@ fun box(): String { val y = "y" return "FAIL1" } finally { - return "FAIL2" // TODO: `e` should not be visible here. + return "FAIL2" } } } finally { - return "OK" // TODO: `e` should not be visible here. + return "OK" } return "FAIL3" } @@ -31,6 +31,5 @@ fun box(): String { // test.kt:9 box: i:int=0:int // test.kt:10 box: i:int=0:int, e:java.lang.Exception=java.lang.RuntimeException // test.kt:11 box: i:int=0:int, e:java.lang.Exception=java.lang.RuntimeException, y:java.lang.String="y":java.lang.String -// test.kt:13 box: i:int=0:int, e:java.lang.Exception=java.lang.RuntimeException -// test.kt:17 box: e:java.lang.Exception=java.lang.RuntimeException - +// test.kt:13 box: i:int=0:int +// test.kt:17 box: diff --git a/compiler/testData/debug/localVariables/tryFinally7.kt b/compiler/testData/debug/localVariables/tryFinally7.kt index d69320960e1..9d55d7bd2a5 100644 --- a/compiler/testData/debug/localVariables/tryFinally7.kt +++ b/compiler/testData/debug/localVariables/tryFinally7.kt @@ -20,7 +20,7 @@ fun compute(): String { } } } finally { - x = "OK" // TODO: `e` should not be visible here. + x = "OK" } return "FAIL" } @@ -45,7 +45,7 @@ fun box() { // test.kt:18 compute: e:java.lang.Exception=java.lang.RuntimeException, y:int=32:int, j:int=0:int // test.kt:4 compute: e:java.lang.Exception=java.lang.RuntimeException, y:int=32:int, j:int=0:int, $i$f$f:int=0:int // test.kt:19 compute: e:java.lang.Exception=java.lang.RuntimeException, y:int=32:int, j:int=0:int, $i$f$f:int=0:int, $i$a$-f-TestKt$compute$1:int=0:int -// test.kt:23 compute: e:java.lang.Exception=java.lang.RuntimeException +// test.kt:23 compute: // test.kt:29 box: // test.kt:30 box: result:java.lang.String="NON_LOCAL_RETURN":java.lang.String // test.kt:31 box: result:java.lang.String="NON_LOCAL_RETURN":java.lang.String, localX:java.lang.String="OK":java.lang.String