[FIR] Add edge kinds to control flow graph

Another changes:
- Remove useless CFG plain text renderer
- Refactor CFG .dot renderer
- Add checking of consistency control flow graph
This commit is contained in:
Dmitriy Novozhilov
2020-01-29 12:45:43 +03:00
parent 0c2157155d
commit 6716cb0bf3
50 changed files with 13215 additions and 11599 deletions
@@ -709,6 +709,11 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
val flow = node.mergeIncomingFlow().flow
/*
* TODO: Here we should handle case when one of arguments is dead (e.g. in cases `false && expr` or `true || expr`)
* But since conditions with const are rare it can be delayed
*/
val leftVariable = variableStorage.getOrCreateVariable(binaryLogicExpression.leftOperand)
val rightVariable = variableStorage.getOrCreateVariable(binaryLogicExpression.rightOperand)
val operatorVariable = variableStorage.getOrCreateVariable(binaryLogicExpression)
@@ -795,7 +800,7 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
val previousFlows = if (node.isDead)
node.previousNodes.map { it.flow }
else
node.previousNodes.mapNotNull { prev -> prev.takeIf { !it.isDead }?.flow }
node.previousNodes.mapNotNull { prev -> prev.takeIf { node.incomingEdges[it] != EdgeKind.Dead }?.flow }
val flow = logicSystem.joinFlow(previousFlows)
if (updateReceivers) {
logicSystem.updateAllReceivers(flow)
@@ -24,13 +24,34 @@ class ControlFlowGraph(val name: String, val kind: Kind) {
}
}
enum class EdgeKind {
Simple, Dead
}
sealed class CFGNode<out E : FirElement>(val owner: ControlFlowGraph, val level: Int, private val id: Int) {
companion object {
fun addEdge(from: CFGNode<*>, to: CFGNode<*>, kind: EdgeKind, propagateDeadness: Boolean) {
from.followingNodes += to
to.previousNodes += from
if (kind != EdgeKind.Simple) {
from.outgoingEdges[to] = kind
to.incomingEdges[from] = kind
}
if (propagateDeadness && kind == EdgeKind.Dead) {
to.isDead = true
}
}
}
init {
owner.nodes += this
}
val previousNodes = mutableListOf<CFGNode<*>>()
val followingNodes = mutableListOf<CFGNode<*>>()
val previousNodes: MutableList<CFGNode<*>> = mutableListOf()
val followingNodes: MutableList<CFGNode<*>> = mutableListOf()
val incomingEdges = mutableMapOf<CFGNode<*>, EdgeKind>().withDefault { EdgeKind.Simple }
val outgoingEdges = mutableMapOf<CFGNode<*>, EdgeKind>().withDefault { EdgeKind.Simple }
val firstPreviousNode: CFGNode<*> get() = previousNodes.first()
@@ -47,7 +68,6 @@ sealed class CFGNode<out E : FirElement>(val owner: ControlFlowGraph, val level:
}
}
interface EnterNode
interface ExitNode
@@ -314,7 +314,7 @@ class ControlFlowGraphBuilder {
val conditionExitNode = createLoopConditionExitNode(loop.condition)
addNewSimpleNode(conditionExitNode)
val conditionConstBooleanValue = conditionExitNode.booleanConstValue
addEdge(conditionExitNode, loopExitNodes.top(), isDead = conditionConstBooleanValue == true)
addEdge(conditionExitNode, loopExitNodes.top(), propagateDeadness = false, isDead = conditionConstBooleanValue == true)
val loopBlockEnterNode = createLoopBlockEnterNode(loop)
addNewSimpleNode(loopBlockEnterNode, conditionConstBooleanValue == false)
levelCounter++
@@ -431,11 +431,11 @@ class ControlFlowGraphBuilder {
val leftExitNode = createBinaryOrExitLeftOperandNode(binaryLogicExpression).also {
addEdge(previousNode, it)
addEdge(it, binaryOrExitNodes.top(), isDead = leftBooleanValue == false)
addEdge(it, binaryOrExitNodes.top(), propagateDeadness = false, isDead = leftBooleanValue == false)
}
val rightExitNode = createBinaryOrEnterRightOperandNode(binaryLogicExpression).also {
addEdge(leftExitNode, it, isDead = leftBooleanValue == true)
addEdge(leftExitNode, it, propagateDeadness = true, isDead = leftBooleanValue == true)
lastNodes.push(it)
levelCounter++
}
@@ -639,13 +639,14 @@ class ControlFlowGraphBuilder {
fun exitSafeCall(qualifiedAccess: FirQualifiedAccess): ExitSafeCallNode {
return exitSafeCallNodes.pop().also {
addNewSimpleNode(it)
it.markAsDeadIfNecessary()
}
}
// -------------------------------------------------------------------------------------------------------------------------
private fun CFGNode<*>.markAsDeadIfNecessary() {
isDead = previousNodes.all { it.isDead }
isDead = incomingEdges.size == previousNodes.size && incomingEdges.values.all { it == EdgeKind.Dead }
}
private fun addNodeThatReturnsNothing(node: CFGNode<*>) {
@@ -674,22 +675,9 @@ class ControlFlowGraphBuilder {
return oldNode
}
private fun addDeadEdge(from: CFGNode<*>, to: CFGNode<*>, propagateDeadness: Boolean) {
val stub = createStubNode()
addEdge(from, stub)
addEdge(stub, to, propagateDeadness = propagateDeadness)
}
private fun addEdge(from: CFGNode<*>, to: CFGNode<*>, propagateDeadness: Boolean = true, isDead: Boolean = false) {
if (isDead) {
addDeadEdge(from, to, propagateDeadness)
return
}
if (propagateDeadness && from.isDead) {
to.isDead = true
}
from.followingNodes += to
to.previousNodes += from
val kind = if (isDead || from.isDead || to.isDead) EdgeKind.Dead else EdgeKind.Simple
CFGNode.addEdge(from, to, kind, propagateDeadness)
}
private val FirFunction<*>.invocationKind: InvocationKind?
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.resolve.dfa.cfg
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirRenderer
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirDoWhileLoop
@@ -12,75 +13,125 @@ import org.jetbrains.kotlin.fir.expressions.FirLoop
import org.jetbrains.kotlin.fir.expressions.FirWhileLoop
import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.dfa.FirControlFlowGraphReferenceImpl
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.utils.DFS
import org.jetbrains.kotlin.utils.Printer
import java.util.*
private const val INDENT = " "
private const val DEAD = "[DEAD]"
class FirControlFlowGraphRenderVisitor(
builder: StringBuilder,
) : FirVisitorVoid() {
companion object {
private const val EDGE = " -> "
private const val RED = "red"
private const val BLUE = "blue"
fun List<CFGNode<*>>.indicesMap(): Map<CFGNode<*>, Int> = mapIndexed { i, node -> node to i }.toMap()
fun ControlFlowGraph.sortNodes(): List<CFGNode<*>> {
return DFS.topologicalOrder(
nodes
) {
val result = if (it !is WhenBranchConditionExitNode || it.followingNodes.size < 2) {
it.followingNodes
} else {
it.followingNodes.sortedBy { node -> if (node is BlockEnterNode) 1 else 0 }
}
result
}
private val EDGE_STYLE = EnumMap(
mapOf(
EdgeKind.Simple to "",
EdgeKind.Dead to "[style=dotted]",
)
)
}
fun ControlFlowGraph.renderToStringBuilder(builder: StringBuilder) {
val sortedNodes = sortNodes()
private val printer = Printer(builder)
val indices = sortedNodes.indicesMap()
val notVisited = sortedNodes.toMutableSet()
val maxLineNumberSize = sortedNodes.size.toString().length
private var indexOffset = 0
private var clusterCounter = 0
fun List<CFGNode<*>>.renderEdges(nodeIsDead: Boolean): String = map {
indices.getValue(it) to it.isDead
}.sortedBy { it.first }.joinToString(", ") { (index, isDead) ->
index.toString() + if (isDead && !nodeIsDead) DEAD else ""
override fun visitFile(file: FirFile) {
printer
.println("digraph ${file.name.replace(".", "_")} {")
.pushIndent()
.println("graph [splines=ortho nodesep=3]")
.println("node [shape=box penwidth=2]")
.println("edge [penwidth=2]")
.println()
visitElement(file)
printer
.popIndent()
.println("}")
}
fun StringBuilder.renderNode(node: CFGNode<*>, index: Int) {
append(index.toString().padStart(maxLineNumberSize))
append(": ")
append(INDENT.repeat(node.level))
append(node.render())
append(" -> ")
append(node.followingNodes.renderEdges(node.isDead))
if (node.previousNodes.isNotEmpty()) {
append(" | <- ")
append(node.previousNodes.renderEdges(node.isDead))
}
appendln()
override fun visitElement(element: FirElement) {
element.acceptChildren(this)
}
with(builder) {
override fun visitControlFlowGraphReference(controlFlowGraphReference: FirControlFlowGraphReference) {
val controlFlowGraph = (controlFlowGraphReference as? FirControlFlowGraphReferenceImpl)?.controlFlowGraph ?: return
indexOffset = controlFlowGraph.dotRenderToStringBuilder(printer)
printer.println()
}
private fun Printer.enterCluster(color: String) {
println("subgraph cluster_${clusterCounter++} {")
pushIndent()
println("color=$color")
}
private fun Printer.exitCluster() {
popIndent()
println("}")
}
private fun ControlFlowGraph.dotRenderToStringBuilder(printer: Printer): Int {
with(printer) {
val graph = this@dotRenderToStringBuilder
val sortedNodes = graph.sortNodes()
val indices = sortedNodes.indicesMap().mapValues { (_, index) -> index + indexOffset }
var color = RED
sortedNodes.forEach {
if (it is EnterNode) {
enterCluster(color)
color = BLUE
}
val attributes = mutableListOf<String>()
attributes += "label=\"${it.render().replace("\"", "")}\""
if (it == enterNode || it == exitNode) {
attributes += "style=\"filled\""
attributes += "fillcolor=red"
}
if (it.isDead) {
attributes += "style=\"filled\""
attributes += "fillcolor=gray"
}
println(indices.getValue(it), attributes.joinToString(separator = " ", prefix = " [", postfix = "];"))
if (it is ExitNode) {
exitCluster()
}
}
println()
sortedNodes.forEachIndexed { i, node ->
notVisited.remove(node)
renderNode(node, i)
if (node.followingNodes.isEmpty()) return@forEachIndexed
fun renderEdges(kind: EdgeKind) {
val edges = node.followingNodes.filter { node.outgoingEdges.getValue(it) == kind }
if (edges.isEmpty()) return
print(
i + indexOffset,
EDGE,
edges.joinToString(prefix = "{", postfix = "}", separator = " ") { indices.getValue(it).toString() }
)
EDGE_STYLE.getValue(kind).takeIf { it.isNotBlank() }?.let { printWithNoIndent(" $it") }
printlnWithNoIndent(";")
}
if (notVisited.isNotEmpty()) {
appendln("Not visited nodes:")
notVisited.forEach { node ->
renderNode(node, indices.getValue(node))
for (kind in EdgeKind.values()) {
renderEdges(kind)
}
}
appendln()
return indexOffset + sortedNodes.size
}
}
}
fun ControlFlowGraph.render(): String = buildString { renderToStringBuilder(this) }
fun CFGNode<*>.render(): String =
private fun CFGNode<*>.render(): String =
buildString {
append(
when (this@render) {
@@ -154,7 +205,7 @@ fun CFGNode<*>.render(): String =
is ExitSafeCallNode -> "Exit safe call"
else -> TODO(this@render.toString())
}
},
)
}
@@ -172,3 +223,16 @@ private fun FirLoop.type(): String = when (this) {
is FirDoWhileLoop -> "do-while"
else -> throw IllegalArgumentException()
}
private fun ControlFlowGraph.sortNodes(): List<CFGNode<*>> {
return DFS.topologicalOrder(nodes) {
val result = if (it !is WhenBranchConditionExitNode || it.followingNodes.size < 2) {
it.followingNodes
} else {
it.followingNodes.sortedBy { node -> if (node is BlockEnterNode) 1 else 0 }
}
result
}
}
private fun List<CFGNode<*>>.indicesMap(): Map<CFGNode<*>, Int> = mapIndexed { i, node -> node to i }.toMap()
@@ -71,23 +71,22 @@ digraph booleanOperatorsWithConsts_kt {
23 [label="Exit left part of ||"];
24 [label="Enter right part of ||"];
25 [label="Access variable R|<local>/b|"];
26 [label="Stub" style="filled" fillcolor=gray];
27 [label="Exit ||"];
26 [label="Exit ||"];
}
28 [label="Exit when branch condition"];
27 [label="Exit when branch condition"];
}
29 [label="Synthetic else branch"];
30 [label="Enter when branch result"];
28 [label="Synthetic else branch"];
29 [label="Enter when branch result"];
subgraph cluster_9 {
color=blue
31 [label="Enter block"];
32 [label="Const: IntegerLiteral(1)"];
33 [label="Exit block"];
30 [label="Enter block"];
31 [label="Const: IntegerLiteral(1)"];
32 [label="Exit block"];
}
34 [label="Exit when branch result"];
35 [label="Exit when"];
33 [label="Exit when branch result"];
34 [label="Exit when"];
}
36 [label="Exit function test_2" style="filled" fillcolor=red];
35 [label="Exit function test_2" style="filled" fillcolor=red];
}
18 -> {19};
@@ -98,337 +97,330 @@ digraph booleanOperatorsWithConsts_kt {
23 -> {24};
23 -> {26} [style=dotted];
24 -> {25};
25 -> {27};
26 -> {27} [style=dotted];
27 -> {28};
28 -> {30 29};
29 -> {35};
25 -> {26};
26 -> {27};
27 -> {29 28};
28 -> {34};
29 -> {30};
30 -> {31};
31 -> {32};
32 -> {33};
33 -> {34};
34 -> {35};
35 -> {36};
subgraph cluster_10 {
color=red
37 [label="Enter function test_3" style="filled" fillcolor=red];
36 [label="Enter function test_3" style="filled" fillcolor=red];
subgraph cluster_11 {
color=blue
38 [label="Enter when"];
37 [label="Enter when"];
subgraph cluster_12 {
color=blue
39 [label="Enter when branch condition "];
38 [label="Enter when branch condition "];
subgraph cluster_13 {
color=blue
40 [label="Enter ||"];
41 [label="Access variable R|<local>/b|"];
42 [label="Exit left part of ||"];
43 [label="Enter right part of ||"];
44 [label="Const: Boolean(true)"];
45 [label="Exit ||"];
39 [label="Enter ||"];
40 [label="Access variable R|<local>/b|"];
41 [label="Exit left part of ||"];
42 [label="Enter right part of ||"];
43 [label="Const: Boolean(true)"];
44 [label="Exit ||"];
}
46 [label="Exit when branch condition"];
45 [label="Exit when branch condition"];
}
47 [label="Synthetic else branch"];
48 [label="Enter when branch result"];
46 [label="Synthetic else branch"];
47 [label="Enter when branch result"];
subgraph cluster_14 {
color=blue
49 [label="Enter block"];
50 [label="Const: IntegerLiteral(1)"];
51 [label="Exit block"];
48 [label="Enter block"];
49 [label="Const: IntegerLiteral(1)"];
50 [label="Exit block"];
}
52 [label="Exit when branch result"];
53 [label="Exit when"];
51 [label="Exit when branch result"];
52 [label="Exit when"];
}
54 [label="Exit function test_3" style="filled" fillcolor=red];
53 [label="Exit function test_3" style="filled" fillcolor=red];
}
36 -> {37};
37 -> {38};
38 -> {39};
39 -> {40};
40 -> {41};
41 -> {42};
42 -> {45 43};
41 -> {44 42};
42 -> {43};
43 -> {44};
44 -> {45};
45 -> {46};
46 -> {48 47};
47 -> {53};
45 -> {47 46};
46 -> {52};
47 -> {48};
48 -> {49};
49 -> {50};
50 -> {51};
51 -> {52};
52 -> {53};
53 -> {54};
subgraph cluster_15 {
color=red
55 [label="Enter function test_4" style="filled" fillcolor=red];
54 [label="Enter function test_4" style="filled" fillcolor=red];
subgraph cluster_16 {
color=blue
56 [label="Enter when"];
55 [label="Enter when"];
subgraph cluster_17 {
color=blue
57 [label="Enter when branch condition "];
56 [label="Enter when branch condition "];
subgraph cluster_18 {
color=blue
58 [label="Enter ||"];
59 [label="Const: Boolean(true)"];
60 [label="Exit left part of ||"];
61 [label="Stub" style="filled" fillcolor=gray];
62 [label="Enter right part of ||" style="filled" fillcolor=gray];
63 [label="Access variable R|<local>/b|" style="filled" fillcolor=gray];
64 [label="Exit ||"];
57 [label="Enter ||"];
58 [label="Const: Boolean(true)"];
59 [label="Exit left part of ||"];
60 [label="Enter right part of ||" style="filled" fillcolor=gray];
61 [label="Access variable R|<local>/b|" style="filled" fillcolor=gray];
62 [label="Exit ||"];
}
65 [label="Exit when branch condition"];
63 [label="Exit when branch condition"];
}
66 [label="Synthetic else branch"];
67 [label="Enter when branch result"];
64 [label="Synthetic else branch"];
65 [label="Enter when branch result"];
subgraph cluster_19 {
color=blue
68 [label="Enter block"];
69 [label="Const: IntegerLiteral(1)"];
70 [label="Exit block"];
66 [label="Enter block"];
67 [label="Const: IntegerLiteral(1)"];
68 [label="Exit block"];
}
71 [label="Exit when branch result"];
72 [label="Exit when"];
69 [label="Exit when branch result"];
70 [label="Exit when"];
}
73 [label="Exit function test_4" style="filled" fillcolor=red];
71 [label="Exit function test_4" style="filled" fillcolor=red];
}
54 -> {55};
55 -> {56};
56 -> {57};
57 -> {58};
58 -> {59};
59 -> {60};
60 -> {64};
59 -> {62};
59 -> {60} [style=dotted];
60 -> {61} [style=dotted];
61 -> {62} [style=dotted];
62 -> {63} [style=dotted];
63 -> {64} [style=dotted];
64 -> {65};
65 -> {67 66};
66 -> {72};
62 -> {63};
63 -> {65 64};
64 -> {70};
65 -> {66};
66 -> {67};
67 -> {68};
68 -> {69};
69 -> {70};
70 -> {71};
71 -> {72};
72 -> {73};
subgraph cluster_20 {
color=red
74 [label="Enter function test_5" style="filled" fillcolor=red];
72 [label="Enter function test_5" style="filled" fillcolor=red];
subgraph cluster_21 {
color=blue
75 [label="Enter when"];
73 [label="Enter when"];
subgraph cluster_22 {
color=blue
76 [label="Enter when branch condition "];
74 [label="Enter when branch condition "];
subgraph cluster_23 {
color=blue
77 [label="Enter &&"];
78 [label="Access variable R|<local>/b|"];
79 [label="Exit left part of &&"];
80 [label="Enter right part of &&"];
81 [label="Const: Boolean(false)"];
82 [label="Exit &&"];
75 [label="Enter &&"];
76 [label="Access variable R|<local>/b|"];
77 [label="Exit left part of &&"];
78 [label="Enter right part of &&"];
79 [label="Const: Boolean(false)"];
80 [label="Exit &&"];
}
83 [label="Exit when branch condition"];
81 [label="Exit when branch condition"];
}
84 [label="Synthetic else branch"];
85 [label="Enter when branch result"];
82 [label="Synthetic else branch"];
83 [label="Enter when branch result"];
subgraph cluster_24 {
color=blue
86 [label="Enter block"];
87 [label="Const: IntegerLiteral(1)"];
88 [label="Exit block"];
84 [label="Enter block"];
85 [label="Const: IntegerLiteral(1)"];
86 [label="Exit block"];
}
89 [label="Exit when branch result"];
90 [label="Exit when"];
87 [label="Exit when branch result"];
88 [label="Exit when"];
}
91 [label="Exit function test_5" style="filled" fillcolor=red];
89 [label="Exit function test_5" style="filled" fillcolor=red];
}
72 -> {73};
73 -> {74};
74 -> {75};
75 -> {76};
76 -> {77};
77 -> {78};
77 -> {80 78};
78 -> {79};
79 -> {82 80};
79 -> {80};
80 -> {81};
81 -> {82};
82 -> {83};
83 -> {85 84};
84 -> {90};
81 -> {83 82};
82 -> {88};
83 -> {84};
84 -> {85};
85 -> {86};
86 -> {87};
87 -> {88};
88 -> {89};
89 -> {90};
90 -> {91};
subgraph cluster_25 {
color=red
92 [label="Enter function test_6" style="filled" fillcolor=red];
90 [label="Enter function test_6" style="filled" fillcolor=red];
subgraph cluster_26 {
color=blue
93 [label="Enter when"];
91 [label="Enter when"];
subgraph cluster_27 {
color=blue
94 [label="Enter when branch condition "];
92 [label="Enter when branch condition "];
subgraph cluster_28 {
color=blue
95 [label="Enter &&"];
96 [label="Const: Boolean(false)"];
97 [label="Exit left part of &&"];
98 [label="Stub" style="filled" fillcolor=gray];
99 [label="Enter right part of &&" style="filled" fillcolor=gray];
100 [label="Access variable R|<local>/b|" style="filled" fillcolor=gray];
101 [label="Exit &&"];
93 [label="Enter &&"];
94 [label="Const: Boolean(false)"];
95 [label="Exit left part of &&"];
96 [label="Enter right part of &&" style="filled" fillcolor=gray];
97 [label="Access variable R|<local>/b|" style="filled" fillcolor=gray];
98 [label="Exit &&"];
}
102 [label="Exit when branch condition"];
99 [label="Exit when branch condition"];
}
103 [label="Synthetic else branch"];
104 [label="Enter when branch result"];
100 [label="Synthetic else branch"];
101 [label="Enter when branch result"];
subgraph cluster_29 {
color=blue
105 [label="Enter block"];
106 [label="Const: IntegerLiteral(1)"];
107 [label="Exit block"];
102 [label="Enter block"];
103 [label="Const: IntegerLiteral(1)"];
104 [label="Exit block"];
}
108 [label="Exit when branch result"];
109 [label="Exit when"];
105 [label="Exit when branch result"];
106 [label="Exit when"];
}
110 [label="Exit function test_6" style="filled" fillcolor=red];
107 [label="Exit function test_6" style="filled" fillcolor=red];
}
90 -> {91};
91 -> {92};
92 -> {93};
93 -> {94};
94 -> {95};
95 -> {96};
96 -> {97};
97 -> {101};
95 -> {98};
95 -> {96} [style=dotted];
96 -> {97} [style=dotted];
97 -> {98} [style=dotted];
98 -> {99} [style=dotted];
99 -> {100} [style=dotted];
100 -> {101} [style=dotted];
98 -> {99};
99 -> {101 100};
100 -> {106};
101 -> {102};
102 -> {104 103};
103 -> {109};
102 -> {103};
103 -> {104};
104 -> {105};
105 -> {106};
106 -> {107};
107 -> {108};
108 -> {109};
109 -> {110};
subgraph cluster_30 {
color=red
111 [label="Enter function test_7" style="filled" fillcolor=red];
108 [label="Enter function test_7" style="filled" fillcolor=red];
subgraph cluster_31 {
color=blue
112 [label="Enter when"];
109 [label="Enter when"];
subgraph cluster_32 {
color=blue
113 [label="Enter when branch condition "];
110 [label="Enter when branch condition "];
subgraph cluster_33 {
color=blue
114 [label="Enter &&"];
115 [label="Access variable R|<local>/b|"];
116 [label="Exit left part of &&"];
117 [label="Enter right part of &&"];
118 [label="Const: Boolean(true)"];
119 [label="Exit &&"];
111 [label="Enter &&"];
112 [label="Access variable R|<local>/b|"];
113 [label="Exit left part of &&"];
114 [label="Enter right part of &&"];
115 [label="Const: Boolean(true)"];
116 [label="Exit &&"];
}
120 [label="Exit when branch condition"];
117 [label="Exit when branch condition"];
}
121 [label="Synthetic else branch"];
122 [label="Enter when branch result"];
118 [label="Synthetic else branch"];
119 [label="Enter when branch result"];
subgraph cluster_34 {
color=blue
123 [label="Enter block"];
124 [label="Const: IntegerLiteral(1)"];
125 [label="Exit block"];
120 [label="Enter block"];
121 [label="Const: IntegerLiteral(1)"];
122 [label="Exit block"];
}
126 [label="Exit when branch result"];
127 [label="Exit when"];
123 [label="Exit when branch result"];
124 [label="Exit when"];
}
128 [label="Exit function test_7" style="filled" fillcolor=red];
125 [label="Exit function test_7" style="filled" fillcolor=red];
}
108 -> {109};
109 -> {110};
110 -> {111};
111 -> {112};
112 -> {113};
113 -> {114};
113 -> {116 114};
114 -> {115};
115 -> {116};
116 -> {119 117};
117 -> {118};
118 -> {119};
116 -> {117};
117 -> {119 118};
118 -> {124};
119 -> {120};
120 -> {122 121};
121 -> {127};
120 -> {121};
121 -> {122};
122 -> {123};
123 -> {124};
124 -> {125};
125 -> {126};
126 -> {127};
127 -> {128};
subgraph cluster_35 {
color=red
129 [label="Enter function test_8" style="filled" fillcolor=red];
126 [label="Enter function test_8" style="filled" fillcolor=red];
subgraph cluster_36 {
color=blue
130 [label="Enter when"];
127 [label="Enter when"];
subgraph cluster_37 {
color=blue
131 [label="Enter when branch condition "];
128 [label="Enter when branch condition "];
subgraph cluster_38 {
color=blue
132 [label="Enter &&"];
133 [label="Const: Boolean(true)"];
134 [label="Exit left part of &&"];
135 [label="Enter right part of &&"];
136 [label="Access variable R|<local>/b|"];
137 [label="Stub" style="filled" fillcolor=gray];
138 [label="Exit &&"];
129 [label="Enter &&"];
130 [label="Const: Boolean(true)"];
131 [label="Exit left part of &&"];
132 [label="Enter right part of &&"];
133 [label="Access variable R|<local>/b|"];
134 [label="Exit &&"];
}
139 [label="Exit when branch condition"];
135 [label="Exit when branch condition"];
}
140 [label="Synthetic else branch"];
141 [label="Enter when branch result"];
136 [label="Synthetic else branch"];
137 [label="Enter when branch result"];
subgraph cluster_39 {
color=blue
142 [label="Enter block"];
143 [label="Const: IntegerLiteral(1)"];
144 [label="Exit block"];
138 [label="Enter block"];
139 [label="Const: IntegerLiteral(1)"];
140 [label="Exit block"];
}
145 [label="Exit when branch result"];
146 [label="Exit when"];
141 [label="Exit when branch result"];
142 [label="Exit when"];
}
147 [label="Exit function test_8" style="filled" fillcolor=red];
143 [label="Exit function test_8" style="filled" fillcolor=red];
}
126 -> {127};
127 -> {128};
128 -> {129};
129 -> {130};
130 -> {131};
131 -> {132};
131 -> {134} [style=dotted];
132 -> {133};
133 -> {134};
134 -> {135};
134 -> {137} [style=dotted];
135 -> {136};
136 -> {138};
137 -> {138} [style=dotted];
135 -> {137 136};
136 -> {142};
137 -> {138};
138 -> {139};
139 -> {141 140};
140 -> {146};
139 -> {140};
140 -> {141};
141 -> {142};
142 -> {143};
143 -> {144};
144 -> {145};
145 -> {146};
146 -> {147};
}
+85 -89
View File
@@ -172,12 +172,11 @@ digraph jumps_kt {
}
64 [label="Exit loop block" style="filled" fillcolor=gray];
}
65 [label="Stub" style="filled" fillcolor=gray];
66 [label="Exit whileloop"];
65 [label="Exit whileloop"];
}
67 [label="Access variable R|<local>/x|"];
68 [label="Function call: R|<local>/x|.R|kotlin/Int.inc|()"];
69 [label="Exit function test_3" style="filled" fillcolor=red];
66 [label="Access variable R|<local>/x|"];
67 [label="Function call: R|<local>/x|.R|kotlin/Int.inc|()"];
68 [label="Exit function test_3" style="filled" fillcolor=red];
}
52 -> {53};
@@ -190,174 +189,171 @@ digraph jumps_kt {
58 -> {59};
59 -> {60};
60 -> {61};
61 -> {66};
61 -> {65};
61 -> {62} [style=dotted];
62 -> {63} [style=dotted];
63 -> {64} [style=dotted];
64 -> {54} [style=dotted];
65 -> {66} [style=dotted];
65 -> {66};
66 -> {67};
67 -> {68};
68 -> {69};
subgraph cluster_17 {
color=red
70 [label="Enter function test_4" style="filled" fillcolor=red];
69 [label="Enter function test_4" style="filled" fillcolor=red];
subgraph cluster_18 {
color=blue
71 [label="Enter do-while loop"];
70 [label="Enter do-while loop"];
subgraph cluster_19 {
color=blue
72 [label="Enter loop block"];
71 [label="Enter loop block"];
subgraph cluster_20 {
color=blue
73 [label="Enter block"];
74 [label="Access variable R|<local>/x|"];
75 [label="Type operator: x as Int"];
76 [label="Jump: break@@@[Boolean(true)] "];
77 [label="Stub" style="filled" fillcolor=gray];
78 [label="Exit block" style="filled" fillcolor=gray];
72 [label="Enter block"];
73 [label="Access variable R|<local>/x|"];
74 [label="Type operator: x as Int"];
75 [label="Jump: break@@@[Boolean(true)] "];
76 [label="Stub" style="filled" fillcolor=gray];
77 [label="Exit block" style="filled" fillcolor=gray];
}
79 [label="Exit loop block" style="filled" fillcolor=gray];
78 [label="Exit loop block" style="filled" fillcolor=gray];
}
subgraph cluster_21 {
color=blue
80 [label="Enter loop condition" style="filled" fillcolor=gray];
81 [label="Const: Boolean(true)" style="filled" fillcolor=gray];
82 [label="Exit loop condition" style="filled" fillcolor=gray];
79 [label="Enter loop condition" style="filled" fillcolor=gray];
80 [label="Const: Boolean(true)" style="filled" fillcolor=gray];
81 [label="Exit loop condition" style="filled" fillcolor=gray];
}
83 [label="Stub" style="filled" fillcolor=gray];
84 [label="Exit do-whileloop"];
82 [label="Exit do-whileloop"];
}
85 [label="Access variable R|<local>/x|"];
86 [label="Function call: R|<local>/x|.R|kotlin/Int.inc|()"];
87 [label="Exit function test_4" style="filled" fillcolor=red];
83 [label="Access variable R|<local>/x|"];
84 [label="Function call: R|<local>/x|.R|kotlin/Int.inc|()"];
85 [label="Exit function test_4" style="filled" fillcolor=red];
}
69 -> {70};
70 -> {71};
71 -> {72};
72 -> {73};
73 -> {74};
74 -> {75};
75 -> {76};
76 -> {84};
75 -> {82};
75 -> {76} [style=dotted];
76 -> {77} [style=dotted];
77 -> {78} [style=dotted];
78 -> {79} [style=dotted];
79 -> {80} [style=dotted];
80 -> {81} [style=dotted];
81 -> {82} [style=dotted];
82 -> {72 83} [style=dotted];
83 -> {84} [style=dotted];
81 -> {71 82} [style=dotted];
82 -> {83};
83 -> {84};
84 -> {85};
85 -> {86};
86 -> {87};
subgraph cluster_22 {
color=red
88 [label="Enter function test_5" style="filled" fillcolor=red];
86 [label="Enter function test_5" style="filled" fillcolor=red];
subgraph cluster_23 {
color=blue
89 [label="Enter while loop"];
87 [label="Enter while loop"];
subgraph cluster_24 {
color=blue
90 [label="Enter loop condition"];
91 [label="Access variable R|<local>/b|"];
92 [label="Exit loop condition"];
88 [label="Enter loop condition"];
89 [label="Access variable R|<local>/b|"];
90 [label="Exit loop condition"];
}
subgraph cluster_25 {
color=blue
93 [label="Enter loop block"];
91 [label="Enter loop block"];
subgraph cluster_26 {
color=blue
94 [label="Enter block"];
92 [label="Enter block"];
subgraph cluster_27 {
color=blue
95 [label="Enter when"];
93 [label="Enter when"];
subgraph cluster_28 {
color=blue
96 [label="Enter when branch condition "];
97 [label="Access variable R|<local>/b|"];
98 [label="Exit when branch condition"];
94 [label="Enter when branch condition "];
95 [label="Access variable R|<local>/b|"];
96 [label="Exit when branch condition"];
}
99 [label="Synthetic else branch"];
100 [label="Enter when branch result"];
97 [label="Synthetic else branch"];
98 [label="Enter when branch result"];
subgraph cluster_29 {
color=blue
101 [label="Enter block"];
102 [label="Jump: continue@@@[R|<local>/b|] "];
103 [label="Stub" style="filled" fillcolor=gray];
104 [label="Exit block" style="filled" fillcolor=gray];
99 [label="Enter block"];
100 [label="Jump: continue@@@[R|<local>/b|] "];
101 [label="Stub" style="filled" fillcolor=gray];
102 [label="Exit block" style="filled" fillcolor=gray];
}
105 [label="Exit when branch result" style="filled" fillcolor=gray];
106 [label="Exit when"];
103 [label="Exit when branch result" style="filled" fillcolor=gray];
104 [label="Exit when"];
}
107 [label="Exit block"];
105 [label="Exit block"];
}
108 [label="Exit loop block"];
106 [label="Exit loop block"];
}
109 [label="Exit whileloop"];
107 [label="Exit whileloop"];
}
110 [label="Exit function test_5" style="filled" fillcolor=red];
108 [label="Exit function test_5" style="filled" fillcolor=red];
}
86 -> {87};
87 -> {88};
88 -> {89};
89 -> {90};
90 -> {91};
90 -> {107 91};
91 -> {92};
92 -> {109 93};
92 -> {93};
93 -> {94};
94 -> {95};
95 -> {96};
96 -> {97};
97 -> {98};
98 -> {100 99};
99 -> {106};
100 -> {101};
101 -> {102};
102 -> {89};
96 -> {98 97};
97 -> {104};
98 -> {99};
99 -> {100};
100 -> {87};
100 -> {101} [style=dotted];
101 -> {102} [style=dotted];
102 -> {103} [style=dotted];
103 -> {104} [style=dotted];
104 -> {105} [style=dotted];
105 -> {106} [style=dotted];
106 -> {107};
104 -> {105};
105 -> {106};
106 -> {88};
107 -> {108};
108 -> {90};
109 -> {110};
subgraph cluster_30 {
color=red
111 [label="Enter function run" style="filled" fillcolor=red];
112 [label="Function call: R|<local>/block|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()"];
113 [label="Exit function run" style="filled" fillcolor=red];
109 [label="Enter function run" style="filled" fillcolor=red];
110 [label="Function call: R|<local>/block|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()"];
111 [label="Exit function run" style="filled" fillcolor=red];
}
111 -> {112};
112 -> {113};
109 -> {110};
110 -> {111};
subgraph cluster_31 {
color=red
114 [label="Enter function test_6" style="filled" fillcolor=red];
112 [label="Enter function test_6" style="filled" fillcolor=red];
subgraph cluster_32 {
color=blue
115 [label="Enter function anonymousFunction"];
116 [label="Jump: ^@run Unit"];
117 [label="Stub" style="filled" fillcolor=gray];
118 [label="Exit function anonymousFunction"];
113 [label="Enter function anonymousFunction"];
114 [label="Jump: ^@run Unit"];
115 [label="Stub" style="filled" fillcolor=gray];
116 [label="Exit function anonymousFunction"];
}
119 [label="Function call: R|/run|(<L> = run@fun <anonymous>(): R|kotlin/Unit| <kind=UNKNOWN> {
117 [label="Function call: R|/run|(<L> = run@fun <anonymous>(): R|kotlin/Unit| <kind=UNKNOWN> {
^@run Unit
}
)"];
120 [label="Exit function test_6" style="filled" fillcolor=red];
118 [label="Exit function test_6" style="filled" fillcolor=red];
}
114 -> {115};
115 -> {118 116};
116 -> {118};
116 -> {117} [style=dotted];
117 -> {118} [style=dotted];
118 -> {115 119};
119 -> {120};
112 -> {113};
113 -> {116 114};
114 -> {116};
114 -> {115} [style=dotted];
115 -> {116} [style=dotted];
116 -> {113 117};
117 -> {118};
}
+363
View File
@@ -0,0 +1,363 @@
digraph jumps_kt {
graph [splines=ortho nodesep=3]
node [shape=box penwidth=2]
edge [penwidth=2]
subgraph cluster_0 {
color=red
0 [label="Enter function test_1" style="filled" fillcolor=red];
subgraph cluster_1 {
color=blue
1 [label="Enter when"];
subgraph cluster_2 {
color=blue
2 [label="Enter when branch condition "];
3 [label="Access variable R|<local>/x|"];
4 [label="Const: Null(null)"];
5 [label="Operator =="];
6 [label="Exit when branch condition"];
}
subgraph cluster_3 {
color=blue
7 [label="Enter when branch condition else"];
8 [label="Exit when branch condition"];
}
9 [label="Enter when branch result"];
subgraph cluster_4 {
color=blue
10 [label="Enter block"];
11 [label="Access variable R|<local>/x|"];
12 [label="Exit block"];
}
13 [label="Exit when branch result"];
14 [label="Enter when branch result"];
subgraph cluster_5 {
color=blue
15 [label="Enter block"];
16 [label="Function call: R|kotlin/KotlinNullPointerException.KotlinNullPointerException|()"];
17 [label="Throw: throw R|kotlin/KotlinNullPointerException.KotlinNullPointerException|()"];
18 [label="Stub" style="filled" fillcolor=gray];
19 [label="Exit block" style="filled" fillcolor=gray];
}
20 [label="Exit when branch result" style="filled" fillcolor=gray];
21 [label="Exit when"];
}
22 [label="Variable declaration: lval y: R|kotlin/Int|"];
23 [label="Access variable R|<local>/y|"];
24 [label="Function call: R|<local>/y|.R|kotlin/Int.inc|()"];
25 [label="Access variable R|<local>/x|"];
26 [label="Function call: R|<local>/x|.R|kotlin/Int.inc|()"];
27 [label="Exit function test_1" style="filled" fillcolor=red];
}
0 -> {1};
1 -> {2};
2 -> {3};
3 -> {4};
4 -> {5};
5 -> {6};
6 -> {14 7};
7 -> {8};
8 -> {9};
9 -> {10};
10 -> {11};
11 -> {12};
12 -> {13};
13 -> {21};
14 -> {15};
15 -> {16};
16 -> {17};
17 -> {27};
17 -> {18} [style=dotted];
18 -> {19} [style=dotted];
19 -> {20} [style=dotted];
20 -> {21} [style=dotted];
21 -> {22};
22 -> {23};
23 -> {24};
24 -> {25};
25 -> {26};
26 -> {27};
subgraph cluster_6 {
color=red
28 [label="Enter function test_2" style="filled" fillcolor=red];
subgraph cluster_7 {
color=blue
29 [label="Enter when"];
subgraph cluster_8 {
color=blue
30 [label="Enter when branch condition "];
31 [label="Access variable R|<local>/x|"];
32 [label="Const: Null(null)"];
33 [label="Operator =="];
34 [label="Exit when branch condition"];
}
subgraph cluster_9 {
color=blue
35 [label="Enter when branch condition else"];
36 [label="Exit when branch condition"];
}
37 [label="Enter when branch result"];
subgraph cluster_10 {
color=blue
38 [label="Enter block"];
39 [label="Access variable R|<local>/x|"];
40 [label="Exit block"];
}
41 [label="Exit when branch result"];
42 [label="Enter when branch result"];
subgraph cluster_11 {
color=blue
43 [label="Enter block"];
44 [label="Access variable R|<local>/x|"];
45 [label="Exit block"];
}
46 [label="Exit when branch result"];
47 [label="Exit when"];
}
48 [label="Variable declaration: lval y: R|kotlin/Int?|"];
49 [label="Access variable R|<local>/y|"];
50 [label="Function call: R|<local>/y|.<Ambiguity: inc, [kotlin/inc, kotlin/inc]>#()"];
51 [label="Exit function test_2" style="filled" fillcolor=red];
}
28 -> {29};
29 -> {30};
30 -> {31};
31 -> {32};
32 -> {33};
33 -> {34};
34 -> {42 35};
35 -> {36};
36 -> {37};
37 -> {38};
38 -> {39};
39 -> {40};
40 -> {41};
41 -> {47};
42 -> {43};
43 -> {44};
44 -> {45};
45 -> {46};
46 -> {47};
47 -> {48};
48 -> {49};
49 -> {50};
50 -> {51};
subgraph cluster_12 {
color=red
52 [label="Enter function test_3" style="filled" fillcolor=red];
subgraph cluster_13 {
color=blue
53 [label="Enter while loop"];
subgraph cluster_14 {
color=blue
54 [label="Enter loop condition"];
55 [label="Const: Boolean(true)"];
56 [label="Exit loop condition"];
}
subgraph cluster_15 {
color=blue
57 [label="Enter loop block"];
subgraph cluster_16 {
color=blue
58 [label="Enter block"];
59 [label="Access variable R|<local>/x|"];
60 [label="Type operator: x as Int"];
61 [label="Jump: break@@@[Boolean(true)] "];
62 [label="Stub" style="filled" fillcolor=gray];
63 [label="Exit block" style="filled" fillcolor=gray];
}
64 [label="Exit loop block" style="filled" fillcolor=gray];
}
65 [label="Stub" style="filled" fillcolor=gray];
66 [label="Exit whileloop"];
}
67 [label="Access variable R|<local>/x|"];
68 [label="Function call: R|<local>/x|.R|kotlin/Int.inc|()"];
69 [label="Exit function test_3" style="filled" fillcolor=red];
}
52 -> {53};
53 -> {54};
54 -> {55};
55 -> {56};
56 -> {57};
56 -> {65} [style=dotted];
57 -> {58};
58 -> {59};
59 -> {60};
60 -> {61};
61 -> {66};
61 -> {62} [style=dotted];
62 -> {63} [style=dotted];
63 -> {64} [style=dotted];
64 -> {54} [style=dotted];
65 -> {66} [style=dotted];
66 -> {67};
67 -> {68};
68 -> {69};
subgraph cluster_17 {
color=red
70 [label="Enter function test_4" style="filled" fillcolor=red];
subgraph cluster_18 {
color=blue
71 [label="Enter do-while loop"];
subgraph cluster_19 {
color=blue
72 [label="Enter loop block"];
subgraph cluster_20 {
color=blue
73 [label="Enter block"];
74 [label="Access variable R|<local>/x|"];
75 [label="Type operator: x as Int"];
76 [label="Jump: break@@@[Boolean(true)] "];
77 [label="Stub" style="filled" fillcolor=gray];
78 [label="Exit block" style="filled" fillcolor=gray];
}
79 [label="Exit loop block" style="filled" fillcolor=gray];
}
subgraph cluster_21 {
color=blue
80 [label="Enter loop condition" style="filled" fillcolor=gray];
81 [label="Const: Boolean(true)" style="filled" fillcolor=gray];
82 [label="Exit loop condition" style="filled" fillcolor=gray];
}
83 [label="Stub" style="filled" fillcolor=gray];
84 [label="Exit do-whileloop"];
}
85 [label="Access variable R|<local>/x|"];
86 [label="Function call: R|<local>/x|.R|kotlin/Int.inc|()"];
87 [label="Exit function test_4" style="filled" fillcolor=red];
}
70 -> {71};
71 -> {72};
72 -> {73};
73 -> {74};
74 -> {75};
75 -> {76};
76 -> {84};
76 -> {77} [style=dotted];
77 -> {78} [style=dotted];
78 -> {79} [style=dotted];
79 -> {80} [style=dotted];
80 -> {81} [style=dotted];
81 -> {82} [style=dotted];
82 -> {72 83} [style=dotted];
83 -> {84} [style=dotted];
84 -> {85};
85 -> {86};
86 -> {87};
subgraph cluster_22 {
color=red
88 [label="Enter function test_5" style="filled" fillcolor=red];
subgraph cluster_23 {
color=blue
89 [label="Enter while loop"];
subgraph cluster_24 {
color=blue
90 [label="Enter loop condition"];
91 [label="Access variable R|<local>/b|"];
92 [label="Exit loop condition"];
}
subgraph cluster_25 {
color=blue
93 [label="Enter loop block"];
subgraph cluster_26 {
color=blue
94 [label="Enter block"];
subgraph cluster_27 {
color=blue
95 [label="Enter when"];
subgraph cluster_28 {
color=blue
96 [label="Enter when branch condition "];
97 [label="Access variable R|<local>/b|"];
98 [label="Exit when branch condition"];
}
99 [label="Synthetic else branch"];
100 [label="Enter when branch result"];
subgraph cluster_29 {
color=blue
101 [label="Enter block"];
102 [label="Jump: continue@@@[R|<local>/b|] "];
103 [label="Stub" style="filled" fillcolor=gray];
104 [label="Exit block" style="filled" fillcolor=gray];
}
105 [label="Exit when branch result" style="filled" fillcolor=gray];
106 [label="Exit when"];
}
107 [label="Exit block"];
}
108 [label="Exit loop block"];
}
109 [label="Exit whileloop"];
}
110 [label="Exit function test_5" style="filled" fillcolor=red];
}
88 -> {89};
89 -> {90};
90 -> {91};
91 -> {92};
92 -> {109 93};
93 -> {94};
94 -> {95};
95 -> {96};
96 -> {97};
97 -> {98};
98 -> {100 99};
99 -> {106};
100 -> {101};
101 -> {102};
102 -> {89};
102 -> {103} [style=dotted];
103 -> {104} [style=dotted];
104 -> {105} [style=dotted];
105 -> {106} [style=dotted];
106 -> {107};
107 -> {108};
108 -> {90};
109 -> {110};
subgraph cluster_30 {
color=red
111 [label="Enter function run" style="filled" fillcolor=red];
112 [label="Function call: R|<local>/block|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()"];
113 [label="Exit function run" style="filled" fillcolor=red];
}
111 -> {112};
112 -> {113};
subgraph cluster_31 {
color=red
114 [label="Enter function test_6" style="filled" fillcolor=red];
subgraph cluster_32 {
color=blue
115 [label="Enter function anonymousFunction"];
116 [label="Jump: ^@run Unit"];
117 [label="Stub" style="filled" fillcolor=gray];
118 [label="Exit function anonymousFunction"];
}
119 [label="Function call: R|/run|(<L> = run@fun <anonymous>(): R|kotlin/Unit| <kind=UNKNOWN> {
^@run Unit
}
)"];
120 [label="Exit function test_6" style="filled" fillcolor=red];
}
114 -> {115};
115 -> {118 116};
116 -> {118};
116 -> {117} [style=dotted];
117 -> {118} [style=dotted];
118 -> {115 119};
119 -> {120};
}
+358
View File
@@ -0,0 +1,358 @@
digraph jumps_kt {
graph [splines=ortho nodesep=3]
node [shape=box penwidth=2]
edge [penwidth=2]
subgraph cluster_0 {
color=red
0 [label="Enter function test_1" style="filled" fillcolor=red];
subgraph cluster_1 {
color=blue
1 [label="Enter when"];
subgraph cluster_2 {
color=blue
2 [label="Enter when branch condition "];
3 [label="Access variable R|<local>/x|"];
4 [label="Const: Null(null)"];
5 [label="Operator =="];
6 [label="Exit when branch condition"];
}
subgraph cluster_3 {
color=blue
7 [label="Enter when branch condition else"];
8 [label="Exit when branch condition"];
}
9 [label="Enter when branch result"];
subgraph cluster_4 {
color=blue
10 [label="Enter block"];
11 [label="Access variable R|<local>/x|"];
12 [label="Exit block"];
}
13 [label="Exit when branch result"];
14 [label="Enter when branch result"];
subgraph cluster_5 {
color=blue
15 [label="Enter block"];
16 [label="Function call: R|kotlin/KotlinNullPointerException.KotlinNullPointerException|()"];
17 [label="Throw: throw R|kotlin/KotlinNullPointerException.KotlinNullPointerException|()"];
18 [label="Stub" style="filled" fillcolor=gray];
19 [label="Exit block" style="filled" fillcolor=gray];
}
20 [label="Exit when branch result" style="filled" fillcolor=gray];
21 [label="Exit when"];
}
22 [label="Variable declaration: lval y: R|kotlin/Int|"];
23 [label="Access variable R|<local>/y|"];
24 [label="Function call: R|<local>/y|.R|kotlin/Int.inc|()"];
25 [label="Access variable R|<local>/x|"];
26 [label="Function call: R|<local>/x|.R|kotlin/Int.inc|()"];
27 [label="Exit function test_1" style="filled" fillcolor=red];
}
0 -> {1};
1 -> {2};
2 -> {3};
3 -> {4};
4 -> {5};
5 -> {6};
6 -> {14 7};
7 -> {8};
8 -> {9};
9 -> {10};
10 -> {11};
11 -> {12};
12 -> {13};
13 -> {21};
14 -> {15};
15 -> {16};
16 -> {17};
17 -> {27};
17 -> {18} [style=dotted];
18 -> {19} [style=dotted];
19 -> {20} [style=dotted];
20 -> {21} [style=dotted];
21 -> {22};
22 -> {23};
23 -> {24};
24 -> {25};
25 -> {26};
26 -> {27};
subgraph cluster_6 {
color=red
28 [label="Enter function test_2" style="filled" fillcolor=red];
subgraph cluster_7 {
color=blue
29 [label="Enter when"];
subgraph cluster_8 {
color=blue
30 [label="Enter when branch condition "];
31 [label="Access variable R|<local>/x|"];
32 [label="Const: Null(null)"];
33 [label="Operator =="];
34 [label="Exit when branch condition"];
}
subgraph cluster_9 {
color=blue
35 [label="Enter when branch condition else"];
36 [label="Exit when branch condition"];
}
37 [label="Enter when branch result"];
subgraph cluster_10 {
color=blue
38 [label="Enter block"];
39 [label="Access variable R|<local>/x|"];
40 [label="Exit block"];
}
41 [label="Exit when branch result"];
42 [label="Enter when branch result"];
subgraph cluster_11 {
color=blue
43 [label="Enter block"];
44 [label="Access variable R|<local>/x|"];
45 [label="Exit block"];
}
46 [label="Exit when branch result"];
47 [label="Exit when"];
}
48 [label="Variable declaration: lval y: R|kotlin/Int?|"];
49 [label="Access variable R|<local>/y|"];
50 [label="Function call: R|<local>/y|.<Ambiguity: inc, [kotlin/inc, kotlin/inc]>#()"];
51 [label="Exit function test_2" style="filled" fillcolor=red];
}
28 -> {29};
29 -> {30};
30 -> {31};
31 -> {32};
32 -> {33};
33 -> {34};
34 -> {42 35};
35 -> {36};
36 -> {37};
37 -> {38};
38 -> {39};
39 -> {40};
40 -> {41};
41 -> {47};
42 -> {43};
43 -> {44};
44 -> {45};
45 -> {46};
46 -> {47};
47 -> {48};
48 -> {49};
49 -> {50};
50 -> {51};
subgraph cluster_12 {
color=red
52 [label="Enter function test_3" style="filled" fillcolor=red];
subgraph cluster_13 {
color=blue
53 [label="Enter while loop"];
subgraph cluster_14 {
color=blue
54 [label="Enter loop condition"];
55 [label="Const: Boolean(true)"];
56 [label="Exit loop condition"];
}
subgraph cluster_15 {
color=blue
57 [label="Enter loop block"];
subgraph cluster_16 {
color=blue
58 [label="Enter block"];
59 [label="Access variable R|<local>/x|"];
60 [label="Type operator: x as Int"];
61 [label="Jump: break@@@[Boolean(true)] "];
62 [label="Stub" style="filled" fillcolor=gray];
63 [label="Exit block" style="filled" fillcolor=gray];
}
64 [label="Exit loop block" style="filled" fillcolor=gray];
}
65 [label="Exit whileloop"];
}
66 [label="Access variable R|<local>/x|"];
67 [label="Function call: R|<local>/x|.R|kotlin/Int.inc|()"];
68 [label="Exit function test_3" style="filled" fillcolor=red];
}
52 -> {53};
53 -> {54};
54 -> {55};
55 -> {56};
56 -> {65 57};
57 -> {58};
58 -> {59};
59 -> {60};
60 -> {61};
61 -> {65};
61 -> {62} [style=dotted];
62 -> {63} [style=dotted];
63 -> {64} [style=dotted];
64 -> {54} [style=dotted];
65 -> {66};
66 -> {67};
67 -> {68};
subgraph cluster_17 {
color=red
69 [label="Enter function test_4" style="filled" fillcolor=red];
subgraph cluster_18 {
color=blue
70 [label="Enter do-while loop"];
subgraph cluster_19 {
color=blue
71 [label="Enter loop block"];
subgraph cluster_20 {
color=blue
72 [label="Enter block"];
73 [label="Access variable R|<local>/x|"];
74 [label="Type operator: x as Int"];
75 [label="Jump: break@@@[Boolean(true)] "];
76 [label="Stub" style="filled" fillcolor=gray];
77 [label="Exit block" style="filled" fillcolor=gray];
}
78 [label="Exit loop block" style="filled" fillcolor=gray];
}
subgraph cluster_21 {
color=blue
79 [label="Enter loop condition" style="filled" fillcolor=gray];
80 [label="Const: Boolean(true)" style="filled" fillcolor=gray];
81 [label="Exit loop condition" style="filled" fillcolor=gray];
}
82 [label="Exit do-whileloop"];
}
83 [label="Access variable R|<local>/x|"];
84 [label="Function call: R|<local>/x|.R|kotlin/Int.inc|()"];
85 [label="Exit function test_4" style="filled" fillcolor=red];
}
69 -> {70};
70 -> {71};
71 -> {72};
72 -> {73};
73 -> {74};
74 -> {75};
75 -> {82};
75 -> {76} [style=dotted];
76 -> {77} [style=dotted];
77 -> {78} [style=dotted];
78 -> {79} [style=dotted];
79 -> {80} [style=dotted];
80 -> {81} [style=dotted];
81 -> {71 82} [style=dotted];
82 -> {83};
83 -> {84};
84 -> {85};
subgraph cluster_22 {
color=red
86 [label="Enter function test_5" style="filled" fillcolor=red];
subgraph cluster_23 {
color=blue
87 [label="Enter while loop"];
subgraph cluster_24 {
color=blue
88 [label="Enter loop condition"];
89 [label="Access variable R|<local>/b|"];
90 [label="Exit loop condition"];
}
subgraph cluster_25 {
color=blue
91 [label="Enter loop block"];
subgraph cluster_26 {
color=blue
92 [label="Enter block"];
subgraph cluster_27 {
color=blue
93 [label="Enter when"];
subgraph cluster_28 {
color=blue
94 [label="Enter when branch condition "];
95 [label="Access variable R|<local>/b|"];
96 [label="Exit when branch condition"];
}
97 [label="Synthetic else branch"];
98 [label="Enter when branch result"];
subgraph cluster_29 {
color=blue
99 [label="Enter block"];
100 [label="Jump: continue@@@[R|<local>/b|] "];
101 [label="Stub" style="filled" fillcolor=gray];
102 [label="Exit block" style="filled" fillcolor=gray];
}
103 [label="Exit when branch result" style="filled" fillcolor=gray];
104 [label="Exit when"];
}
105 [label="Exit block"];
}
106 [label="Exit loop block"];
}
107 [label="Exit whileloop"];
}
108 [label="Exit function test_5" style="filled" fillcolor=red];
}
86 -> {87};
87 -> {88};
88 -> {89};
89 -> {90};
90 -> {107 91};
91 -> {92};
92 -> {93};
93 -> {94};
94 -> {95};
95 -> {96};
96 -> {98 97};
97 -> {104};
98 -> {99};
99 -> {100};
100 -> {87};
100 -> {101} [style=dotted];
101 -> {102} [style=dotted];
102 -> {103} [style=dotted];
103 -> {104} [style=dotted];
104 -> {105};
105 -> {106};
106 -> {88};
107 -> {108};
subgraph cluster_30 {
color=red
109 [label="Enter function run" style="filled" fillcolor=red];
110 [label="Function call: R|<local>/block|.R|FakeOverride<kotlin/Function0.invoke: R|kotlin/Unit|>|()"];
111 [label="Exit function run" style="filled" fillcolor=red];
}
109 -> {110};
110 -> {111};
subgraph cluster_31 {
color=red
112 [label="Enter function test_6" style="filled" fillcolor=red];
subgraph cluster_32 {
color=blue
113 [label="Enter function anonymousFunction"];
114 [label="Jump: ^@run Unit"];
115 [label="Stub" style="filled" fillcolor=gray];
116 [label="Exit function anonymousFunction"];
}
117 [label="Function call: R|/run|(<L> = run@fun <anonymous>(): R|kotlin/Unit| <kind=UNKNOWN> {
^@run Unit
}
)"];
118 [label="Exit function test_6" style="filled" fillcolor=red];
}
112 -> {113};
113 -> {116 114};
114 -> {116};
114 -> {115} [style=dotted];
115 -> {116} [style=dotted];
116 -> {113 117};
117 -> {118};
}
+139 -151
View File
@@ -192,11 +192,10 @@ digraph loops_kt {
}
68 [label="Exit loop block"];
}
69 [label="Stub" style="filled" fillcolor=gray];
70 [label="Exit whileloop" style="filled" fillcolor=gray];
69 [label="Exit whileloop" style="filled" fillcolor=gray];
}
71 [label="Const: Int(1)" style="filled" fillcolor=gray];
72 [label="Exit function testWhileTrue" style="filled" fillcolor=red style="filled" fillcolor=gray];
70 [label="Const: Int(1)" style="filled" fillcolor=gray];
71 [label="Exit function testWhileTrue" style="filled" fillcolor=red style="filled" fillcolor=gray];
}
59 -> {60};
@@ -212,295 +211,284 @@ digraph loops_kt {
68 -> {61};
69 -> {70} [style=dotted];
70 -> {71} [style=dotted];
71 -> {72} [style=dotted];
subgraph cluster_20 {
color=red
73 [label="Enter function testWhileTrueWithBreak" style="filled" fillcolor=red];
72 [label="Enter function testWhileTrueWithBreak" style="filled" fillcolor=red];
subgraph cluster_21 {
color=blue
74 [label="Enter while loop"];
73 [label="Enter while loop"];
subgraph cluster_22 {
color=blue
75 [label="Enter loop condition"];
76 [label="Const: Boolean(true)"];
77 [label="Exit loop condition"];
74 [label="Enter loop condition"];
75 [label="Const: Boolean(true)"];
76 [label="Exit loop condition"];
}
subgraph cluster_23 {
color=blue
78 [label="Enter loop block"];
77 [label="Enter loop block"];
subgraph cluster_24 {
color=blue
79 [label="Enter block"];
78 [label="Enter block"];
subgraph cluster_25 {
color=blue
80 [label="Enter when"];
79 [label="Enter when"];
subgraph cluster_26 {
color=blue
81 [label="Enter when branch condition "];
82 [label="Access variable R|<local>/b|"];
83 [label="Exit when branch condition"];
80 [label="Enter when branch condition "];
81 [label="Access variable R|<local>/b|"];
82 [label="Exit when branch condition"];
}
84 [label="Synthetic else branch"];
85 [label="Enter when branch result"];
83 [label="Synthetic else branch"];
84 [label="Enter when branch result"];
subgraph cluster_27 {
color=blue
86 [label="Enter block"];
87 [label="Jump: break@@@[Boolean(true)] "];
88 [label="Stub" style="filled" fillcolor=gray];
89 [label="Exit block" style="filled" fillcolor=gray];
85 [label="Enter block"];
86 [label="Jump: break@@@[Boolean(true)] "];
87 [label="Stub" style="filled" fillcolor=gray];
88 [label="Exit block" style="filled" fillcolor=gray];
}
90 [label="Exit when branch result" style="filled" fillcolor=gray];
91 [label="Exit when"];
89 [label="Exit when branch result" style="filled" fillcolor=gray];
90 [label="Exit when"];
}
92 [label="Exit block"];
91 [label="Exit block"];
}
93 [label="Exit loop block"];
92 [label="Exit loop block"];
}
94 [label="Stub" style="filled" fillcolor=gray];
95 [label="Exit whileloop"];
93 [label="Exit whileloop"];
}
96 [label="Const: Int(1)"];
97 [label="Exit function testWhileTrueWithBreak" style="filled" fillcolor=red];
94 [label="Const: Int(1)"];
95 [label="Exit function testWhileTrueWithBreak" style="filled" fillcolor=red];
}
72 -> {73};
73 -> {74};
74 -> {75};
75 -> {76};
76 -> {77};
76 -> {93} [style=dotted];
77 -> {78};
77 -> {94} [style=dotted];
78 -> {79};
79 -> {80};
80 -> {81};
81 -> {82};
82 -> {83};
83 -> {85 84};
84 -> {91};
82 -> {84 83};
83 -> {90};
84 -> {85};
85 -> {86};
86 -> {87};
87 -> {95};
86 -> {93};
86 -> {87} [style=dotted];
87 -> {88} [style=dotted];
88 -> {89} [style=dotted];
89 -> {90} [style=dotted];
90 -> {91} [style=dotted];
90 -> {91};
91 -> {92};
92 -> {93};
93 -> {75};
94 -> {95} [style=dotted];
95 -> {96};
96 -> {97};
92 -> {74};
93 -> {94};
94 -> {95};
subgraph cluster_28 {
color=red
98 [label="Enter function testWhileFalse" style="filled" fillcolor=red];
96 [label="Enter function testWhileFalse" style="filled" fillcolor=red];
subgraph cluster_29 {
color=blue
99 [label="Enter while loop"];
97 [label="Enter while loop"];
subgraph cluster_30 {
color=blue
100 [label="Enter loop condition"];
101 [label="Const: Boolean(false)"];
102 [label="Exit loop condition"];
98 [label="Enter loop condition"];
99 [label="Const: Boolean(false)"];
100 [label="Exit loop condition"];
}
103 [label="Stub" style="filled" fillcolor=gray];
subgraph cluster_31 {
color=blue
104 [label="Enter loop block" style="filled" fillcolor=gray];
101 [label="Enter loop block" style="filled" fillcolor=gray];
subgraph cluster_32 {
color=blue
105 [label="Enter block" style="filled" fillcolor=gray];
106 [label="Const: Int(1)" style="filled" fillcolor=gray];
107 [label="Exit block" style="filled" fillcolor=gray];
102 [label="Enter block" style="filled" fillcolor=gray];
103 [label="Const: Int(1)" style="filled" fillcolor=gray];
104 [label="Exit block" style="filled" fillcolor=gray];
}
108 [label="Exit loop block" style="filled" fillcolor=gray];
105 [label="Exit loop block" style="filled" fillcolor=gray];
}
109 [label="Exit whileloop"];
106 [label="Exit whileloop"];
}
110 [label="Const: Int(1)"];
111 [label="Exit function testWhileFalse" style="filled" fillcolor=red];
107 [label="Const: Int(1)"];
108 [label="Exit function testWhileFalse" style="filled" fillcolor=red];
}
96 -> {97};
97 -> {98};
98 -> {99};
99 -> {100};
100 -> {101};
101 -> {102};
102 -> {109};
100 -> {106};
100 -> {101} [style=dotted];
101 -> {102} [style=dotted];
102 -> {103} [style=dotted];
103 -> {104} [style=dotted];
104 -> {105} [style=dotted];
105 -> {106} [style=dotted];
106 -> {107} [style=dotted];
107 -> {108} [style=dotted];
108 -> {100} [style=dotted];
109 -> {110};
110 -> {111};
105 -> {98} [style=dotted];
106 -> {107};
107 -> {108};
subgraph cluster_33 {
color=red
112 [label="Enter function testDoWhileTrue" style="filled" fillcolor=red];
109 [label="Enter function testDoWhileTrue" style="filled" fillcolor=red];
subgraph cluster_34 {
color=blue
113 [label="Enter do-while loop"];
110 [label="Enter do-while loop"];
subgraph cluster_35 {
color=blue
114 [label="Enter loop block"];
111 [label="Enter loop block"];
subgraph cluster_36 {
color=blue
115 [label="Enter block"];
116 [label="Const: Int(1)"];
117 [label="Exit block"];
112 [label="Enter block"];
113 [label="Const: Int(1)"];
114 [label="Exit block"];
}
118 [label="Exit loop block"];
115 [label="Exit loop block"];
}
subgraph cluster_37 {
color=blue
119 [label="Enter loop condition"];
120 [label="Const: Boolean(true)"];
121 [label="Exit loop condition"];
116 [label="Enter loop condition"];
117 [label="Const: Boolean(true)"];
118 [label="Exit loop condition"];
}
122 [label="Stub" style="filled" fillcolor=gray];
123 [label="Exit do-whileloop" style="filled" fillcolor=gray];
119 [label="Exit do-whileloop" style="filled" fillcolor=gray];
}
124 [label="Const: Int(1)" style="filled" fillcolor=gray];
125 [label="Exit function testDoWhileTrue" style="filled" fillcolor=red style="filled" fillcolor=gray];
120 [label="Const: Int(1)" style="filled" fillcolor=gray];
121 [label="Exit function testDoWhileTrue" style="filled" fillcolor=red style="filled" fillcolor=gray];
}
109 -> {110};
110 -> {111};
111 -> {112};
112 -> {113};
113 -> {114};
114 -> {115};
115 -> {116};
116 -> {117};
117 -> {118};
118 -> {119};
119 -> {120};
120 -> {121};
121 -> {114};
121 -> {122} [style=dotted];
122 -> {123} [style=dotted];
123 -> {124} [style=dotted];
124 -> {125} [style=dotted];
118 -> {111};
118 -> {119} [style=dotted];
119 -> {120} [style=dotted];
120 -> {121} [style=dotted];
subgraph cluster_38 {
color=red
126 [label="Enter function testDoWhileTrueWithBreak" style="filled" fillcolor=red];
122 [label="Enter function testDoWhileTrueWithBreak" style="filled" fillcolor=red];
subgraph cluster_39 {
color=blue
127 [label="Enter do-while loop"];
123 [label="Enter do-while loop"];
subgraph cluster_40 {
color=blue
128 [label="Enter loop block"];
124 [label="Enter loop block"];
subgraph cluster_41 {
color=blue
129 [label="Enter block"];
125 [label="Enter block"];
subgraph cluster_42 {
color=blue
130 [label="Enter when"];
126 [label="Enter when"];
subgraph cluster_43 {
color=blue
131 [label="Enter when branch condition "];
132 [label="Access variable R|<local>/b|"];
133 [label="Exit when branch condition"];
127 [label="Enter when branch condition "];
128 [label="Access variable R|<local>/b|"];
129 [label="Exit when branch condition"];
}
134 [label="Synthetic else branch"];
135 [label="Enter when branch result"];
130 [label="Synthetic else branch"];
131 [label="Enter when branch result"];
subgraph cluster_44 {
color=blue
136 [label="Enter block"];
137 [label="Jump: break@@@[Boolean(true)] "];
138 [label="Stub" style="filled" fillcolor=gray];
139 [label="Exit block" style="filled" fillcolor=gray];
132 [label="Enter block"];
133 [label="Jump: break@@@[Boolean(true)] "];
134 [label="Stub" style="filled" fillcolor=gray];
135 [label="Exit block" style="filled" fillcolor=gray];
}
140 [label="Exit when branch result" style="filled" fillcolor=gray];
141 [label="Exit when"];
136 [label="Exit when branch result" style="filled" fillcolor=gray];
137 [label="Exit when"];
}
142 [label="Exit block"];
138 [label="Exit block"];
}
143 [label="Exit loop block"];
139 [label="Exit loop block"];
}
subgraph cluster_45 {
color=blue
144 [label="Enter loop condition"];
145 [label="Const: Boolean(true)"];
146 [label="Exit loop condition"];
140 [label="Enter loop condition"];
141 [label="Const: Boolean(true)"];
142 [label="Exit loop condition"];
}
147 [label="Stub" style="filled" fillcolor=gray];
148 [label="Exit do-whileloop"];
143 [label="Exit do-whileloop"];
}
149 [label="Const: Int(1)"];
150 [label="Exit function testDoWhileTrueWithBreak" style="filled" fillcolor=red];
144 [label="Const: Int(1)"];
145 [label="Exit function testDoWhileTrueWithBreak" style="filled" fillcolor=red];
}
122 -> {123};
123 -> {124};
124 -> {125};
125 -> {126};
126 -> {127};
127 -> {128};
128 -> {129};
129 -> {130};
130 -> {131};
129 -> {131 130};
130 -> {137};
131 -> {132};
132 -> {133};
133 -> {135 134};
134 -> {141};
135 -> {136};
136 -> {137};
137 -> {148};
137 -> {138} [style=dotted];
138 -> {139} [style=dotted];
139 -> {140} [style=dotted];
140 -> {141} [style=dotted];
133 -> {143};
133 -> {134} [style=dotted];
134 -> {135} [style=dotted];
135 -> {136} [style=dotted];
136 -> {137} [style=dotted];
137 -> {138};
138 -> {139};
139 -> {140};
140 -> {141};
141 -> {142};
142 -> {143};
142 -> {124};
142 -> {143} [style=dotted];
143 -> {144};
144 -> {145};
145 -> {146};
146 -> {128};
146 -> {147} [style=dotted];
147 -> {148} [style=dotted];
148 -> {149};
149 -> {150};
subgraph cluster_46 {
color=red
151 [label="Enter function testDoWhileFalse" style="filled" fillcolor=red];
146 [label="Enter function testDoWhileFalse" style="filled" fillcolor=red];
subgraph cluster_47 {
color=blue
152 [label="Enter do-while loop"];
147 [label="Enter do-while loop"];
subgraph cluster_48 {
color=blue
153 [label="Enter loop block"];
148 [label="Enter loop block"];
subgraph cluster_49 {
color=blue
154 [label="Enter block"];
155 [label="Const: Int(1)"];
156 [label="Exit block"];
149 [label="Enter block"];
150 [label="Const: Int(1)"];
151 [label="Exit block"];
}
157 [label="Exit loop block"];
152 [label="Exit loop block"];
}
subgraph cluster_50 {
color=blue
158 [label="Enter loop condition"];
159 [label="Const: Boolean(false)"];
160 [label="Exit loop condition"];
153 [label="Enter loop condition"];
154 [label="Const: Boolean(false)"];
155 [label="Exit loop condition"];
}
161 [label="Exit do-whileloop"];
156 [label="Exit do-whileloop"];
}
162 [label="Const: Int(1)"];
163 [label="Exit function testDoWhileFalse" style="filled" fillcolor=red];
157 [label="Const: Int(1)"];
158 [label="Exit function testDoWhileFalse" style="filled" fillcolor=red];
}
164 [label="Stub" style="filled" fillcolor=gray];
146 -> {147};
147 -> {148};
148 -> {149};
149 -> {150};
150 -> {151};
151 -> {152};
152 -> {153};
153 -> {154};
154 -> {155};
155 -> {156};
155 -> {148} [style=dotted];
156 -> {157};
157 -> {158};
158 -> {159};
159 -> {160};
160 -> {161};
160 -> {164} [style=dotted];
161 -> {162};
162 -> {163};
164 -> {153} [style=dotted];
}
+11 -13
View File
@@ -229,12 +229,11 @@ digraph tryCatch_kt {
}
92 [label="Exit loop block"];
}
93 [label="Stub" style="filled" fillcolor=gray];
94 [label="Exit whileloop"];
93 [label="Exit whileloop"];
}
95 [label="Const: Int(3)"];
96 [label="Variable declaration: lval z: R|kotlin/Int|"];
97 [label="Exit function test_3" style="filled" fillcolor=red];
94 [label="Const: Int(3)"];
95 [label="Variable declaration: lval z: R|kotlin/Int|"];
96 [label="Exit function test_3" style="filled" fillcolor=red];
}
37 -> {38};
@@ -246,7 +245,7 @@ digraph tryCatch_kt {
42 -> {43};
43 -> {44};
44 -> {45};
45 -> {97 82 76 46};
45 -> {96 82 76 46};
46 -> {47};
47 -> {48};
48 -> {49};
@@ -255,7 +254,7 @@ digraph tryCatch_kt {
51 -> {58};
52 -> {53};
53 -> {54};
54 -> {97};
54 -> {96};
54 -> {55} [style=dotted];
55 -> {56} [style=dotted];
56 -> {57} [style=dotted];
@@ -271,7 +270,7 @@ digraph tryCatch_kt {
66 -> {73};
67 -> {68};
68 -> {69};
69 -> {94};
69 -> {93};
69 -> {70} [style=dotted];
70 -> {71} [style=dotted];
71 -> {72} [style=dotted];
@@ -279,14 +278,14 @@ digraph tryCatch_kt {
73 -> {74};
74 -> {75};
75 -> {88};
76 -> {97 77};
76 -> {96 77};
77 -> {78};
78 -> {94};
78 -> {93};
78 -> {79} [style=dotted];
79 -> {80} [style=dotted];
80 -> {81} [style=dotted];
81 -> {88} [style=dotted];
82 -> {97 83};
82 -> {96 83};
83 -> {84};
84 -> {38};
84 -> {85} [style=dotted];
@@ -298,9 +297,8 @@ digraph tryCatch_kt {
90 -> {91};
91 -> {92};
92 -> {39};
93 -> {94} [style=dotted];
93 -> {94};
94 -> {95};
95 -> {96};
96 -> {97};
}
@@ -289,14 +289,14 @@ digraph booleanOperators_kt {
101 [label="Enter when branch condition "];
subgraph cluster_26 {
color=blue
102 [label="Enter ||"];
102 [label="Enter &&"];
103 [label="Access variable R|<local>/x|"];
104 [label="Const: Null(null)"];
105 [label="Operator !="];
106 [label="Exit left part of ||"];
107 [label="Enter right part of ||"];
108 [label="Const: Boolean(false)"];
109 [label="Exit ||"];
104 [label="Type operator: x is A"];
105 [label="Exit left part of &&"];
106 [label="Enter right part of &&"];
107 [label="Access variable R|<local>/x|"];
108 [label="Function call: R|<local>/x|.R|/A.bool|()"];
109 [label="Exit &&"];
}
110 [label="Exit when branch condition"];
}
@@ -306,7 +306,7 @@ digraph booleanOperators_kt {
color=blue
113 [label="Enter block"];
114 [label="Access variable R|<local>/x|"];
115 [label="Function call: R|<local>/x|.<Inapplicable(WRONG_RECEIVER): [/A.foo]>#()"];
115 [label="Function call: R|<local>/x|.R|/A.foo|()"];
116 [label="Exit block"];
}
117 [label="Exit when branch result"];
@@ -321,8 +321,8 @@ digraph booleanOperators_kt {
102 -> {103};
103 -> {104};
104 -> {105};
105 -> {106};
106 -> {109 107};
105 -> {109 106};
106 -> {107};
107 -> {108};
108 -> {109};
109 -> {110};
@@ -345,33 +345,24 @@ digraph booleanOperators_kt {
subgraph cluster_30 {
color=blue
122 [label="Enter when branch condition "];
123 [label="Access variable R|<local>/x|"];
124 [label="Type operator: x !is A"];
125 [label="Function call: (R|<local>/x| !is R|A|).R|kotlin/Boolean.not|()"];
126 [label="Exit when branch condition"];
}
127 [label="Synthetic else branch"];
128 [label="Enter when branch result"];
subgraph cluster_31 {
color=blue
123 [label="Enter ||"];
124 [label="Const: Boolean(false)"];
125 [label="Exit left part of ||"];
126 [label="Enter right part of ||"];
127 [label="Access variable R|<local>/x|"];
128 [label="Const: Null(null)"];
129 [label="Operator !="];
130 [label="Stub" style="filled" fillcolor=gray];
131 [label="Exit ||"];
129 [label="Enter block"];
130 [label="Access variable R|<local>/x|"];
131 [label="Function call: R|<local>/x|.R|/A.foo|()"];
132 [label="Exit block"];
}
132 [label="Exit when branch condition"];
133 [label="Exit when branch result"];
134 [label="Exit when"];
}
133 [label="Synthetic else branch"];
134 [label="Enter when branch result"];
subgraph cluster_32 {
color=blue
135 [label="Enter block"];
136 [label="Access variable R|<local>/x|"];
137 [label="Function call: R|<local>/x|.<Inapplicable(WRONG_RECEIVER): [/A.foo]>#()"];
138 [label="Exit block"];
}
139 [label="Exit when branch result"];
140 [label="Exit when"];
}
141 [label="Exit function test_6" style="filled" fillcolor=red];
135 [label="Exit function test_6" style="filled" fillcolor=red];
}
120 -> {121};
@@ -380,124 +371,466 @@ digraph booleanOperators_kt {
123 -> {124};
124 -> {125};
125 -> {126};
125 -> {130} [style=dotted];
126 -> {127};
127 -> {128};
126 -> {128 127};
127 -> {134};
128 -> {129};
129 -> {131};
130 -> {131} [style=dotted];
129 -> {130};
130 -> {131};
131 -> {132};
132 -> {134 133};
133 -> {140};
132 -> {133};
133 -> {134};
134 -> {135};
135 -> {136};
subgraph cluster_32 {
color=red
136 [label="Enter function test_7" style="filled" fillcolor=red];
subgraph cluster_33 {
color=blue
137 [label="Enter when"];
subgraph cluster_34 {
color=blue
138 [label="Enter when branch condition "];
subgraph cluster_35 {
color=blue
139 [label="Enter ||"];
140 [label="Access variable R|<local>/x|"];
141 [label="Type operator: x is A"];
142 [label="Exit left part of ||"];
143 [label="Enter right part of ||"];
144 [label="Const: Boolean(false)"];
145 [label="Exit ||"];
}
146 [label="Exit when branch condition"];
}
147 [label="Synthetic else branch"];
148 [label="Enter when branch result"];
subgraph cluster_36 {
color=blue
149 [label="Enter block"];
150 [label="Access variable R|<local>/x|"];
151 [label="Function call: R|<local>/x|.<Unresolved name: foo>#()"];
152 [label="Exit block"];
}
153 [label="Exit when branch result"];
154 [label="Exit when"];
}
155 [label="Exit function test_7" style="filled" fillcolor=red];
}
136 -> {137};
137 -> {138};
138 -> {139};
139 -> {140};
140 -> {141};
subgraph cluster_33 {
color=red
142 [label="Enter function test_7" style="filled" fillcolor=red];
subgraph cluster_34 {
color=blue
143 [label="Enter when"];
subgraph cluster_35 {
color=blue
144 [label="Enter when branch condition "];
subgraph cluster_36 {
color=blue
145 [label="Enter &&"];
146 [label="Access variable R|<local>/x|"];
147 [label="Type operator: x is A"];
148 [label="Exit left part of &&"];
149 [label="Enter right part of &&"];
150 [label="Access variable R|<local>/x|"];
151 [label="Function call: R|<local>/x|.R|/A.bool|()"];
152 [label="Exit &&"];
}
153 [label="Exit when branch condition"];
}
154 [label="Synthetic else branch"];
155 [label="Enter when branch result"];
subgraph cluster_37 {
color=blue
156 [label="Enter block"];
157 [label="Access variable R|<local>/x|"];
158 [label="Function call: R|<local>/x|.R|/A.foo|()"];
159 [label="Exit block"];
}
160 [label="Exit when branch result"];
161 [label="Exit when"];
}
162 [label="Exit function test_7" style="filled" fillcolor=red];
}
142 -> {143};
141 -> {142};
142 -> {145 143};
143 -> {144};
144 -> {145};
145 -> {146};
146 -> {147};
147 -> {148};
148 -> {152 149};
146 -> {148 147};
147 -> {154};
148 -> {149};
149 -> {150};
150 -> {151};
151 -> {152};
152 -> {153};
153 -> {155 154};
154 -> {161};
155 -> {156};
153 -> {154};
154 -> {155};
subgraph cluster_37 {
color=red
156 [label="Enter function test_8" style="filled" fillcolor=red];
subgraph cluster_38 {
color=blue
157 [label="Enter when"];
subgraph cluster_39 {
color=blue
158 [label="Enter when branch condition "];
subgraph cluster_40 {
color=blue
159 [label="Enter ||"];
160 [label="Const: Boolean(false)"];
161 [label="Exit left part of ||"];
162 [label="Enter right part of ||"];
163 [label="Access variable R|<local>/x|"];
164 [label="Type operator: x is A"];
165 [label="Exit ||"];
}
166 [label="Exit when branch condition"];
}
167 [label="Synthetic else branch"];
168 [label="Enter when branch result"];
subgraph cluster_41 {
color=blue
169 [label="Enter block"];
170 [label="Access variable R|<local>/x|"];
171 [label="Function call: R|<local>/x|.<Unresolved name: foo>#()"];
172 [label="Exit block"];
}
173 [label="Exit when branch result"];
174 [label="Exit when"];
}
175 [label="Exit function test_8" style="filled" fillcolor=red];
}
156 -> {157};
157 -> {158};
158 -> {159};
159 -> {160};
160 -> {161};
161 -> {162};
subgraph cluster_38 {
color=red
163 [label="Enter function test_8" style="filled" fillcolor=red];
subgraph cluster_39 {
color=blue
164 [label="Enter when"];
subgraph cluster_40 {
color=blue
165 [label="Enter when branch condition "];
166 [label="Access variable R|<local>/x|"];
167 [label="Type operator: x !is A"];
168 [label="Function call: (R|<local>/x| !is R|A|).R|kotlin/Boolean.not|()"];
169 [label="Exit when branch condition"];
}
170 [label="Synthetic else branch"];
171 [label="Enter when branch result"];
subgraph cluster_41 {
color=blue
172 [label="Enter block"];
173 [label="Access variable R|<local>/x|"];
174 [label="Function call: R|<local>/x|.R|/A.foo|()"];
175 [label="Exit block"];
}
176 [label="Exit when branch result"];
177 [label="Exit when"];
}
178 [label="Exit function test_8" style="filled" fillcolor=red];
}
161 -> {165} [style=dotted];
162 -> {163};
163 -> {164};
164 -> {165};
165 -> {166};
166 -> {167};
167 -> {168};
166 -> {168 167};
167 -> {174};
168 -> {169};
169 -> {171 170};
170 -> {177};
169 -> {170};
170 -> {171};
171 -> {172};
172 -> {173};
173 -> {174};
174 -> {175};
175 -> {176};
subgraph cluster_42 {
color=red
176 [label="Enter function test_9" style="filled" fillcolor=red];
subgraph cluster_43 {
color=blue
177 [label="Enter when"];
subgraph cluster_44 {
color=blue
178 [label="Enter when branch condition "];
subgraph cluster_45 {
color=blue
179 [label="Enter ||"];
180 [label="Access variable R|<local>/x|"];
181 [label="Type operator: x is A"];
182 [label="Exit left part of ||"];
183 [label="Enter right part of ||"];
184 [label="Const: Boolean(true)"];
185 [label="Exit ||"];
}
186 [label="Exit when branch condition"];
}
187 [label="Synthetic else branch"];
188 [label="Enter when branch result"];
subgraph cluster_46 {
color=blue
189 [label="Enter block"];
190 [label="Access variable R|<local>/x|"];
191 [label="Function call: R|<local>/x|.<Unresolved name: foo>#()"];
192 [label="Exit block"];
}
193 [label="Exit when branch result"];
194 [label="Exit when"];
}
195 [label="Exit function test_9" style="filled" fillcolor=red];
}
176 -> {177};
177 -> {178};
178 -> {179};
179 -> {180};
180 -> {181};
181 -> {182};
182 -> {185 183};
183 -> {184};
184 -> {185};
185 -> {186};
186 -> {188 187};
187 -> {194};
188 -> {189};
189 -> {190};
190 -> {191};
191 -> {192};
192 -> {193};
193 -> {194};
194 -> {195};
subgraph cluster_47 {
color=red
196 [label="Enter function test_10" style="filled" fillcolor=red];
subgraph cluster_48 {
color=blue
197 [label="Enter when"];
subgraph cluster_49 {
color=blue
198 [label="Enter when branch condition "];
subgraph cluster_50 {
color=blue
199 [label="Enter ||"];
200 [label="Const: Boolean(true)"];
201 [label="Exit left part of ||"];
202 [label="Enter right part of ||" style="filled" fillcolor=gray];
203 [label="Access variable R|<local>/x|" style="filled" fillcolor=gray];
204 [label="Type operator: x is A" style="filled" fillcolor=gray];
205 [label="Exit ||"];
}
206 [label="Exit when branch condition"];
}
207 [label="Synthetic else branch"];
208 [label="Enter when branch result"];
subgraph cluster_51 {
color=blue
209 [label="Enter block"];
210 [label="Access variable R|<local>/x|"];
211 [label="Function call: R|<local>/x|.<Unresolved name: foo>#()"];
212 [label="Exit block"];
}
213 [label="Exit when branch result"];
214 [label="Exit when"];
}
215 [label="Exit function test_10" style="filled" fillcolor=red];
}
196 -> {197};
197 -> {198};
198 -> {199};
199 -> {200};
200 -> {201};
201 -> {205};
201 -> {202} [style=dotted];
202 -> {203} [style=dotted];
203 -> {204} [style=dotted];
204 -> {205} [style=dotted];
205 -> {206};
206 -> {208 207};
207 -> {214};
208 -> {209};
209 -> {210};
210 -> {211};
211 -> {212};
212 -> {213};
213 -> {214};
214 -> {215};
subgraph cluster_52 {
color=red
216 [label="Enter function test_11" style="filled" fillcolor=red];
subgraph cluster_53 {
color=blue
217 [label="Enter when"];
subgraph cluster_54 {
color=blue
218 [label="Enter when branch condition "];
subgraph cluster_55 {
color=blue
219 [label="Enter &&"];
220 [label="Const: Boolean(false)"];
221 [label="Exit left part of &&"];
222 [label="Enter right part of &&" style="filled" fillcolor=gray];
223 [label="Access variable R|<local>/x|" style="filled" fillcolor=gray];
224 [label="Type operator: x is A" style="filled" fillcolor=gray];
225 [label="Exit &&"];
}
226 [label="Exit when branch condition"];
}
227 [label="Synthetic else branch"];
228 [label="Enter when branch result"];
subgraph cluster_56 {
color=blue
229 [label="Enter block"];
230 [label="Access variable R|<local>/x|"];
231 [label="Function call: R|<local>/x|.R|/A.foo|()"];
232 [label="Exit block"];
}
233 [label="Exit when branch result"];
234 [label="Exit when"];
}
235 [label="Exit function test_11" style="filled" fillcolor=red];
}
216 -> {217};
217 -> {218};
218 -> {219};
219 -> {220};
220 -> {221};
221 -> {225};
221 -> {222} [style=dotted];
222 -> {223} [style=dotted];
223 -> {224} [style=dotted];
224 -> {225} [style=dotted];
225 -> {226};
226 -> {228 227};
227 -> {234};
228 -> {229};
229 -> {230};
230 -> {231};
231 -> {232};
232 -> {233};
233 -> {234};
234 -> {235};
subgraph cluster_57 {
color=red
236 [label="Enter function test_12" style="filled" fillcolor=red];
subgraph cluster_58 {
color=blue
237 [label="Enter when"];
subgraph cluster_59 {
color=blue
238 [label="Enter when branch condition "];
subgraph cluster_60 {
color=blue
239 [label="Enter &&"];
240 [label="Access variable R|<local>/x|"];
241 [label="Type operator: x is A"];
242 [label="Exit left part of &&"];
243 [label="Enter right part of &&"];
244 [label="Const: Boolean(false)"];
245 [label="Exit &&"];
}
246 [label="Exit when branch condition"];
}
247 [label="Synthetic else branch"];
248 [label="Enter when branch result"];
subgraph cluster_61 {
color=blue
249 [label="Enter block"];
250 [label="Access variable R|<local>/x|"];
251 [label="Function call: R|<local>/x|.R|/A.foo|()"];
252 [label="Exit block"];
}
253 [label="Exit when branch result"];
254 [label="Exit when"];
}
255 [label="Exit function test_12" style="filled" fillcolor=red];
}
236 -> {237};
237 -> {238};
238 -> {239};
239 -> {240};
240 -> {241};
241 -> {242};
242 -> {245 243};
243 -> {244};
244 -> {245};
245 -> {246};
246 -> {248 247};
247 -> {254};
248 -> {249};
249 -> {250};
250 -> {251};
251 -> {252};
252 -> {253};
253 -> {254};
254 -> {255};
subgraph cluster_62 {
color=red
256 [label="Enter function test_13" style="filled" fillcolor=red];
subgraph cluster_63 {
color=blue
257 [label="Enter when"];
subgraph cluster_64 {
color=blue
258 [label="Enter when branch condition "];
subgraph cluster_65 {
color=blue
259 [label="Enter &&"];
260 [label="Const: Boolean(true)"];
261 [label="Exit left part of &&"];
262 [label="Enter right part of &&"];
263 [label="Access variable R|<local>/x|"];
264 [label="Type operator: x is A"];
265 [label="Exit &&"];
}
266 [label="Exit when branch condition"];
}
267 [label="Synthetic else branch"];
268 [label="Enter when branch result"];
subgraph cluster_66 {
color=blue
269 [label="Enter block"];
270 [label="Access variable R|<local>/x|"];
271 [label="Function call: R|<local>/x|.R|/A.foo|()"];
272 [label="Exit block"];
}
273 [label="Exit when branch result"];
274 [label="Exit when"];
}
275 [label="Exit function test_13" style="filled" fillcolor=red];
}
256 -> {257};
257 -> {258};
258 -> {259};
259 -> {260};
260 -> {261};
261 -> {262};
261 -> {265} [style=dotted];
262 -> {263};
263 -> {264};
264 -> {265};
265 -> {266};
266 -> {268 267};
267 -> {274};
268 -> {269};
269 -> {270};
270 -> {271};
271 -> {272};
272 -> {273};
273 -> {274};
274 -> {275};
subgraph cluster_67 {
color=red
276 [label="Enter function test_14" style="filled" fillcolor=red];
subgraph cluster_68 {
color=blue
277 [label="Enter when"];
subgraph cluster_69 {
color=blue
278 [label="Enter when branch condition "];
subgraph cluster_70 {
color=blue
279 [label="Enter &&"];
280 [label="Access variable R|<local>/x|"];
281 [label="Type operator: x is A"];
282 [label="Exit left part of &&"];
283 [label="Enter right part of &&"];
284 [label="Const: Boolean(false)"];
285 [label="Exit &&"];
}
286 [label="Exit when branch condition"];
}
287 [label="Synthetic else branch"];
288 [label="Enter when branch result"];
subgraph cluster_71 {
color=blue
289 [label="Enter block"];
290 [label="Access variable R|<local>/x|"];
291 [label="Function call: R|<local>/x|.R|/A.foo|()"];
292 [label="Exit block"];
}
293 [label="Exit when branch result"];
294 [label="Exit when"];
}
295 [label="Exit function test_14" style="filled" fillcolor=red];
}
276 -> {277};
277 -> {278};
278 -> {279};
279 -> {280};
280 -> {281};
281 -> {282};
282 -> {285 283};
283 -> {284};
284 -> {285};
285 -> {286};
286 -> {288 287};
287 -> {294};
288 -> {289};
289 -> {290};
290 -> {291};
291 -> {292};
292 -> {293};
293 -> {294};
294 -> {295};
}
@@ -41,26 +41,68 @@ fun test_4(x: Any) {
x.<!UNRESOLVED_REFERENCE!>length<!>
}
fun test_5(x: A?) {
if (x != null || false) {
x.<!INAPPLICABLE_CANDIDATE!>foo<!>()
}
}
fun test_6(x: A?) {
if (false || x != null) {
x.<!INAPPLICABLE_CANDIDATE!>foo<!>()
}
}
fun test_7(x: Any) {
fun test_5(x: Any) {
if (x is A && x.bool()) {
x.foo()
}
}
fun test_8(x: Any) {
fun test_6(x: Any) {
if ((x !is A).not()) {
x.foo()
}
}
// || and const
fun test_7(x: Any) {
if (x is A || false) {
// TODO: should be smartcast
x.<!UNRESOLVED_REFERENCE!>foo<!>()
}
}
fun test_8(x: Any) {
if (false || x is A) {
// TODO: should be smartcast
x.<!UNRESOLVED_REFERENCE!>foo<!>()
}
}
fun test_9(x: Any) {
if (x is A || true) {
x.<!UNRESOLVED_REFERENCE!>foo<!>()
}
}
fun test_10(x: Any) {
if (true || x is A) {
x.<!UNRESOLVED_REFERENCE!>foo<!>()
}
}
// && and const
fun test_11(x: Any, b: Boolean) {
if (false && x is A) {
x.foo()
}
}
fun test_12(x: Any, b: Boolean) {
if (x is A && false) {
x.foo()
}
}
fun test_13(x: Any, b: Boolean) {
if (true && x is A) {
x.foo()
}
}
fun test_14(x: Any, b: Boolean) {
if (x is A && false) {
x.foo()
}
}
@@ -50,23 +50,7 @@ FILE: booleanOperators.kt
R|<local>/x|.<Unresolved name: length>#
}
public final fun test_5(x: R|A?|): R|kotlin/Unit| {
when () {
!=(R|<local>/x|, Null(null)) || Boolean(false) -> {
R|<local>/x|.<Inapplicable(WRONG_RECEIVER): [/A.foo]>#()
}
}
}
public final fun test_6(x: R|A?|): R|kotlin/Unit| {
when () {
Boolean(false) || !=(R|<local>/x|, Null(null)) -> {
R|<local>/x|.<Inapplicable(WRONG_RECEIVER): [/A.foo]>#()
}
}
}
public final fun test_7(x: R|kotlin/Any|): R|kotlin/Unit| {
public final fun test_5(x: R|kotlin/Any|): R|kotlin/Unit| {
when () {
(R|<local>/x| is R|A|) && R|<local>/x|.R|/A.bool|() -> {
R|<local>/x|.R|/A.foo|()
@@ -74,7 +58,7 @@ FILE: booleanOperators.kt
}
}
public final fun test_8(x: R|kotlin/Any|): R|kotlin/Unit| {
public final fun test_6(x: R|kotlin/Any|): R|kotlin/Unit| {
when () {
(R|<local>/x| !is R|A|).R|kotlin/Boolean.not|() -> {
R|<local>/x|.R|/A.foo|()
@@ -82,3 +66,67 @@ FILE: booleanOperators.kt
}
}
public final fun test_7(x: R|kotlin/Any|): R|kotlin/Unit| {
when () {
(R|<local>/x| is R|A|) || Boolean(false) -> {
R|<local>/x|.<Unresolved name: foo>#()
}
}
}
public final fun test_8(x: R|kotlin/Any|): R|kotlin/Unit| {
when () {
Boolean(false) || (R|<local>/x| is R|A|) -> {
R|<local>/x|.<Unresolved name: foo>#()
}
}
}
public final fun test_9(x: R|kotlin/Any|): R|kotlin/Unit| {
when () {
(R|<local>/x| is R|A|) || Boolean(true) -> {
R|<local>/x|.<Unresolved name: foo>#()
}
}
}
public final fun test_10(x: R|kotlin/Any|): R|kotlin/Unit| {
when () {
Boolean(true) || (R|<local>/x| is R|A|) -> {
R|<local>/x|.<Unresolved name: foo>#()
}
}
}
public final fun test_11(x: R|kotlin/Any|, b: R|kotlin/Boolean|): R|kotlin/Unit| {
when () {
Boolean(false) && (R|<local>/x| is R|A|) -> {
R|<local>/x|.R|/A.foo|()
}
}
}
public final fun test_12(x: R|kotlin/Any|, b: R|kotlin/Boolean|): R|kotlin/Unit| {
when () {
(R|<local>/x| is R|A|) && Boolean(false) -> {
R|<local>/x|.R|/A.foo|()
}
}
}
public final fun test_13(x: R|kotlin/Any|, b: R|kotlin/Boolean|): R|kotlin/Unit| {
when () {
Boolean(true) && (R|<local>/x| is R|A|) -> {
R|<local>/x|.R|/A.foo|()
}
}
}
public final fun test_14(x: R|kotlin/Any|, b: R|kotlin/Boolean|): R|kotlin/Unit| {
when () {
(R|<local>/x| is R|A|) && Boolean(false) -> {
R|<local>/x|.R|/A.foo|()
}
}
}
@@ -0,0 +1,503 @@
digraph booleanOperators_kt {
graph [splines=ortho nodesep=3]
node [shape=box penwidth=2]
edge [penwidth=2]
subgraph cluster_0 {
color=red
0 [label="Enter function foo" style="filled" fillcolor=red];
1 [label="Exit function foo" style="filled" fillcolor=red];
}
0 -> {1};
subgraph cluster_1 {
color=red
2 [label="Enter function bool" style="filled" fillcolor=red];
3 [label="Exit function bool" style="filled" fillcolor=red];
}
2 -> {3};
subgraph cluster_2 {
color=red
4 [label="Enter function bar" style="filled" fillcolor=red];
5 [label="Exit function bar" style="filled" fillcolor=red];
}
4 -> {5};
subgraph cluster_3 {
color=red
6 [label="Enter function baz" style="filled" fillcolor=red];
7 [label="Exit function baz" style="filled" fillcolor=red];
}
6 -> {7};
subgraph cluster_4 {
color=red
8 [label="Enter function test_1" style="filled" fillcolor=red];
subgraph cluster_5 {
color=blue
9 [label="Enter when"];
subgraph cluster_6 {
color=blue
10 [label="Enter when branch condition "];
subgraph cluster_7 {
color=blue
11 [label="Enter &&"];
12 [label="Access variable R|<local>/x|"];
13 [label="Type operator: x is B"];
14 [label="Exit left part of &&"];
15 [label="Enter right part of &&"];
16 [label="Access variable R|<local>/x|"];
17 [label="Type operator: x is C"];
18 [label="Exit &&"];
}
19 [label="Exit when branch condition"];
}
20 [label="Synthetic else branch"];
21 [label="Enter when branch result"];
subgraph cluster_8 {
color=blue
22 [label="Enter block"];
23 [label="Access variable R|<local>/x|"];
24 [label="Function call: R|<local>/x|.R|/A.foo|()"];
25 [label="Access variable R|<local>/x|"];
26 [label="Function call: R|<local>/x|.R|/B.bar|()"];
27 [label="Access variable R|<local>/x|"];
28 [label="Function call: R|<local>/x|.R|/C.baz|()"];
29 [label="Exit block"];
}
30 [label="Exit when branch result"];
31 [label="Exit when"];
}
32 [label="Exit function test_1" style="filled" fillcolor=red];
}
8 -> {9};
9 -> {10};
10 -> {11};
11 -> {12};
12 -> {13};
13 -> {14};
14 -> {18 15};
15 -> {16};
16 -> {17};
17 -> {18};
18 -> {19};
19 -> {21 20};
20 -> {31};
21 -> {22};
22 -> {23};
23 -> {24};
24 -> {25};
25 -> {26};
26 -> {27};
27 -> {28};
28 -> {29};
29 -> {30};
30 -> {31};
31 -> {32};
subgraph cluster_9 {
color=red
33 [label="Enter function test_2" style="filled" fillcolor=red];
subgraph cluster_10 {
color=blue
34 [label="Enter when"];
subgraph cluster_11 {
color=blue
35 [label="Enter when branch condition "];
subgraph cluster_12 {
color=blue
36 [label="Enter ||"];
37 [label="Access variable R|<local>/x|"];
38 [label="Type operator: x is B"];
39 [label="Exit left part of ||"];
40 [label="Enter right part of ||"];
41 [label="Access variable R|<local>/x|"];
42 [label="Type operator: x is C"];
43 [label="Exit ||"];
}
44 [label="Exit when branch condition"];
}
45 [label="Synthetic else branch"];
46 [label="Enter when branch result"];
subgraph cluster_13 {
color=blue
47 [label="Enter block"];
48 [label="Access variable R|<local>/x|"];
49 [label="Function call: R|<local>/x|.R|/A.foo|()"];
50 [label="Access variable R|<local>/x|"];
51 [label="Function call: R|<local>/x|.<Unresolved name: bar>#()"];
52 [label="Access variable R|<local>/x|"];
53 [label="Function call: R|<local>/x|.<Unresolved name: baz>#()"];
54 [label="Exit block"];
}
55 [label="Exit when branch result"];
56 [label="Exit when"];
}
57 [label="Exit function test_2" style="filled" fillcolor=red];
}
33 -> {34};
34 -> {35};
35 -> {36};
36 -> {37};
37 -> {38};
38 -> {39};
39 -> {43 40};
40 -> {41};
41 -> {42};
42 -> {43};
43 -> {44};
44 -> {46 45};
45 -> {56};
46 -> {47};
47 -> {48};
48 -> {49};
49 -> {50};
50 -> {51};
51 -> {52};
52 -> {53};
53 -> {54};
54 -> {55};
55 -> {56};
56 -> {57};
subgraph cluster_14 {
color=red
58 [label="Enter function test_3" style="filled" fillcolor=red];
subgraph cluster_15 {
color=blue
59 [label="Enter when"];
subgraph cluster_16 {
color=blue
60 [label="Enter when branch condition "];
61 [label="Access variable R|<local>/x|"];
62 [label="Type operator: x !is A"];
63 [label="Function call: (R|<local>/x| !is R|A|).R|kotlin/Boolean.not|()"];
64 [label="Exit when branch condition"];
}
65 [label="Synthetic else branch"];
66 [label="Enter when branch result"];
subgraph cluster_17 {
color=blue
67 [label="Enter block"];
68 [label="Access variable R|<local>/x|"];
69 [label="Function call: R|<local>/x|.R|/A.foo|()"];
70 [label="Exit block"];
}
71 [label="Exit when branch result"];
72 [label="Exit when"];
}
73 [label="Exit function test_3" style="filled" fillcolor=red];
}
58 -> {59};
59 -> {60};
60 -> {61};
61 -> {62};
62 -> {63};
63 -> {64};
64 -> {66 65};
65 -> {72};
66 -> {67};
67 -> {68};
68 -> {69};
69 -> {70};
70 -> {71};
71 -> {72};
72 -> {73};
subgraph cluster_18 {
color=red
74 [label="Enter function test_4" style="filled" fillcolor=red];
subgraph cluster_19 {
color=blue
75 [label="Enter when"];
subgraph cluster_20 {
color=blue
76 [label="Enter when branch condition "];
subgraph cluster_21 {
color=blue
77 [label="Enter ||"];
78 [label="Access variable R|<local>/x|"];
79 [label="Type operator: x !is String"];
80 [label="Exit left part of ||"];
81 [label="Enter right part of ||"];
82 [label="Access variable R|<local>/x|"];
83 [label="Access variable R|kotlin/String.length|"];
84 [label="Const: Int(0)"];
85 [label="Operator =="];
86 [label="Exit ||"];
}
87 [label="Exit when branch condition"];
}
88 [label="Synthetic else branch"];
89 [label="Enter when branch result"];
subgraph cluster_22 {
color=blue
90 [label="Enter block"];
91 [label="Access variable R|<local>/x|"];
92 [label="Access variable <Unresolved name: length>#"];
93 [label="Exit block"];
}
94 [label="Exit when branch result"];
95 [label="Exit when"];
}
96 [label="Access variable R|<local>/x|"];
97 [label="Access variable <Unresolved name: length>#"];
98 [label="Exit function test_4" style="filled" fillcolor=red];
}
74 -> {75};
75 -> {76};
76 -> {77};
77 -> {78};
78 -> {79};
79 -> {80};
80 -> {86 81};
81 -> {82};
82 -> {83};
83 -> {84};
84 -> {85};
85 -> {86};
86 -> {87};
87 -> {89 88};
88 -> {95};
89 -> {90};
90 -> {91};
91 -> {92};
92 -> {93};
93 -> {94};
94 -> {95};
95 -> {96};
96 -> {97};
97 -> {98};
subgraph cluster_23 {
color=red
99 [label="Enter function test_5" style="filled" fillcolor=red];
subgraph cluster_24 {
color=blue
100 [label="Enter when"];
subgraph cluster_25 {
color=blue
101 [label="Enter when branch condition "];
subgraph cluster_26 {
color=blue
102 [label="Enter ||"];
103 [label="Access variable R|<local>/x|"];
104 [label="Const: Null(null)"];
105 [label="Operator !="];
106 [label="Exit left part of ||"];
107 [label="Enter right part of ||"];
108 [label="Const: Boolean(false)"];
109 [label="Exit ||"];
}
110 [label="Exit when branch condition"];
}
111 [label="Synthetic else branch"];
112 [label="Enter when branch result"];
subgraph cluster_27 {
color=blue
113 [label="Enter block"];
114 [label="Access variable R|<local>/x|"];
115 [label="Function call: R|<local>/x|.<Inapplicable(WRONG_RECEIVER): [/A.foo]>#()"];
116 [label="Exit block"];
}
117 [label="Exit when branch result"];
118 [label="Exit when"];
}
119 [label="Exit function test_5" style="filled" fillcolor=red];
}
99 -> {100};
100 -> {101};
101 -> {102};
102 -> {103};
103 -> {104};
104 -> {105};
105 -> {106};
106 -> {109 107};
107 -> {108};
108 -> {109};
109 -> {110};
110 -> {112 111};
111 -> {118};
112 -> {113};
113 -> {114};
114 -> {115};
115 -> {116};
116 -> {117};
117 -> {118};
118 -> {119};
subgraph cluster_28 {
color=red
120 [label="Enter function test_6" style="filled" fillcolor=red];
subgraph cluster_29 {
color=blue
121 [label="Enter when"];
subgraph cluster_30 {
color=blue
122 [label="Enter when branch condition "];
subgraph cluster_31 {
color=blue
123 [label="Enter ||"];
124 [label="Const: Boolean(false)"];
125 [label="Exit left part of ||"];
126 [label="Enter right part of ||"];
127 [label="Access variable R|<local>/x|"];
128 [label="Const: Null(null)"];
129 [label="Operator !="];
130 [label="Stub" style="filled" fillcolor=gray];
131 [label="Exit ||"];
}
132 [label="Exit when branch condition"];
}
133 [label="Synthetic else branch"];
134 [label="Enter when branch result"];
subgraph cluster_32 {
color=blue
135 [label="Enter block"];
136 [label="Access variable R|<local>/x|"];
137 [label="Function call: R|<local>/x|.<Inapplicable(WRONG_RECEIVER): [/A.foo]>#()"];
138 [label="Exit block"];
}
139 [label="Exit when branch result"];
140 [label="Exit when"];
}
141 [label="Exit function test_6" style="filled" fillcolor=red];
}
120 -> {121};
121 -> {122};
122 -> {123};
123 -> {124};
124 -> {125};
125 -> {126};
125 -> {130} [style=dotted];
126 -> {127};
127 -> {128};
128 -> {129};
129 -> {131};
130 -> {131} [style=dotted];
131 -> {132};
132 -> {134 133};
133 -> {140};
134 -> {135};
135 -> {136};
136 -> {137};
137 -> {138};
138 -> {139};
139 -> {140};
140 -> {141};
subgraph cluster_33 {
color=red
142 [label="Enter function test_7" style="filled" fillcolor=red];
subgraph cluster_34 {
color=blue
143 [label="Enter when"];
subgraph cluster_35 {
color=blue
144 [label="Enter when branch condition "];
subgraph cluster_36 {
color=blue
145 [label="Enter &&"];
146 [label="Access variable R|<local>/x|"];
147 [label="Type operator: x is A"];
148 [label="Exit left part of &&"];
149 [label="Enter right part of &&"];
150 [label="Access variable R|<local>/x|"];
151 [label="Function call: R|<local>/x|.R|/A.bool|()"];
152 [label="Exit &&"];
}
153 [label="Exit when branch condition"];
}
154 [label="Synthetic else branch"];
155 [label="Enter when branch result"];
subgraph cluster_37 {
color=blue
156 [label="Enter block"];
157 [label="Access variable R|<local>/x|"];
158 [label="Function call: R|<local>/x|.R|/A.foo|()"];
159 [label="Exit block"];
}
160 [label="Exit when branch result"];
161 [label="Exit when"];
}
162 [label="Exit function test_7" style="filled" fillcolor=red];
}
142 -> {143};
143 -> {144};
144 -> {145};
145 -> {146};
146 -> {147};
147 -> {148};
148 -> {152 149};
149 -> {150};
150 -> {151};
151 -> {152};
152 -> {153};
153 -> {155 154};
154 -> {161};
155 -> {156};
156 -> {157};
157 -> {158};
158 -> {159};
159 -> {160};
160 -> {161};
161 -> {162};
subgraph cluster_38 {
color=red
163 [label="Enter function test_8" style="filled" fillcolor=red];
subgraph cluster_39 {
color=blue
164 [label="Enter when"];
subgraph cluster_40 {
color=blue
165 [label="Enter when branch condition "];
166 [label="Access variable R|<local>/x|"];
167 [label="Type operator: x !is A"];
168 [label="Function call: (R|<local>/x| !is R|A|).R|kotlin/Boolean.not|()"];
169 [label="Exit when branch condition"];
}
170 [label="Synthetic else branch"];
171 [label="Enter when branch result"];
subgraph cluster_41 {
color=blue
172 [label="Enter block"];
173 [label="Access variable R|<local>/x|"];
174 [label="Function call: R|<local>/x|.R|/A.foo|()"];
175 [label="Exit block"];
}
176 [label="Exit when branch result"];
177 [label="Exit when"];
}
178 [label="Exit function test_8" style="filled" fillcolor=red];
}
163 -> {164};
164 -> {165};
165 -> {166};
166 -> {167};
167 -> {168};
168 -> {169};
169 -> {171 170};
170 -> {177};
171 -> {172};
172 -> {173};
173 -> {174};
174 -> {175};
175 -> {176};
176 -> {177};
177 -> {178};
}
@@ -56,12 +56,11 @@ digraph endlessLoops_kt {
}
24 [label="Exit loop block"];
}
25 [label="Stub" style="filled" fillcolor=gray];
26 [label="Exit whileloop"];
25 [label="Exit whileloop"];
}
27 [label="Access variable R|<local>/x|"];
28 [label="Function call: R|<local>/x|.R|/A.foo|()"];
29 [label="Exit function test_1" style="filled" fillcolor=red];
26 [label="Access variable R|<local>/x|"];
27 [label="Function call: R|<local>/x|.R|/A.foo|()"];
28 [label="Exit function test_1" style="filled" fillcolor=red];
}
2 -> {3};
@@ -81,7 +80,7 @@ digraph endlessLoops_kt {
15 -> {22};
16 -> {17};
17 -> {18};
18 -> {26};
18 -> {25};
18 -> {19} [style=dotted];
19 -> {20} [style=dotted];
20 -> {21} [style=dotted];
@@ -89,512 +88,499 @@ digraph endlessLoops_kt {
22 -> {23};
23 -> {24};
24 -> {4};
25 -> {26} [style=dotted];
25 -> {26};
26 -> {27};
27 -> {28};
28 -> {29};
subgraph cluster_9 {
color=red
30 [label="Enter function test_2" style="filled" fillcolor=red];
29 [label="Enter function test_2" style="filled" fillcolor=red];
subgraph cluster_10 {
color=blue
31 [label="Enter while loop"];
30 [label="Enter while loop"];
subgraph cluster_11 {
color=blue
32 [label="Enter loop condition"];
33 [label="Const: Boolean(true)"];
34 [label="Exit loop condition"];
31 [label="Enter loop condition"];
32 [label="Const: Boolean(true)"];
33 [label="Exit loop condition"];
}
subgraph cluster_12 {
color=blue
35 [label="Enter loop block"];
34 [label="Enter loop block"];
subgraph cluster_13 {
color=blue
36 [label="Enter block"];
35 [label="Enter block"];
subgraph cluster_14 {
color=blue
37 [label="Enter when"];
36 [label="Enter when"];
subgraph cluster_15 {
color=blue
38 [label="Enter when branch condition "];
39 [label="Access variable R|<local>/b|"];
40 [label="Exit when branch condition"];
37 [label="Enter when branch condition "];
38 [label="Access variable R|<local>/b|"];
39 [label="Exit when branch condition"];
}
41 [label="Synthetic else branch"];
42 [label="Enter when branch result"];
40 [label="Synthetic else branch"];
41 [label="Enter when branch result"];
subgraph cluster_16 {
color=blue
43 [label="Enter block"];
44 [label="Access variable R|<local>/x|"];
45 [label="Type operator: x as A"];
46 [label="Jump: break@@@[Boolean(true)] "];
47 [label="Stub" style="filled" fillcolor=gray];
48 [label="Exit block" style="filled" fillcolor=gray];
42 [label="Enter block"];
43 [label="Access variable R|<local>/x|"];
44 [label="Type operator: x as A"];
45 [label="Jump: break@@@[Boolean(true)] "];
46 [label="Stub" style="filled" fillcolor=gray];
47 [label="Exit block" style="filled" fillcolor=gray];
}
49 [label="Exit when branch result" style="filled" fillcolor=gray];
50 [label="Exit when"];
48 [label="Exit when branch result" style="filled" fillcolor=gray];
49 [label="Exit when"];
}
51 [label="Exit block"];
50 [label="Exit block"];
}
52 [label="Exit loop block"];
51 [label="Exit loop block"];
}
53 [label="Stub" style="filled" fillcolor=gray];
54 [label="Exit whileloop"];
52 [label="Exit whileloop"];
}
55 [label="Access variable R|<local>/x|"];
56 [label="Function call: R|<local>/x|.R|/A.foo|()"];
57 [label="Exit function test_2" style="filled" fillcolor=red];
53 [label="Access variable R|<local>/x|"];
54 [label="Function call: R|<local>/x|.R|/A.foo|()"];
55 [label="Exit function test_2" style="filled" fillcolor=red];
}
29 -> {30};
30 -> {31};
31 -> {32};
32 -> {33};
33 -> {34};
33 -> {52} [style=dotted];
34 -> {35};
34 -> {53} [style=dotted];
35 -> {36};
36 -> {37};
37 -> {38};
38 -> {39};
39 -> {40};
40 -> {42 41};
41 -> {50};
39 -> {41 40};
40 -> {49};
41 -> {42};
42 -> {43};
43 -> {44};
44 -> {45};
45 -> {46};
46 -> {54};
45 -> {52};
45 -> {46} [style=dotted];
46 -> {47} [style=dotted];
47 -> {48} [style=dotted];
48 -> {49} [style=dotted];
49 -> {50} [style=dotted];
49 -> {50};
50 -> {51};
51 -> {52};
52 -> {32};
53 -> {54} [style=dotted];
51 -> {31};
52 -> {53};
53 -> {54};
54 -> {55};
55 -> {56};
56 -> {57};
subgraph cluster_17 {
color=red
58 [label="Enter function test_3" style="filled" fillcolor=red];
56 [label="Enter function test_3" style="filled" fillcolor=red];
subgraph cluster_18 {
color=blue
59 [label="Enter while loop"];
57 [label="Enter while loop"];
subgraph cluster_19 {
color=blue
60 [label="Enter loop condition"];
61 [label="Const: Boolean(true)"];
62 [label="Exit loop condition"];
58 [label="Enter loop condition"];
59 [label="Const: Boolean(true)"];
60 [label="Exit loop condition"];
}
subgraph cluster_20 {
color=blue
63 [label="Enter loop block"];
61 [label="Enter loop block"];
subgraph cluster_21 {
color=blue
64 [label="Enter block"];
65 [label="Access variable R|<local>/x|"];
66 [label="Type operator: x as A"];
62 [label="Enter block"];
63 [label="Access variable R|<local>/x|"];
64 [label="Type operator: x as A"];
subgraph cluster_22 {
color=blue
67 [label="Enter when"];
65 [label="Enter when"];
subgraph cluster_23 {
color=blue
68 [label="Enter when branch condition "];
69 [label="Access variable R|<local>/b|"];
70 [label="Exit when branch condition"];
66 [label="Enter when branch condition "];
67 [label="Access variable R|<local>/b|"];
68 [label="Exit when branch condition"];
}
71 [label="Synthetic else branch"];
72 [label="Enter when branch result"];
69 [label="Synthetic else branch"];
70 [label="Enter when branch result"];
subgraph cluster_24 {
color=blue
73 [label="Enter block"];
74 [label="Jump: break@@@[Boolean(true)] "];
75 [label="Stub" style="filled" fillcolor=gray];
76 [label="Exit block" style="filled" fillcolor=gray];
71 [label="Enter block"];
72 [label="Jump: break@@@[Boolean(true)] "];
73 [label="Stub" style="filled" fillcolor=gray];
74 [label="Exit block" style="filled" fillcolor=gray];
}
77 [label="Exit when branch result" style="filled" fillcolor=gray];
78 [label="Exit when"];
75 [label="Exit when branch result" style="filled" fillcolor=gray];
76 [label="Exit when"];
}
subgraph cluster_25 {
color=blue
79 [label="Enter when"];
77 [label="Enter when"];
subgraph cluster_26 {
color=blue
80 [label="Enter when branch condition "];
81 [label="Access variable R|<local>/b|"];
82 [label="Exit when branch condition"];
78 [label="Enter when branch condition "];
79 [label="Access variable R|<local>/b|"];
80 [label="Exit when branch condition"];
}
83 [label="Synthetic else branch"];
84 [label="Enter when branch result"];
81 [label="Synthetic else branch"];
82 [label="Enter when branch result"];
subgraph cluster_27 {
color=blue
85 [label="Enter block"];
86 [label="Jump: break@@@[Boolean(true)] "];
87 [label="Stub" style="filled" fillcolor=gray];
88 [label="Exit block" style="filled" fillcolor=gray];
83 [label="Enter block"];
84 [label="Jump: break@@@[Boolean(true)] "];
85 [label="Stub" style="filled" fillcolor=gray];
86 [label="Exit block" style="filled" fillcolor=gray];
}
89 [label="Exit when branch result" style="filled" fillcolor=gray];
90 [label="Exit when"];
87 [label="Exit when branch result" style="filled" fillcolor=gray];
88 [label="Exit when"];
}
91 [label="Exit block"];
89 [label="Exit block"];
}
92 [label="Exit loop block"];
90 [label="Exit loop block"];
}
93 [label="Stub" style="filled" fillcolor=gray];
94 [label="Exit whileloop"];
91 [label="Exit whileloop"];
}
95 [label="Access variable R|<local>/x|"];
96 [label="Function call: R|<local>/x|.R|/A.foo|()"];
97 [label="Exit function test_3" style="filled" fillcolor=red];
92 [label="Access variable R|<local>/x|"];
93 [label="Function call: R|<local>/x|.R|/A.foo|()"];
94 [label="Exit function test_3" style="filled" fillcolor=red];
}
56 -> {57};
57 -> {58};
58 -> {59};
59 -> {60};
60 -> {61};
60 -> {91} [style=dotted];
61 -> {62};
62 -> {63};
62 -> {93} [style=dotted];
63 -> {64};
64 -> {65};
65 -> {66};
66 -> {67};
67 -> {68};
68 -> {69};
69 -> {70};
70 -> {72 71};
71 -> {78};
72 -> {73};
73 -> {74};
74 -> {94};
68 -> {70 69};
69 -> {76};
70 -> {71};
71 -> {72};
72 -> {91};
72 -> {73} [style=dotted];
73 -> {74} [style=dotted];
74 -> {75} [style=dotted];
75 -> {76} [style=dotted];
76 -> {77} [style=dotted];
77 -> {78} [style=dotted];
76 -> {77};
77 -> {78};
78 -> {79};
79 -> {80};
80 -> {81};
81 -> {82};
82 -> {84 83};
83 -> {90};
84 -> {85};
85 -> {86};
86 -> {94};
80 -> {82 81};
81 -> {88};
82 -> {83};
83 -> {84};
84 -> {91};
84 -> {85} [style=dotted];
85 -> {86} [style=dotted];
86 -> {87} [style=dotted];
87 -> {88} [style=dotted];
88 -> {89} [style=dotted];
89 -> {90} [style=dotted];
90 -> {91};
88 -> {89};
89 -> {90};
90 -> {58};
91 -> {92};
92 -> {60};
93 -> {94} [style=dotted];
94 -> {95};
95 -> {96};
96 -> {97};
92 -> {93};
93 -> {94};
subgraph cluster_28 {
color=red
98 [label="Enter function test_4" style="filled" fillcolor=red];
95 [label="Enter function test_4" style="filled" fillcolor=red];
subgraph cluster_29 {
color=blue
99 [label="Enter while loop"];
96 [label="Enter while loop"];
subgraph cluster_30 {
color=blue
100 [label="Enter loop condition"];
101 [label="Const: Boolean(true)"];
102 [label="Exit loop condition"];
97 [label="Enter loop condition"];
98 [label="Const: Boolean(true)"];
99 [label="Exit loop condition"];
}
subgraph cluster_31 {
color=blue
103 [label="Enter loop block"];
100 [label="Enter loop block"];
subgraph cluster_32 {
color=blue
104 [label="Enter block"];
101 [label="Enter block"];
subgraph cluster_33 {
color=blue
105 [label="Enter when"];
102 [label="Enter when"];
subgraph cluster_34 {
color=blue
106 [label="Enter when branch condition "];
107 [label="Access variable R|<local>/b|"];
108 [label="Exit when branch condition"];
103 [label="Enter when branch condition "];
104 [label="Access variable R|<local>/b|"];
105 [label="Exit when branch condition"];
}
109 [label="Synthetic else branch"];
110 [label="Enter when branch result"];
106 [label="Synthetic else branch"];
107 [label="Enter when branch result"];
subgraph cluster_35 {
color=blue
111 [label="Enter block"];
112 [label="Access variable R|<local>/x|"];
113 [label="Type operator: x as A"];
114 [label="Jump: break@@@[Boolean(true)] "];
115 [label="Stub" style="filled" fillcolor=gray];
116 [label="Exit block" style="filled" fillcolor=gray];
108 [label="Enter block"];
109 [label="Access variable R|<local>/x|"];
110 [label="Type operator: x as A"];
111 [label="Jump: break@@@[Boolean(true)] "];
112 [label="Stub" style="filled" fillcolor=gray];
113 [label="Exit block" style="filled" fillcolor=gray];
}
117 [label="Exit when branch result" style="filled" fillcolor=gray];
118 [label="Exit when"];
114 [label="Exit when branch result" style="filled" fillcolor=gray];
115 [label="Exit when"];
}
119 [label="Jump: break@@@[Boolean(true)] "];
120 [label="Stub" style="filled" fillcolor=gray];
121 [label="Exit block" style="filled" fillcolor=gray];
116 [label="Jump: break@@@[Boolean(true)] "];
117 [label="Stub" style="filled" fillcolor=gray];
118 [label="Exit block" style="filled" fillcolor=gray];
}
122 [label="Exit loop block" style="filled" fillcolor=gray];
119 [label="Exit loop block" style="filled" fillcolor=gray];
}
123 [label="Stub" style="filled" fillcolor=gray];
124 [label="Exit whileloop"];
120 [label="Exit whileloop"];
}
125 [label="Access variable R|<local>/x|"];
126 [label="Function call: R|<local>/x|.<Unresolved name: foo>#()"];
127 [label="Exit function test_4" style="filled" fillcolor=red];
121 [label="Access variable R|<local>/x|"];
122 [label="Function call: R|<local>/x|.<Unresolved name: foo>#()"];
123 [label="Exit function test_4" style="filled" fillcolor=red];
}
95 -> {96};
96 -> {97};
97 -> {98};
98 -> {99};
99 -> {100};
99 -> {120} [style=dotted];
100 -> {101};
101 -> {102};
102 -> {103};
102 -> {123} [style=dotted];
103 -> {104};
104 -> {105};
105 -> {106};
106 -> {107};
105 -> {107 106};
106 -> {115};
107 -> {108};
108 -> {110 109};
109 -> {118};
108 -> {109};
109 -> {110};
110 -> {111};
111 -> {112};
112 -> {113};
113 -> {114};
114 -> {124};
111 -> {120};
111 -> {112} [style=dotted];
112 -> {113} [style=dotted];
113 -> {114} [style=dotted];
114 -> {115} [style=dotted];
115 -> {116} [style=dotted];
115 -> {116};
116 -> {120};
116 -> {117} [style=dotted];
117 -> {118} [style=dotted];
118 -> {119};
119 -> {124};
119 -> {120} [style=dotted];
120 -> {121} [style=dotted];
121 -> {122} [style=dotted];
122 -> {100} [style=dotted];
123 -> {124} [style=dotted];
124 -> {125};
125 -> {126};
126 -> {127};
118 -> {119} [style=dotted];
119 -> {97} [style=dotted];
120 -> {121};
121 -> {122};
122 -> {123};
subgraph cluster_36 {
color=red
128 [label="Enter function test_5" style="filled" fillcolor=red];
124 [label="Enter function test_5" style="filled" fillcolor=red];
subgraph cluster_37 {
color=blue
129 [label="Enter do-while loop"];
125 [label="Enter do-while loop"];
subgraph cluster_38 {
color=blue
130 [label="Enter loop block"];
126 [label="Enter loop block"];
subgraph cluster_39 {
color=blue
131 [label="Enter block"];
127 [label="Enter block"];
subgraph cluster_40 {
color=blue
132 [label="Enter when"];
128 [label="Enter when"];
subgraph cluster_41 {
color=blue
133 [label="Enter when branch condition "];
134 [label="Access variable R|<local>/b|"];
135 [label="Exit when branch condition"];
129 [label="Enter when branch condition "];
130 [label="Access variable R|<local>/b|"];
131 [label="Exit when branch condition"];
}
136 [label="Synthetic else branch"];
137 [label="Enter when branch result"];
132 [label="Synthetic else branch"];
133 [label="Enter when branch result"];
subgraph cluster_42 {
color=blue
138 [label="Enter block"];
139 [label="Access variable R|<local>/x|"];
140 [label="Type operator: x as A"];
141 [label="Jump: break@@@[Boolean(true)] "];
142 [label="Stub" style="filled" fillcolor=gray];
143 [label="Exit block" style="filled" fillcolor=gray];
134 [label="Enter block"];
135 [label="Access variable R|<local>/x|"];
136 [label="Type operator: x as A"];
137 [label="Jump: break@@@[Boolean(true)] "];
138 [label="Stub" style="filled" fillcolor=gray];
139 [label="Exit block" style="filled" fillcolor=gray];
}
144 [label="Exit when branch result" style="filled" fillcolor=gray];
145 [label="Exit when"];
140 [label="Exit when branch result" style="filled" fillcolor=gray];
141 [label="Exit when"];
}
146 [label="Exit block"];
142 [label="Exit block"];
}
147 [label="Exit loop block"];
143 [label="Exit loop block"];
}
subgraph cluster_43 {
color=blue
148 [label="Enter loop condition"];
149 [label="Const: Boolean(true)"];
150 [label="Exit loop condition"];
144 [label="Enter loop condition"];
145 [label="Const: Boolean(true)"];
146 [label="Exit loop condition"];
}
151 [label="Stub" style="filled" fillcolor=gray];
152 [label="Exit do-whileloop"];
147 [label="Exit do-whileloop"];
}
153 [label="Access variable R|<local>/x|"];
154 [label="Function call: R|<local>/x|.R|/A.foo|()"];
155 [label="Exit function test_5" style="filled" fillcolor=red];
148 [label="Access variable R|<local>/x|"];
149 [label="Function call: R|<local>/x|.R|/A.foo|()"];
150 [label="Exit function test_5" style="filled" fillcolor=red];
}
124 -> {125};
125 -> {126};
126 -> {127};
127 -> {128};
128 -> {129};
129 -> {130};
130 -> {131};
131 -> {132};
132 -> {133};
131 -> {133 132};
132 -> {141};
133 -> {134};
134 -> {135};
135 -> {137 136};
136 -> {145};
137 -> {138};
138 -> {139};
139 -> {140};
140 -> {141};
141 -> {152};
141 -> {142} [style=dotted];
142 -> {143} [style=dotted];
143 -> {144} [style=dotted];
144 -> {145} [style=dotted];
135 -> {136};
136 -> {137};
137 -> {147};
137 -> {138} [style=dotted];
138 -> {139} [style=dotted];
139 -> {140} [style=dotted];
140 -> {141} [style=dotted];
141 -> {142};
142 -> {143};
143 -> {144};
144 -> {145};
145 -> {146};
146 -> {147};
146 -> {126};
146 -> {147} [style=dotted];
147 -> {148};
148 -> {149};
149 -> {150};
150 -> {130};
150 -> {151} [style=dotted];
151 -> {152} [style=dotted];
152 -> {153};
153 -> {154};
154 -> {155};
subgraph cluster_44 {
color=red
156 [label="Enter function test_6" style="filled" fillcolor=red];
151 [label="Enter function test_6" style="filled" fillcolor=red];
subgraph cluster_45 {
color=blue
157 [label="Enter do-while loop"];
152 [label="Enter do-while loop"];
subgraph cluster_46 {
color=blue
158 [label="Enter loop block"];
153 [label="Enter loop block"];
subgraph cluster_47 {
color=blue
159 [label="Enter block"];
160 [label="Access variable R|<local>/x|"];
161 [label="Type operator: x as A"];
154 [label="Enter block"];
155 [label="Access variable R|<local>/x|"];
156 [label="Type operator: x as A"];
subgraph cluster_48 {
color=blue
162 [label="Enter when"];
157 [label="Enter when"];
subgraph cluster_49 {
color=blue
163 [label="Enter when branch condition "];
164 [label="Access variable R|<local>/b|"];
165 [label="Exit when branch condition"];
158 [label="Enter when branch condition "];
159 [label="Access variable R|<local>/b|"];
160 [label="Exit when branch condition"];
}
166 [label="Synthetic else branch"];
167 [label="Enter when branch result"];
161 [label="Synthetic else branch"];
162 [label="Enter when branch result"];
subgraph cluster_50 {
color=blue
168 [label="Enter block"];
169 [label="Jump: break@@@[Boolean(true)] "];
170 [label="Stub" style="filled" fillcolor=gray];
171 [label="Exit block" style="filled" fillcolor=gray];
163 [label="Enter block"];
164 [label="Jump: break@@@[Boolean(true)] "];
165 [label="Stub" style="filled" fillcolor=gray];
166 [label="Exit block" style="filled" fillcolor=gray];
}
172 [label="Exit when branch result" style="filled" fillcolor=gray];
173 [label="Exit when"];
167 [label="Exit when branch result" style="filled" fillcolor=gray];
168 [label="Exit when"];
}
174 [label="Exit block"];
169 [label="Exit block"];
}
175 [label="Exit loop block"];
170 [label="Exit loop block"];
}
subgraph cluster_51 {
color=blue
176 [label="Enter loop condition"];
177 [label="Const: Boolean(true)"];
178 [label="Exit loop condition"];
171 [label="Enter loop condition"];
172 [label="Const: Boolean(true)"];
173 [label="Exit loop condition"];
}
179 [label="Stub" style="filled" fillcolor=gray];
180 [label="Exit do-whileloop"];
174 [label="Exit do-whileloop"];
}
181 [label="Access variable R|<local>/x|"];
182 [label="Function call: R|<local>/x|.R|/A.foo|()"];
183 [label="Exit function test_6" style="filled" fillcolor=red];
175 [label="Access variable R|<local>/x|"];
176 [label="Function call: R|<local>/x|.R|/A.foo|()"];
177 [label="Exit function test_6" style="filled" fillcolor=red];
}
151 -> {152};
152 -> {153};
153 -> {154};
154 -> {155};
155 -> {156};
156 -> {157};
157 -> {158};
158 -> {159};
159 -> {160};
160 -> {161};
161 -> {162};
160 -> {162 161};
161 -> {168};
162 -> {163};
163 -> {164};
164 -> {165};
165 -> {167 166};
166 -> {173};
167 -> {168};
164 -> {174};
164 -> {165} [style=dotted];
165 -> {166} [style=dotted];
166 -> {167} [style=dotted];
167 -> {168} [style=dotted];
168 -> {169};
169 -> {180};
169 -> {170} [style=dotted];
170 -> {171} [style=dotted];
171 -> {172} [style=dotted];
172 -> {173} [style=dotted];
173 -> {174};
169 -> {170};
170 -> {171};
171 -> {172};
172 -> {173};
173 -> {153};
173 -> {174} [style=dotted];
174 -> {175};
175 -> {176};
176 -> {177};
177 -> {178};
178 -> {158};
178 -> {179} [style=dotted];
179 -> {180} [style=dotted];
180 -> {181};
181 -> {182};
182 -> {183};
subgraph cluster_52 {
color=red
184 [label="Enter function test_7" style="filled" fillcolor=red];
178 [label="Enter function test_7" style="filled" fillcolor=red];
subgraph cluster_53 {
color=blue
185 [label="Enter do-while loop"];
179 [label="Enter do-while loop"];
subgraph cluster_54 {
color=blue
186 [label="Enter loop block"];
180 [label="Enter loop block"];
subgraph cluster_55 {
color=blue
187 [label="Enter block"];
188 [label="Access variable R|<local>/x|"];
189 [label="Type operator: x as A"];
190 [label="Exit block"];
181 [label="Enter block"];
182 [label="Access variable R|<local>/x|"];
183 [label="Type operator: x as A"];
184 [label="Exit block"];
}
191 [label="Exit loop block"];
185 [label="Exit loop block"];
}
subgraph cluster_56 {
color=blue
192 [label="Enter loop condition"];
193 [label="Const: Boolean(true)"];
194 [label="Exit loop condition"];
186 [label="Enter loop condition"];
187 [label="Const: Boolean(true)"];
188 [label="Exit loop condition"];
}
195 [label="Stub" style="filled" fillcolor=gray];
196 [label="Exit do-whileloop" style="filled" fillcolor=gray];
189 [label="Exit do-whileloop" style="filled" fillcolor=gray];
}
197 [label="Access variable R|<local>/x|" style="filled" fillcolor=gray];
198 [label="Function call: R|<local>/x|.R|/A.foo|()" style="filled" fillcolor=gray];
199 [label="Exit function test_7" style="filled" fillcolor=red style="filled" fillcolor=gray];
190 [label="Access variable R|<local>/x|" style="filled" fillcolor=gray];
191 [label="Function call: R|<local>/x|.R|/A.foo|()" style="filled" fillcolor=gray];
192 [label="Exit function test_7" style="filled" fillcolor=red style="filled" fillcolor=gray];
}
178 -> {179};
179 -> {180};
180 -> {181};
181 -> {182};
182 -> {183};
183 -> {184};
184 -> {185};
185 -> {186};
186 -> {187};
187 -> {188};
188 -> {189};
189 -> {190};
190 -> {191};
191 -> {192};
192 -> {193};
193 -> {194};
194 -> {186};
194 -> {195} [style=dotted];
195 -> {196} [style=dotted];
196 -> {197} [style=dotted];
197 -> {198} [style=dotted];
198 -> {199} [style=dotted];
188 -> {180};
188 -> {189} [style=dotted];
189 -> {190} [style=dotted];
190 -> {191} [style=dotted];
191 -> {192} [style=dotted];
}
@@ -203,23 +203,22 @@ digraph safeCalls_kt {
^test_5 Unit
}
)" style="filled" fillcolor=gray];
76 [label="Exit safe call" style="filled" fillcolor=gray];
77 [label="Enter safe call" style="filled" fillcolor=gray];
78 [label="Access variable R|<local>/x|" style="filled" fillcolor=gray];
79 [label="Function call: R|<local>/x|.R|/A.bool|()" style="filled" fillcolor=gray];
76 [label="Exit safe call"];
77 [label="Enter safe call"];
78 [label="Access variable R|<local>/x|"];
79 [label="Function call: R|<local>/x|.R|/A.bool|()"];
80 [label="Function call: R|<local>/x|?.R|kotlin/let|<R|A|, R|kotlin/Nothing|>(<L> = let@fun <anonymous>(it: R|A|): R|kotlin/Nothing| <kind=EXACTLY_ONCE> {
^test_5 Unit
}
)?.R|/boo|(R|<local>/x|.R|/A.bool|())" style="filled" fillcolor=gray];
81 [label="Exit safe call" style="filled" fillcolor=gray];
82 [label="Access variable R|<local>/x|" style="filled" fillcolor=gray];
83 [label="Function call: R|<local>/x|.<Inapplicable(WRONG_RECEIVER): [/A.id]>#()" style="filled" fillcolor=gray];
)?.R|/boo|(R|<local>/x|.R|/A.bool|())"];
81 [label="Exit safe call"];
82 [label="Access variable R|<local>/x|"];
83 [label="Function call: R|<local>/x|.<Inapplicable(WRONG_RECEIVER): [/A.id]>#()"];
84 [label="Exit function test_5" style="filled" fillcolor=red];
}
68 -> {69};
69 -> {70};
69 -> {76} [style=dotted];
69 -> {70 76};
70 -> {71};
71 -> {72};
72 -> {84};
@@ -227,13 +226,13 @@ digraph safeCalls_kt {
73 -> {74} [style=dotted];
74 -> {75} [style=dotted];
75 -> {76} [style=dotted];
76 -> {77 81} [style=dotted];
77 -> {78} [style=dotted];
78 -> {79} [style=dotted];
79 -> {80} [style=dotted];
80 -> {81} [style=dotted];
81 -> {82} [style=dotted];
82 -> {83} [style=dotted];
83 -> {84} [style=dotted];
76 -> {77 81};
77 -> {78};
78 -> {79};
79 -> {80};
80 -> {81};
81 -> {82};
82 -> {83};
83 -> {84};
}
@@ -5,18 +5,20 @@
package org.jetbrains.kotlin.fir
import junit.framework.TestCase
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
import org.jetbrains.kotlin.fir.resolve.dfa.FirControlFlowGraphReferenceImpl
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.CFGNode
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.ControlFlowGraph
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.EdgeKind
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.FirControlFlowGraphRenderVisitor
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
import java.io.File
private const val EDGE = " -> "
private const val INDENT = " "
private const val RED = "red"
private const val BLUE = "blue"
/*
* For comfort viewing dumps of control flow graph you can setup external tool in IDEA that opens .dot files
@@ -43,122 +45,53 @@ abstract class AbstractFirDiagnosticsWithCfgTest : AbstractFirDiagnosticsTest()
super.runAnalysis(testDataFile, testFiles, firFilesPerSession)
val allFirFiles = firFilesPerSession.values.flatten()
checkCfg(testDataFile, allFirFiles)
checkCfgEdgeConsistency(allFirFiles)
}
fun checkCfg(testDataFile: File, firFiles: List<FirFile>) {
val simpleBuilder = StringBuilder()
val dotBuilder = StringBuilder()
private fun checkCfg(testDataFile: File, firFiles: List<FirFile>) {
val builder = StringBuilder()
firFiles.first().accept(FirControlFlowGraphRenderVisitor(simpleBuilder, dotBuilder), null)
firFiles.first().accept(FirControlFlowGraphRenderVisitor(builder), null)
val dotCfgDump = dotBuilder.toString()
val dotCfgDump = builder.toString()
val dotExpectedPath = testDataFile.absolutePath.replace(".kt", ".dot")
KotlinTestUtils.assertEqualsToFile(File(dotExpectedPath), dotCfgDump)
}
private class FirControlFlowGraphRenderVisitor(
private val simpleBuilder: StringBuilder,
private val dotBuilder: StringBuilder
) : FirVisitorVoid() {
private var indexOffset = 0
private var clusterCounter = 0
private var offset = 1
override fun visitFile(file: FirFile) {
dotBuilder.appendln("digraph ${file.name.replace(".", "_")} {")
.appendln("${INDENT}graph [splines=ortho nodesep=3]")
.appendln("${INDENT}node [shape=box penwidth=2]")
.appendln("${INDENT}edge [penwidth=2]")
.appendln()
visitElement(file)
dotBuilder.appendln("}")
private fun checkCfgEdgeConsistency(firFiles: List<FirFile>) {
firFiles.forEach { it.accept(CfgConsistencyChecker) }
}
private object CfgConsistencyChecker : FirVisitorVoid() {
override fun visitElement(element: FirElement) {
element.acceptChildren(this)
}
override fun visitControlFlowGraphReference(controlFlowGraphReference: FirControlFlowGraphReference) {
val controlFlowGraph = (controlFlowGraphReference as? FirControlFlowGraphReferenceImpl)?.controlFlowGraph ?: return
controlFlowGraph.renderToStringBuilder(simpleBuilder)
indexOffset = controlFlowGraph.dotRenderToStringBuilder(dotBuilder)
dotBuilder.appendln()
val graph = (controlFlowGraphReference as? FirControlFlowGraphReferenceImpl)?.controlFlowGraph ?: return
checkConsistency(graph)
}
private fun StringBuilder.enterCluster(color: String) {
indent()
appendln("subgraph cluster_${clusterCounter++} {")
offset++
indent()
appendln("color=$color")
private fun checkConsistency(graph: ControlFlowGraph) {
for (node in graph.nodes) {
for (to in node.followingNodes) {
checkEdge(node, to)
}
for (from in node.previousNodes) {
checkEdge(from, node)
}
TestCase.assertTrue(node.followingNodes.isNotEmpty() || node.previousNodes.isNotEmpty())
}
}
private fun StringBuilder.exitCluster() {
offset--
indent()
appendln("}")
}
private fun StringBuilder.indent() {
append(INDENT.repeat(offset))
}
fun ControlFlowGraph.dotRenderToStringBuilder(builder: StringBuilder): Int {
with(builder) {
val sortedNodes = sortNodes()
val indices = sortedNodes.indicesMap().mapValues { (_, index) -> index + indexOffset }
fun CFGNode<*>.splitEdges(): Pair<List<CFGNode<*>>, List<CFGNode<*>>> =
if (isDead) emptyList<CFGNode<*>>() to followingNodes
else followingNodes.filter { !it.isDead } to followingNodes.filter { it.isDead }
var color = RED
sortedNodes.forEach {
if (it is EnterNode) {
enterCluster(color)
color = BLUE
}
indent()
append(indices.getValue(it))
val attributes = mutableListOf<String>()
attributes += "label=\"${it.render().replace("\"", "")}\""
if (it == enterNode || it == exitNode) {
attributes += "style=\"filled\""
attributes += "fillcolor=red"
}
if (it.isDead) {
attributes += "style=\"filled\""
attributes += "fillcolor=gray"
}
appendln(attributes.joinToString(separator = " ", prefix = " [", postfix = "];"))
if (it is ExitNode) {
exitCluster()
}
}
appendln()
sortedNodes.forEachIndexed { i, node ->
if (node.followingNodes.isEmpty()) return@forEachIndexed
val (aliveEdges, deadEdges) = node.splitEdges()
fun renderEdges(edges: List<CFGNode<*>>, isDead: Boolean) {
if (edges.isEmpty()) return
indent()
append(i + indexOffset)
append(EDGE)
append(edges.joinToString(prefix = "{", postfix = "}", separator = " ") { indices.getValue(it).toString() })
if (isDead) {
append(" [style=dotted]")
}
appendln(";")
}
renderEdges(aliveEdges, false)
renderEdges(deadEdges, true)
}
return indexOffset + sortedNodes.size
private fun checkEdge(from: CFGNode<*>, to: CFGNode<*>) {
KtUsefulTestCase.assertContainsElements(from.followingNodes, to)
KtUsefulTestCase.assertContainsElements(to.previousNodes, from)
val fromKind = from.outgoingEdges.getValue(to)
val toKind = to.incomingEdges.getValue(from)
TestCase.assertEquals(fromKind, toKind)
if (from.isDead || to.isDead) {
TestCase.assertEquals(EdgeKind.Dead, fromKind)
}
}
}