FIR CFA: add a hack for enum classes and LL API

No clue what's going on there.
This commit is contained in:
pyos
2022-12-11 21:58:32 +01:00
committed by Dmitriy Novozhilov
parent 377b7bdf5e
commit dca6caaafa
@@ -434,15 +434,25 @@ class ControlFlowGraphBuilder {
} }
fun exitClass(): Pair<ClassExitNode?, ControlFlowGraph>? { fun exitClass(): Pair<ClassExitNode?, ControlFlowGraph>? {
assert(currentGraph.kind == ControlFlowGraph.Kind.Class)
if (currentGraph.declaration == null) { if (currentGraph.declaration == null) {
graphs.pop().also { assert(it.kind == ControlFlowGraph.Kind.Class) } graphs.pop()
return null return null
} }
// Members of a class can be visited in any order, so data flow between them is unordered, // 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. // and we have to recreate the control flow after the fact.
assert(currentGraph.kind == ControlFlowGraph.Kind.Class) val enterNode = lastNodes.pop() as ClassEnterNode
val klass = currentGraph.declaration as FirClass 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<ControlFlowGraph>() val calledInPlace = mutableListOf<ControlFlowGraph>()
val calledLater = mutableListOf<ControlFlowGraph>() val calledLater = mutableListOf<ControlFlowGraph>()
klass.forEachGraphOwner { member, isInPlace -> klass.forEachGraphOwner { member, isInPlace ->
@@ -450,9 +460,6 @@ class ControlFlowGraphBuilder {
if (isInPlace) calledInPlace.add(graph) else calledLater.add(graph) 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. // 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 mergeDataFlow = klass is FirAnonymousObject && klass.classKind != ClassKind.ENUM_ENTRY
val exitKind = if (mergeDataFlow) EdgeKind.Forward else EdgeKind.CfgForward val exitKind = if (mergeDataFlow) EdgeKind.Forward else EdgeKind.CfgForward