[JVM_IR] Fix range of locals in connection with finally blocks.
For code such as:
```
try {
var y = "y"
for (i in 0 until 1) {
return y
}
} finally {
println("finally")
}
```
The local variables `y` and `i` ended up covering the finally block as
well in the debugger.
This change splits the range of the locals so that they do
not cover the finally block.
This change does not change the inliner to do similar transformations,
so the range of locals is still wrong win finally blocks when inlined
into an inline function. Added a failing test to that effect.
This commit is contained in:
committed by
Mikhael Bogdanov
parent
0764a0601c
commit
6d9f02cfc6
+6
@@ -8659,6 +8659,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/controlStructures/tryCatchInExpressions/multipleCatchBlocks.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonLocalReturnInTryFinally.kt")
|
||||
public void testNonLocalReturnInTryFinally() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/tryCatchInExpressions/nonLocalReturnInTryFinally.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("splitTry.kt")
|
||||
public void testSplitTry() throws Exception {
|
||||
|
||||
+41
-5
@@ -70,7 +70,9 @@ import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import java.util.*
|
||||
|
||||
sealed class ExpressionInfo
|
||||
sealed class ExpressionInfo {
|
||||
var blockInfo: BlockInfo? = null
|
||||
}
|
||||
|
||||
class LoopInfo(val loop: IrLoop, val continueLabel: Label, val breakLabel: Label) : ExpressionInfo()
|
||||
|
||||
@@ -89,11 +91,12 @@ class BlockInfo(val parent: BlockInfo? = null) {
|
||||
fun hasFinallyBlocks(): Boolean = infos.firstIsInstanceOrNull<TryWithFinallyInfo>() != null
|
||||
|
||||
internal inline fun <T : ExpressionInfo, R> withBlock(info: T, f: (T) -> R): R {
|
||||
info.blockInfo = this
|
||||
infos.add(info)
|
||||
try {
|
||||
return f(info)
|
||||
} finally {
|
||||
infos.pop()
|
||||
infos.pop().blockInfo = null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +113,11 @@ class BlockInfo(val parent: BlockInfo? = null) {
|
||||
}
|
||||
}
|
||||
|
||||
class VariableInfo(val declaration: IrVariable, val index: Int, val type: Type, val startLabel: Label)
|
||||
class Gap(val start: Label, val end: Label)
|
||||
|
||||
class VariableInfo(val declaration: IrVariable, val index: Int, val type: Type, val startLabel: Label) {
|
||||
val gaps = mutableListOf<Gap>()
|
||||
}
|
||||
|
||||
class ExpressionCodegen(
|
||||
val irFunction: IrFunction,
|
||||
@@ -384,7 +391,12 @@ class ExpressionCodegen(
|
||||
private fun writeLocalVariablesInTable(info: BlockInfo, endLabel: Label) {
|
||||
info.variables.forEach {
|
||||
if (it.declaration.isVisibleInLVT) {
|
||||
mv.visitLocalVariable(it.declaration.name.asString(), it.type.descriptor, null, it.startLabel, endLabel, it.index)
|
||||
var start = it.startLabel
|
||||
for (gap in it.gaps) {
|
||||
mv.visitLocalVariable(it.declaration.name.asString(), it.type.descriptor, null, start, gap.start, it.index)
|
||||
start = gap.end
|
||||
}
|
||||
mv.visitLocalVariable(it.declaration.name.asString(), it.type.descriptor, null, start, endLabel, it.index)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -393,6 +405,23 @@ class ExpressionCodegen(
|
||||
}
|
||||
}
|
||||
|
||||
private fun addLocalVariableGapsForFinallyBlocks(
|
||||
info: BlockInfo,
|
||||
tryWithFinallyInfo: TryWithFinallyInfo,
|
||||
gapStart: Label,
|
||||
restartLabel: Label
|
||||
) {
|
||||
var current: BlockInfo? = info
|
||||
while (current != null && current != tryWithFinallyInfo.blockInfo) {
|
||||
for (variable in current.variables) {
|
||||
if (variable.declaration.isVisibleInLVT) {
|
||||
variable.gaps.add(Gap(gapStart, restartLabel))
|
||||
}
|
||||
}
|
||||
current = current.parent
|
||||
}
|
||||
}
|
||||
|
||||
private fun visitStatementContainer(container: IrStatementContainer, data: BlockInfo) =
|
||||
container.statements.fold(unitValue) { prev, exp ->
|
||||
prev.discard()
|
||||
@@ -1210,6 +1239,7 @@ class ExpressionCodegen(
|
||||
nestedTryWithoutFinally: MutableList<TryInfo> = arrayListOf()
|
||||
) {
|
||||
val gapStart = markNewLinkedLabel()
|
||||
|
||||
finallyDepth++
|
||||
if (isFinallyMarkerRequired()) {
|
||||
generateFinallyMarker(mv, finallyDepth, true)
|
||||
@@ -1223,7 +1253,13 @@ class ExpressionCodegen(
|
||||
tryWithFinallyInfo.onExit.markLineNumber(startOffset = false)
|
||||
mv.goTo(tryCatchBlockEnd)
|
||||
}
|
||||
val gapEnd = afterJumpLabel ?: markNewLabel()
|
||||
|
||||
// Split the local variables for the blocks on the way to the finally. Variables introduced in these blocks do not
|
||||
// cover the finally block code.
|
||||
val endOfFinallyCode = markNewLinkedLabel()
|
||||
addLocalVariableGapsForFinallyBlocks(data, tryWithFinallyInfo, gapStart, endOfFinallyCode)
|
||||
|
||||
val gapEnd = afterJumpLabel ?: endOfFinallyCode
|
||||
tryWithFinallyInfo.gaps.add(gapStart to gapEnd)
|
||||
if (state.languageVersionSettings.supportsFeature(LanguageFeature.ProperFinally)) {
|
||||
for (it in nestedTryWithoutFinally) {
|
||||
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
inline fun g(block: () -> Unit): Unit = block()
|
||||
|
||||
fun box(): String {
|
||||
try {
|
||||
for (c in emptyArray<String>()) {
|
||||
g {
|
||||
for (d in emptyArray<Int>()) {
|
||||
return "Fail"
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {}
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// FILE: test.kt
|
||||
fun box() {
|
||||
var result = ""
|
||||
for (x in listOf("A", "B")) {
|
||||
try {
|
||||
val y = "y"
|
||||
result += y
|
||||
break
|
||||
}
|
||||
finally {
|
||||
val z = "z"
|
||||
result += z
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The old backend has the local y covering the finally block as well.
|
||||
// IGNORE_BACKEND: JVM
|
||||
|
||||
// LOCAL VARIABLES
|
||||
// test.kt:3 box:
|
||||
// test.kt:4 box: result:java.lang.String="":java.lang.String
|
||||
// test.kt:5 box: result:java.lang.String="":java.lang.String, x:java.lang.String="A":java.lang.String
|
||||
// test.kt:6 box: result:java.lang.String="":java.lang.String, x:java.lang.String="A":java.lang.String
|
||||
// test.kt:7 box: result:java.lang.String="":java.lang.String, x:java.lang.String="A":java.lang.String, y:java.lang.String="y":java.lang.String
|
||||
// test.kt:11 box: result:java.lang.String="y":java.lang.String, x:java.lang.String="A":java.lang.String
|
||||
// test.kt:12 box: result:java.lang.String="y":java.lang.String, x:java.lang.String="A":java.lang.String, z:java.lang.String="z":java.lang.String
|
||||
// test.kt:15 box: result:java.lang.String="yz":java.lang.String
|
||||
@@ -0,0 +1,35 @@
|
||||
// FILE: test.kt
|
||||
fun box() {
|
||||
var result = ""
|
||||
for (x in listOf("A", "B")) {
|
||||
try {
|
||||
val y = "y"
|
||||
result += y
|
||||
continue
|
||||
}
|
||||
finally {
|
||||
val z = "z"
|
||||
result += z
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The old backend has the local y covering the finally block as well.
|
||||
// IGNORE_BACKEND: JVM
|
||||
|
||||
// LOCAL VARIABLES
|
||||
// test.kt:3 box:
|
||||
// test.kt:4 box: result:java.lang.String="":java.lang.String
|
||||
// test.kt:5 box: result:java.lang.String="":java.lang.String, x:java.lang.String="A":java.lang.String
|
||||
// test.kt:6 box: result:java.lang.String="":java.lang.String, x:java.lang.String="A":java.lang.String
|
||||
// test.kt:7 box: result:java.lang.String="":java.lang.String, x:java.lang.String="A":java.lang.String, y:java.lang.String="y":java.lang.String
|
||||
// test.kt:11 box: result:java.lang.String="y":java.lang.String, x:java.lang.String="A":java.lang.String
|
||||
// test.kt:12 box: result:java.lang.String="y":java.lang.String, x:java.lang.String="A":java.lang.String, z:java.lang.String="z":java.lang.String
|
||||
// test.kt:4 box: result:java.lang.String="yz":java.lang.String
|
||||
// test.kt:5 box: result:java.lang.String="yz":java.lang.String, x:java.lang.String="B":java.lang.String
|
||||
// test.kt:6 box: result:java.lang.String="yz":java.lang.String, x:java.lang.String="B":java.lang.String
|
||||
// test.kt:7 box: result:java.lang.String="yz":java.lang.String, x:java.lang.String="B":java.lang.String, y:java.lang.String="y":java.lang.String
|
||||
// test.kt:11 box: result:java.lang.String="yzy":java.lang.String, x:java.lang.String="B":java.lang.String
|
||||
// test.kt:12 box: result:java.lang.String="yzy":java.lang.String, x:java.lang.String="B":java.lang.String, z:java.lang.String="z":java.lang.String
|
||||
// test.kt:4 box: result:java.lang.String="yzyz":java.lang.String
|
||||
// test.kt:15 box: result:java.lang.String="yzyz":java.lang.String
|
||||
@@ -0,0 +1,38 @@
|
||||
// FILE: test.kt
|
||||
|
||||
fun compute(): String {
|
||||
var result = ""
|
||||
for (x in listOf("A", "B")) {
|
||||
try {
|
||||
val y = "y"
|
||||
result += y
|
||||
return result
|
||||
}
|
||||
finally {
|
||||
val z = "z"
|
||||
result += z
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun box() {
|
||||
compute()
|
||||
}
|
||||
|
||||
// The old backend has the local y covering the finally block as well.
|
||||
// IGNORE_BACKEND: JVM
|
||||
|
||||
// LOCAL VARIABLES
|
||||
// test.kt:20 box:
|
||||
// test.kt:4 compute:
|
||||
// test.kt:5 compute: result:java.lang.String="":java.lang.String
|
||||
// test.kt:6 compute: result:java.lang.String="":java.lang.String, x:java.lang.String="A":java.lang.String
|
||||
// test.kt:7 compute: result:java.lang.String="":java.lang.String, x:java.lang.String="A":java.lang.String
|
||||
// test.kt:8 compute: result:java.lang.String="":java.lang.String, x:java.lang.String="A":java.lang.String, y:java.lang.String="y":java.lang.String
|
||||
// test.kt:9 compute: result:java.lang.String="y":java.lang.String, x:java.lang.String="A":java.lang.String, y:java.lang.String="y":java.lang.String
|
||||
// test.kt:12 compute: result:java.lang.String="y":java.lang.String, x:java.lang.String="A":java.lang.String
|
||||
// test.kt:13 compute: result:java.lang.String="y":java.lang.String, x:java.lang.String="A":java.lang.String, z:java.lang.String="z":java.lang.String
|
||||
// test.kt:9 compute: result:java.lang.String="yz":java.lang.String, x:java.lang.String="A":java.lang.String, y:java.lang.String="y":java.lang.String
|
||||
// test.kt:20 box:
|
||||
// test.kt:21 box:
|
||||
@@ -0,0 +1,49 @@
|
||||
// FILE: test.kt
|
||||
|
||||
fun compute(): String {
|
||||
var result = ""
|
||||
try {
|
||||
val a = "a"
|
||||
try {
|
||||
val b = "b"
|
||||
for (i in 0 until 1) {
|
||||
val e = "e"
|
||||
result += b
|
||||
return result
|
||||
}
|
||||
} finally {
|
||||
val c = "c"
|
||||
result += c
|
||||
}
|
||||
} finally {
|
||||
val d = "d"
|
||||
result += d
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun box() {
|
||||
compute()
|
||||
}
|
||||
|
||||
// The old backend gets the local variables for finally blocks wrong.
|
||||
// IGNORE_BACKEND: JVM
|
||||
|
||||
// LOCAL VARIABLES
|
||||
// test.kt:26 box:
|
||||
// test.kt:4 compute:
|
||||
// test.kt:5 compute: result:java.lang.String="":java.lang.String
|
||||
// test.kt:6 compute: result:java.lang.String="":java.lang.String
|
||||
// test.kt:7 compute: result:java.lang.String="":java.lang.String, a:java.lang.String="a":java.lang.String
|
||||
// test.kt:8 compute: result:java.lang.String="":java.lang.String, a:java.lang.String="a":java.lang.String
|
||||
// test.kt:9 compute: result:java.lang.String="":java.lang.String, a:java.lang.String="a":java.lang.String, b:java.lang.String="b":java.lang.String
|
||||
// test.kt:10 compute: result:java.lang.String="":java.lang.String, a:java.lang.String="a":java.lang.String, b:java.lang.String="b":java.lang.String, i:int=0:int
|
||||
// test.kt:11 compute: result:java.lang.String="":java.lang.String, a:java.lang.String="a":java.lang.String, b:java.lang.String="b":java.lang.String, i:int=0:int, e:java.lang.String="e":java.lang.String
|
||||
// test.kt:12 compute: result:java.lang.String="b":java.lang.String, a:java.lang.String="a":java.lang.String, b:java.lang.String="b":java.lang.String, i:int=0:int, e:java.lang.String="e":java.lang.String
|
||||
// test.kt:15 compute: result:java.lang.String="b":java.lang.String, a:java.lang.String="a":java.lang.String
|
||||
// test.kt:16 compute: result:java.lang.String="b":java.lang.String, a:java.lang.String="a":java.lang.String, c:java.lang.String="c":java.lang.String
|
||||
// test.kt:19 compute: result:java.lang.String="bc":java.lang.String
|
||||
// test.kt:20 compute: result:java.lang.String="bc":java.lang.String, d:java.lang.String="d":java.lang.String
|
||||
// test.kt:12 compute: result:java.lang.String="bcd":java.lang.String, a:java.lang.String="a":java.lang.String, b:java.lang.String="b":java.lang.String, i:int=0:int, e:java.lang.String="e":java.lang.String
|
||||
// test.kt:26 box:
|
||||
// test.kt:27 box:
|
||||
@@ -0,0 +1,48 @@
|
||||
// FILE: test.kt
|
||||
|
||||
inline fun g(block: () -> Unit) {
|
||||
block()
|
||||
}
|
||||
|
||||
var x: String? = null
|
||||
|
||||
fun compute(): String {
|
||||
try {
|
||||
for (a in listOf("a")) {
|
||||
g {
|
||||
for (b in listOf("b")) {
|
||||
return b
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
x = "OK"
|
||||
}
|
||||
return "FAIL"
|
||||
}
|
||||
|
||||
fun box() {
|
||||
val result = compute()
|
||||
val localX = x
|
||||
}
|
||||
|
||||
// JVM_IR backend correctly gets rid of the `a` local in the finally, but the inliner
|
||||
// does not get rid of `b` or the inlining locals.
|
||||
|
||||
// JVM backend does not get rid of `a` and also the inliner does not get rid of `b`
|
||||
// or the inlining locals.
|
||||
|
||||
// IGNORE_BACKEND: JVM_IR, JVM
|
||||
|
||||
// LOCAL VARIABLES
|
||||
// test.kt:25 box:
|
||||
// test.kt:10 compute:
|
||||
// test.kt:11 compute:
|
||||
// test.kt:12 compute: a:java.lang.String="a":java.lang.String
|
||||
// test.kt:4 compute: a:java.lang.String="a":java.lang.String, $i$f$g:int=0:int
|
||||
// test.kt:13 compute: a:java.lang.String="a":java.lang.String, $i$f$g:int=0:int, $i$a$-g-TestKt$compute$1:int=0:int
|
||||
// test.kt:14 compute: a:java.lang.String="a":java.lang.String, $i$f$g:int=0:int, $i$a$-g-TestKt$compute$1:int=0:int, b:java.lang.String="b":java.lang.String
|
||||
// test.kt:19 compute:
|
||||
// test.kt:25 box:
|
||||
// test.kt:26 box: result:java.lang.String="b":java.lang.String
|
||||
// test.kt:27 box: result:java.lang.String="b":java.lang.String, localX:java.lang.String="OK":java.lang.String
|
||||
+6
@@ -8659,6 +8659,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/tryCatchInExpressions/multipleCatchBlocks.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonLocalReturnInTryFinally.kt")
|
||||
public void testNonLocalReturnInTryFinally() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/tryCatchInExpressions/nonLocalReturnInTryFinally.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("splitTry.kt")
|
||||
public void testSplitTry() throws Exception {
|
||||
|
||||
+6
@@ -8659,6 +8659,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/controlStructures/tryCatchInExpressions/multipleCatchBlocks.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonLocalReturnInTryFinally.kt")
|
||||
public void testNonLocalReturnInTryFinally() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/tryCatchInExpressions/nonLocalReturnInTryFinally.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("splitTry.kt")
|
||||
public void testSplitTry() throws Exception {
|
||||
|
||||
+5
@@ -6725,6 +6725,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/controlStructures/tryCatchInExpressions/multipleCatchBlocks.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonLocalReturnInTryFinally.kt")
|
||||
public void testNonLocalReturnInTryFinally() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/tryCatchInExpressions/nonLocalReturnInTryFinally.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("splitTry.kt")
|
||||
public void testSplitTry() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/tryCatchInExpressions/splitTry.kt");
|
||||
|
||||
Generated
+30
@@ -86,6 +86,36 @@ public class IrLocalVariableTestGenerated extends AbstractIrLocalVariableTest {
|
||||
runTest("compiler/testData/debug/localVariables/localFunUnused.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("tryFinally.kt")
|
||||
public void testTryFinally() throws Exception {
|
||||
runTest("compiler/testData/debug/localVariables/tryFinally.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("tryFinally2.kt")
|
||||
public void testTryFinally2() throws Exception {
|
||||
runTest("compiler/testData/debug/localVariables/tryFinally2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("tryFinally3.kt")
|
||||
public void testTryFinally3() throws Exception {
|
||||
runTest("compiler/testData/debug/localVariables/tryFinally3.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("tryFinally4.kt")
|
||||
public void testTryFinally4() throws Exception {
|
||||
runTest("compiler/testData/debug/localVariables/tryFinally4.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("tryFinally5.kt")
|
||||
public void testTryFinally5() throws Exception {
|
||||
runTest("compiler/testData/debug/localVariables/tryFinally5.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("underscoreNames.kt")
|
||||
public void testUnderscoreNames() throws Exception {
|
||||
|
||||
Generated
+30
@@ -86,6 +86,36 @@ public class LocalVariableTestGenerated extends AbstractLocalVariableTest {
|
||||
runTest("compiler/testData/debug/localVariables/localFunUnused.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("tryFinally.kt")
|
||||
public void testTryFinally() throws Exception {
|
||||
runTest("compiler/testData/debug/localVariables/tryFinally.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("tryFinally2.kt")
|
||||
public void testTryFinally2() throws Exception {
|
||||
runTest("compiler/testData/debug/localVariables/tryFinally2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("tryFinally3.kt")
|
||||
public void testTryFinally3() throws Exception {
|
||||
runTest("compiler/testData/debug/localVariables/tryFinally3.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("tryFinally4.kt")
|
||||
public void testTryFinally4() throws Exception {
|
||||
runTest("compiler/testData/debug/localVariables/tryFinally4.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("tryFinally5.kt")
|
||||
public void testTryFinally5() throws Exception {
|
||||
runTest("compiler/testData/debug/localVariables/tryFinally5.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("underscoreNames.kt")
|
||||
public void testUnderscoreNames() throws Exception {
|
||||
|
||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java
Generated
+5
@@ -6014,6 +6014,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
|
||||
runTest("compiler/testData/codegen/box/controlStructures/tryCatchInExpressions/multipleCatchBlocks.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonLocalReturnInTryFinally.kt")
|
||||
public void testNonLocalReturnInTryFinally() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/tryCatchInExpressions/nonLocalReturnInTryFinally.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("splitTry.kt")
|
||||
public void testSplitTry() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/tryCatchInExpressions/splitTry.kt");
|
||||
|
||||
Generated
+5
@@ -5425,6 +5425,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/tryCatchInExpressions/multipleCatchBlocks.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonLocalReturnInTryFinally.kt")
|
||||
public void testNonLocalReturnInTryFinally() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/tryCatchInExpressions/nonLocalReturnInTryFinally.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("splitTry.kt")
|
||||
public void testSplitTry() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/tryCatchInExpressions/splitTry.kt");
|
||||
|
||||
Generated
+5
@@ -5425,6 +5425,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/tryCatchInExpressions/multipleCatchBlocks.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nonLocalReturnInTryFinally.kt")
|
||||
public void testNonLocalReturnInTryFinally() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/tryCatchInExpressions/nonLocalReturnInTryFinally.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("splitTry.kt")
|
||||
public void testSplitTry() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/controlStructures/tryCatchInExpressions/splitTry.kt");
|
||||
|
||||
Reference in New Issue
Block a user