| == fn == |
| fun fn() : String? = null |
| --------------------- |
| L0: |
| 1 <START> |
| r(null) -> <v0> |
| ret(*|<v0>) L1 |
| L1: |
| <END> NEXT:[<SINK>] |
| error: |
| <ERROR> PREV:[] |
| sink: |
| <SINK> PREV:[<ERROR>, <END>] |
| ===================== |
| == let == |
| inline fun <T, R> T.let(f: (T) -> R): R = f(this) |
| --------------------- |
| L0: |
| 1 <START> |
| v(f: (T) -> R) |
| magic[FAKE_INITIALIZER](f: (T) -> R) -> <v0> |
| w(f|<v0>) |
| r(f) -> <v1> |
| r(this, <this>) -> <v2> |
| mark(f(this)) |
| call(f(this), invoke|<v1>, <v2>) -> <v3> |
| ret(*|<v3>) L1 |
| L1: |
| <END> NEXT:[<SINK>] |
| error: |
| <ERROR> PREV:[] |
| sink: |
| <SINK> PREV:[<ERROR>, <END>] |
| ===================== |
| == foo == |
| fun foo(): String { |
| val x = fn()?.let { throw Exception() } ?: "unreachable?" |
| return x |
| } |
| --------------------- |
| L0: |
| 1 <START> |
| 2 mark({ val x = fn()?.let { throw Exception() } ?: "unreachable?" return x }) |
| v(val x = fn()?.let { throw Exception() } ?: "unreachable?") |
| mark(fn()?.let { throw Exception() }) |
| jf(L2) NEXT:[mark(fn()?.let { throw Exception() } ?: "unreachable?"), mark(fn())] |
| mark(fn()) |
| call(fn(), fn) -> <v0> |
| mark({ throw Exception() }) |
| jmp?(L3) NEXT:[r({ throw Exception() }) -> <v1>, d({ throw Exception() })] |
| d({ throw Exception() }) NEXT:[<SINK>] |
| L3 [after local declaration]: |
| r({ throw Exception() }) -> <v1> PREV:[jmp?(L3)] |
| mark(let { throw Exception() }) |
| call(let { throw Exception() }, let|<v0>, <v1>) -> <v2> |
| L2 [result of call]: |
| mark(fn()?.let { throw Exception() } ?: "unreachable?") PREV:[jf(L2), call(let { throw Exception() }, let|<v0>, <v1>) -> <v2>] |
| jt(L6|<v2>) NEXT:[mark("unreachable?"), merge(fn()?.let { throw Exception() } ?: "unreachable?"|<v2>, <v3>) -> <v4>] |
| mark("unreachable?") |
| r("unreachable?") -> <v3> |
| L6 [after elvis operator]: |
| merge(fn()?.let { throw Exception() } ?: "unreachable?"|<v2>, <v3>) -> <v4> PREV:[jt(L6|<v2>), r("unreachable?") -> <v3>] |
| w(x|<v4>) |
| r(x) -> <v5> |
| ret(*|<v5>) L1 |
| L1: |
| 1 <END> NEXT:[<SINK>] |
| error: |
| <ERROR> PREV:[] |
| sink: |
| <SINK> PREV:[<ERROR>, <END>, d({ throw Exception() })] |
| ===================== |
| == anonymous_0 == |
| { throw Exception() } |
| --------------------- |
| L4: |
| 3 <START> |
| 4 mark(throw Exception()) |
| mark(throw Exception()) |
| mark(Exception()) |
| call(Exception(), <init>) -> <v0> |
| throw (throw Exception()|<v0>) NEXT:[<ERROR>] |
| - 3 ret(*|!<v1>) L5 PREV:[] |
| L5: |
| <END> NEXT:[<SINK>] PREV:[] |
| error: |
| <ERROR> PREV:[throw (throw Exception()|<v0>)] |
| sink: |
| <SINK> PREV:[<ERROR>, <END>] |
| ===================== |
| == bar == |
| fun bar(): String { |
| val x = fn() ?: return "" |
| val y = x?.let { throw Exception() } ?: "unreachable" |
| return y |
| } |
| --------------------- |
| L0: |
| 1 <START> |
| 2 mark({ val x = fn() ?: return "" val y = x?.let { throw Exception() } ?: "unreachable" return y }) |
| v(val x = fn() ?: return "") |
| mark(fn()) |
| call(fn(), fn) -> <v0> |
| mark(fn() ?: return "") |
| jt(L2|<v0>) NEXT:[mark(""), merge(fn() ?: return ""|<v0>, !<v2>) -> <v3>] |
| mark("") |
| r("") -> <v1> |
| ret(*|<v1>) L1 NEXT:[<END>] |
| L2 [after elvis operator]: |
| merge(fn() ?: return ""|<v0>, !<v2>) -> <v3> PREV:[jt(L2|<v0>)] |
| w(x|<v3>) |
| v(val y = x?.let { throw Exception() } ?: "unreachable") |
| mark(x?.let { throw Exception() }) |
| jf(L3) NEXT:[jmp(error), r(x) -> <v4>] |
| r(x) -> <v4> |
| mark({ throw Exception() }) |
| jmp?(L4) NEXT:[r({ throw Exception() }) -> <v5>, d({ throw Exception() })] |
| d({ throw Exception() }) NEXT:[<SINK>] |
| L4 [after local declaration]: |
| r({ throw Exception() }) -> <v5> PREV:[jmp?(L4)] |
| mark(let { throw Exception() }) |
| call(let { throw Exception() }, let|<v4>, <v5>) -> <v6> |
| jmp(error) NEXT:[<ERROR>] |
| L3 [result of call]: |
| jmp(error) NEXT:[<ERROR>] PREV:[jf(L3)] |
| - mark(x?.let { throw Exception() } ?: "unreachable") PREV:[] |
| - jt(L7|<v6>) NEXT:[mark("unreachable"), merge(x?.let { throw Exception() } ?: "unreachable"|<v6>, <v7>) -> <v8>] PREV:[] |
| - mark("unreachable") PREV:[] |
| - r("unreachable") -> <v7> PREV:[] |
| L7 [after elvis operator]: |
| - merge(x?.let { throw Exception() } ?: "unreachable"|<v6>, <v7>) -> <v8> PREV:[] |
| - w(y|<v8>) PREV:[] |
| - r(y) -> <v9> PREV:[] |
| - ret(*|<v9>) L1 PREV:[] |
| L1: |
| 1 <END> NEXT:[<SINK>] PREV:[ret(*|<v1>) L1] |
| error: |
| <ERROR> PREV:[jmp(error), jmp(error)] |
| sink: |
| <SINK> PREV:[<ERROR>, <END>, d({ throw Exception() })] |
| ===================== |
| == anonymous_1 == |
| { throw Exception() } |
| --------------------- |
| L5: |
| 3 <START> |
| 4 mark(throw Exception()) |
| mark(throw Exception()) |
| mark(Exception()) |
| call(Exception(), <init>) -> <v0> |
| throw (throw Exception()|<v0>) NEXT:[<ERROR>] |
| - 3 ret(*|!<v1>) L6 PREV:[] |
| L6: |
| <END> NEXT:[<SINK>] PREV:[] |
| error: |
| <ERROR> PREV:[throw (throw Exception()|<v0>)] |
| sink: |
| <SINK> PREV:[<ERROR>, <END>] |
| ===================== |