[FIR][CFG] Link finally exit to jump target
Instead of try exit node. So try exit is used only for real exits from try expressions.
This commit is contained in:
committed by
teamcityserver
parent
32426da625
commit
6dd4164f1e
+2
-2
@@ -817,8 +817,8 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
graphBuilder.enterFinallyBlock().mergeIncomingFlow(updateReceivers = true, shouldForkFlow = true)
|
graphBuilder.enterFinallyBlock().mergeIncomingFlow(updateReceivers = true, shouldForkFlow = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exitFinallyBlock(tryExpression: FirTryExpression) {
|
fun exitFinallyBlock() {
|
||||||
graphBuilder.exitFinallyBlock(tryExpression).mergeIncomingFlow()
|
graphBuilder.exitFinallyBlock().mergeIncomingFlow()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exitTryExpression(callCompleted: Boolean) {
|
fun exitTryExpression(callCompleted: Boolean) {
|
||||||
|
|||||||
+14
-10
@@ -96,6 +96,7 @@ class ControlFlowGraphBuilder {
|
|||||||
private val catchNodeStorage: NodeStorage<FirCatch, CatchClauseEnterNode> get() = catchNodeStorages.top()
|
private val catchNodeStorage: NodeStorage<FirCatch, CatchClauseEnterNode> get() = catchNodeStorages.top()
|
||||||
private val catchExitNodeStorages: Stack<NodeStorage<FirCatch, CatchClauseExitNode>> = stackOf()
|
private val catchExitNodeStorages: Stack<NodeStorage<FirCatch, CatchClauseExitNode>> = stackOf()
|
||||||
private val finallyEnterNodes: Stack<FinallyBlockEnterNode> = stackOf()
|
private val finallyEnterNodes: Stack<FinallyBlockEnterNode> = stackOf()
|
||||||
|
private val finallyExitNodes: NodeStorage<FirTryExpression, FinallyBlockExitNode> = NodeStorage()
|
||||||
|
|
||||||
private val initBlockExitNodes: Stack<InitBlockExitNode> = stackOf()
|
private val initBlockExitNodes: Stack<InitBlockExitNode> = stackOf()
|
||||||
|
|
||||||
@@ -872,6 +873,7 @@ class ControlFlowGraphBuilder {
|
|||||||
// 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, propagateDeadness = false, label = UncaughtExceptionPath)
|
addEdge(enterTryExpressionNode, finallyEnterNode, propagateDeadness = false, label = UncaughtExceptionPath)
|
||||||
finallyEnterNodes.push(finallyEnterNode)
|
finallyEnterNodes.push(finallyEnterNode)
|
||||||
|
finallyExitNodes.push(createFinallyBlockExitNode(tryExpression))
|
||||||
}
|
}
|
||||||
|
|
||||||
return enterTryExpressionNode to enterTryNodeBlock
|
return enterTryExpressionNode to enterTryNodeBlock
|
||||||
@@ -938,18 +940,19 @@ class ControlFlowGraphBuilder {
|
|||||||
return enterNode
|
return enterNode
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exitFinallyBlock(tryExpression: FirTryExpression): FinallyBlockExitNode {
|
fun exitFinallyBlock(): FinallyBlockExitNode {
|
||||||
return createFinallyBlockExitNode(tryExpression).also {
|
return finallyExitNodes.pop().also { finallyExit ->
|
||||||
popAndAddEdge(it)
|
popAndAddEdge(finallyExit)
|
||||||
val tryExitNode = tryExitNodes.top()
|
val tryExitNode = tryExitNodes.top()
|
||||||
// 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(finallyExit, tryExitNode)
|
||||||
if (tryExitNode.isDead) {
|
if (finallyExit.isDead) {
|
||||||
//refresh forward links, which were created before finalizing try expression (eg created by `break`)
|
//refresh forward links, which were created before finalizing try expression (eg created by `break`)
|
||||||
propagateDeadnessForward(tryExitNode)
|
propagateDeadnessForward(finallyExit)
|
||||||
}
|
}
|
||||||
// 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(), propagateDeadness = false, label = UncaughtExceptionPath)
|
//todo this edge might exist already if try has jump outside, so we effectively lose labeled edge here
|
||||||
|
addEdgeIfNotExist(finallyExit, 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
|
||||||
@@ -1423,9 +1426,10 @@ class ControlFlowGraphBuilder {
|
|||||||
lastNodes.push(stub)
|
lastNodes.push(stub)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun finallyBefore(target: CFGNode<*>): List<Pair<FinallyBlockEnterNode, TryExpressionExitNode>> {
|
private fun finallyBefore(target: CFGNode<*>): List<Pair<FinallyBlockEnterNode, FinallyBlockExitNode>> {
|
||||||
return finallyEnterNodes.all().takeWhile { it.level > target.level }.map {
|
return finallyEnterNodes.all().takeWhile { it.level > target.level }.map { finallyEnter ->
|
||||||
it to tryExitNodes[it.fir]!!
|
val finallyExit = finallyExitNodes[finallyEnter.fir]!!
|
||||||
|
finallyEnter to finallyExit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -154,7 +154,7 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran
|
|||||||
result = if (result.finallyBlock != null) {
|
result = if (result.finallyBlock != null) {
|
||||||
result.also { dataFlowAnalyzer.enterFinallyBlock() }
|
result.also { dataFlowAnalyzer.enterFinallyBlock() }
|
||||||
.transformFinallyBlock(transformer, ResolutionMode.ContextIndependent)
|
.transformFinallyBlock(transformer, ResolutionMode.ContextIndependent)
|
||||||
.also(dataFlowAnalyzer::exitFinallyBlock)
|
.also { dataFlowAnalyzer.exitFinallyBlock() }
|
||||||
} else {
|
} else {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user