CFA merge for definition / initialization : more accurate handling of unknown variables #KT-13969 Fixed
(cherry picked from commit 4a96589)
This commit is contained in:
committed by
Mikhail Glukhikh
parent
797f7ab28e
commit
436b0ec873
@@ -0,0 +1,43 @@
|
||||
== test ==
|
||||
fun test(cond1: Boolean) {
|
||||
do {
|
||||
if (cond1) continue
|
||||
val cond2 = false
|
||||
} while (cond2)
|
||||
}
|
||||
---------------------
|
||||
L0:
|
||||
1 <START> INIT: in: {} out: {}
|
||||
v(cond1: Boolean) INIT: in: {} out: {cond1=D}
|
||||
magic[FAKE_INITIALIZER](cond1: Boolean) -> <v0> INIT: in: {cond1=D} out: {cond1=D}
|
||||
w(cond1|<v0>) INIT: in: {cond1=D} out: {cond1=ID}
|
||||
2 mark({ do { if (cond1) continue val cond2 = false } while (cond2) }) INIT: in: {cond1=ID} out: {cond1=ID} USE: in: {cond1=READ} out: {cond1=READ}
|
||||
3 mark(do { if (cond1) continue val cond2 = false } while (cond2))
|
||||
L2 [loop entry point]:
|
||||
L4 [body entry point]:
|
||||
mark({ if (cond1) continue val cond2 = false }) INIT: in: {cond1=ID, cond2=I?} out: {cond1=ID, cond2=I?}
|
||||
mark(if (cond1) continue)
|
||||
r(cond1) -> <v1>
|
||||
jf(L7|<v1>)
|
||||
jmp(L6) USE: in: {cond1=READ, cond2=READ} out: {cond1=READ, cond2=READ}
|
||||
- jmp(L8)
|
||||
L7 [else branch]:
|
||||
read (Unit) INIT: in: {cond1=ID, cond2=I?} out: {cond1=ID, cond2=I?}
|
||||
L8 ['if' expression result]:
|
||||
merge(if (cond1) continue|!<v2>) -> <v3>
|
||||
v(val cond2 = false) INIT: in: {cond1=ID, cond2=I?} out: {cond1=ID, cond2=ID}
|
||||
r(false) -> <v4> INIT: in: {cond1=ID, cond2=ID} out: {cond1=ID, cond2=ID}
|
||||
w(cond2|<v4>)
|
||||
L5 [body exit point]:
|
||||
L6 [condition entry point]:
|
||||
r(cond2) -> <v5> INIT: in: {cond1=ID, cond2=I?} out: {cond1=ID, cond2=I?}
|
||||
jt(L2|<v5>) USE: in: {cond1=READ, cond2=READ} out: {cond1=READ, cond2=READ}
|
||||
L3 [loop exit point]:
|
||||
read (Unit)
|
||||
L1:
|
||||
1 <END> INIT: in: {cond1=ID} out: {cond1=ID}
|
||||
error:
|
||||
<ERROR> INIT: in: {} out: {}
|
||||
sink:
|
||||
<SINK> INIT: in: {cond1=I?} out: {cond1=I?} USE: in: {} out: {}
|
||||
=====================
|
||||
@@ -0,0 +1,6 @@
|
||||
fun test(cond1: Boolean) {
|
||||
do {
|
||||
if (cond1) continue
|
||||
val cond2 = false
|
||||
} while (cond2)
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
== test ==
|
||||
fun test(cond1: Boolean) {
|
||||
do {
|
||||
if (cond1) continue
|
||||
val cond2 = false
|
||||
} while (cond2)
|
||||
}
|
||||
---------------------
|
||||
<v0>: Boolean NEW: magic[FAKE_INITIALIZER](cond1: Boolean) -> <v0>
|
||||
cond1 <v1>: Boolean NEW: r(cond1) -> <v1>
|
||||
continue !<v2>: *
|
||||
if (cond1) continue <v3>: * NEW: merge(if (cond1) continue|!<v2>) -> <v3>
|
||||
false <v4>: Boolean NEW: r(false) -> <v4>
|
||||
cond2 <v5>: Boolean NEW: r(cond2) -> <v5>
|
||||
do { if (cond1) continue val cond2 = false } while (cond2) !<v6>: *
|
||||
{ do { if (cond1) continue val cond2 = false } while (cond2) } !<v6>: * COPY
|
||||
=====================
|
||||
+15
-15
@@ -9,7 +9,7 @@ L1:
|
||||
error:
|
||||
<ERROR> INIT: in: {} out: {}
|
||||
sink:
|
||||
<SINK> INIT: in: {x=D} out: {x=D} USE: in: {} out: {}
|
||||
<SINK> INIT: in: {x=-} out: {x=-} USE: in: {} out: {}
|
||||
=====================
|
||||
== foo ==
|
||||
fun foo(f: Boolean) {
|
||||
@@ -32,46 +32,46 @@ L0:
|
||||
mark(try { if (f) { x = 0 } } finally { fun bar() {} })
|
||||
jmp?(L2)
|
||||
3 mark({ if (f) { x = 0 } })
|
||||
mark(if (f) { x = 0 }) USE: in: {f=READ, x=ONLY_WRITTEN_NEVER_READ} out: {f=READ, x=ONLY_WRITTEN_NEVER_READ}
|
||||
r(f) -> <v1> USE: in: {x=ONLY_WRITTEN_NEVER_READ} out: {f=READ, x=ONLY_WRITTEN_NEVER_READ}
|
||||
mark(if (f) { x = 0 }) USE: in: {f=READ, x=ONLY_WRITTEN_NEVER_READ} out: {f=READ, x=ONLY_WRITTEN_NEVER_READ}
|
||||
r(f) -> <v1> USE: in: {x=ONLY_WRITTEN_NEVER_READ} out: {f=READ, x=ONLY_WRITTEN_NEVER_READ}
|
||||
jf(L3|<v1>)
|
||||
4 mark({ x = 0 })
|
||||
r(0) -> <v2> USE: in: {x=ONLY_WRITTEN_NEVER_READ} out: {x=ONLY_WRITTEN_NEVER_READ}
|
||||
w(x|<v2>) INIT: in: {f=ID} out: {f=ID, x=I} USE: in: {} out: {x=ONLY_WRITTEN_NEVER_READ}
|
||||
r(0) -> <v2> USE: in: {x=ONLY_WRITTEN_NEVER_READ} out: {x=ONLY_WRITTEN_NEVER_READ}
|
||||
w(x|<v2>) INIT: in: {f=ID} out: {f=ID, x=I} USE: in: {} out: {x=ONLY_WRITTEN_NEVER_READ}
|
||||
3 jmp(L4) INIT: in: {f=ID, x=I} out: {f=ID, x=I}
|
||||
L3 [else branch]:
|
||||
read (Unit) INIT: in: {f=ID} out: {f=ID}
|
||||
L4 ['if' expression result]:
|
||||
merge(if (f) { x = 0 }|!<v3>) -> <v4> INIT: in: {f=ID, x=I} out: {f=ID, x=I}
|
||||
merge(if (f) { x = 0 }|!<v3>) -> <v4> INIT: in: {f=ID, x=I?} out: {f=ID, x=I?}
|
||||
2 jmp?(L2)
|
||||
jmp(L5)
|
||||
L2 [onExceptionToFinallyBlock]:
|
||||
L6 [start finally]:
|
||||
3 mark({ fun bar() {} })
|
||||
jmp?(L7)
|
||||
d(fun bar() {})
|
||||
d(fun bar() {}) INIT: in: {f=I?, x=I?} out: {f=I?, x=I?}
|
||||
L7 [after local declaration]:
|
||||
L10 [finish finally]:
|
||||
2 jmp(error)
|
||||
2 jmp(error) INIT: in: {f=ID, x=I?} out: {f=ID, x=I?}
|
||||
L5 [skipFinallyToErrorBlock]:
|
||||
L11 [copy of L2, onExceptionToFinallyBlock]:
|
||||
3 mark({ fun bar() {} })
|
||||
jmp?(L12)
|
||||
d(fun bar() {})
|
||||
d(fun bar() {}) INIT: in: {f=I?, x=I?} out: {f=I?, x=I?}
|
||||
L12 [copy of L7, after local declaration]:
|
||||
2 merge(try { if (f) { x = 0 } } finally { fun bar() {} }|<v4>) -> <v5>
|
||||
2 merge(try { if (f) { x = 0 } } finally { fun bar() {} }|<v4>) -> <v5> INIT: in: {f=ID, x=I?} out: {f=ID, x=I?}
|
||||
L1:
|
||||
1 <END>
|
||||
error:
|
||||
<ERROR>
|
||||
sink:
|
||||
<SINK> USE: in: {} out: {}
|
||||
<SINK> INIT: in: {f=I?, x=I?} out: {f=I?, x=I?} USE: in: {} out: {}
|
||||
=====================
|
||||
== bar ==
|
||||
fun bar() {}
|
||||
---------------------
|
||||
L8:
|
||||
4 <START> INIT: in: {f=ID, x=I} out: {f=ID, x=I}
|
||||
4 <START> INIT: in: {f=ID, x=I?} out: {f=ID, x=I?}
|
||||
5 mark({})
|
||||
read (Unit)
|
||||
L9:
|
||||
@@ -79,13 +79,13 @@ L9:
|
||||
error:
|
||||
<ERROR> INIT: in: {} out: {}
|
||||
sink:
|
||||
<SINK> INIT: in: {f=ID, x=I} out: {f=ID, x=I} USE: in: {} out: {}
|
||||
<SINK> INIT: in: {f=I?, x=I?} out: {f=I?, x=I?} USE: in: {} out: {}
|
||||
=====================
|
||||
== bar ==
|
||||
fun bar() {}
|
||||
---------------------
|
||||
L2 [copy of L8, null]:
|
||||
4 <START> INIT: in: {f=ID, x=I} out: {f=ID, x=I}
|
||||
4 <START> INIT: in: {f=ID, x=I?} out: {f=ID, x=I?}
|
||||
5 mark({})
|
||||
read (Unit)
|
||||
L3 [copy of L9, null]:
|
||||
@@ -93,5 +93,5 @@ L3 [copy of L9, null]:
|
||||
L0 [copy of error, null]:
|
||||
<ERROR> INIT: in: {} out: {}
|
||||
L1 [copy of sink, null]:
|
||||
<SINK> INIT: in: {f=ID, x=I} out: {f=ID, x=I} USE: in: {} out: {}
|
||||
<SINK> INIT: in: {f=I?, x=I?} out: {f=I?, x=I?} USE: in: {} out: {}
|
||||
=====================
|
||||
|
||||
+10
-10
@@ -10,16 +10,16 @@ L0:
|
||||
v(val sum: (Int)->Int = { x: Int -> sum(x - 1) + x }) INIT: in: {} out: {sum=D}
|
||||
mark({ x: Int -> sum(x - 1) + x }) INIT: in: {sum=D} out: {sum=D}
|
||||
jmp?(L2)
|
||||
d({ x: Int -> sum(x - 1) + x }) USE: in: {sum=READ} out: {sum=READ}
|
||||
d({ x: Int -> sum(x - 1) + x }) INIT: in: {sum=-} out: {sum=-} USE: in: {sum=READ} out: {sum=READ}
|
||||
L2 [after local declaration]:
|
||||
r({ x: Int -> sum(x - 1) + x }) -> <v0>
|
||||
r({ x: Int -> sum(x - 1) + x }) -> <v0> INIT: in: {sum=D} out: {sum=D}
|
||||
w(sum|<v0>) INIT: in: {sum=D} out: {sum=ID}
|
||||
L1:
|
||||
<END> INIT: in: {sum=ID} out: {sum=ID}
|
||||
error:
|
||||
<ERROR> INIT: in: {} out: {}
|
||||
sink:
|
||||
<SINK> INIT: in: {sum=I?D} out: {sum=I?D} USE: in: {} out: {}
|
||||
<SINK> INIT: in: {sum=I?} out: {sum=I?} USE: in: {} out: {}
|
||||
=====================
|
||||
== anonymous_0 ==
|
||||
{ x: Int ->
|
||||
@@ -49,7 +49,7 @@ L4:
|
||||
error:
|
||||
<ERROR> INIT: in: {} out: {}
|
||||
sink:
|
||||
<SINK> INIT: in: {sum=D, x=ID} out: {sum=D, x=ID} USE: in: {} out: {}
|
||||
<SINK> INIT: in: {sum=-, x=I?} out: {sum=-, x=I?} USE: in: {} out: {}
|
||||
=====================
|
||||
== A ==
|
||||
open class A(val a: A)
|
||||
@@ -64,7 +64,7 @@ L1:
|
||||
error:
|
||||
<ERROR> INIT: in: {} out: {}
|
||||
sink:
|
||||
<SINK> INIT: in: {a=ID} out: {a=ID} USE: in: {} out: {}
|
||||
<SINK> INIT: in: {a=I?} out: {a=I?} USE: in: {} out: {}
|
||||
=====================
|
||||
== TestObjectLiteral ==
|
||||
class TestObjectLiteral {
|
||||
@@ -92,16 +92,16 @@ L0:
|
||||
r(obj|<v3>) -> <v4>
|
||||
w(x|<v4>) INIT: in: {obj=D, x=D} out: {obj=D, x=ID}
|
||||
1 jmp?(L2) INIT: in: {obj=D} out: {obj=D}
|
||||
d(fun foo() { val y = obj }) USE: in: {obj=READ} out: {obj=READ}
|
||||
d(fun foo() { val y = obj }) INIT: in: {obj=-} out: {obj=-} USE: in: {obj=READ} out: {obj=READ}
|
||||
L2 [after local declaration]:
|
||||
r(object: A(obj) { init { val x = obj } fun foo() { val y = obj } }) -> <v5>
|
||||
r(object: A(obj) { init { val x = obj } fun foo() { val y = obj } }) -> <v5> INIT: in: {obj=D} out: {obj=D}
|
||||
w(obj|<v5>) INIT: in: {obj=D} out: {obj=ID}
|
||||
L1:
|
||||
<END> INIT: in: {obj=ID} out: {obj=ID}
|
||||
error:
|
||||
<ERROR> INIT: in: {} out: {}
|
||||
sink:
|
||||
<SINK> INIT: in: {obj=I?D} out: {obj=I?D} USE: in: {} out: {}
|
||||
<SINK> INIT: in: {obj=I?} out: {obj=I?} USE: in: {} out: {}
|
||||
=====================
|
||||
== foo ==
|
||||
fun foo() {
|
||||
@@ -120,7 +120,7 @@ L4:
|
||||
error:
|
||||
<ERROR> INIT: in: {} out: {}
|
||||
sink:
|
||||
<SINK> INIT: in: {obj=D} out: {obj=D} USE: in: {} out: {}
|
||||
<SINK> INIT: in: {obj=-} out: {obj=-} USE: in: {} out: {}
|
||||
=====================
|
||||
== TestOther ==
|
||||
class TestOther {
|
||||
@@ -141,5 +141,5 @@ L1:
|
||||
error:
|
||||
<ERROR> INIT: in: {} out: {}
|
||||
sink:
|
||||
<SINK> INIT: in: {x=ID} out: {x=ID} USE: in: {} out: {}
|
||||
<SINK> INIT: in: {x=I?} out: {x=I?} USE: in: {} out: {}
|
||||
=====================
|
||||
|
||||
+2
-2
@@ -59,7 +59,7 @@ L1:
|
||||
error:
|
||||
<ERROR> INIT: in: {} out: {}
|
||||
sink:
|
||||
<SINK> INIT: in: {numbers=ID} out: {numbers=ID} USE: in: {} out: {}
|
||||
<SINK> INIT: in: {numbers=I?} out: {numbers=I?} USE: in: {} out: {}
|
||||
=====================
|
||||
== use ==
|
||||
fun use(vararg a: Any?) = a
|
||||
@@ -76,5 +76,5 @@ L1:
|
||||
error:
|
||||
<ERROR> INIT: in: {} out: {}
|
||||
sink:
|
||||
<SINK> INIT: in: {a=ID} out: {a=ID} USE: in: {} out: {}
|
||||
<SINK> INIT: in: {a=I?} out: {a=I?} USE: in: {} out: {}
|
||||
=====================
|
||||
Reference in New Issue
Block a user