From dca6caaafa570ed6f34fd8e3af8c4226bb9f74d7 Mon Sep 17 00:00:00 2001 From: pyos Date: Sun, 11 Dec 2022 21:58:32 +0100 Subject: [PATCH] FIR CFA: add a hack for enum classes and LL API No clue what's going on there. --- .../dfa/cfg/ControlFlowGraphBuilder.kt | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) 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 e4e8cb879bf..56bb08ce701 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 @@ -434,15 +434,25 @@ class ControlFlowGraphBuilder { } fun exitClass(): Pair? { + assert(currentGraph.kind == ControlFlowGraph.Kind.Class) if (currentGraph.declaration == null) { - graphs.pop().also { assert(it.kind == ControlFlowGraph.Kind.Class) } + graphs.pop() return null } // Members of a class can be visited in any order, so data flow between them is unordered, // and we have to recreate the control flow after the fact. - assert(currentGraph.kind == ControlFlowGraph.Kind.Class) - val klass = currentGraph.declaration as FirClass + val enterNode = lastNodes.pop() as ClassEnterNode + val exitNode = currentGraph.exitNode as ClassExitNode + val klass = enterNode.fir + if ((klass as FirControlFlowGraphOwner).controlFlowGraphReference != null) { + // TODO: IDE LL API sometimes attempts to analyze a enum class while already analyzing it, causing + // this graph to be built twice (or more). Not sure what this means. Nothing good, probably. + // In any case, attempting to add more edges to subgraphs will be fatal. + graphs.pop() + return null + } + val calledInPlace = mutableListOf() val calledLater = mutableListOf() klass.forEachGraphOwner { member, isInPlace -> @@ -450,9 +460,6 @@ class ControlFlowGraphBuilder { if (isInPlace) calledInPlace.add(graph) else calledLater.add(graph) } - val enterNode = lastNodes.pop() as ClassEnterNode - val exitNode = currentGraph.exitNode as ClassExitNode - // Classes are not initialized in place so no point in merging data flow - it will not be used. val mergeDataFlow = klass is FirAnonymousObject && klass.classKind != ClassKind.ENUM_ENTRY val exitKind = if (mergeDataFlow) EdgeKind.Forward else EdgeKind.CfgForward