FIR CFG: don't propagate deadness on the uncaught exception path

This commit is contained in:
Jinseong Jeon
2021-03-12 12:37:42 -08:00
committed by TeamCityServer
parent d27ecca0e9
commit 8dce6f2ac9
3 changed files with 4 additions and 225 deletions
@@ -843,7 +843,7 @@ class ControlFlowGraphBuilder {
if (tryExpression.finallyBlock != null) {
val finallyEnterNode = createFinallyBlockEnterNode(tryExpression)
// a flow where an uncaught exception is thrown before executing any of try-main block.
addEdge(enterTryExpressionNode, finallyEnterNode, label = UncaughtExceptionPath)
addEdge(enterTryExpressionNode, finallyEnterNode, propagateDeadness = false, label = UncaughtExceptionPath)
finallyEnterNodes.push(finallyEnterNode)
}
@@ -875,7 +875,7 @@ class ControlFlowGraphBuilder {
// a flow where an uncaught exception is thrown before executing any of catch clause.
// NB: Check the level to avoid adding an edge to the finally block at an upper level.
if (finallyEnterNode != null && finallyEnterNode.level == levelCounter + 1) {
addEdge(it, finallyEnterNode, label = UncaughtExceptionPath)
addEdge(it, finallyEnterNode, propagateDeadness = false, label = UncaughtExceptionPath)
} else {
addEdge(it, exitTargetsForTry.top(), label = UncaughtExceptionPath)
}
@@ -912,7 +912,7 @@ class ControlFlowGraphBuilder {
// a flow where either there wasn't any exception or caught if any.
addEdge(it, tryExitNode)
// a flow that exits to the exit target while there was an uncaught exception.
addEdge(it, exitTargetsForTry.top(), label = UncaughtExceptionPath)
addEdge(it, exitTargetsForTry.top(), propagateDeadness = false, label = UncaughtExceptionPath)
// TODO: differentiate flows that return/(re)throw in try main block and/or catch clauses
// To do so, we need mappings from such distinct label to original exit target (fun exit or loop)
// Also, CFG should support multiple edges towards the same destination node
@@ -1,222 +0,0 @@
fun foo(): Int = 42
object ThrowInTryWithCatch {
private val p: String
init {
try {
throw Exception()
} catch (e: Exception) {
}
p = "OK"
}
}
object ThrowInTryWithCatchAndFinally {
private val p: String
init {
try {
throw Exception()
} catch (e: Exception) {
} finally {
}
p = "OK"
}
}
object ThrowInFinally {
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>private val p: String<!>
init {
try {
foo()
} catch (e: Exception) {
} finally {
throw Exception()
}
p = "OK"
}
}
object RethrowInCatch {
private val p: String
init {
try {
foo()
} catch (e: Exception) {
throw e
}
p = "OK"
}
}
object RethrowInCatchWithFinally {
private val p: String
init {
try {
foo()
} catch (e: Exception) {
throw e
} finally {
}
p = "OK"
}
}
object InnerTryWithCatch {
private val p: String
init {
try {
foo()
} catch (e: Exception) {
try {
throw e
} catch (ee: Exception) {
}
}
p = "OK"
}
}
object InnerTryWithFinally {
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>private val p: String<!>
init {
try {
foo()
} catch (e: Exception) {
try {
throw e
} finally {
}
}
p = "OK"
}
}
object InnerTryWithCatchAndFinally {
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>private val p: String<!>
init {
try {
foo()
} catch (e: Exception) {
try {
throw e
} catch (ee: Exception) {
} finally {
}
}
p = "OK"
}
}
object InnerCatch {
private val p: String
init {
try {
foo()
} catch (e: Exception) {
try {
foo()
} catch (ee: Exception) {
throw ee
}
}
p = "OK"
}
}
object InnerCatchWithFinally {
private val p: String
init {
try {
foo()
} catch (e: Exception) {
try {
foo()
} catch (ee: Exception) {
throw ee
} finally {
}
}
p = "OK"
}
}
object InnerCatchOuterRethrow {
private val p: String
init {
try {
foo()
} catch (e: Exception) {
try {
foo()
} catch (ee: Exception) {
throw e
}
}
p = "OK"
}
}
object InnerCatchOuterRethrowWithFinally {
private val p: String
init {
try {
foo()
} catch (e: Exception) {
try {
foo()
} catch (ee: Exception) {
throw e
} finally {
}
}
p = "OK"
}
}
object InnerFinally {
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>private val p: String<!>
init {
try {
foo()
} catch (e: Exception) {
try {
foo()
} finally {
throw e
}
}
p = "OK"
}
}
object InnerFinallyWithCatch {
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>private val p: String<!>
init {
try {
foo()
} catch (e: Exception) {
try {
foo()
} catch (ee: Exception) {
} finally {
throw e
}
}
p = "OK"
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
fun foo(): Int = 42
object ThrowInTryWithCatch {