FIR CFG: don't propagate deadness on the uncaught exception path
This commit is contained in:
committed by
TeamCityServer
parent
d27ecca0e9
commit
8dce6f2ac9
+3
-3
@@ -843,7 +843,7 @@ class ControlFlowGraphBuilder {
|
|||||||
if (tryExpression.finallyBlock != null) {
|
if (tryExpression.finallyBlock != null) {
|
||||||
val finallyEnterNode = createFinallyBlockEnterNode(tryExpression)
|
val finallyEnterNode = createFinallyBlockEnterNode(tryExpression)
|
||||||
// a flow where an uncaught exception is thrown before executing any of try-main block.
|
// 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)
|
finallyEnterNodes.push(finallyEnterNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -875,7 +875,7 @@ class ControlFlowGraphBuilder {
|
|||||||
// a flow where an uncaught exception is thrown before executing any of catch clause.
|
// 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.
|
// NB: Check the level to avoid adding an edge to the finally block at an upper level.
|
||||||
if (finallyEnterNode != null && finallyEnterNode.level == levelCounter + 1) {
|
if (finallyEnterNode != null && finallyEnterNode.level == levelCounter + 1) {
|
||||||
addEdge(it, finallyEnterNode, label = UncaughtExceptionPath)
|
addEdge(it, finallyEnterNode, propagateDeadness = false, label = UncaughtExceptionPath)
|
||||||
} else {
|
} else {
|
||||||
addEdge(it, exitTargetsForTry.top(), label = UncaughtExceptionPath)
|
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.
|
// a flow where either there wasn't any exception or caught if any.
|
||||||
addEdge(it, tryExitNode)
|
addEdge(it, tryExitNode)
|
||||||
// a flow that exits to the exit target while there was an uncaught exception.
|
// 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
|
// 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)
|
// 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
|
// 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
|
fun foo(): Int = 42
|
||||||
|
|
||||||
object ThrowInTryWithCatch {
|
object ThrowInTryWithCatch {
|
||||||
|
|||||||
Reference in New Issue
Block a user