diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java index 1ad8d1a3ada..b1b4a8c5013 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java @@ -1075,6 +1075,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis runTest("compiler/fir/analysis-tests/testData/resolve/cfg/annotatedLocalClass.kt"); } + @Test + @TestMetadata("anonymousObjectInUnreachableCode.kt") + public void testAnonymousObjectInUnreachableCode() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/cfg/anonymousObjectInUnreachableCode.kt"); + } + @Test @TestMetadata("binaryOperations.kt") public void testBinaryOperations() throws Exception { diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java index e32ebbe8403..8ad6776be8c 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java @@ -931,6 +931,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract runTest("compiler/fir/analysis-tests/testData/resolve/cfg/annotatedLocalClass.kt"); } + @TestMetadata("anonymousObjectInUnreachableCode.kt") + public void testAnonymousObjectInUnreachableCode() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/cfg/anonymousObjectInUnreachableCode.kt"); + } + @TestMetadata("binaryOperations.kt") public void testBinaryOperations() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/cfg/binaryOperations.kt"); diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/anonymousObjectInUnreachableCode.fir.txt b/compiler/fir/analysis-tests/testData/resolve/cfg/anonymousObjectInUnreachableCode.fir.txt new file mode 100644 index 00000000000..27d1ba1e0b1 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/anonymousObjectInUnreachableCode.fir.txt @@ -0,0 +1,11 @@ +FILE: anonymousObjectInUnreachableCode.kt + public final fun test(): R|kotlin/Unit| { + ^test Unit + object : R|kotlin/Any| { + private constructor(): R|| { + super() + } + + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/anonymousObjectInUnreachableCode.kt b/compiler/fir/analysis-tests/testData/resolve/cfg/anonymousObjectInUnreachableCode.kt new file mode 100644 index 00000000000..cf1164d54a6 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/anonymousObjectInUnreachableCode.kt @@ -0,0 +1,6 @@ +// ISSUE: KT-53920 + +fun test() { + return + object {} +} diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java index 2cc19f7d777..d84a3895a74 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java @@ -1075,6 +1075,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest { runTest("compiler/fir/analysis-tests/testData/resolve/cfg/annotatedLocalClass.kt"); } + @Test + @TestMetadata("anonymousObjectInUnreachableCode.kt") + public void testAnonymousObjectInUnreachableCode() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/cfg/anonymousObjectInUnreachableCode.kt"); + } + @Test @TestMetadata("binaryOperations.kt") public void testBinaryOperations() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java index 42a3cc6f799..2591b4b7e19 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java @@ -1075,6 +1075,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/analysis-tests/testData/resolve/cfg/annotatedLocalClass.kt"); } + @Test + @TestMetadata("anonymousObjectInUnreachableCode.kt") + public void testAnonymousObjectInUnreachableCode() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/cfg/anonymousObjectInUnreachableCode.kt"); + } + @Test @TestMetadata("binaryOperations.kt") public void testBinaryOperations() throws Exception { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt index 504fca960bb..1aa7805a696 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/FirDataFlowAnalyzer.kt @@ -355,7 +355,6 @@ abstract class FirDataFlowAnalyzer( } fun exitAnonymousObject(anonymousObject: FirAnonymousObject): ControlFlowGraph { - // TODO: support capturing of mutable properties, KT-44877 val (node, controlFlowGraph) = graphBuilder.exitAnonymousObject(anonymousObject) node.mergeIncomingFlow() return controlFlowGraph @@ -1555,13 +1554,13 @@ abstract class FirDataFlowAnalyzer( var deadForwardCount = 0 for (previousNode in previousNodes) { val incomingEdgeKind = incomingEdges.getValue(previousNode).kind - if (isDead) { - if (!incomingEdgeKind.isBack) { - previousFlows += previousNode.flow - } + + if (isDead && incomingEdgeKind.usedInDeadDfa) { + previousFlows += previousNode.flow } else if (incomingEdgeKind.usedInDfa) { previousFlows += previousNode.flow } + if (incomingEdgeKind == EdgeKind.DeadForward) { deadForwardCount++ } diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt index ef2c8865828..c68ba1f5684 100644 --- a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt @@ -157,17 +157,18 @@ class ReturnPath( ) : EdgeLabel(label = "\"return@${returnTargetSymbol.callableId}\"") enum class EdgeKind( - val usedInDfa: Boolean, + val usedInDfa: Boolean, // propagate flow to alive nodes + val usedInDeadDfa: Boolean, // propagate flow to dead nodes val usedInCfa: Boolean, val isBack: Boolean, val isDead: Boolean ) { - Forward(usedInDfa = true, usedInCfa = true, isBack = false, isDead = false), - DeadForward(usedInDfa = false, usedInCfa = true, isBack = false, isDead = true), - DfgForward(usedInDfa = true, usedInCfa = false, isBack = false, isDead = false), - CfgForward(usedInDfa = false, usedInCfa = true, isBack = false, isDead = false), - CfgBackward(usedInDfa = false, usedInCfa = true, isBack = true, isDead = false), - DeadBackward(usedInDfa = false, usedInCfa = true, isBack = true, isDead = true) + Forward(usedInDfa = true, usedInDeadDfa = true, usedInCfa = true, isBack = false, isDead = false), + DeadForward(usedInDfa = false, usedInDeadDfa = true, usedInCfa = true, isBack = false, isDead = true), + DfgForward(usedInDfa = true, usedInDeadDfa = true, usedInCfa = false, isBack = false, isDead = false), + CfgForward(usedInDfa = false, usedInDeadDfa = false, usedInCfa = true, isBack = false, isDead = false), + CfgBackward(usedInDfa = false, usedInDeadDfa = false, usedInCfa = true, isBack = true, isDead = false), + DeadBackward(usedInDfa = false, usedInDeadDfa = false, usedInCfa = true, isBack = true, isDead = true) } @OptIn(ExperimentalStdlibApi::class)