diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt index 330378cbe06..78f0630c871 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/dfa/cfg/ControlFlowGraphBuilder.kt @@ -301,13 +301,18 @@ class ControlFlowGraphBuilder : ControlFlowGraphNodeBuilder() { fun exitLeftBinaryAndArgument(binaryLogicExpression: FirBinaryLogicExpression) { assert(binaryLogicExpression.kind == FirBinaryLogicExpression.OperationKind.AND) - addEdge(lastNode, binaryAndExitNodes.top()) + addEdge(lastNode, binaryAndExitNodes.top(), propagateDeadness = false, isDead = lastNode.booleanConstValue == true) } fun exitBinaryAnd(binaryLogicExpression: FirBinaryLogicExpression): BinaryAndExitNode { levelCounter-- assert(binaryLogicExpression.kind == FirBinaryLogicExpression.OperationKind.AND) - return binaryAndExitNodes.pop().also { addNewSimpleNode(it) } + return binaryAndExitNodes.pop().also { + val rightNode = lastNodes.pop() + addEdge(rightNode, it, propagateDeadness = false, isDead = it.leftOperandNode.booleanConstValue == false) + it.isDead = it.previousNodes.all { it.isDead } + lastNodes.push(it) + } } fun enterBinaryOr(binaryLogicExpression: FirBinaryLogicExpression): BinaryOrEnterNode { @@ -322,9 +327,10 @@ class ControlFlowGraphBuilder : ControlFlowGraphNodeBuilder() { levelCounter-- assert(binaryLogicExpression.kind == FirBinaryLogicExpression.OperationKind.OR) val previousNode = lastNodes.pop() - addEdge(previousNode, binaryOrExitNodes.top()) + val leftBooleanValue = previousNode.booleanConstValue + addEdge(previousNode, binaryOrExitNodes.top(), isDead = leftBooleanValue == false) return createBinaryOrExitLeftOperandNode(binaryLogicExpression).also { - addEdge(previousNode, it) + addEdge(previousNode, it, isDead = leftBooleanValue == true) lastNodes.push(it) levelCounter++ } @@ -334,11 +340,15 @@ class ControlFlowGraphBuilder : ControlFlowGraphNodeBuilder() { assert(binaryLogicExpression.kind == FirBinaryLogicExpression.OperationKind.OR) levelCounter-- return binaryOrExitNodes.pop().also { - addEdge(lastNodes.pop(), it) + val rightNode = lastNodes.pop() + addEdge(rightNode, it, propagateDeadness = false) + it.isDead = it.previousNodes.all { it.isDead } lastNodes.push(it) } } + private val CFGNode<*>.booleanConstValue: Boolean? get() = (fir as? FirConstExpression<*>)?.value as? Boolean? + // ----------------------------------- Try-catch-finally ----------------------------------- private val finallyEnterNodes: Stack = stackOf() @@ -525,7 +535,17 @@ class ControlFlowGraphBuilder : ControlFlowGraphNodeBuilder() { return oldNode } - private fun addEdge(from: CFGNode<*>, to: CFGNode<*>, propagateDeadness: Boolean = true) { + private fun addDeadEdge(from: CFGNode<*>, to: CFGNode<*>) { + val stub = createStubNode() + addEdge(from, stub) + addEdge(stub, to) + } + + private fun addEdge(from: CFGNode<*>, to: CFGNode<*>, propagateDeadness: Boolean = true, isDead: Boolean = false) { + if (isDead) { + addDeadEdge(from, to) + return + } if (propagateDeadness && from.isDead) { to.isDead = true } diff --git a/compiler/fir/resolve/testData/resolve/cfg/booleanOperatorsWithConsts.dot b/compiler/fir/resolve/testData/resolve/cfg/booleanOperatorsWithConsts.dot new file mode 100644 index 00000000000..bcf4b4b593c --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/cfg/booleanOperatorsWithConsts.dot @@ -0,0 +1,381 @@ +digraph booleanOperatorsWithConsts_kt { +subgraph test_1 { + 0 [shape=box label="Enter function test_1"]; + 1 [shape=box label="Enter block"]; + 2 [shape=box label="Enter when"]; + 3 [shape=box label="Enter when branch condition "]; + 4 [shape=box label="Enter ||"]; + 5 [shape=box label="Access variable R|/b|"]; + 6 [shape=box label="Exit left part of ||"]; + 7 [shape=box label="Const: Boolean(false)"]; + 8 [shape=box label="Exit ||"]; + 9 [shape=box label="Exit when branch condition"]; + 10 [shape=box label="Enter block"]; + 11 [shape=box label="Const: Int(1)"]; + 12 [shape=box label="Exit block"]; + 13 [shape=box label="Exit when branch result"]; + 14 [shape=box label="Enter when branch condition else"]; + 15 [shape=box label="Exit when branch condition"]; + 16 [shape=box label="Enter block"]; + 17 [shape=box label="Exit block"]; + 18 [shape=box label="Exit when branch result"]; + 19 [shape=box label="Exit when"]; + 20 [shape=box label="Exit block"]; + 21 [shape=box label="Exit function test_1"]; + + 0 -> {1}; + 1 -> {2}; + 2 -> {3}; + 3 -> {4}; + 4 -> {5}; + 5 -> {8 6}; + 6 -> {7}; + 7 -> {8}; + 8 -> {9}; + 9 -> {10 14}; + 10 -> {11}; + 11 -> {12}; + 12 -> {13}; + 13 -> {19}; + 14 -> {15}; + 15 -> {16}; + 16 -> {17}; + 17 -> {18}; + 18 -> {19}; + 19 -> {20}; + 20 -> {21}; +} + +subgraph test_2 { + 22 [shape=box label="Enter function test_2"]; + 23 [shape=box label="Enter block"]; + 24 [shape=box label="Enter when"]; + 25 [shape=box label="Enter when branch condition "]; + 26 [shape=box label="Enter ||"]; + 27 [shape=box label="Const: Boolean(false)"]; + 28 [shape=box label="Exit left part of ||"]; + 29 [shape=box label="Access variable R|/b|"]; + 30 [shape=box label="Stub[DEAD]"]; + 31 [shape=box label="Exit ||"]; + 32 [shape=box label="Exit when branch condition"]; + 33 [shape=box label="Enter block"]; + 34 [shape=box label="Const: Int(1)"]; + 35 [shape=box label="Exit block"]; + 36 [shape=box label="Exit when branch result"]; + 37 [shape=box label="Enter when branch condition else"]; + 38 [shape=box label="Exit when branch condition"]; + 39 [shape=box label="Enter block"]; + 40 [shape=box label="Exit block"]; + 41 [shape=box label="Exit when branch result"]; + 42 [shape=box label="Exit when"]; + 43 [shape=box label="Exit block"]; + 44 [shape=box label="Exit function test_2"]; + + 22 -> {23}; + 23 -> {24}; + 24 -> {25}; + 25 -> {26}; + 26 -> {27}; + 27 -> {28}; + 27 -> {30} [style=dotted]; + 28 -> {29}; + 29 -> {31}; + 30 -> {31} [style=dotted]; + 31 -> {32}; + 32 -> {33 37}; + 33 -> {34}; + 34 -> {35}; + 35 -> {36}; + 36 -> {42}; + 37 -> {38}; + 38 -> {39}; + 39 -> {40}; + 40 -> {41}; + 41 -> {42}; + 42 -> {43}; + 43 -> {44}; +} + +subgraph test_3 { + 45 [shape=box label="Enter function test_3"]; + 46 [shape=box label="Enter block"]; + 47 [shape=box label="Enter when"]; + 48 [shape=box label="Enter when branch condition "]; + 49 [shape=box label="Enter ||"]; + 50 [shape=box label="Access variable R|/b|"]; + 51 [shape=box label="Exit left part of ||"]; + 52 [shape=box label="Const: Boolean(true)"]; + 53 [shape=box label="Exit ||"]; + 54 [shape=box label="Exit when branch condition"]; + 55 [shape=box label="Enter block"]; + 56 [shape=box label="Const: Int(1)"]; + 57 [shape=box label="Exit block"]; + 58 [shape=box label="Exit when branch result"]; + 59 [shape=box label="Enter when branch condition else"]; + 60 [shape=box label="Exit when branch condition"]; + 61 [shape=box label="Enter block"]; + 62 [shape=box label="Exit block"]; + 63 [shape=box label="Exit when branch result"]; + 64 [shape=box label="Exit when"]; + 65 [shape=box label="Exit block"]; + 66 [shape=box label="Exit function test_3"]; + + 45 -> {46}; + 46 -> {47}; + 47 -> {48}; + 48 -> {49}; + 49 -> {50}; + 50 -> {53 51}; + 51 -> {52}; + 52 -> {53}; + 53 -> {54}; + 54 -> {55 59}; + 55 -> {56}; + 56 -> {57}; + 57 -> {58}; + 58 -> {64}; + 59 -> {60}; + 60 -> {61}; + 61 -> {62}; + 62 -> {63}; + 63 -> {64}; + 64 -> {65}; + 65 -> {66}; +} + +subgraph test_4 { + 67 [shape=box label="Enter function test_4"]; + 68 [shape=box label="Enter block"]; + 69 [shape=box label="Enter when"]; + 70 [shape=box label="Enter when branch condition "]; + 71 [shape=box label="Enter ||"]; + 72 [shape=box label="Const: Boolean(true)"]; + 73 [shape=box label="Stub[DEAD]"]; + 74 [shape=box label="Exit left part of ||[DEAD]"]; + 75 [shape=box label="Access variable R|/b|[DEAD]"]; + 76 [shape=box label="Exit ||"]; + 77 [shape=box label="Exit when branch condition"]; + 78 [shape=box label="Enter block"]; + 79 [shape=box label="Const: Int(1)"]; + 80 [shape=box label="Exit block"]; + 81 [shape=box label="Exit when branch result"]; + 82 [shape=box label="Enter when branch condition else"]; + 83 [shape=box label="Exit when branch condition"]; + 84 [shape=box label="Enter block"]; + 85 [shape=box label="Exit block"]; + 86 [shape=box label="Exit when branch result"]; + 87 [shape=box label="Exit when"]; + 88 [shape=box label="Exit block"]; + 89 [shape=box label="Exit function test_4"]; + + 67 -> {68}; + 68 -> {69}; + 69 -> {70}; + 70 -> {71}; + 71 -> {72}; + 72 -> {76}; + 72 -> {73} [style=dotted]; + 73 -> {74} [style=dotted]; + 74 -> {75} [style=dotted]; + 75 -> {76} [style=dotted]; + 76 -> {77}; + 77 -> {78 82}; + 78 -> {79}; + 79 -> {80}; + 80 -> {81}; + 81 -> {87}; + 82 -> {83}; + 83 -> {84}; + 84 -> {85}; + 85 -> {86}; + 86 -> {87}; + 87 -> {88}; + 88 -> {89}; +} + +subgraph test_5 { + 90 [shape=box label="Enter function test_5"]; + 91 [shape=box label="Enter block"]; + 92 [shape=box label="Enter when"]; + 93 [shape=box label="Enter when branch condition "]; + 94 [shape=box label="Enter &&"]; + 95 [shape=box label="Access variable R|/b|"]; + 96 [shape=box label="Const: Boolean(false)"]; + 97 [shape=box label="Exit &&"]; + 98 [shape=box label="Exit when branch condition"]; + 99 [shape=box label="Enter block"]; + 100 [shape=box label="Const: Int(1)"]; + 101 [shape=box label="Exit block"]; + 102 [shape=box label="Exit when branch result"]; + 103 [shape=box label="Enter when branch condition else"]; + 104 [shape=box label="Exit when branch condition"]; + 105 [shape=box label="Enter block"]; + 106 [shape=box label="Exit block"]; + 107 [shape=box label="Exit when branch result"]; + 108 [shape=box label="Exit when"]; + 109 [shape=box label="Exit block"]; + 110 [shape=box label="Exit function test_5"]; + + 90 -> {91}; + 91 -> {92}; + 92 -> {93}; + 93 -> {94}; + 94 -> {95}; + 95 -> {97 96}; + 96 -> {97}; + 97 -> {98}; + 98 -> {99 103}; + 99 -> {100}; + 100 -> {101}; + 101 -> {102}; + 102 -> {108}; + 103 -> {104}; + 104 -> {105}; + 105 -> {106}; + 106 -> {107}; + 107 -> {108}; + 108 -> {109}; + 109 -> {110}; +} + +subgraph test_6 { + 111 [shape=box label="Enter function test_6"]; + 112 [shape=box label="Enter block"]; + 113 [shape=box label="Enter when"]; + 114 [shape=box label="Enter when branch condition "]; + 115 [shape=box label="Enter &&"]; + 116 [shape=box label="Const: Boolean(false)"]; + 117 [shape=box label="Access variable R|/b|"]; + 118 [shape=box label="Stub[DEAD]"]; + 119 [shape=box label="Exit &&"]; + 120 [shape=box label="Exit when branch condition"]; + 121 [shape=box label="Enter block"]; + 122 [shape=box label="Const: Int(1)"]; + 123 [shape=box label="Exit block"]; + 124 [shape=box label="Exit when branch result"]; + 125 [shape=box label="Enter when branch condition else"]; + 126 [shape=box label="Exit when branch condition"]; + 127 [shape=box label="Enter block"]; + 128 [shape=box label="Exit block"]; + 129 [shape=box label="Exit when branch result"]; + 130 [shape=box label="Exit when"]; + 131 [shape=box label="Exit block"]; + 132 [shape=box label="Exit function test_6"]; + + 111 -> {112}; + 112 -> {113}; + 113 -> {114}; + 114 -> {115}; + 115 -> {116}; + 116 -> {119 117}; + 117 -> {118} [style=dotted]; + 118 -> {119} [style=dotted]; + 119 -> {120}; + 120 -> {121 125}; + 121 -> {122}; + 122 -> {123}; + 123 -> {124}; + 124 -> {130}; + 125 -> {126}; + 126 -> {127}; + 127 -> {128}; + 128 -> {129}; + 129 -> {130}; + 130 -> {131}; + 131 -> {132}; +} + +subgraph test_7 { + 133 [shape=box label="Enter function test_7"]; + 134 [shape=box label="Enter block"]; + 135 [shape=box label="Enter when"]; + 136 [shape=box label="Enter when branch condition "]; + 137 [shape=box label="Enter &&"]; + 138 [shape=box label="Access variable R|/b|"]; + 139 [shape=box label="Const: Boolean(true)"]; + 140 [shape=box label="Exit &&"]; + 141 [shape=box label="Exit when branch condition"]; + 142 [shape=box label="Enter block"]; + 143 [shape=box label="Const: Int(1)"]; + 144 [shape=box label="Exit block"]; + 145 [shape=box label="Exit when branch result"]; + 146 [shape=box label="Enter when branch condition else"]; + 147 [shape=box label="Exit when branch condition"]; + 148 [shape=box label="Enter block"]; + 149 [shape=box label="Exit block"]; + 150 [shape=box label="Exit when branch result"]; + 151 [shape=box label="Exit when"]; + 152 [shape=box label="Exit block"]; + 153 [shape=box label="Exit function test_7"]; + + 133 -> {134}; + 134 -> {135}; + 135 -> {136}; + 136 -> {137}; + 137 -> {138}; + 138 -> {140 139}; + 139 -> {140}; + 140 -> {141}; + 141 -> {142 146}; + 142 -> {143}; + 143 -> {144}; + 144 -> {145}; + 145 -> {151}; + 146 -> {147}; + 147 -> {148}; + 148 -> {149}; + 149 -> {150}; + 150 -> {151}; + 151 -> {152}; + 152 -> {153}; +} + +subgraph test_8 { + 154 [shape=box label="Enter function test_8"]; + 155 [shape=box label="Enter block"]; + 156 [shape=box label="Enter when"]; + 157 [shape=box label="Enter when branch condition "]; + 158 [shape=box label="Enter &&"]; + 159 [shape=box label="Const: Boolean(true)"]; + 160 [shape=box label="Access variable R|/b|"]; + 161 [shape=box label="Stub[DEAD]"]; + 162 [shape=box label="Exit &&"]; + 163 [shape=box label="Exit when branch condition"]; + 164 [shape=box label="Enter block"]; + 165 [shape=box label="Const: Int(1)"]; + 166 [shape=box label="Exit block"]; + 167 [shape=box label="Exit when branch result"]; + 168 [shape=box label="Enter when branch condition else"]; + 169 [shape=box label="Exit when branch condition"]; + 170 [shape=box label="Enter block"]; + 171 [shape=box label="Exit block"]; + 172 [shape=box label="Exit when branch result"]; + 173 [shape=box label="Exit when"]; + 174 [shape=box label="Exit block"]; + 175 [shape=box label="Exit function test_8"]; + + 154 -> {155}; + 155 -> {156}; + 156 -> {157}; + 157 -> {158}; + 158 -> {159}; + 159 -> {160}; + 159 -> {161} [style=dotted]; + 160 -> {162}; + 161 -> {162} [style=dotted]; + 162 -> {163}; + 163 -> {164 168}; + 164 -> {165}; + 165 -> {166}; + 166 -> {167}; + 167 -> {173}; + 168 -> {169}; + 169 -> {170}; + 170 -> {171}; + 171 -> {172}; + 172 -> {173}; + 173 -> {174}; + 174 -> {175}; +} + +} diff --git a/compiler/fir/resolve/testData/resolve/cfg/booleanOperatorsWithConsts.kt b/compiler/fir/resolve/testData/resolve/cfg/booleanOperatorsWithConsts.kt new file mode 100644 index 00000000000..97ee5188bfc --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/cfg/booleanOperatorsWithConsts.kt @@ -0,0 +1,47 @@ +fun test_1(b: Boolean) { + if (b || false) { + 1 + } +} + +fun test_2(b: Boolean) { + if (false || b) { + 1 + } +} + +fun test_3(b: Boolean) { + if (b || true) { + 1 + } +} + +fun test_4(b: Boolean) { + if (true || b) { + 1 + } +} + +fun test_5(b: Boolean) { + if (b && false) { + 1 + } +} + +fun test_6(b: Boolean) { + if (false && b) { + 1 + } +} + +fun test_7(b: Boolean) { + if (b && true) { + 1 + } +} + +fun test_8(b: Boolean) { + if (true && b) { + 1 + } +} \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/cfg/booleanOperatorsWithConsts.txt b/compiler/fir/resolve/testData/resolve/cfg/booleanOperatorsWithConsts.txt new file mode 100644 index 00000000000..cbde24debd4 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/cfg/booleanOperatorsWithConsts.txt @@ -0,0 +1,81 @@ +FILE: booleanOperatorsWithConsts.kt + public final fun test_1(b: R|kotlin/Boolean|): R|kotlin/Unit| { + when () { + R|/b| || Boolean(false) -> { + Int(1) + } + else -> { + } + } + + } + public final fun test_2(b: R|kotlin/Boolean|): R|kotlin/Unit| { + when () { + Boolean(false) || R|/b| -> { + Int(1) + } + else -> { + } + } + + } + public final fun test_3(b: R|kotlin/Boolean|): R|kotlin/Unit| { + when () { + R|/b| || Boolean(true) -> { + Int(1) + } + else -> { + } + } + + } + public final fun test_4(b: R|kotlin/Boolean|): R|kotlin/Unit| { + when () { + Boolean(true) || R|/b| -> { + Int(1) + } + else -> { + } + } + + } + public final fun test_5(b: R|kotlin/Boolean|): R|kotlin/Unit| { + when () { + R|/b| && Boolean(false) -> { + Int(1) + } + else -> { + } + } + + } + public final fun test_6(b: R|kotlin/Boolean|): R|kotlin/Unit| { + when () { + Boolean(false) && R|/b| -> { + Int(1) + } + else -> { + } + } + + } + public final fun test_7(b: R|kotlin/Boolean|): R|kotlin/Unit| { + when () { + R|/b| && Boolean(true) -> { + Int(1) + } + else -> { + } + } + + } + public final fun test_8(b: R|kotlin/Boolean|): R|kotlin/Unit| { + when () { + Boolean(true) && R|/b| -> { + Int(1) + } + else -> { + } + } + + } diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.dot b/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.dot index c9947b062a2..7de232c8a2e 100644 --- a/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.dot +++ b/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.dot @@ -246,4 +246,113 @@ subgraph test_4 { 111 -> {112}; } +subgraph test_5 { + 113 [shape=box label="Enter function test_5"]; + 114 [shape=box label="Enter block"]; + 115 [shape=box label="Enter when"]; + 116 [shape=box label="Enter when branch condition "]; + 117 [shape=box label="Enter ||"]; + 118 [shape=box label="Access variable R|/x|"]; + 119 [shape=box label="Const: Null(null)"]; + 120 [shape=box label="Operator !="]; + 121 [shape=box label="Exit left part of ||"]; + 122 [shape=box label="Const: Boolean(false)"]; + 123 [shape=box label="Exit ||"]; + 124 [shape=box label="Exit when branch condition"]; + 125 [shape=box label="Enter block"]; + 126 [shape=box label="Access variable R|/x|"]; + 127 [shape=box label="Function call: R|/x|.#()"]; + 128 [shape=box label="Exit block"]; + 129 [shape=box label="Exit when branch result"]; + 130 [shape=box label="Enter when branch condition else"]; + 131 [shape=box label="Exit when branch condition"]; + 132 [shape=box label="Enter block"]; + 133 [shape=box label="Exit block"]; + 134 [shape=box label="Exit when branch result"]; + 135 [shape=box label="Exit when"]; + 136 [shape=box label="Exit block"]; + 137 [shape=box label="Exit function test_5"]; + + 113 -> {114}; + 114 -> {115}; + 115 -> {116}; + 116 -> {117}; + 117 -> {118}; + 118 -> {119}; + 119 -> {120}; + 120 -> {123 121}; + 121 -> {122}; + 122 -> {123}; + 123 -> {124}; + 124 -> {125 130}; + 125 -> {126}; + 126 -> {127}; + 127 -> {128}; + 128 -> {129}; + 129 -> {135}; + 130 -> {131}; + 131 -> {132}; + 132 -> {133}; + 133 -> {134}; + 134 -> {135}; + 135 -> {136}; + 136 -> {137}; +} + +subgraph test_6 { + 138 [shape=box label="Enter function test_6"]; + 139 [shape=box label="Enter block"]; + 140 [shape=box label="Enter when"]; + 141 [shape=box label="Enter when branch condition "]; + 142 [shape=box label="Enter ||"]; + 143 [shape=box label="Const: Boolean(false)"]; + 144 [shape=box label="Exit left part of ||"]; + 145 [shape=box label="Access variable R|/x|"]; + 146 [shape=box label="Const: Null(null)"]; + 147 [shape=box label="Operator !="]; + 148 [shape=box label="Stub[DEAD]"]; + 149 [shape=box label="Exit ||"]; + 150 [shape=box label="Exit when branch condition"]; + 151 [shape=box label="Enter block"]; + 152 [shape=box label="Access variable R|/x|"]; + 153 [shape=box label="Function call: R|/x|.#()"]; + 154 [shape=box label="Exit block"]; + 155 [shape=box label="Exit when branch result"]; + 156 [shape=box label="Enter when branch condition else"]; + 157 [shape=box label="Exit when branch condition"]; + 158 [shape=box label="Enter block"]; + 159 [shape=box label="Exit block"]; + 160 [shape=box label="Exit when branch result"]; + 161 [shape=box label="Exit when"]; + 162 [shape=box label="Exit block"]; + 163 [shape=box label="Exit function test_6"]; + + 138 -> {139}; + 139 -> {140}; + 140 -> {141}; + 141 -> {142}; + 142 -> {143}; + 143 -> {144}; + 143 -> {148} [style=dotted]; + 144 -> {145}; + 145 -> {146}; + 146 -> {147}; + 147 -> {149}; + 148 -> {149} [style=dotted]; + 149 -> {150}; + 150 -> {151 156}; + 151 -> {152}; + 152 -> {153}; + 153 -> {154}; + 154 -> {155}; + 155 -> {161}; + 156 -> {157}; + 157 -> {158}; + 158 -> {159}; + 159 -> {160}; + 160 -> {161}; + 161 -> {162}; + 162 -> {163}; +} + } diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.kt b/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.kt index 49cf05c9edd..83090fd17c8 100644 --- a/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.kt +++ b/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.kt @@ -37,4 +37,16 @@ fun test_4(x: Any) { x.length } x.length +} + +fun test_5(x: A?) { + if (x != null || false) { + x.foo() + } +} + +fun test_6(x: A?) { + if (false || x != null) { + x.foo() + } } \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.txt b/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.txt index 74caaa9413b..7fc7de1a1bf 100644 --- a/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.txt +++ b/compiler/fir/resolve/testData/resolve/smartcasts/booleanOperators.txt @@ -56,3 +56,23 @@ FILE: booleanOperators.kt R|/x|.# } + public final fun test_5(x: R|A?|): R|kotlin/Unit| { + when () { + !=(R|/x|, Null(null)) || Boolean(false) -> { + R|/x|.#() + } + else -> { + } + } + + } + public final fun test_6(x: R|A?|): R|kotlin/Unit| { + when () { + Boolean(false) || !=(R|/x|, Null(null)) -> { + R|/x|.#() + } + else -> { + } + } + + } diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirCfgBuildingTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirCfgBuildingTestGenerated.java index 41b54ad6103..856f966fbaf 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirCfgBuildingTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirCfgBuildingTestGenerated.java @@ -36,6 +36,11 @@ public class FirCfgBuildingTestGenerated extends AbstractFirCfgBuildingTest { runTest("compiler/fir/resolve/testData/resolve/cfg/binaryOperations.kt"); } + @TestMetadata("booleanOperatorsWithConsts.kt") + public void testBooleanOperatorsWithConsts() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/cfg/booleanOperatorsWithConsts.kt"); + } + @TestMetadata("complex.kt") public void testComplex() throws Exception { runTest("compiler/fir/resolve/testData/resolve/cfg/complex.kt");