From 20d0e8647df27ae128c0d85e2136ffbdb2f242f5 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Tue, 31 Mar 2020 17:53:47 +0300 Subject: [PATCH] [FIR] Pass data flow to init blocks of local classes --- .../resolve/cfg/propertiesAndInitBlocks.dot | 38 +++++++------------ .../dfa/cfg/ControlFlowGraphBuilder.kt | 21 ++++++---- .../body/resolve/LocalClassesNavigation.kt | 9 ++++- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/compiler/fir/analysis-tests/testData/resolve/cfg/propertiesAndInitBlocks.dot b/compiler/fir/analysis-tests/testData/resolve/cfg/propertiesAndInitBlocks.dot index a7a41a4b618..1bc82dfba81 100644 --- a/compiler/fir/analysis-tests/testData/resolve/cfg/propertiesAndInitBlocks.dot +++ b/compiler/fir/analysis-tests/testData/resolve/cfg/propertiesAndInitBlocks.dot @@ -144,27 +144,15 @@ digraph propertiesAndInitBlocks_kt { 50 [label="Exit local class "]; 49 [label="Exit function getter" style="filled" fillcolor=red]; } - subgraph cluster_16 { - color=blue - 51 [label="Enter function " style="filled" fillcolor=red]; - 53 [label="Delegated constructor call: super()"]; - 52 [label="Exit function " style="filled" fillcolor=red]; - } 65 [label="Postponed enter to lambda"]; - subgraph cluster_17 { + subgraph cluster_16 { color=blue 20 [label="Enter function anonymousFunction" style="filled" fillcolor=red]; 22 [label="Exit local class "]; 23 [label="Function call: R|java/lang/Exception.Exception|()"]; 24 [label="Throw: throw R|java/lang/Exception.Exception|()"]; 25 [label="Stub" style="filled" fillcolor=gray]; - subgraph cluster_18 { - color=blue - 35 [label="Enter function " style="filled" fillcolor=red]; - 37 [label="Delegated constructor call: super()"]; - 36 [label="Exit function " style="filled" fillcolor=red]; - } - subgraph cluster_19 { + subgraph cluster_17 { color=blue 26 [label="Enter function foo" style="filled" fillcolor=red]; 28 [label="Const: Int(1)"]; @@ -188,7 +176,7 @@ digraph propertiesAndInitBlocks_kt { 66 -> {67}; 67 -> {64}; 20 -> {21 22}; - 20 -> {26 35} [color=red]; + 20 -> {26 35 38} [color=red]; 21 -> {20}; 21 -> {66} [color=green]; 22 -> {23}; @@ -206,24 +194,24 @@ digraph propertiesAndInitBlocks_kt { 33 -> {34} [style=dotted]; 34 -> {27} [style=dotted]; 48 -> {50}; - 48 -> {51} [color=red]; + 48 -> {51 54} [color=red]; 50 -> {49}; - subgraph cluster_20 { + subgraph cluster_18 { color=red 70 [label="Enter property" style="filled" fillcolor=red]; - subgraph cluster_21 { + subgraph cluster_19 { color=blue 68 [label="Enter function getter" style="filled" fillcolor=red]; 69 [label="Exit function getter" style="filled" fillcolor=red]; } - subgraph cluster_22 { + subgraph cluster_20 { color=blue 72 [label="Try expression enter"]; - subgraph cluster_23 { + subgraph cluster_21 { color=blue 74 [label="Try main block enter"]; - subgraph cluster_24 { + subgraph cluster_22 { color=blue 77 [label="Enter block"]; 78 [label="Const: Int(1)"]; @@ -231,10 +219,10 @@ digraph propertiesAndInitBlocks_kt { } 80 [label="Try main block exit"]; } - subgraph cluster_25 { + subgraph cluster_23 { color=blue 76 [label="Enter finally"]; - subgraph cluster_26 { + subgraph cluster_24 { color=blue 85 [label="Enter block"]; 86 [label="Const: Int(0)"]; @@ -242,10 +230,10 @@ digraph propertiesAndInitBlocks_kt { } 88 [label="Exit finally"]; } - subgraph cluster_27 { + subgraph cluster_25 { color=blue 75 [label="Catch enter"]; - subgraph cluster_28 { + subgraph cluster_26 { color=blue 81 [label="Enter block"]; 82 [label="Const: Int(2)"]; 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 e59d12e74e4..3862f7eecb6 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 @@ -7,12 +7,13 @@ package org.jetbrains.kotlin.fir.resolve.dfa.cfg import org.jetbrains.kotlin.contracts.description.InvocationKind import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.FirSymbolOwner import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.resolve.dfa.* import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType -import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol +import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol import org.jetbrains.kotlin.fir.types.isNothing import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitorVoid @@ -58,7 +59,7 @@ class ControlFlowGraphBuilder { private val exitsFromCompletedPostponedAnonymousFunctions: MutableList = mutableListOf() - private val enterToLocalClassesMembers: MutableMap, CFGNode<*>?> = mutableMapOf() + private val enterToLocalClassesMembers: MutableMap, CFGNode<*>?> = mutableMapOf() var levelCounter: Int = 0 private set @@ -253,19 +254,19 @@ class ControlFlowGraphBuilder { return graphs.pop() } - fun prepareForLocalClassMembers(members: Collection>) { + fun prepareForLocalClassMembers(members: Collection>) { members.forEachMember { enterToLocalClassesMembers[it.symbol] = lastNodes.topOrNull() } } - fun cleanAfterForLocalClassMembers(members: Collection>) { + fun cleanAfterForLocalClassMembers(members: Collection>) { members.forEachMember { enterToLocalClassesMembers.remove(it.symbol) } } - private inline fun Collection>.forEachMember(block: (FirCallableDeclaration<*>) -> Unit) { + private inline fun Collection>.forEachMember(block: (FirSymbolOwner<*>) -> Unit) { for (member in this) { for (callableDeclaration in member.unwrap()) { block(callableDeclaration) @@ -273,9 +274,12 @@ class ControlFlowGraphBuilder { } } - private fun FirCallableMemberDeclaration<*>.unwrap(): List> = + private fun FirSymbolOwner<*>.unwrap(): List> = when (this) { - is FirFunction<*> -> listOf(this) + is FirFunction<*>, + is FirAnonymousInitializer + -> listOf(this) + is FirProperty -> listOfNotNull(this.getter, this.setter, this) else -> emptyList() } @@ -824,6 +828,9 @@ class ControlFlowGraphBuilder { lexicalScopes.push(stackOf(it)) } val exitNode = createInitBlockExitNode(initBlock) + enterToLocalClassesMembers[initBlock.symbol]?.let { + addEdge(it, enterNode, preferredKind = EdgeKind.Dfg) + } initBlockExitNodes.push(exitNode) exitNodes.push(exitNode) levelCounter++ diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/LocalClassesNavigation.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/LocalClassesNavigation.kt index c27d2d4e944..3e7cba86ab4 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/LocalClassesNavigation.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/LocalClassesNavigation.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.resolve.transformers.body.resolve import kotlinx.collections.immutable.persistentListOf import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.FirSymbolOwner import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitorVoid @@ -15,7 +16,7 @@ import org.jetbrains.kotlin.utils.keysToMap class LocalClassesNavigationInfo( val parentForClass: Map, FirClass<*>?>, private val parentClassForFunction: Map, FirClass<*>>, - val allMembers: List> + val allMembers: List> ) { val designationMap by lazy { parentClassForFunction.keys.keysToMap { @@ -46,7 +47,7 @@ fun FirClass<*>.collectLocalClassesNavigationInfo(): LocalClassesNavigationInfo private class NavigationInfoVisitor : FirDefaultVisitorVoid() { val resultingMap = mutableMapOf, FirClass<*>>() val parentForClass = mutableMapOf, FirClass<*>?>() - val allMembers = mutableListOf>() + val allMembers = mutableListOf>() private var currentPath = persistentListOf>() override fun visitElement(element: FirElement) {} @@ -88,4 +89,8 @@ private class NavigationInfoVisitor : FirDefaultVisitorVoid() { if (callableMemberDeclaration.returnTypeRef !is FirImplicitTypeRef) return resultingMap[callableMemberDeclaration] = currentPath.last() } + + override fun visitAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer) { + allMembers += anonymousInitializer + } }