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 b2e5cf38b95..fd5eabf5157 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 @@ -64,7 +64,13 @@ class FirDataFlowAnalyzer(transformer: FirBodyResolveTransformer) : BodyResolveC // ----------------------------------- Named function ----------------------------------- fun enterFunction(function: FirFunction<*>) { - graphBuilder.enterFunction(function).mergeIncomingFlow() + val (functionEnterNode, previousNode) = graphBuilder.enterFunction(function) + if (previousNode == null) { + functionEnterNode.mergeIncomingFlow() + } else { + assert(functionEnterNode.previousNodes.isEmpty()) + functionEnterNode.flow = logicSystem.forkFlow(previousNode.flow) + } } fun exitFunction(function: FirFunction<*>): ControlFlowGraph? { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt index 2024cda1ffe..514e9ab809c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraph.kt @@ -12,10 +12,14 @@ import org.jetbrains.kotlin.fir.declarations.FirFunction import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.expressions.* -class ControlFlowGraph(val name: String) { +class ControlFlowGraph(val name: String, val kind: Kind) { val nodes = mutableListOf>() lateinit var enterNode: CFGNode<*> lateinit var exitNode: CFGNode<*> + + enum class Kind { + Function, ClassInitializer, PropertyInitializer, TopLevel + } } sealed class CFGNode(val owner: ControlFlowGraph, val level: Int) { 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 01fdfa50a20..2930c211385 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 @@ -16,7 +16,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.resultType import org.jetbrains.kotlin.fir.types.isNothing class ControlFlowGraphBuilder { - private val graphs: Stack = stackOf(ControlFlowGraph("")) + private val graphs: Stack = stackOf(ControlFlowGraph("", ControlFlowGraph.Kind.TopLevel)) val graph: ControlFlowGraph get() = graphs.top() private val lexicalScopes: Stack>> = stackOf(stackOf()) @@ -50,7 +50,11 @@ class ControlFlowGraphBuilder { // ----------------------------------- Named function ----------------------------------- - fun enterFunction(function: FirFunction<*>): FunctionEnterNode { + /* + * Second argument of pair is not null only if function is local and it is a + * previous node before function declaration + */ + fun enterFunction(function: FirFunction<*>): Pair?> { val name = when (function) { is FirNamedFunction -> function.name.asString() is FirAbstractPropertyAccessor -> if (function.isGetter) "" else "" @@ -60,9 +64,17 @@ class ControlFlowGraphBuilder { } val invocationKind = function.invocationKind val isInplace = invocationKind.isInplace() - if (!isInplace) { - graphs.push(ControlFlowGraph(name)) + + val previousNode = if (!isInplace && graphs.topOrNull()?.let { it.kind != ControlFlowGraph.Kind.TopLevel } == true) { + lastNodes.top() + } else { + null } + + if (!isInplace) { + graphs.push(ControlFlowGraph(name, ControlFlowGraph.Kind.Function)) + } + val enterNode = createFunctionEnterNode(function, isInplace).also { if (isInplace) { addNewSimpleNode(it) @@ -88,7 +100,7 @@ class ControlFlowGraphBuilder { exitNodes.push(exitNode) } levelCounter++ - return enterNode + return enterNode to previousNode } fun exitFunction(function: FirFunction<*>): Pair { @@ -127,7 +139,7 @@ class ControlFlowGraphBuilder { // ----------------------------------- Property ----------------------------------- fun enterProperty(property: FirProperty): PropertyInitializerEnterNode { - graphs.push(ControlFlowGraph("val ${property.name}")) + graphs.push(ControlFlowGraph("val ${property.name}", ControlFlowGraph.Kind.PropertyInitializer)) val enterNode = createPropertyInitializerEnterNode(property) val exitNode = createPropertyInitializerExitNode(property) topLevelVariableInitializerExitNodes.push(exitNode) @@ -522,7 +534,7 @@ class ControlFlowGraphBuilder { // ----------------------------------- Block ----------------------------------- fun enterInitBlock(initBlock: FirAnonymousInitializer): InitBlockEnterNode { - graphs.push(ControlFlowGraph("init block")) + graphs.push(ControlFlowGraph("init block", ControlFlowGraph.Kind.ClassInitializer)) val enterNode = createInitBlockEnterNode(initBlock).also { lexicalScopes.push(stackOf(it)) } diff --git a/compiler/fir/resolve/testData/resolve/cfg/lambdas.dot b/compiler/fir/resolve/testData/resolve/cfg/lambdas.dot index e5924ead206..2af10c818ec 100644 --- a/compiler/fir/resolve/testData/resolve/cfg/lambdas.dot +++ b/compiler/fir/resolve/testData/resolve/cfg/lambdas.dot @@ -112,7 +112,7 @@ digraph lambdas_kt { color=blue 33 [label="Enter block"]; 34 [label="Access variable R|/x|"]; - 35 [label="Function call: R|/x|.#()"]; + 35 [label="Function call: R|/x|.R|kotlin/Int.inc|()"]; 36 [label="Exit block"]; } 37 [label="Exit function anonymousFunction" style="filled" fillcolor=red]; @@ -156,7 +156,7 @@ digraph lambdas_kt { subgraph cluster_19 { color=blue 52 [label="Enter block"]; - 53 [label="Variable declaration: lval lambda: R|kotlin/Function0|"]; + 53 [label="Variable declaration: lval lambda: R|kotlin/Function0|"]; 54 [label="Exit block"]; } 55 [label="Exit when branch result"]; diff --git a/compiler/fir/resolve/testData/resolve/cfg/lambdas.txt b/compiler/fir/resolve/testData/resolve/cfg/lambdas.txt index 8457d22b9d3..ceadab5488b 100644 --- a/compiler/fir/resolve/testData/resolve/cfg/lambdas.txt +++ b/compiler/fir/resolve/testData/resolve/cfg/lambdas.txt @@ -18,8 +18,8 @@ FILE: lambdas.kt public final fun test_2(x: R|kotlin/Any?|): R|kotlin/Unit| { when () { (R|/x| is R|kotlin/Int|) -> { - lval lambda: R|kotlin/Function0| = fun (): { - R|/x|.#() + lval lambda: R|kotlin/Function0| = fun (): R|kotlin/Int| { + R|/x|.R|kotlin/Int.inc|() } }