From 8dce6f2ac90cf4008af64268d58b353ef8782e92 Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Fri, 12 Mar 2021 12:37:42 -0800 Subject: [PATCH] FIR CFG: don't propagate deadness on the uncaught exception path --- .../dfa/cfg/ControlFlowGraphBuilder.kt | 6 +- .../tests/initializedAfterRethrow.fir.kt | 222 ------------------ .../tests/initializedAfterRethrow.kt | 1 + 3 files changed, 4 insertions(+), 225 deletions(-) delete mode 100644 compiler/testData/diagnostics/tests/initializedAfterRethrow.fir.kt diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt index 70a7869bc98..94aad8c2570 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt @@ -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 diff --git a/compiler/testData/diagnostics/tests/initializedAfterRethrow.fir.kt b/compiler/testData/diagnostics/tests/initializedAfterRethrow.fir.kt deleted file mode 100644 index 3b2c5705aca..00000000000 --- a/compiler/testData/diagnostics/tests/initializedAfterRethrow.fir.kt +++ /dev/null @@ -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 { - 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 { - private val p: String - - init { - try { - foo() - } catch (e: Exception) { - try { - throw e - } finally { - } - } - p = "OK" - } -} - - -object InnerTryWithCatchAndFinally { - 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 { - private val p: String - - init { - try { - foo() - } catch (e: Exception) { - try { - foo() - } finally { - throw e - } - } - p = "OK" - } -} - -object InnerFinallyWithCatch { - private val p: String - - init { - try { - foo() - } catch (e: Exception) { - try { - foo() - } catch (ee: Exception) { - } finally { - throw e - } - } - p = "OK" - } -} diff --git a/compiler/testData/diagnostics/tests/initializedAfterRethrow.kt b/compiler/testData/diagnostics/tests/initializedAfterRethrow.kt index af394e1fa19..f3aeb466978 100644 --- a/compiler/testData/diagnostics/tests/initializedAfterRethrow.kt +++ b/compiler/testData/diagnostics/tests/initializedAfterRethrow.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL fun foo(): Int = 42 object ThrowInTryWithCatch {