FIR CFG: create TryMainBlockExitNode before visiting try main block

so that a node that returns Nothing inside try main block can route to
the exit of try main block, instead of exit target for try directly.
This commit is contained in:
Jinseong Jeon
2021-03-15 23:57:52 -07:00
committed by TeamCityServer
parent 7e5b562b33
commit 7a7114f896
3 changed files with 9 additions and 7 deletions
@@ -718,8 +718,8 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
tryMainBlockEnterNode.mergeIncomingFlow(shouldForkFlow = true) tryMainBlockEnterNode.mergeIncomingFlow(shouldForkFlow = true)
} }
fun exitTryMainBlock(tryExpression: FirTryExpression) { fun exitTryMainBlock() {
graphBuilder.exitTryMainBlock(tryExpression).mergeIncomingFlow() graphBuilder.exitTryMainBlock().mergeIncomingFlow()
} }
fun enterCatchClause(catch: FirCatch) { fun enterCatchClause(catch: FirCatch) {
@@ -832,6 +832,9 @@ class ControlFlowGraphBuilder {
val enterTryNodeBlock = createTryMainBlockEnterNode(tryExpression) val enterTryNodeBlock = createTryMainBlockEnterNode(tryExpression)
addNewSimpleNode(enterTryNodeBlock) addNewSimpleNode(enterTryNodeBlock)
val exitTryNodeBlock = createTryMainBlockExitNode(tryExpression)
tryMainExitNodes.push(exitTryNodeBlock)
for (catch in tryExpression.catches) { for (catch in tryExpression.catches) {
val catchNode = createCatchClauseEnterNode(catch) val catchNode = createCatchClauseEnterNode(catch)
catchNodeStorage.push(catchNode) catchNodeStorage.push(catchNode)
@@ -850,10 +853,9 @@ class ControlFlowGraphBuilder {
return enterTryExpressionNode to enterTryNodeBlock return enterTryExpressionNode to enterTryNodeBlock
} }
fun exitTryMainBlock(tryExpression: FirTryExpression): TryMainBlockExitNode { fun exitTryMainBlock(): TryMainBlockExitNode {
levelCounter-- levelCounter--
val node = createTryMainBlockExitNode(tryExpression) val node = tryMainExitNodes.top()
tryMainExitNodes.push(node)
popAndAddEdge(node) popAndAddEdge(node)
val finallyEnterNode = finallyEnterNodes.topOrNull() val finallyEnterNode = finallyEnterNodes.topOrNull()
// 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.
@@ -1266,7 +1268,7 @@ class ControlFlowGraphBuilder {
tryExitNodes.top().fir.finallyBlock == null -> { tryExitNodes.top().fir.finallyBlock == null -> {
// (3)... without finally ...(4) // (3)... without finally ...(4)
// Either in try-main or catch. // Either in try-main or catch.
if (tryExitNodes.size == tryMainExitNodes.size) { if (tryMainExitNodes.top().followingNodes.isNotEmpty()) {
// (4)... in catch, i.e., re-throw. // (4)... in catch, i.e., re-throw.
exitTargetsForTry.top() exitTargetsForTry.top()
} else { } else {
@@ -144,7 +144,7 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran
tryExpression.transformAnnotations(transformer, ResolutionMode.ContextIndependent) tryExpression.transformAnnotations(transformer, ResolutionMode.ContextIndependent)
dataFlowAnalyzer.enterTryExpression(tryExpression) dataFlowAnalyzer.enterTryExpression(tryExpression)
tryExpression.transformTryBlock(transformer, ResolutionMode.ContextDependent) tryExpression.transformTryBlock(transformer, ResolutionMode.ContextDependent)
dataFlowAnalyzer.exitTryMainBlock(tryExpression) dataFlowAnalyzer.exitTryMainBlock()
tryExpression.transformCatches(this, ResolutionMode.ContextDependent) tryExpression.transformCatches(this, ResolutionMode.ContextDependent)
var callCompleted = false var callCompleted = false