CFA merge for definition / initialization : more accurate handling of unknown variables #KT-13969 Fixed

(cherry picked from commit 4a96589)
This commit is contained in:
Mikhail Glukhikh
2016-09-26 12:51:24 +03:00
committed by Mikhail Glukhikh
parent 797f7ab28e
commit 436b0ec873
28 changed files with 167 additions and 91 deletions
@@ -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
View File
@@ -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,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: {}
=====================
@@ -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: {}
=====================