Save/restore stack in try-expressions (and statements).
Parse TryCatchBlockNode's in generated bytecode, infer stack save/restore points. Save stack to local variables before 'try'. Restore stack after the beginning of try-block, catch-block, and default handler. Integrate before/after inline markers rewriting (otherwise it'll break our stacks). #KT-3309 Fixed
This commit is contained in:
+2
@@ -0,0 +1,2 @@
|
||||
fun box(): String =
|
||||
"O" + try { throw Exception("oops!") } catch (e: Exception) { "K" }
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
fun cleanup() {}
|
||||
|
||||
inline fun concat(x: String, y: String): String = x + y
|
||||
|
||||
inline fun throws() {
|
||||
try {
|
||||
throw Exception()
|
||||
}
|
||||
finally {
|
||||
cleanup()
|
||||
}
|
||||
}
|
||||
|
||||
inline fun first(x: String, y: String): String = x
|
||||
|
||||
fun box(): String =
|
||||
"" + concat(
|
||||
try { "" } finally { "0" },
|
||||
"" + concat(
|
||||
first(
|
||||
try {
|
||||
try {
|
||||
"O"
|
||||
}
|
||||
finally {
|
||||
"1"
|
||||
}
|
||||
}
|
||||
catch (e: Exception) {
|
||||
throw e
|
||||
}
|
||||
finally {
|
||||
cleanup()
|
||||
},
|
||||
"2"
|
||||
),
|
||||
first(
|
||||
try {
|
||||
throws()
|
||||
throw Exception()
|
||||
"3"
|
||||
}
|
||||
catch (e: Exception) {
|
||||
"K"
|
||||
}
|
||||
finally {
|
||||
cleanup()
|
||||
},
|
||||
"4"
|
||||
)
|
||||
)
|
||||
)
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
fun foo(b: Byte, s: String, i: Int, d: Double, li: Long): String = "$b $s $i $d $li"
|
||||
|
||||
fun box(): String {
|
||||
val test = foo(1, "abc", 1, 1.0, try { 1L } catch (e: Exception) { 10L })
|
||||
if (test != "1 abc 1 1.0 1") return "Failed, test==$test"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
public inline fun fails(block: () -> Unit): Throwable? {
|
||||
var thrown: Throwable? = null
|
||||
try {
|
||||
block()
|
||||
} catch (e: Throwable) {
|
||||
thrown = e
|
||||
}
|
||||
if (thrown == null)
|
||||
throw Exception("Expected an exception to be thrown")
|
||||
return thrown
|
||||
}
|
||||
|
||||
public inline fun throwIt(msg: String) {
|
||||
throw Exception(msg)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
fails {
|
||||
throwIt("oops!")
|
||||
}
|
||||
|
||||
var x = 0
|
||||
try {
|
||||
fails {
|
||||
x = 1
|
||||
}
|
||||
}
|
||||
catch (e: Exception) {
|
||||
x = 2
|
||||
}
|
||||
|
||||
if (x != 2) return "Failed: x==$x"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
fun box(): String =
|
||||
"O" + try { "K" } finally { "hmmm" }
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
inline fun <T> tryOrElse(f1: () -> T, f2: () -> T): T {
|
||||
try {
|
||||
return f1()
|
||||
}
|
||||
catch (e: Exception) {
|
||||
return f2()
|
||||
}
|
||||
}
|
||||
|
||||
fun testIt() = "abc" + tryOrElse({ "def" }, { "oops" }) + "ghi"
|
||||
|
||||
fun box(): String {
|
||||
val test = testIt()
|
||||
if (test != "abcdefghi") return "Failed, test==$test"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
inline fun <T> tryOrElse(f1: () -> T, f2: () -> T): T =
|
||||
try { f1() } catch (e: Exception) { f2() }
|
||||
|
||||
fun testIt() =
|
||||
"abc" +
|
||||
tryOrElse({ try { "def" } catch(e: Exception) { "oops!" } }, { "hmmm..." }) +
|
||||
"ghi"
|
||||
|
||||
fun box(): String {
|
||||
val test = testIt()
|
||||
if (test != "abcdefghi") return "Failed, test==$test"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
inline fun <T> tryAndThen(f1: () -> Unit, f2: () -> Unit, f3: () -> T): T {
|
||||
try {
|
||||
f1()
|
||||
}
|
||||
catch (e: Exception) {
|
||||
f2()
|
||||
}
|
||||
finally {
|
||||
return f3()
|
||||
}
|
||||
}
|
||||
|
||||
fun testIt() = "abc" +
|
||||
tryAndThen({}, {}, { "def" }) +
|
||||
"ghi"
|
||||
|
||||
fun box(): String {
|
||||
val test = testIt()
|
||||
if (test != "abcdefghi") return "Failed, test==$test"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
class Exception1(msg: String): Exception(msg)
|
||||
class Exception2(msg: String): Exception(msg)
|
||||
class Exception3(msg: String): Exception(msg)
|
||||
|
||||
fun box(): String =
|
||||
"O" + try {
|
||||
throw Exception3("K")
|
||||
}
|
||||
catch (e1: Exception1) {
|
||||
"e1"
|
||||
}
|
||||
catch (e2: Exception2) {
|
||||
"e2"
|
||||
}
|
||||
catch (e3: Exception3) {
|
||||
e3.getMessage()
|
||||
}
|
||||
catch (e: Exception) {
|
||||
"e"
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
inline fun test(s: () -> Int): Int =
|
||||
try {
|
||||
val i = s()
|
||||
i + 10
|
||||
}
|
||||
finally {
|
||||
0
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
test {
|
||||
try {
|
||||
val p = 1
|
||||
return "OK"
|
||||
}
|
||||
catch(e: Exception) {
|
||||
-2
|
||||
}
|
||||
finally {
|
||||
-3
|
||||
}
|
||||
}
|
||||
|
||||
return "Failed"
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fun shouldReturnFalse() : Boolean {
|
||||
try {
|
||||
return true
|
||||
} finally {
|
||||
if (true)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String =
|
||||
if (shouldReturnFalse()) "Failed" else "OK"
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
fun shouldReturn11() : Int {
|
||||
var x = 0
|
||||
while (true) {
|
||||
try {
|
||||
if(x < 10)
|
||||
x++
|
||||
else
|
||||
break
|
||||
}
|
||||
finally {
|
||||
x++
|
||||
}
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val test = shouldReturn11()
|
||||
if (test != 11) return "Failed, test=$test"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fun box(): String =
|
||||
"O" + try { "K" } catch (e: Exception) { "oops!" }
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
fun box(): String =
|
||||
"" +
|
||||
try { "O" } catch (e: Exception) { "1" } +
|
||||
try { throw Exception("oops!") } catch (e: Exception) { "K" }
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
fun idiv(a: Int, b: Int): Int =
|
||||
if (b == 0) throw Exception("Division by zero") else a / b
|
||||
|
||||
fun foo(): Int {
|
||||
var sum = 0
|
||||
var i = 2
|
||||
while (i > -10) {
|
||||
sum += try { idiv(100, i) } catch (e: Exception) { break }
|
||||
i--
|
||||
}
|
||||
return sum
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val test = foo()
|
||||
if (test != 150) return "Failed, test=$test"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
fun idiv(a: Int, b: Int): Int =
|
||||
if (b == 0) throw Exception("Division by zero") else a / b
|
||||
|
||||
fun foo(): Int {
|
||||
var sum = 0
|
||||
for (i in -10 .. 10) {
|
||||
sum += try { idiv(100, i) } catch (e: Exception) { continue }
|
||||
}
|
||||
return sum
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val test = foo()
|
||||
if (test != 0) return "Failed, test=$test"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
fun box(): String =
|
||||
"O" +
|
||||
try {
|
||||
throw Exception("oops!")
|
||||
}
|
||||
catch (e: Exception) {
|
||||
try { "K" } catch (e: Exception) { "2" }
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
class MyException(message: String): Exception(message)
|
||||
|
||||
fun box(): String =
|
||||
"O" +
|
||||
try {
|
||||
try { throw Exception("oops!") } catch (mye: MyException) { "1" }
|
||||
}
|
||||
catch (e: Exception) {
|
||||
"K"
|
||||
}
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
inline fun catchAll(x: String, block: () -> Unit): String {
|
||||
try {
|
||||
block()
|
||||
} catch (e: Throwable) {
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
inline fun throwIt(msg: String) {
|
||||
throw Exception(msg)
|
||||
}
|
||||
|
||||
inline fun bar(x: String): String =
|
||||
x + catchAll("") { throwIt("oops!") }
|
||||
|
||||
fun box(): String =
|
||||
bar("OK")
|
||||
Reference in New Issue
Block a user