From d27ecca0e9ef94ad4c0aa4f144a4bf74636efd79 Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Thu, 11 Mar 2021 23:46:19 -0800 Subject: [PATCH] FIR CFA: keep UncaughtExceptionPath separated --- .../analysis/cfa/PathAwareControlFlowInfo.kt | 24 +++++++++++++------ .../tests/initializedAfterRethrow.fir.kt | 8 +++---- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/PathAwareControlFlowInfo.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/PathAwareControlFlowInfo.kt index 269fc45dd7f..5cc69eb63eb 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/PathAwareControlFlowInfo.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/cfa/PathAwareControlFlowInfo.kt @@ -7,10 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.cfa import kotlinx.collections.immutable.PersistentMap import kotlinx.collections.immutable.persistentMapOf -import org.jetbrains.kotlin.fir.resolve.dfa.cfg.CFGNode -import org.jetbrains.kotlin.fir.resolve.dfa.cfg.EdgeLabel -import org.jetbrains.kotlin.fir.resolve.dfa.cfg.NormalPath -import org.jetbrains.kotlin.fir.resolve.dfa.cfg.TryExpressionExitNode +import org.jetbrains.kotlin.fir.resolve.dfa.cfg.* abstract class PathAwareControlFlowInfo

, S : ControlFlowInfo>( map: PersistentMap, @@ -43,11 +40,24 @@ abstract class PathAwareControlFlowInfo

, S : val hasAbnormalLabels = map.keys.any { !it.isNormal } return if (hasAbnormalLabels) { - // { |-> ... l1 |-> I1, l2 |-> I2, ... } + // { |-> ..., l1 |-> I1, l2 |-> I2, ... } // | l1 // path exit: if the given info has non-null labels, this acts like a filtering - // { |-> I1 } // NB: remove the path info + // { |-> I1 } // NB: remove the path label, except for uncaught exception path if (map.keys.contains(label)) { - constructor(persistentMapOf(NormalPath to map[label]!!)) + if (label == UncaughtExceptionPath) { + // Special case: uncaught exception path, which still represents an uncaught exception path + // Target node is most likely fun/init exit, and we should keep info separated. + constructor(persistentMapOf(label to map[label]!!)) + } else { + // { |-> I } + // | l1 // e.g., enter to proxy1 with l1 + // { l1 -> I } + // ... + // { |-> ..., l1 -> I', ... } + // | l1 // e.g., exit proxy1 with l1 + // { l1 -> I' } + constructor(persistentMapOf(NormalPath to map[label]!!)) + } } else { /* This means no info for the specific label. */ empty() diff --git a/compiler/testData/diagnostics/tests/initializedAfterRethrow.fir.kt b/compiler/testData/diagnostics/tests/initializedAfterRethrow.fir.kt index 77660e93157..3b2c5705aca 100644 --- a/compiler/testData/diagnostics/tests/initializedAfterRethrow.fir.kt +++ b/compiler/testData/diagnostics/tests/initializedAfterRethrow.fir.kt @@ -13,7 +13,7 @@ object ThrowInTryWithCatch { } object ThrowInTryWithCatchAndFinally { - private val p: String + private val p: String init { try { @@ -53,7 +53,7 @@ object RethrowInCatch { } object RethrowInCatchWithFinally { - private val p: String + private val p: String init { try { @@ -134,7 +134,7 @@ object InnerCatch { } object InnerCatchWithFinally { - private val p: String + private val p: String init { try { @@ -169,7 +169,7 @@ object InnerCatchOuterRethrow { } object InnerCatchOuterRethrowWithFinally { - private val p: String + private val p: String init { try {