[FIR] Fix data-flow after while loops
This commit is contained in:
committed by
Mikhail Glukhikh
parent
91b432b4a1
commit
645602b675
+16
-1
@@ -392,6 +392,19 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
|
|
||||||
// ----------------------------------- While Loop -----------------------------------
|
// ----------------------------------- While Loop -----------------------------------
|
||||||
|
|
||||||
|
private fun exitCommonLoop(exitNode: LoopExitNode) {
|
||||||
|
val singlePreviousNode = exitNode.previousNodes.singleOrNull { !it.isDead }
|
||||||
|
if (singlePreviousNode is LoopConditionExitNode) {
|
||||||
|
val variable = variableStorage.getOrCreateVariable(singlePreviousNode.fir)
|
||||||
|
exitNode.flow = logicSystem.approveStatementsInsideFlow(
|
||||||
|
exitNode.flow,
|
||||||
|
variable eq false,
|
||||||
|
shouldForkFlow = false,
|
||||||
|
shouldRemoveSynthetics = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun enterWhileLoop(loop: FirLoop) {
|
fun enterWhileLoop(loop: FirLoop) {
|
||||||
val (loopEnterNode, loopConditionEnterNode) = graphBuilder.enterWhileLoop(loop)
|
val (loopEnterNode, loopConditionEnterNode) = graphBuilder.enterWhileLoop(loop)
|
||||||
loopEnterNode.mergeIncomingFlow()
|
loopEnterNode.mergeIncomingFlow()
|
||||||
@@ -407,7 +420,7 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
loopBlockEnterNode.flow,
|
loopBlockEnterNode.flow,
|
||||||
conditionVariable eq true,
|
conditionVariable eq true,
|
||||||
shouldForkFlow = false,
|
shouldForkFlow = false,
|
||||||
shouldRemoveSynthetics = true
|
shouldRemoveSynthetics = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -416,6 +429,7 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
val (blockExitNode, exitNode) = graphBuilder.exitWhileLoop(loop)
|
val (blockExitNode, exitNode) = graphBuilder.exitWhileLoop(loop)
|
||||||
blockExitNode.mergeIncomingFlow()
|
blockExitNode.mergeIncomingFlow()
|
||||||
exitNode.mergeIncomingFlow()
|
exitNode.mergeIncomingFlow()
|
||||||
|
exitCommonLoop(exitNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------- Do while Loop -----------------------------------
|
// ----------------------------------- Do while Loop -----------------------------------
|
||||||
@@ -436,6 +450,7 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
val (loopConditionExitNode, loopExitNode) = graphBuilder.exitDoWhileLoop(loop)
|
val (loopConditionExitNode, loopExitNode) = graphBuilder.exitDoWhileLoop(loop)
|
||||||
loopConditionExitNode.mergeIncomingFlow()
|
loopConditionExitNode.mergeIncomingFlow()
|
||||||
loopExitNode.mergeIncomingFlow()
|
loopExitNode.mergeIncomingFlow()
|
||||||
|
exitCommonLoop(loopExitNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------- Try-catch-finally -----------------------------------
|
// ----------------------------------- Try-catch-finally -----------------------------------
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ class C {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
a.<!INAPPLICABLE_CANDIDATE!>compareTo<!>("2")
|
a.compareTo("2")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun containsBreakWithLabel(a: String?) {
|
fun containsBreakWithLabel(a: String?) {
|
||||||
@@ -52,7 +52,7 @@ class C {
|
|||||||
loop@ while(a == null) {
|
loop@ while(a == null) {
|
||||||
break@label
|
break@label
|
||||||
}
|
}
|
||||||
a.<!INAPPLICABLE_CANDIDATE!>compareTo<!>("2")
|
a.compareTo("2")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun containsBreakToOuterLoop(a: String?, b: String?) {
|
fun containsBreakToOuterLoop(a: String?, b: String?) {
|
||||||
@@ -60,7 +60,7 @@ class C {
|
|||||||
while(a == null) {
|
while(a == null) {
|
||||||
break@loop
|
break@loop
|
||||||
}
|
}
|
||||||
a.<!INAPPLICABLE_CANDIDATE!>compareTo<!>("2")
|
a.compareTo("2")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -151,7 +151,7 @@ fun test() {
|
|||||||
out2?.println();
|
out2?.println();
|
||||||
out2.<!INAPPLICABLE_CANDIDATE!>println<!>();
|
out2.<!INAPPLICABLE_CANDIDATE!>println<!>();
|
||||||
}
|
}
|
||||||
out2.<!INAPPLICABLE_CANDIDATE!>println<!>()
|
out2.println()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +228,7 @@ fun f6(s : String?) {
|
|||||||
do {
|
do {
|
||||||
s?.get(0)
|
s?.get(0)
|
||||||
} while (s == null)
|
} while (s == null)
|
||||||
s.<!INAPPLICABLE_CANDIDATE!>get<!>(0)
|
s.get(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun f7(s : String?, t : String?) {
|
fun f7(s : String?, t : String?) {
|
||||||
|
|||||||
@@ -127,12 +127,12 @@ fun f13(a : A?) {
|
|||||||
fun f14(a : A?) {
|
fun f14(a : A?) {
|
||||||
while (!(a is B)) {
|
while (!(a is B)) {
|
||||||
}
|
}
|
||||||
a.<!UNRESOLVED_REFERENCE!>bar<!>()
|
a.bar()
|
||||||
}
|
}
|
||||||
fun f15(a : A?) {
|
fun f15(a : A?) {
|
||||||
do {
|
do {
|
||||||
} while (!(a is B))
|
} while (!(a is B))
|
||||||
a.<!UNRESOLVED_REFERENCE!>bar<!>()
|
a.bar()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getStringLength(obj : Any) : Char? {
|
fun getStringLength(obj : Any) : Char? {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
fun foo(s: String?): Int {
|
fun foo(s: String?): Int {
|
||||||
do {
|
do {
|
||||||
} while (s==null)
|
} while (s==null)
|
||||||
return s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
return s.length
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@ public fun foo(p: String?, r: String?): Int {
|
|||||||
} while (r == null)
|
} while (r == null)
|
||||||
} while (!x())
|
} while (!x())
|
||||||
// Auto cast possible
|
// Auto cast possible
|
||||||
r.<!INAPPLICABLE_CANDIDATE!>length<!>
|
r.length
|
||||||
// Auto cast possible
|
// Auto cast possible
|
||||||
return p.length
|
return p.length
|
||||||
}
|
}
|
||||||
+1
-1
@@ -8,7 +8,7 @@ public fun foo(p: String?, r: String?): Int {
|
|||||||
} while (r == null)
|
} while (r == null)
|
||||||
} while (!x())
|
} while (!x())
|
||||||
// Auto cast NOT possible due to long continue
|
// Auto cast NOT possible due to long continue
|
||||||
r.<!INAPPLICABLE_CANDIDATE!>length<!>
|
r.length
|
||||||
// Auto cast possible
|
// Auto cast possible
|
||||||
return p.length
|
return p.length
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,7 @@ public fun foo(p: String?, r: String?, q: String?): Int {
|
|||||||
if (!x()) break
|
if (!x()) break
|
||||||
}
|
}
|
||||||
// Smart cast is possible everywhere
|
// Smart cast is possible everywhere
|
||||||
r.<!INAPPLICABLE_CANDIDATE!>length<!>
|
r.length
|
||||||
q.length
|
q.length
|
||||||
return p.length
|
return p.length
|
||||||
}
|
}
|
||||||
+1
-1
@@ -9,7 +9,7 @@ public fun foo(p: String?, r: String?, q: String?): Int {
|
|||||||
if (!x()) break
|
if (!x()) break
|
||||||
}
|
}
|
||||||
// Smart cast is possible everywhere
|
// Smart cast is possible everywhere
|
||||||
r.<!INAPPLICABLE_CANDIDATE!>length<!>
|
r.length
|
||||||
q.length
|
q.length
|
||||||
return p.length
|
return p.length
|
||||||
}
|
}
|
||||||
+1
-1
@@ -12,7 +12,7 @@ public fun foo(p: String?, r: String?, q: String?): Int {
|
|||||||
if (!x()) break
|
if (!x()) break
|
||||||
}
|
}
|
||||||
// Smart cast is possible everywhere
|
// Smart cast is possible everywhere
|
||||||
r.<!INAPPLICABLE_CANDIDATE!>length<!>
|
r.length
|
||||||
q.length
|
q.length
|
||||||
return p.length
|
return p.length
|
||||||
}
|
}
|
||||||
+1
-1
@@ -14,6 +14,6 @@ public fun foo(p: String?, r: String?, q: String?): Int {
|
|||||||
// Smart cast is possible only for q
|
// Smart cast is possible only for q
|
||||||
q.length
|
q.length
|
||||||
// But not possible for the others
|
// But not possible for the others
|
||||||
r.<!INAPPLICABLE_CANDIDATE!>length<!>
|
r.length
|
||||||
return p.length
|
return p.length
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fun foo(s: String?): Int {
|
fun foo(s: String?): Int {
|
||||||
while (s==null) {
|
while (s==null) {
|
||||||
}
|
}
|
||||||
return s.<!INAPPLICABLE_CANDIDATE!>length<!>
|
return s.length
|
||||||
}
|
}
|
||||||
+1
-1
@@ -5,5 +5,5 @@ fun main() {
|
|||||||
if (i == 10) result = "non null"
|
if (i == 10) result = "non null"
|
||||||
else i++
|
else i++
|
||||||
}
|
}
|
||||||
result.<!INAPPLICABLE_CANDIDATE!>length<!>
|
result.length
|
||||||
}
|
}
|
||||||
+1
-1
@@ -11,5 +11,5 @@ public fun foo(xx: Any): Int {
|
|||||||
// y!! in both branches
|
// y!! in both branches
|
||||||
y.length
|
y.length
|
||||||
} while (!(x is String))
|
} while (!(x is String))
|
||||||
return x.<!UNRESOLVED_REFERENCE!>length<!>
|
return x.length
|
||||||
}
|
}
|
||||||
+1
-1
@@ -9,7 +9,7 @@ public fun foo(pp: String?, rr: String?): Int {
|
|||||||
} while (r == null)
|
} while (r == null)
|
||||||
} while (!x())
|
} while (!x())
|
||||||
// Auto cast possible
|
// Auto cast possible
|
||||||
r.<!INAPPLICABLE_CANDIDATE!>length<!>
|
r.length
|
||||||
// Auto cast possible
|
// Auto cast possible
|
||||||
return p.length
|
return p.length
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user