CFA: additional jumps to catch / finally generated in the end of try / before exits from try #KT-5469 Fixed
Also #KT-13612 Fixed (cherry picked from commit 7c188b3)
This commit is contained in:
committed by
Mikhail Glukhikh
parent
43954699a7
commit
f8039249c6
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.cfg
|
||||
|
||||
import com.google.common.collect.Lists
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.util.SmartFMap
|
||||
@@ -104,8 +105,12 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
||||
builder.bindLabel(afterDeclaration)
|
||||
}
|
||||
|
||||
private class CatchFinallyLabels(val onException: Label?, val toFinally: Label?, val tryExpression: KtTryExpression?)
|
||||
|
||||
private inner class CFPVisitor(private val builder: ControlFlowBuilder) : KtVisitorVoid() {
|
||||
|
||||
private val catchFinallyStack = Stack<CatchFinallyLabels>()
|
||||
|
||||
private val conditionVisitor = object : KtVisitorVoid() {
|
||||
|
||||
private fun getSubjectExpression(condition: KtWhenCondition): KtExpression? {
|
||||
@@ -567,9 +572,11 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
||||
|
||||
fun generate() {
|
||||
val finalExpression = finallyBlock?.finalExpression ?: return
|
||||
catchFinallyStack.push(CatchFinallyLabels(null, null, null))
|
||||
startFinally?.let {
|
||||
assert(finishFinally != null) { "startFinally label is set to $startFinally but finishFinally label is not set" }
|
||||
builder.repeatPseudocode(it, finishFinally!!)
|
||||
catchFinallyStack.pop()
|
||||
return
|
||||
}
|
||||
builder.createUnboundLabel("start finally").let {
|
||||
@@ -581,6 +588,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
||||
finishFinally = it
|
||||
builder.bindLabel(it)
|
||||
}
|
||||
catchFinallyStack.pop()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -647,7 +655,10 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
||||
}
|
||||
|
||||
val tryBlock = expression.tryBlock
|
||||
catchFinallyStack.push(CatchFinallyLabels(onException, onExceptionToFinallyBlock, expression))
|
||||
generateInstructions(tryBlock)
|
||||
generateJumpsToCatchAndFinally()
|
||||
catchFinallyStack.pop()
|
||||
|
||||
if (hasCatches && onException != null) {
|
||||
val afterCatches = builder.createUnboundLabel("afterCatches")
|
||||
@@ -796,6 +807,9 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
||||
override fun visitBreakExpression(expression: KtBreakExpression) {
|
||||
val loop = getCorrespondingLoop(expression)
|
||||
if (loop != null) {
|
||||
if (jumpCrossesTryCatchBoundary(expression, loop)) {
|
||||
generateJumpsToCatchAndFinally()
|
||||
}
|
||||
if (jumpDoesNotCrossFunctionBoundary(expression, loop)) {
|
||||
builder.getLoopExitPoint(loop)?.let { builder.jump(it, expression) }
|
||||
}
|
||||
@@ -805,6 +819,9 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
||||
override fun visitContinueExpression(expression: KtContinueExpression) {
|
||||
val loop = getCorrespondingLoop(expression)
|
||||
if (loop != null) {
|
||||
if (jumpCrossesTryCatchBoundary(expression, loop)) {
|
||||
generateJumpsToCatchAndFinally()
|
||||
}
|
||||
if (jumpDoesNotCrossFunctionBoundary(expression, loop)) {
|
||||
builder.getLoopConditionEntryPoint(loop)?.let { builder.jump(it, expression) }
|
||||
}
|
||||
@@ -860,6 +877,24 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
||||
return loop
|
||||
}
|
||||
|
||||
private fun returnCrossesTryCatchBoundary(returnExpression: KtReturnExpression): Boolean {
|
||||
val targetLabel = returnExpression.getTargetLabel() ?: return true
|
||||
val labeledElement = trace.get(BindingContext.LABEL_TARGET, targetLabel) ?: return true
|
||||
return jumpCrossesTryCatchBoundary(returnExpression, labeledElement)
|
||||
}
|
||||
|
||||
private fun jumpCrossesTryCatchBoundary(jumpExpression: KtExpressionWithLabel, jumpTarget: PsiElement): Boolean {
|
||||
var current = jumpExpression.parent
|
||||
while (current != null) {
|
||||
when (current) {
|
||||
jumpTarget -> return false
|
||||
is KtTryExpression -> return true
|
||||
else -> current = current.parent
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun jumpDoesNotCrossFunctionBoundary(jumpExpression: KtExpressionWithLabel, jumpTarget: KtLoopExpression): Boolean {
|
||||
val bindingContext = trace.bindingContext
|
||||
|
||||
@@ -882,6 +917,9 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
||||
}
|
||||
|
||||
override fun visitReturnExpression(expression: KtReturnExpression) {
|
||||
if (returnCrossesTryCatchBoundary(expression)) {
|
||||
generateJumpsToCatchAndFinally()
|
||||
}
|
||||
val returnedExpression = expression.returnedExpression
|
||||
if (returnedExpression != null) {
|
||||
generateInstructions(returnedExpression)
|
||||
@@ -1124,15 +1162,30 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateJumpsToCatchAndFinally() {
|
||||
if (catchFinallyStack.isNotEmpty()) {
|
||||
with(catchFinallyStack.peek()) {
|
||||
if (tryExpression != null) {
|
||||
onException?.let {
|
||||
builder.nondeterministicJump(it, tryExpression, null)
|
||||
}
|
||||
toFinally?.let {
|
||||
builder.nondeterministicJump(it, tryExpression, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitThrowExpression(expression: KtThrowExpression) {
|
||||
mark(expression)
|
||||
|
||||
val thrownExpression = expression.thrownExpression ?: return
|
||||
generateJumpsToCatchAndFinally()
|
||||
|
||||
val thrownExpression = expression.thrownExpression ?: return
|
||||
generateInstructions(thrownExpression)
|
||||
|
||||
val thrownValue = builder.getBoundValue(thrownExpression) ?: return
|
||||
|
||||
builder.throwException(expression, thrownValue)
|
||||
}
|
||||
|
||||
|
||||
@@ -43,10 +43,11 @@ L3 [else branch]:
|
||||
read (Unit) INIT: in: {f=ID} out: {f=ID}
|
||||
L4 ['if' expression result]:
|
||||
merge(if (f) { x = 0 }|!<v3>) -> <v4> INIT: in: {f=ID, x=I} out: {f=ID, x=I}
|
||||
2 jmp(L5)
|
||||
2 jmp?(L2)
|
||||
jmp(L5)
|
||||
L2 [onExceptionToFinallyBlock]:
|
||||
L6 [start finally]:
|
||||
3 mark({ fun bar() {} }) INIT: in: {f=ID} out: {f=ID}
|
||||
3 mark({ fun bar() {} })
|
||||
jmp?(L7)
|
||||
d(fun bar() {})
|
||||
L7 [after local declaration]:
|
||||
@@ -54,7 +55,7 @@ L10 [finish finally]:
|
||||
2 jmp(error)
|
||||
L5 [skipFinallyToErrorBlock]:
|
||||
L11 [copy of L2, onExceptionToFinallyBlock]:
|
||||
3 mark({ fun bar() {} }) INIT: in: {f=ID, x=I} out: {f=ID, x=I}
|
||||
3 mark({ fun bar() {} })
|
||||
jmp?(L12)
|
||||
d(fun bar() {})
|
||||
L12 [copy of L7, after local declaration]:
|
||||
@@ -62,15 +63,15 @@ L12 [copy of L7, after local declaration]:
|
||||
L1:
|
||||
1 <END>
|
||||
error:
|
||||
<ERROR> INIT: in: {f=ID} out: {f=ID}
|
||||
<ERROR>
|
||||
sink:
|
||||
<SINK> INIT: in: {f=ID, x=I} out: {f=ID, x=I} USE: in: {} out: {}
|
||||
<SINK> USE: in: {} out: {}
|
||||
=====================
|
||||
== bar ==
|
||||
fun bar() {}
|
||||
---------------------
|
||||
L8:
|
||||
4 <START> INIT: in: {f=ID} out: {f=ID}
|
||||
4 <START> INIT: in: {f=ID, x=I} out: {f=ID, x=I}
|
||||
5 mark({})
|
||||
read (Unit)
|
||||
L9:
|
||||
@@ -78,7 +79,7 @@ L9:
|
||||
error:
|
||||
<ERROR> INIT: in: {} out: {}
|
||||
sink:
|
||||
<SINK> INIT: in: {f=ID} out: {f=ID} USE: in: {} out: {}
|
||||
<SINK> INIT: in: {f=ID, x=I} out: {f=ID, x=I} USE: in: {} out: {}
|
||||
=====================
|
||||
== bar ==
|
||||
fun bar() {}
|
||||
|
||||
@@ -32,6 +32,7 @@ L0:
|
||||
r(false) -> <v0>
|
||||
jf(L3|<v0>)
|
||||
4 mark({ return "fail" })
|
||||
jmp?(L2)
|
||||
mark("fail")
|
||||
r("fail") -> <v1>
|
||||
L4 [start finally]:
|
||||
@@ -60,12 +61,15 @@ L3 [else branch]:
|
||||
mark("test")
|
||||
r("test") -> <v6> USE: in: {foo=WRITTEN_AFTER_READ} out: {foo=WRITTEN_AFTER_READ}
|
||||
w(foo|<v6>) USE: in: {foo=READ} out: {foo=WRITTEN_AFTER_READ}
|
||||
6 jmp(L11)
|
||||
6 jmp?(L9)
|
||||
jmp?(L10)
|
||||
jmp(L11)
|
||||
L9 [onException]:
|
||||
7 v(e: Exception) INIT: in: {foo=ID} out: {e=D, foo=ID}
|
||||
magic[FAKE_INITIALIZER](e: Exception) -> <v8> INIT: in: {e=D, foo=ID} out: {e=D, foo=ID}
|
||||
w(e|<v8>) INIT: in: {e=D, foo=ID} out: {e=ID, foo=ID}
|
||||
8 mark({ return "fail" }) INIT: in: {e=ID, foo=ID} out: {e=ID, foo=ID}
|
||||
jmp?(L2)
|
||||
mark("fail")
|
||||
r("fail") -> <v9>
|
||||
L12 [start finally]:
|
||||
@@ -99,6 +103,7 @@ L8 [else branch]:
|
||||
read (Unit)
|
||||
L15 ['if' expression result]:
|
||||
merge(if (false) { var foo: String? = null try { foo = "test" } catch (e: Exception) { return "fail" } finally { println(foo) // Variable 'foo' must be initialized } }|<v14>) -> <v15>
|
||||
jmp?(L2)
|
||||
mark("fail")
|
||||
r("fail") -> <v16>
|
||||
mark({})
|
||||
@@ -111,7 +116,8 @@ L16 ['if' expression result]:
|
||||
merge(if (false) { if (false) { var foo: String? = null try { foo = "test" } catch (e: Exception) { return "fail" } finally { println(foo) // Variable 'foo' must be initialized } } return "fail" }|!<v17>) -> <v18>
|
||||
L6 ['if' expression result]:
|
||||
3 merge(if (false) { return "fail" } else { if (false) { if (false) { var foo: String? = null try { foo = "test" } catch (e: Exception) { return "fail" } finally { println(foo) // Variable 'foo' must be initialized } } return "fail" } }|!<v2>, <v18>) -> <v19>
|
||||
2 jmp(L17)
|
||||
2 jmp?(L2)
|
||||
jmp(L17)
|
||||
L2 [onExceptionToFinallyBlock]:
|
||||
5 mark({})
|
||||
read (Unit)
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
== f ==
|
||||
fun f() {
|
||||
var foo = 1
|
||||
try {
|
||||
foo = 2
|
||||
throw RuntimeException()
|
||||
} catch (e: Throwable) {
|
||||
println(foo)
|
||||
}
|
||||
}
|
||||
---------------------
|
||||
L0:
|
||||
1 <START> INIT: in: {} out: {} USE: in: {} out: {}
|
||||
2 mark({ var foo = 1 try { foo = 2 throw RuntimeException() } catch (e: Throwable) { println(foo) } })
|
||||
v(var foo = 1) INIT: in: {} out: {foo=D}
|
||||
r(1) -> <v0> INIT: in: {foo=D} out: {foo=D}
|
||||
w(foo|<v0>) INIT: in: {foo=D} out: {foo=ID}
|
||||
mark(try { foo = 2 throw RuntimeException() } catch (e: Throwable) { println(foo) }) INIT: in: {foo=ID} out: {foo=ID}
|
||||
jmp?(L2) USE: in: {foo=READ} out: {foo=READ}
|
||||
3 mark({ foo = 2 throw RuntimeException() })
|
||||
r(2) -> <v1> USE: in: {foo=WRITTEN_AFTER_READ} out: {foo=WRITTEN_AFTER_READ}
|
||||
w(foo|<v1>) USE: in: {foo=READ} out: {foo=WRITTEN_AFTER_READ}
|
||||
mark(throw RuntimeException())
|
||||
jmp?(L2) USE: in: {foo=READ} out: {foo=READ}
|
||||
mark(RuntimeException())
|
||||
call(RuntimeException(), <init>) -> <v2>
|
||||
throw (throw RuntimeException()|<v2>) USE: in: {} out: {}
|
||||
- 2 jmp?(L2)
|
||||
- jmp(L3)
|
||||
L2 [onException]:
|
||||
3 v(e: Throwable) INIT: in: {foo=ID} out: {e=D, foo=ID}
|
||||
magic[FAKE_INITIALIZER](e: Throwable) -> <v4> INIT: in: {e=D, foo=ID} out: {e=D, foo=ID}
|
||||
w(e|<v4>) INIT: in: {e=D, foo=ID} out: {e=ID, foo=ID}
|
||||
4 mark({ println(foo) }) INIT: in: {e=ID, foo=ID} out: {e=ID, foo=ID} USE: in: {foo=READ} out: {foo=READ}
|
||||
r(foo) -> <v5> USE: in: {} out: {foo=READ}
|
||||
mark(println(foo))
|
||||
magic[UNRESOLVED_CALL](println(foo)|<v5>, !<v6>) -> <v7>
|
||||
3 jmp(L3)
|
||||
L3 [afterCatches]:
|
||||
2 merge(try { foo = 2 throw RuntimeException() } catch (e: Throwable) { println(foo) }|!<v3>, <v7>) -> <v8> INIT: in: {foo=ID} out: {foo=ID}
|
||||
L1:
|
||||
1 <END> INIT: in: {} out: {}
|
||||
error:
|
||||
<ERROR>
|
||||
sink:
|
||||
<SINK> USE: in: {} out: {}
|
||||
=====================
|
||||
@@ -0,0 +1,9 @@
|
||||
fun f() {
|
||||
var foo = 1
|
||||
try {
|
||||
foo = 2
|
||||
throw RuntimeException()
|
||||
} catch (e: Throwable) {
|
||||
println(foo)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
== f ==
|
||||
fun f() {
|
||||
var foo = 1
|
||||
try {
|
||||
foo = 2
|
||||
throw RuntimeException()
|
||||
} catch (e: Throwable) {
|
||||
println(foo)
|
||||
}
|
||||
}
|
||||
---------------------
|
||||
<v4>: {<: Throwable} NEW: magic[FAKE_INITIALIZER](e: Throwable) -> <v4>
|
||||
1 <v0>: Int NEW: r(1) -> <v0>
|
||||
2 <v1>: Int NEW: r(2) -> <v1>
|
||||
RuntimeException() <v2>: {<: Throwable} NEW: call(RuntimeException(), <init>) -> <v2>
|
||||
throw RuntimeException() !<v3>: *
|
||||
{ foo = 2 throw RuntimeException() } !<v3>: * COPY
|
||||
println !<v6>: *
|
||||
foo <v5>: * NEW: r(foo) -> <v5>
|
||||
println(foo) <v7>: * NEW: magic[UNRESOLVED_CALL](println(foo)|<v5>, !<v6>) -> <v7>
|
||||
{ println(foo) } <v7>: * COPY
|
||||
try { foo = 2 throw RuntimeException() } catch (e: Throwable) { println(foo) } <v8>: * NEW: merge(try { foo = 2 throw RuntimeException() } catch (e: Throwable) { println(foo) }|!<v3>, <v7>) -> <v8>
|
||||
{ var foo = 1 try { foo = 2 throw RuntimeException() } catch (e: Throwable) { println(foo) } } <v8>: * COPY
|
||||
=====================
|
||||
+12
-11
@@ -11,7 +11,7 @@ fun test5() {
|
||||
}
|
||||
---------------------
|
||||
L0:
|
||||
1 <START> INIT: in: {} out: {} USE: in: {} out: {}
|
||||
1 <START> INIT: in: {} out: {} USE: in: {} out: {}
|
||||
2 mark({ var a: Int try { a = 3 } finally { a = 5 } a.hashCode() })
|
||||
v(var a: Int) INIT: in: {} out: {a=D}
|
||||
mark(try { a = 3 } finally { a = 5 }) INIT: in: {a=D} out: {a=D}
|
||||
@@ -19,22 +19,23 @@ L0:
|
||||
3 mark({ a = 3 })
|
||||
r(3) -> <v0>
|
||||
w(a|<v0>) INIT: in: {a=D} out: {a=ID}
|
||||
2 jmp(L3) INIT: in: {a=ID} out: {a=ID} USE: in: {a=WRITTEN_AFTER_READ} out: {a=WRITTEN_AFTER_READ}
|
||||
2 jmp?(L2) INIT: in: {a=ID} out: {a=ID}
|
||||
jmp(L3) USE: in: {a=WRITTEN_AFTER_READ} out: {a=WRITTEN_AFTER_READ}
|
||||
L2 [onExceptionToFinallyBlock]:
|
||||
L4 [start finally]:
|
||||
3 mark({ a = 5 }) INIT: in: {a=D} out: {a=D}
|
||||
r(5) -> <v2> USE: in: {a=ONLY_WRITTEN_NEVER_READ} out: {a=ONLY_WRITTEN_NEVER_READ}
|
||||
w(a|<v2>) INIT: in: {a=D} out: {a=ID} USE: in: {} out: {a=ONLY_WRITTEN_NEVER_READ}
|
||||
3 mark({ a = 5 }) INIT: in: {a=I?D} out: {a=I?D}
|
||||
r(5) -> <v2> USE: in: {a=ONLY_WRITTEN_NEVER_READ} out: {a=ONLY_WRITTEN_NEVER_READ}
|
||||
w(a|<v2>) INIT: in: {a=I?D} out: {a=ID} USE: in: {} out: {a=ONLY_WRITTEN_NEVER_READ}
|
||||
L5 [finish finally]:
|
||||
2 jmp(error) INIT: in: {a=ID} out: {a=ID} USE: in: {} out: {}
|
||||
2 jmp(error) INIT: in: {a=ID} out: {a=ID} USE: in: {} out: {}
|
||||
L3 [skipFinallyToErrorBlock]:
|
||||
L6 [copy of L2, onExceptionToFinallyBlock]:
|
||||
3 mark({ a = 5 })
|
||||
r(5) -> <v2> USE: in: {a=WRITTEN_AFTER_READ} out: {a=WRITTEN_AFTER_READ}
|
||||
w(a|<v2>) USE: in: {a=READ} out: {a=WRITTEN_AFTER_READ}
|
||||
r(5) -> <v2> USE: in: {a=WRITTEN_AFTER_READ} out: {a=WRITTEN_AFTER_READ}
|
||||
w(a|<v2>) USE: in: {a=READ} out: {a=WRITTEN_AFTER_READ}
|
||||
2 merge(try { a = 3 } finally { a = 5 }|!<v1>) -> <v4>
|
||||
mark(a.hashCode()) USE: in: {a=READ} out: {a=READ}
|
||||
r(a) -> <v5> USE: in: {} out: {a=READ}
|
||||
mark(a.hashCode()) USE: in: {a=READ} out: {a=READ}
|
||||
r(a) -> <v5> USE: in: {} out: {a=READ}
|
||||
mark(hashCode())
|
||||
call(hashCode(), hashCode|<v5>) -> <v6>
|
||||
L1:
|
||||
@@ -42,5 +43,5 @@ L1:
|
||||
error:
|
||||
<ERROR>
|
||||
sink:
|
||||
<SINK> USE: in: {} out: {}
|
||||
<SINK> USE: in: {} out: {}
|
||||
=====================
|
||||
|
||||
@@ -24,7 +24,9 @@ L0:
|
||||
3 mark({ foo() })
|
||||
mark(foo())
|
||||
call(foo(), foo) -> <v1>
|
||||
2 jmp(L4) USE: in: {} out: {}
|
||||
2 jmp?(L2)
|
||||
jmp?(L3)
|
||||
jmp(L4) USE: in: {} out: {}
|
||||
L2 [onException]:
|
||||
3 v(e: Exception) INIT: in: {} out: {e=D}
|
||||
magic[FAKE_INITIALIZER](e: Exception) -> <v2> INIT: in: {e=D} out: {e=D}
|
||||
@@ -59,4 +61,4 @@ error:
|
||||
<ERROR>
|
||||
sink:
|
||||
<SINK> USE: in: {} out: {}
|
||||
=====================
|
||||
=====================
|
||||
|
||||
+65
-35
@@ -14,10 +14,11 @@ L0:
|
||||
jmp?(L2) NEXT:[mark({ 2 }), mark({ 1 })]
|
||||
3 mark({ 1 })
|
||||
r(1) -> <v0>
|
||||
2 jmp(L3) NEXT:[mark({ 2 })]
|
||||
2 jmp?(L2) NEXT:[mark({ 2 }), jmp(L3)]
|
||||
jmp(L3) NEXT:[mark({ 2 })]
|
||||
L2 [onExceptionToFinallyBlock]:
|
||||
L4 [start finally]:
|
||||
3 mark({ 2 }) PREV:[jmp?(L2)]
|
||||
3 mark({ 2 }) PREV:[jmp?(L2), jmp?(L2)]
|
||||
r(2) -> <v1>
|
||||
L5 [finish finally]:
|
||||
2 jmp(error) NEXT:[<ERROR>]
|
||||
@@ -59,6 +60,7 @@ L0:
|
||||
call(2 > 3, compareTo|<v1>, <v2>) -> <v3>
|
||||
jf(L3|<v3>) NEXT:[read (Unit), mark({ return })]
|
||||
4 mark({ return })
|
||||
jmp?(L2) NEXT:[mark({ 2 }), mark({ 2 })]
|
||||
L4 [start finally]:
|
||||
5 mark({ 2 })
|
||||
r(2) -> <v4>
|
||||
@@ -69,9 +71,10 @@ L3 [else branch]:
|
||||
read (Unit) PREV:[jf(L3|<v3>)]
|
||||
L6 ['if' expression result]:
|
||||
merge(if (2 > 3) { return }|!<v5>) -> <v6>
|
||||
2 jmp(L7) NEXT:[mark({ 2 })]
|
||||
2 jmp?(L2) NEXT:[mark({ 2 }), jmp(L7)]
|
||||
jmp(L7) NEXT:[mark({ 2 })]
|
||||
L2 [onExceptionToFinallyBlock]:
|
||||
5 mark({ 2 }) PREV:[jmp?(L2)]
|
||||
5 mark({ 2 }) PREV:[jmp?(L2), jmp?(L2), jmp?(L2)]
|
||||
r(2) -> <v4>
|
||||
2 jmp(error) NEXT:[<ERROR>]
|
||||
L7 [skipFinallyToErrorBlock]:
|
||||
@@ -112,10 +115,11 @@ L0:
|
||||
d({ -> if (2 > 3) { return@l } }) NEXT:[<SINK>]
|
||||
L3 [after local declaration]:
|
||||
r({ -> if (2 > 3) { return@l } }) -> <v1> PREV:[jmp?(L3)]
|
||||
2 jmp(L8) NEXT:[mark({ 2 })]
|
||||
2 jmp?(L2) NEXT:[mark({ 2 }), jmp(L8)]
|
||||
jmp(L8) NEXT:[mark({ 2 })]
|
||||
L2 [onExceptionToFinallyBlock]:
|
||||
L9 [start finally]:
|
||||
3 mark({ 2 }) PREV:[jmp?(L2)]
|
||||
3 mark({ 2 }) PREV:[jmp?(L2), jmp?(L2)]
|
||||
r(2) -> <v2>
|
||||
L10 [finish finally]:
|
||||
2 jmp(error) NEXT:[<ERROR>]
|
||||
@@ -217,6 +221,7 @@ L3:
|
||||
call(2 > 3, compareTo|<v1>, <v2>) -> <v3>
|
||||
jf(L6|<v3>) NEXT:[read (Unit), mark({ return@l })]
|
||||
6 mark({ return@l })
|
||||
jmp?(L5) NEXT:[mark({ 2 }), mark({ 2 })]
|
||||
L7 [start finally]:
|
||||
7 mark({ 2 })
|
||||
r(2) -> <v4>
|
||||
@@ -227,9 +232,10 @@ L6 [else branch]:
|
||||
read (Unit) PREV:[jf(L6|<v3>)]
|
||||
L9 ['if' expression result]:
|
||||
merge(if (2 > 3) { return@l }|!<v5>) -> <v6>
|
||||
4 jmp(L10) NEXT:[mark({ 2 })]
|
||||
4 jmp?(L5) NEXT:[mark({ 2 }), jmp(L10)]
|
||||
jmp(L10) NEXT:[mark({ 2 })]
|
||||
L5 [onExceptionToFinallyBlock]:
|
||||
7 mark({ 2 }) PREV:[jmp?(L5)]
|
||||
7 mark({ 2 }) PREV:[jmp?(L5), jmp?(L5), jmp?(L5)]
|
||||
r(2) -> <v4>
|
||||
4 jmp(error) NEXT:[<ERROR>]
|
||||
L10 [skipFinallyToErrorBlock]:
|
||||
@@ -279,6 +285,7 @@ L4 [body entry point]:
|
||||
call(2 > 3, compareTo|<v3>, <v4>) -> <v5>
|
||||
jf(L8|<v5>) NEXT:[read (Unit), mark({ break@l })]
|
||||
5 mark({ break@l })
|
||||
jmp?(L7) NEXT:[mark({ 2 }), mark({ 2 })]
|
||||
L9 [start finally]:
|
||||
6 mark({ 2 })
|
||||
r(2) -> <v6>
|
||||
@@ -289,9 +296,10 @@ L8 [else branch]:
|
||||
read (Unit) PREV:[jf(L8|<v5>)]
|
||||
L11 ['if' expression result]:
|
||||
merge(if (2 > 3) { break@l }|!<v7>) -> <v8>
|
||||
3 jmp(L12) NEXT:[mark({ 2 })]
|
||||
3 jmp?(L7) NEXT:[mark({ 2 }), jmp(L12)]
|
||||
jmp(L12) NEXT:[mark({ 2 })]
|
||||
L7 [onExceptionToFinallyBlock]:
|
||||
6 mark({ 2 }) PREV:[jmp?(L7)]
|
||||
6 mark({ 2 }) PREV:[jmp?(L7), jmp?(L7), jmp?(L7)]
|
||||
r(2) -> <v6>
|
||||
3 jmp(error) NEXT:[<ERROR>]
|
||||
L12 [skipFinallyToErrorBlock]:
|
||||
@@ -357,10 +365,11 @@ L4 [loop exit point]:
|
||||
L6 [body exit point]:
|
||||
read (Unit) PREV:[jmp(L4)]
|
||||
r(5) -> <v9>
|
||||
2 jmp(L10) NEXT:[mark({ 2 })]
|
||||
2 jmp?(L2) NEXT:[mark({ 2 }), jmp(L10)]
|
||||
jmp(L10) NEXT:[mark({ 2 })]
|
||||
L2 [onExceptionToFinallyBlock]:
|
||||
L11 [start finally]:
|
||||
3 mark({ 2 }) PREV:[jmp?(L2)]
|
||||
3 mark({ 2 }) PREV:[jmp?(L2), jmp?(L2)]
|
||||
r(2) -> <v10>
|
||||
L12 [finish finally]:
|
||||
2 jmp(error) NEXT:[<ERROR>]
|
||||
@@ -422,10 +431,11 @@ L9 ['if' expression result]:
|
||||
L4 [loop exit point]:
|
||||
L6 [body exit point]:
|
||||
read (Unit) PREV:[jmp(L4)]
|
||||
2 jmp(L10) NEXT:[mark({ 2 })]
|
||||
2 jmp?(L2) NEXT:[mark({ 2 }), jmp(L10)]
|
||||
jmp(L10) NEXT:[mark({ 2 })]
|
||||
L2 [onExceptionToFinallyBlock]:
|
||||
L11 [start finally]:
|
||||
3 mark({ 2 }) PREV:[jmp?(L2)]
|
||||
3 mark({ 2 }) PREV:[jmp?(L2), jmp?(L2)]
|
||||
r(2) -> <v9>
|
||||
L12 [finish finally]:
|
||||
2 jmp(error) NEXT:[<ERROR>]
|
||||
@@ -486,6 +496,7 @@ L4 [body entry point]:
|
||||
call(2 > 3, compareTo|<v6>, <v7>) -> <v8>
|
||||
jf(L8|<v8>) NEXT:[read (Unit), mark({ continue@l })]
|
||||
6 mark({ continue@l })
|
||||
jmp?(L7) NEXT:[mark({ 2 }), mark({ 2 })]
|
||||
L9 [start finally]:
|
||||
7 mark({ 2 })
|
||||
r(2) -> <v9>
|
||||
@@ -496,9 +507,10 @@ L8 [else branch]:
|
||||
read (Unit) PREV:[jf(L8|<v8>)]
|
||||
L11 ['if' expression result]:
|
||||
merge(if (2 > 3) { continue@l }|!<v10>) -> <v11>
|
||||
4 jmp(L12) NEXT:[mark({ 2 })]
|
||||
4 jmp?(L7) NEXT:[mark({ 2 }), jmp(L12)]
|
||||
jmp(L12) NEXT:[mark({ 2 })]
|
||||
L7 [onExceptionToFinallyBlock]:
|
||||
7 mark({ 2 }) PREV:[jmp?(L7)]
|
||||
7 mark({ 2 }) PREV:[jmp?(L7), jmp?(L7), jmp?(L7)]
|
||||
r(2) -> <v9>
|
||||
4 jmp(error) NEXT:[<ERROR>]
|
||||
L12 [skipFinallyToErrorBlock]:
|
||||
@@ -573,10 +585,11 @@ L4 [loop exit point]:
|
||||
L6 [body exit point]:
|
||||
read (Unit) PREV:[jmp?(L4)]
|
||||
3 r(5) -> <v12>
|
||||
2 jmp(L10) NEXT:[mark({ 2 })]
|
||||
2 jmp?(L2) NEXT:[mark({ 2 }), jmp(L10)]
|
||||
jmp(L10) NEXT:[mark({ 2 })]
|
||||
L2 [onExceptionToFinallyBlock]:
|
||||
L11 [start finally]:
|
||||
3 mark({ 2 }) PREV:[jmp?(L2)]
|
||||
3 mark({ 2 }) PREV:[jmp?(L2), jmp?(L2)]
|
||||
r(2) -> <v13>
|
||||
L12 [finish finally]:
|
||||
2 jmp(error) NEXT:[<ERROR>]
|
||||
@@ -647,10 +660,11 @@ L9 ['if' expression result]:
|
||||
L4 [loop exit point]:
|
||||
L6 [body exit point]:
|
||||
read (Unit) PREV:[jmp?(L4)]
|
||||
2 jmp(L10) NEXT:[mark({ 2 })]
|
||||
2 jmp?(L2) NEXT:[mark({ 2 }), jmp(L10)]
|
||||
jmp(L10) NEXT:[mark({ 2 })]
|
||||
L2 [onExceptionToFinallyBlock]:
|
||||
L11 [start finally]:
|
||||
3 mark({ 2 }) PREV:[jmp?(L2)]
|
||||
3 mark({ 2 }) PREV:[jmp?(L2), jmp?(L2)]
|
||||
r(2) -> <v12>
|
||||
L12 [finish finally]:
|
||||
2 jmp(error) NEXT:[<ERROR>]
|
||||
@@ -682,6 +696,7 @@ L0:
|
||||
mark(try { return 1 } finally { return 2 })
|
||||
jmp?(L2) NEXT:[mark({ return 2 }), mark({ return 1 })]
|
||||
3 mark({ return 1 })
|
||||
jmp?(L2) NEXT:[mark({ return 2 }), r(1) -> <v0>]
|
||||
r(1) -> <v0>
|
||||
L3 [start finally]:
|
||||
4 mark({ return 2 })
|
||||
@@ -689,9 +704,10 @@ L3 [start finally]:
|
||||
ret(*|<v1>) L1 NEXT:[<END>]
|
||||
L4 [finish finally]:
|
||||
- 3 ret(*|<v0>) L1 NEXT:[<END>] PREV:[]
|
||||
- 2 jmp(L5) NEXT:[mark({ return 2 })] PREV:[]
|
||||
- 2 jmp?(L2) NEXT:[mark({ return 2 }), jmp(L5)] PREV:[]
|
||||
- jmp(L5) NEXT:[mark({ return 2 })] PREV:[]
|
||||
L2 [onExceptionToFinallyBlock]:
|
||||
4 mark({ return 2 }) PREV:[jmp?(L2)]
|
||||
4 mark({ return 2 }) PREV:[jmp?(L2), jmp?(L2)]
|
||||
r(2) -> <v1>
|
||||
ret(*|<v1>) L1 NEXT:[<END>]
|
||||
- 2 jmp(error) NEXT:[<ERROR>] PREV:[]
|
||||
@@ -723,6 +739,7 @@ L0:
|
||||
mark(try { return 1 } finally { doSmth(3) })
|
||||
jmp?(L2) NEXT:[mark({ doSmth(3) }), mark({ return 1 })]
|
||||
3 mark({ return 1 })
|
||||
jmp?(L2) NEXT:[mark({ doSmth(3) }), r(1) -> <v0>]
|
||||
r(1) -> <v0>
|
||||
L3 [start finally]:
|
||||
4 mark({ doSmth(3) })
|
||||
@@ -731,9 +748,10 @@ L3 [start finally]:
|
||||
call(doSmth(3), doSmth|<v1>) -> <v2>
|
||||
L4 [finish finally]:
|
||||
3 ret(*|<v0>) L1 NEXT:[<END>]
|
||||
- 2 jmp(L5) NEXT:[mark({ doSmth(3) })] PREV:[]
|
||||
- 2 jmp?(L2) NEXT:[mark({ doSmth(3) }), jmp(L5)] PREV:[]
|
||||
- jmp(L5) NEXT:[mark({ doSmth(3) })] PREV:[]
|
||||
L2 [onExceptionToFinallyBlock]:
|
||||
4 mark({ doSmth(3) }) PREV:[jmp?(L2)]
|
||||
4 mark({ doSmth(3) }) PREV:[jmp?(L2), jmp?(L2)]
|
||||
r(3) -> <v1>
|
||||
mark(doSmth(3))
|
||||
call(doSmth(3), doSmth|<v1>) -> <v2>
|
||||
@@ -771,6 +789,8 @@ L0:
|
||||
jmp?(L2) NEXT:[v(e: UnsupportedOperationException), jmp?(L3)]
|
||||
jmp?(L3) NEXT:[mark({ doSmth(3) }), mark({ return 1 })]
|
||||
3 mark({ return 1 })
|
||||
jmp?(L2) NEXT:[v(e: UnsupportedOperationException), jmp?(L3)]
|
||||
jmp?(L3) NEXT:[mark({ doSmth(3) }), r(1) -> <v0>]
|
||||
r(1) -> <v0>
|
||||
L4 [start finally]:
|
||||
4 mark({ doSmth(3) })
|
||||
@@ -779,9 +799,11 @@ L4 [start finally]:
|
||||
call(doSmth(3), doSmth|<v1>) -> <v2>
|
||||
L5 [finish finally]:
|
||||
3 ret(*|<v0>) L1 NEXT:[<END>]
|
||||
- 2 jmp(L6) NEXT:[jmp(L7)] PREV:[]
|
||||
- 2 jmp?(L2) NEXT:[v(e: UnsupportedOperationException), jmp?(L3)] PREV:[]
|
||||
- jmp?(L3) NEXT:[mark({ doSmth(3) }), jmp(L6)] PREV:[]
|
||||
- jmp(L6) NEXT:[jmp(L7)] PREV:[]
|
||||
L2 [onException]:
|
||||
3 v(e: UnsupportedOperationException) PREV:[jmp?(L2)]
|
||||
3 v(e: UnsupportedOperationException) PREV:[jmp?(L2), jmp?(L2)]
|
||||
magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> <v4>
|
||||
w(e|<v4>)
|
||||
4 mark({ doSmth(2) })
|
||||
@@ -792,7 +814,7 @@ L2 [onException]:
|
||||
L6 [afterCatches]:
|
||||
2 jmp(L7) NEXT:[mark({ doSmth(3) })]
|
||||
L3 [onExceptionToFinallyBlock]:
|
||||
4 mark({ doSmth(3) }) PREV:[jmp?(L3)]
|
||||
4 mark({ doSmth(3) }) PREV:[jmp?(L3), jmp?(L3)]
|
||||
r(3) -> <v1>
|
||||
mark(doSmth(3))
|
||||
call(doSmth(3), doSmth|<v1>) -> <v2>
|
||||
@@ -826,11 +848,13 @@ L0:
|
||||
mark(try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) })
|
||||
jmp?(L2) NEXT:[v(e: UnsupportedOperationException), mark({ return 1 })]
|
||||
3 mark({ return 1 })
|
||||
jmp?(L2) NEXT:[v(e: UnsupportedOperationException), r(1) -> <v0>]
|
||||
r(1) -> <v0>
|
||||
ret(*|<v0>) L1 NEXT:[<END>]
|
||||
- 2 jmp(L3) NEXT:[merge(try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) }|!<v1>, <v4>) -> <v5>] PREV:[]
|
||||
- 2 jmp?(L2) NEXT:[v(e: UnsupportedOperationException), jmp(L3)] PREV:[]
|
||||
- jmp(L3) NEXT:[merge(try { return 1 } catch (e: UnsupportedOperationException) { doSmth(2) }|!<v1>, <v4>) -> <v5>] PREV:[]
|
||||
L2 [onException]:
|
||||
3 v(e: UnsupportedOperationException) PREV:[jmp?(L2)]
|
||||
3 v(e: UnsupportedOperationException) PREV:[jmp?(L2), jmp?(L2)]
|
||||
magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> <v2>
|
||||
w(e|<v2>)
|
||||
4 mark({ doSmth(2) })
|
||||
@@ -867,6 +891,8 @@ L0:
|
||||
jmp?(L2) NEXT:[v(e: UnsupportedOperationException), jmp?(L3)]
|
||||
jmp?(L3) NEXT:[mark({ doSmth(3) }), mark({ return 1 })]
|
||||
3 mark({ return 1 })
|
||||
jmp?(L2) NEXT:[v(e: UnsupportedOperationException), jmp?(L3)]
|
||||
jmp?(L3) NEXT:[mark({ doSmth(3) }), r(1) -> <v0>]
|
||||
r(1) -> <v0>
|
||||
L4 [start finally]:
|
||||
4 mark({ doSmth(3) })
|
||||
@@ -875,9 +901,11 @@ L4 [start finally]:
|
||||
call(doSmth(3), doSmth|<v1>) -> <v2>
|
||||
L5 [finish finally]:
|
||||
3 ret(*|<v0>) L1 NEXT:[<END>]
|
||||
- 2 jmp(L6) NEXT:[jmp(L7)] PREV:[]
|
||||
- 2 jmp?(L2) NEXT:[v(e: UnsupportedOperationException), jmp?(L3)] PREV:[]
|
||||
- jmp?(L3) NEXT:[mark({ doSmth(3) }), jmp(L6)] PREV:[]
|
||||
- jmp(L6) NEXT:[jmp(L7)] PREV:[]
|
||||
L2 [onException]:
|
||||
3 v(e: UnsupportedOperationException) PREV:[jmp?(L2)]
|
||||
3 v(e: UnsupportedOperationException) PREV:[jmp?(L2), jmp?(L2)]
|
||||
magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> <v4>
|
||||
w(e|<v4>)
|
||||
4 mark({ return 2 })
|
||||
@@ -891,7 +919,7 @@ L2 [onException]:
|
||||
L6 [afterCatches]:
|
||||
- 2 jmp(L7) NEXT:[mark({ doSmth(3) })] PREV:[]
|
||||
L3 [onExceptionToFinallyBlock]:
|
||||
4 mark({ doSmth(3) }) PREV:[jmp?(L3)]
|
||||
4 mark({ doSmth(3) }) PREV:[jmp?(L3), jmp?(L3)]
|
||||
r(3) -> <v1>
|
||||
mark(doSmth(3))
|
||||
call(doSmth(3), doSmth|<v1>) -> <v2>
|
||||
@@ -932,9 +960,11 @@ L0:
|
||||
r(1) -> <v0>
|
||||
mark(doSmth(1))
|
||||
call(doSmth(1), doSmth|<v0>) -> <v1>
|
||||
2 jmp(L4) NEXT:[jmp(L7)]
|
||||
2 jmp?(L2) NEXT:[v(e: UnsupportedOperationException), jmp?(L3)]
|
||||
jmp?(L3) NEXT:[mark({ doSmth(3) }), jmp(L4)]
|
||||
jmp(L4) NEXT:[jmp(L7)]
|
||||
L2 [onException]:
|
||||
3 v(e: UnsupportedOperationException) PREV:[jmp?(L2)]
|
||||
3 v(e: UnsupportedOperationException) PREV:[jmp?(L2), jmp?(L2)]
|
||||
magic[FAKE_INITIALIZER](e: UnsupportedOperationException) -> <v2>
|
||||
w(e|<v2>)
|
||||
4 mark({ return 2 })
|
||||
@@ -950,7 +980,7 @@ L6 [finish finally]:
|
||||
L4 [afterCatches]:
|
||||
2 jmp(L7) NEXT:[mark({ doSmth(3) })] PREV:[jmp(L4)]
|
||||
L3 [onExceptionToFinallyBlock]:
|
||||
5 mark({ doSmth(3) }) PREV:[jmp?(L3)]
|
||||
5 mark({ doSmth(3) }) PREV:[jmp?(L3), jmp?(L3)]
|
||||
r(3) -> <v4>
|
||||
mark(doSmth(3))
|
||||
call(doSmth(3), doSmth|<v4>) -> <v5>
|
||||
|
||||
@@ -79,9 +79,11 @@ L0:
|
||||
3 mark({ doSmth() })
|
||||
mark(doSmth())
|
||||
call(doSmth(), doSmth) -> <v0>
|
||||
2 jmp(L4) NEXT:[jmp(L6)]
|
||||
2 jmp?(L2) NEXT:[jmp?(L5), jmp?(L3)]
|
||||
jmp?(L3) NEXT:[mark({ return 1 }), jmp(L4)]
|
||||
jmp(L4) NEXT:[jmp(L6)]
|
||||
L2 [onException]:
|
||||
jmp?(L5) NEXT:[v(e: Exception), v(e: NullPointerException)] PREV:[jmp?(L2)]
|
||||
jmp?(L5) NEXT:[v(e: Exception), v(e: NullPointerException)] PREV:[jmp?(L2), jmp?(L2)]
|
||||
3 v(e: NullPointerException)
|
||||
magic[FAKE_INITIALIZER](e: NullPointerException) -> <v1>
|
||||
w(e|<v1>)
|
||||
@@ -101,7 +103,7 @@ L4 [afterCatches]:
|
||||
2 jmp(L6) NEXT:[mark({ return 1 })] PREV:[jmp(L4), jmp(L4), jmp(L4)]
|
||||
L3 [onExceptionToFinallyBlock]:
|
||||
L7 [start finally]:
|
||||
3 mark({ return 1 }) PREV:[jmp?(L3)]
|
||||
3 mark({ return 1 }) PREV:[jmp?(L3), jmp?(L3)]
|
||||
r(1) -> <v5>
|
||||
ret(*|<v5>) L1 NEXT:[<END>]
|
||||
L8 [finish finally]:
|
||||
@@ -155,9 +157,11 @@ L4 [body entry point]:
|
||||
4 mark({ doSmth() })
|
||||
mark(doSmth())
|
||||
call(doSmth(), doSmth) -> <v1>
|
||||
3 jmp(L9) NEXT:[jmp(L11)]
|
||||
3 jmp?(L7) NEXT:[jmp?(L10), jmp?(L8)]
|
||||
jmp?(L8) NEXT:[mark({ if (cond()) return else continue }), jmp(L9)]
|
||||
jmp(L9) NEXT:[jmp(L11)]
|
||||
L7 [onException]:
|
||||
jmp?(L10) NEXT:[v(e: Exception), v(e: NullPointerException)] PREV:[jmp?(L7)]
|
||||
jmp?(L10) NEXT:[v(e: Exception), v(e: NullPointerException)] PREV:[jmp?(L7), jmp?(L7)]
|
||||
4 v(e: NullPointerException)
|
||||
magic[FAKE_INITIALIZER](e: NullPointerException) -> <v2>
|
||||
w(e|<v2>)
|
||||
@@ -177,7 +181,7 @@ L9 [afterCatches]:
|
||||
3 jmp(L11) NEXT:[mark({ if (cond()) return else continue })] PREV:[jmp(L9), jmp(L9), jmp(L9)]
|
||||
L8 [onExceptionToFinallyBlock]:
|
||||
L12 [start finally]:
|
||||
4 mark({ if (cond()) return else continue }) PREV:[jmp?(L8)]
|
||||
4 mark({ if (cond()) return else continue }) PREV:[jmp?(L8), jmp?(L8)]
|
||||
mark(if (cond()) return else continue)
|
||||
mark(cond())
|
||||
call(cond(), cond) -> <v6>
|
||||
@@ -240,9 +244,11 @@ L0:
|
||||
3 mark({ doSmth() })
|
||||
mark(doSmth())
|
||||
call(doSmth(), doSmth) -> <v0>
|
||||
2 jmp(L4) NEXT:[jmp(L6)]
|
||||
2 jmp?(L2) NEXT:[jmp?(L5), jmp?(L3)]
|
||||
jmp?(L3) NEXT:[mark({ while (cond()); }), jmp(L4)]
|
||||
jmp(L4) NEXT:[jmp(L6)]
|
||||
L2 [onException]:
|
||||
jmp?(L5) NEXT:[v(e: Exception), v(e: NullPointerException)] PREV:[jmp?(L2)]
|
||||
jmp?(L5) NEXT:[v(e: Exception), v(e: NullPointerException)] PREV:[jmp?(L2), jmp?(L2)]
|
||||
3 v(e: NullPointerException)
|
||||
magic[FAKE_INITIALIZER](e: NullPointerException) -> <v1>
|
||||
w(e|<v1>)
|
||||
@@ -262,7 +268,7 @@ L4 [afterCatches]:
|
||||
2 jmp(L6) NEXT:[mark({ while (cond()); })] PREV:[jmp(L4), jmp(L4), jmp(L4)]
|
||||
L3 [onExceptionToFinallyBlock]:
|
||||
L7 [start finally]:
|
||||
3 mark({ while (cond()); }) PREV:[jmp?(L3)]
|
||||
3 mark({ while (cond()); }) PREV:[jmp?(L3), jmp?(L3)]
|
||||
L8 [loop entry point]:
|
||||
L12 [condition entry point]:
|
||||
mark(cond()) PREV:[mark({ while (cond()); }), jmp(L8)]
|
||||
@@ -320,10 +326,11 @@ L0:
|
||||
3 mark({ doSmth() })
|
||||
mark(doSmth())
|
||||
call(doSmth(), doSmth) -> <v1>
|
||||
2 jmp(L3) NEXT:[mark({ if(list != null) { } })]
|
||||
2 jmp?(L2) NEXT:[mark({ if(list != null) { } }), jmp(L3)]
|
||||
jmp(L3) NEXT:[mark({ if(list != null) { } })]
|
||||
L2 [onExceptionToFinallyBlock]:
|
||||
L4 [start finally]:
|
||||
3 mark({ if(list != null) { } }) PREV:[jmp?(L2)]
|
||||
3 mark({ if(list != null) { } }) PREV:[jmp?(L2), jmp?(L2)]
|
||||
mark(if(list != null) { })
|
||||
r(list) -> <v2>
|
||||
r(null) -> <v3>
|
||||
|
||||
+76
-4
@@ -33,6 +33,7 @@ L12 [condition entry point]:
|
||||
magic[VALUE_CONSUMER](true|<v2>) -> <v3>
|
||||
L10 [body entry point]:
|
||||
5 mark({ continue@outer })
|
||||
jmp?(L7) NEXT:[mark({ break }), mark({ break })]
|
||||
L13 [start finally]:
|
||||
6 mark({ break })
|
||||
jmp(L3) NEXT:[read (Unit)]
|
||||
@@ -42,9 +43,10 @@ L14 [finish finally]:
|
||||
L9 [loop exit point]:
|
||||
L11 [body exit point]:
|
||||
- read (Unit) PREV:[]
|
||||
- 3 jmp(L15) NEXT:[mark({ break })] PREV:[]
|
||||
- 3 jmp?(L7) NEXT:[mark({ break }), jmp(L15)] PREV:[]
|
||||
- jmp(L15) NEXT:[mark({ break })] PREV:[]
|
||||
L7 [onExceptionToFinallyBlock]:
|
||||
6 mark({ break }) PREV:[jmp?(L7)]
|
||||
6 mark({ break }) PREV:[jmp?(L7), jmp?(L7)]
|
||||
jmp(L3) NEXT:[read (Unit)]
|
||||
- 3 jmp(error) NEXT:[<ERROR>] PREV:[]
|
||||
L15 [skipFinallyToErrorBlock]:
|
||||
@@ -100,6 +102,7 @@ L12 [condition entry point]:
|
||||
magic[VALUE_CONSUMER](true|<v2>) -> <v3>
|
||||
L10 [body entry point]:
|
||||
5 mark({ continue@outer })
|
||||
jmp?(L7) NEXT:[mark({ return "OK" }), mark({ return "OK" })]
|
||||
L13 [start finally]:
|
||||
6 mark({ return "OK" })
|
||||
mark("OK")
|
||||
@@ -111,9 +114,10 @@ L14 [finish finally]:
|
||||
L9 [loop exit point]:
|
||||
L11 [body exit point]:
|
||||
- read (Unit) PREV:[]
|
||||
- 3 jmp(L15) NEXT:[mark({ return "OK" })] PREV:[]
|
||||
- 3 jmp?(L7) NEXT:[mark({ return "OK" }), jmp(L15)] PREV:[]
|
||||
- jmp(L15) NEXT:[mark({ return "OK" })] PREV:[]
|
||||
L7 [onExceptionToFinallyBlock]:
|
||||
6 mark({ return "OK" }) PREV:[jmp?(L7)]
|
||||
6 mark({ return "OK" }) PREV:[jmp?(L7), jmp?(L7)]
|
||||
mark("OK")
|
||||
r("OK") -> <v4>
|
||||
ret(*|<v4>) L1 NEXT:[<END>]
|
||||
@@ -135,3 +139,71 @@ error:
|
||||
sink:
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== baz ==
|
||||
fun baz(): String {
|
||||
outer@while (true) {
|
||||
try {
|
||||
inner@while (true) {
|
||||
continue@inner
|
||||
}
|
||||
} finally {
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
---------------------
|
||||
L0:
|
||||
1 <START>
|
||||
2 mark({ outer@while (true) { try { inner@while (true) { continue@inner } } finally { return "OK" } } })
|
||||
mark(outer@while (true) { try { inner@while (true) { continue@inner } } finally { return "OK" } })
|
||||
L2 [loop entry point]:
|
||||
L6 [condition entry point]:
|
||||
r(true) -> <v0>
|
||||
mark(while (true) { try { inner@while (true) { continue@inner } } finally { return "OK" } })
|
||||
magic[VALUE_CONSUMER](true|<v0>) -> <v1>
|
||||
L4 [body entry point]:
|
||||
3 mark({ try { inner@while (true) { continue@inner } } finally { return "OK" } })
|
||||
mark(try { inner@while (true) { continue@inner } } finally { return "OK" })
|
||||
jmp?(L7) NEXT:[mark({ return "OK" }), mark({ inner@while (true) { continue@inner } })]
|
||||
4 mark({ inner@while (true) { continue@inner } })
|
||||
mark(inner@while (true) { continue@inner })
|
||||
L8 [loop entry point]:
|
||||
L12 [condition entry point]:
|
||||
r(true) -> <v2> PREV:[mark(inner@while (true) { continue@inner }), jmp(L12)]
|
||||
mark(while (true) { continue@inner })
|
||||
magic[VALUE_CONSUMER](true|<v2>) -> <v3>
|
||||
L10 [body entry point]:
|
||||
5 mark({ continue@inner })
|
||||
jmp(L12) NEXT:[r(true) -> <v2>]
|
||||
- 4 jmp(L8) NEXT:[r(true) -> <v2>] PREV:[]
|
||||
L9 [loop exit point]:
|
||||
L11 [body exit point]:
|
||||
- read (Unit) PREV:[]
|
||||
- 3 jmp?(L7) NEXT:[mark({ return "OK" }), jmp(L13)] PREV:[]
|
||||
- jmp(L13) NEXT:[mark({ return "OK" })] PREV:[]
|
||||
L7 [onExceptionToFinallyBlock]:
|
||||
L14 [start finally]:
|
||||
4 mark({ return "OK" }) PREV:[jmp?(L7)]
|
||||
mark("OK")
|
||||
r("OK") -> <v6>
|
||||
ret(*|<v6>) L1 NEXT:[<END>]
|
||||
L15 [finish finally]:
|
||||
- 3 jmp(error) NEXT:[<ERROR>] PREV:[]
|
||||
L13 [skipFinallyToErrorBlock]:
|
||||
L16 [copy of L7, onExceptionToFinallyBlock]:
|
||||
- 4 mark({ return "OK" }) PREV:[]
|
||||
- mark("OK") PREV:[]
|
||||
- r("OK") -> <v6> PREV:[]
|
||||
- ret(*|<v6>) L1 NEXT:[<END>] PREV:[]
|
||||
- 3 merge(try { inner@while (true) { continue@inner } } finally { return "OK" }|!<v5>) -> <v8> PREV:[]
|
||||
- 2 jmp(L2) NEXT:[r(true) -> <v0>] PREV:[]
|
||||
L3 [loop exit point]:
|
||||
L5 [body exit point]:
|
||||
- read (Unit) PREV:[]
|
||||
L1:
|
||||
1 <END> NEXT:[<SINK>] PREV:[ret(*|<v6>) L1]
|
||||
error:
|
||||
<ERROR> PREV:[]
|
||||
sink:
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
|
||||
@@ -22,3 +22,15 @@ fun bar(): String {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun baz(): String {
|
||||
outer@while (true) {
|
||||
try {
|
||||
inner@while (true) {
|
||||
continue@inner
|
||||
}
|
||||
} finally {
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,3 +61,34 @@ while (true) { try { while (true) { continue@outer } } finally { return "OK" } }
|
||||
outer@while (true) { try { while (true) { continue@outer } } finally { return "OK" } } !<v9>: * COPY
|
||||
{ outer@while (true) { try { while (true) { continue@outer } } finally { return "OK" } } } !<v9>: * COPY
|
||||
=====================
|
||||
== baz ==
|
||||
fun baz(): String {
|
||||
outer@while (true) {
|
||||
try {
|
||||
inner@while (true) {
|
||||
continue@inner
|
||||
}
|
||||
} finally {
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
}
|
||||
---------------------
|
||||
<v1>: * NEW: magic[VALUE_CONSUMER](true|<v0>) -> <v1>
|
||||
<v3>: * NEW: magic[VALUE_CONSUMER](true|<v2>) -> <v3>
|
||||
true <v0>: Boolean NEW: r(true) -> <v0>
|
||||
true <v2>: Boolean NEW: r(true) -> <v2>
|
||||
continue@inner !<v4>: *
|
||||
{ continue@inner } !<v4>: * COPY
|
||||
while (true) { continue@inner } !<v5>: *
|
||||
inner@while (true) { continue@inner } !<v5>: * COPY
|
||||
{ inner@while (true) { continue@inner } } !<v5>: * COPY
|
||||
"OK" <v6>: String NEW: r("OK") -> <v6>
|
||||
return "OK" !<v7>: *
|
||||
{ return "OK" } !<v7>: * COPY
|
||||
try { inner@while (true) { continue@inner } } finally { return "OK" } <v8>: * NEW: merge(try { inner@while (true) { continue@inner } } finally { return "OK" }|!<v5>) -> <v8>
|
||||
{ try { inner@while (true) { continue@inner } } finally { return "OK" } } <v8>: * COPY
|
||||
while (true) { try { inner@while (true) { continue@inner } } finally { return "OK" } } !<v9>: *
|
||||
outer@while (true) { try { inner@while (true) { continue@inner } } finally { return "OK" } } !<v9>: * COPY
|
||||
{ outer@while (true) { try { inner@while (true) { continue@inner } } finally { return "OK" } } } !<v9>: * COPY
|
||||
=====================
|
||||
|
||||
+5
-3
@@ -58,7 +58,8 @@ L0:
|
||||
r(0) -> <v2>
|
||||
mark(n < 0)
|
||||
call(n < 0, compareTo|<v1>, <v2>) -> <v3>
|
||||
jf(L3|<v3>) NEXT:[read (Unit), r(0) -> <v4>]
|
||||
jf(L3|<v3>) NEXT:[read (Unit), jmp?(L2)]
|
||||
jmp?(L2) NEXT:[mark({ for (i in 1..2) { } return bar() }), r(0) -> <v4>]
|
||||
r(0) -> <v4>
|
||||
L4 [start finally]:
|
||||
4 mark({ for (i in 1..2) { } return bar() })
|
||||
@@ -99,9 +100,10 @@ L12 [after local declaration]:
|
||||
r({ return it }) -> <v14> PREV:[jmp?(L12)]
|
||||
mark(let { return it })
|
||||
call(let { return it }, let|<v13>, <v14>) -> <v15>
|
||||
2 jmp(L20) NEXT:[mark({ for (i in 1..2) { } return bar() })]
|
||||
2 jmp?(L2) NEXT:[mark({ for (i in 1..2) { } return bar() }), jmp(L20)]
|
||||
jmp(L20) NEXT:[mark({ for (i in 1..2) { } return bar() })]
|
||||
L2 [onExceptionToFinallyBlock]:
|
||||
4 mark({ for (i in 1..2) { } return bar() }) PREV:[jmp?(L2)]
|
||||
4 mark({ for (i in 1..2) { } return bar() }) PREV:[jmp?(L2), jmp?(L2), jmp?(L2)]
|
||||
5 r(1) -> <v5>
|
||||
r(2) -> <v6>
|
||||
mark(1..2)
|
||||
|
||||
+3
-2
@@ -21,10 +21,11 @@ L0:
|
||||
3 mark({ i = 1 })
|
||||
r(1) -> <v1>
|
||||
w(i|<v1>)
|
||||
2 jmp(L3) NEXT:[mark({ fun bar() {} return i })]
|
||||
2 jmp?(L2) NEXT:[mark({ fun bar() {} return i }), jmp(L3)]
|
||||
jmp(L3) NEXT:[mark({ fun bar() {} return i })]
|
||||
L2 [onExceptionToFinallyBlock]:
|
||||
L4 [start finally]:
|
||||
3 mark({ fun bar() {} return i }) PREV:[jmp?(L2)]
|
||||
3 mark({ fun bar() {} return i }) PREV:[jmp?(L2), jmp?(L2)]
|
||||
jmp?(L5) NEXT:[r(i) -> <v3>, d(fun bar() {})]
|
||||
d(fun bar() {}) NEXT:[<SINK>]
|
||||
L5 [after local declaration]:
|
||||
|
||||
+3
-2
@@ -14,10 +14,11 @@ L0:
|
||||
jmp?(L2) NEXT:[mark({ test() }), mark({ // do nothing })]
|
||||
3 mark({ // do nothing })
|
||||
read (Unit)
|
||||
2 jmp(L3) NEXT:[mark({ test() })]
|
||||
2 jmp?(L2) NEXT:[mark({ test() }), jmp(L3)]
|
||||
jmp(L3) NEXT:[mark({ test() })]
|
||||
L2 [onExceptionToFinallyBlock]:
|
||||
L4 [start finally]:
|
||||
3 mark({ test() }) PREV:[jmp?(L2)]
|
||||
3 mark({ test() }) PREV:[jmp?(L2), jmp?(L2)]
|
||||
mark(test())
|
||||
call(test(), test) -> <v0>
|
||||
L5 [finish finally]:
|
||||
|
||||
@@ -14,10 +14,11 @@ L0:
|
||||
jmp?(L2) NEXT:[mark({ return test() }), mark({ // do nothing })]
|
||||
3 mark({ // do nothing })
|
||||
read (Unit)
|
||||
2 jmp(L3) NEXT:[mark({ return test() })]
|
||||
2 jmp?(L2) NEXT:[mark({ return test() }), jmp(L3)]
|
||||
jmp(L3) NEXT:[mark({ return test() })]
|
||||
L2 [onExceptionToFinallyBlock]:
|
||||
L4 [start finally]:
|
||||
3 mark({ return test() }) PREV:[jmp?(L2)]
|
||||
3 mark({ return test() }) PREV:[jmp?(L2), jmp?(L2)]
|
||||
mark(test())
|
||||
call(test(), test) -> <v0>
|
||||
ret(*|<v0>) L1 NEXT:[<END>]
|
||||
|
||||
+5
-3
@@ -13,12 +13,14 @@ L0:
|
||||
mark(try { return foo() } catch (e: Throwable) { })
|
||||
jmp?(L2) NEXT:[v(e: Throwable), mark({ return foo() })]
|
||||
3 mark({ return foo() })
|
||||
jmp?(L2) NEXT:[v(e: Throwable), mark(foo())]
|
||||
mark(foo())
|
||||
call(foo(), foo) -> <v0>
|
||||
ret(*|<v0>) L1 NEXT:[<END>]
|
||||
- 2 jmp(L3) NEXT:[merge(try { return foo() } catch (e: Throwable) { }|!<v1>, !<v3>) -> <v4>] PREV:[]
|
||||
- 2 jmp?(L2) NEXT:[v(e: Throwable), jmp(L3)] PREV:[]
|
||||
- jmp(L3) NEXT:[merge(try { return foo() } catch (e: Throwable) { }|!<v1>, !<v3>) -> <v4>] PREV:[]
|
||||
L2 [onException]:
|
||||
3 v(e: Throwable) PREV:[jmp?(L2)]
|
||||
3 v(e: Throwable) PREV:[jmp?(L2), jmp?(L2)]
|
||||
magic[FAKE_INITIALIZER](e: Throwable) -> <v2>
|
||||
w(e|<v2>)
|
||||
4 mark({ })
|
||||
@@ -32,4 +34,4 @@ error:
|
||||
<ERROR> PREV:[]
|
||||
sink:
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
=====================
|
||||
|
||||
@@ -18,9 +18,11 @@ L0:
|
||||
3 mark({ test() })
|
||||
mark(test())
|
||||
call(test(), test) -> <v0>
|
||||
2 jmp(L4) NEXT:[jmp(L5)]
|
||||
2 jmp?(L2) NEXT:[v(any : Exception), jmp?(L3)]
|
||||
jmp?(L3) NEXT:[mark({ test() }), jmp(L4)]
|
||||
jmp(L4) NEXT:[jmp(L5)]
|
||||
L2 [onException]:
|
||||
3 v(any : Exception) PREV:[jmp?(L2)]
|
||||
3 v(any : Exception) PREV:[jmp?(L2), jmp?(L2)]
|
||||
magic[FAKE_INITIALIZER](any : Exception) -> <v1>
|
||||
w(any|<v1>)
|
||||
4 mark({ test() })
|
||||
@@ -31,7 +33,7 @@ L4 [afterCatches]:
|
||||
2 jmp(L5) NEXT:[mark({ test() })] PREV:[jmp(L4), jmp(L4)]
|
||||
L3 [onExceptionToFinallyBlock]:
|
||||
L6 [start finally]:
|
||||
3 mark({ test() }) PREV:[jmp?(L3)]
|
||||
3 mark({ test() }) PREV:[jmp?(L3), jmp?(L3)]
|
||||
mark(test())
|
||||
call(test(), test) -> <v3>
|
||||
L7 [finish finally]:
|
||||
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
// KT-13612 related tests (reassignment in try-catch-finally)
|
||||
|
||||
fun f1() {
|
||||
val n: Int
|
||||
try {
|
||||
<!UNUSED_VALUE!>n =<!> 1
|
||||
throw Exception()
|
||||
}
|
||||
catch (e: Exception) {
|
||||
// KT-13612: reassignment
|
||||
<!VAL_REASSIGNMENT!>n<!> = 2
|
||||
}
|
||||
n.hashCode()
|
||||
}
|
||||
|
||||
fun f2() {
|
||||
val <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>n<!>: Int
|
||||
try {
|
||||
<!UNUSED_VALUE!>n =<!> 1
|
||||
throw Exception()
|
||||
}
|
||||
finally {
|
||||
<!UNUSED_VALUE!><!VAL_REASSIGNMENT!>n<!> =<!> 2
|
||||
}
|
||||
<!UNREACHABLE_CODE!>n.hashCode()<!>
|
||||
}
|
||||
|
||||
fun g1(flag: Boolean) {
|
||||
val n: Int
|
||||
try {
|
||||
if (flag) throw Exception()
|
||||
n = 1
|
||||
}
|
||||
catch (e: Exception) {
|
||||
// KT-13612: ? reassignment or definite assignment ?
|
||||
<!VAL_REASSIGNMENT!>n<!> = 2
|
||||
}
|
||||
n.hashCode()
|
||||
}
|
||||
|
||||
fun g2(flag: Boolean) {
|
||||
val n: Int
|
||||
try {
|
||||
if (flag) throw Exception()
|
||||
<!UNUSED_VALUE!>n =<!> 1
|
||||
}
|
||||
finally {
|
||||
<!VAL_REASSIGNMENT!>n<!> = 2
|
||||
}
|
||||
n.hashCode()
|
||||
}
|
||||
|
||||
fun h1(flag: Boolean) {
|
||||
val n = try {
|
||||
if (flag) throw Exception()
|
||||
1
|
||||
}
|
||||
catch (e: Exception) {
|
||||
2
|
||||
}
|
||||
n.hashCode()
|
||||
}
|
||||
|
||||
fun h2(flag: Boolean) {
|
||||
val n = try {
|
||||
if (flag) throw Exception()
|
||||
1
|
||||
}
|
||||
finally {
|
||||
<!UNUSED_EXPRESSION!>2<!>
|
||||
}
|
||||
n.hashCode()
|
||||
}
|
||||
|
||||
fun j(flag: Boolean) {
|
||||
if (flag) throw Exception()
|
||||
}
|
||||
|
||||
fun k1(flag: Boolean) {
|
||||
val n: Int
|
||||
try {
|
||||
n = 1
|
||||
j(flag)
|
||||
}
|
||||
catch (e: Exception) {
|
||||
// KT-13612: reassignment
|
||||
<!VAL_REASSIGNMENT!>n<!> = 2
|
||||
}
|
||||
n.hashCode()
|
||||
}
|
||||
|
||||
fun k2(flag: Boolean) {
|
||||
val n: Int
|
||||
try {
|
||||
<!UNUSED_VALUE!>n =<!> 1
|
||||
j(flag)
|
||||
}
|
||||
finally {
|
||||
<!VAL_REASSIGNMENT!>n<!> = 2
|
||||
}
|
||||
n.hashCode()
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package
|
||||
|
||||
public fun f1(): kotlin.Unit
|
||||
public fun f2(): kotlin.Unit
|
||||
public fun g1(/*0*/ flag: kotlin.Boolean): kotlin.Unit
|
||||
public fun g2(/*0*/ flag: kotlin.Boolean): kotlin.Unit
|
||||
public fun h1(/*0*/ flag: kotlin.Boolean): kotlin.Unit
|
||||
public fun h2(/*0*/ flag: kotlin.Boolean): kotlin.Unit
|
||||
public fun j(/*0*/ flag: kotlin.Boolean): kotlin.Unit
|
||||
public fun k1(/*0*/ flag: kotlin.Boolean): kotlin.Unit
|
||||
public fun k2(/*0*/ flag: kotlin.Boolean): kotlin.Unit
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
fun exc(flag: Boolean) {
|
||||
if (flag) throw Exception()
|
||||
}
|
||||
|
||||
fun f1(flag: Boolean) {
|
||||
val n: Int
|
||||
try {
|
||||
if (flag) {
|
||||
<!UNUSED_VALUE!>n =<!> 1
|
||||
exc(flag)
|
||||
return
|
||||
}
|
||||
}
|
||||
catch (e: Exception) {
|
||||
// KT-13612: reassignment
|
||||
<!VAL_REASSIGNMENT!>n<!> = 3
|
||||
}
|
||||
<!UNINITIALIZED_VARIABLE!>n<!>.hashCode()
|
||||
}
|
||||
|
||||
fun f2(flag: Boolean) {
|
||||
while (true) {
|
||||
val n: Int
|
||||
try {
|
||||
if (flag) {
|
||||
<!UNUSED_VALUE!>n =<!> 1
|
||||
exc(flag)
|
||||
break
|
||||
}
|
||||
}
|
||||
catch (e: Exception) {
|
||||
// KT-13612: reassignment
|
||||
<!VAL_REASSIGNMENT!>n<!> = 3
|
||||
}
|
||||
<!UNINITIALIZED_VARIABLE!>n<!>.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
fun f3(flag: Boolean) {
|
||||
while (true) {
|
||||
val n: Int
|
||||
try {
|
||||
if (flag) {
|
||||
<!UNUSED_VALUE!>n =<!> 1
|
||||
exc(flag)
|
||||
continue
|
||||
}
|
||||
}
|
||||
catch (e: Exception) {
|
||||
// KT-13612: reassignment
|
||||
<!VAL_REASSIGNMENT!>n<!> = 3
|
||||
}
|
||||
<!UNINITIALIZED_VARIABLE!>n<!>.hashCode()
|
||||
}
|
||||
}
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
package
|
||||
|
||||
public fun exc(/*0*/ flag: kotlin.Boolean): kotlin.Unit
|
||||
public fun f1(/*0*/ flag: kotlin.Boolean): kotlin.Unit
|
||||
public fun f2(/*0*/ flag: kotlin.Boolean): kotlin.Unit
|
||||
public fun f3(/*0*/ flag: kotlin.Boolean): kotlin.Unit
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
fun f() {
|
||||
var foo = 1
|
||||
try {
|
||||
foo = 2
|
||||
throw RuntimeException()
|
||||
} catch (e: Throwable) {
|
||||
foo.hashCode()
|
||||
}
|
||||
throw Exception()
|
||||
}
|
||||
|
||||
fun g() {
|
||||
var foo = 1
|
||||
try {
|
||||
foo = 2
|
||||
f()
|
||||
} catch (e: Throwable) {
|
||||
foo.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
fun h() {
|
||||
try {
|
||||
|
||||
}
|
||||
finally {
|
||||
var foo = 1
|
||||
try {
|
||||
foo = 2
|
||||
g()
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
foo.hashCode()
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package
|
||||
|
||||
public fun f(): kotlin.Unit
|
||||
public fun g(): kotlin.Unit
|
||||
public fun h(): kotlin.Unit
|
||||
@@ -112,6 +112,12 @@ public class DataFlowTestGenerated extends AbstractDataFlowTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt5469.kt")
|
||||
public void testKt5469() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/kt5469.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt9825.kt")
|
||||
public void testKt9825() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/kt9825.kt");
|
||||
|
||||
@@ -870,6 +870,12 @@ public class PseudoValueTestGenerated extends AbstractPseudoValueTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt5469.kt")
|
||||
public void testKt5469() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/kt5469.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("kt9825.kt")
|
||||
public void testKt9825() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/kt9825.kt");
|
||||
|
||||
@@ -3606,6 +3606,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("reassignmentInTryCatch.kt")
|
||||
public void testReassignmentInTryCatch() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/reassignmentInTryCatch.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("reassignmentInTryCatchWithJumps.kt")
|
||||
public void testReassignmentInTryCatchWithJumps() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/reassignmentInTryCatchWithJumps.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("referenceToPropertyInitializer.kt")
|
||||
public void testReferenceToPropertyInitializer() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/referenceToPropertyInitializer.kt");
|
||||
@@ -3630,6 +3642,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("tryWithAssignmentUsedInCatch.kt")
|
||||
public void testTryWithAssignmentUsedInCatch() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/tryWithAssignmentUsedInCatch.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("uninitializedInLocalDeclarations.kt")
|
||||
public void testUninitializedInLocalDeclarations() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/uninitializedInLocalDeclarations.kt");
|
||||
|
||||
Reference in New Issue
Block a user