Initialization analysis : more accurate handling of non-local variables while merging data #KT-14304 Fixed

This commit is contained in:
Mikhail Glukhikh
2016-10-20 13:41:07 +03:00
parent bba34e0caa
commit a19d178867
19 changed files with 1053 additions and 51 deletions
@@ -94,7 +94,7 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
) {
instruction: Instruction, incomingEdgesData: Collection<InitControlFlowInfo> ->
val enterInstructionData = mergeIncomingEdgesDataForInitializers(incomingEdgesData)
val enterInstructionData = mergeIncomingEdgesDataForInitializers(instruction, incomingEdgesData, blockScopeVariableInfo)
val exitInstructionData = addVariableInitStateFromCurrentInstructionIfAny(
instruction, enterInstructionData, blockScopeVariableInfo)
Edges(enterInstructionData, exitInstructionData)
@@ -207,7 +207,9 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
}
private fun mergeIncomingEdgesDataForInitializers(
incomingEdgesData: Collection<InitControlFlowInfo>
instruction: Instruction,
incomingEdgesData: Collection<InitControlFlowInfo>,
blockScopeVariableInfo: BlockScopeVariableInfo
): InitControlFlowInfo {
if (incomingEdgesData.size == 1) return incomingEdgesData.single()
val variablesInScope = linkedSetOf<VariableDescriptor>()
@@ -220,7 +222,8 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
var initState: InitState? = null
var isDeclared = true
for (edgeData in incomingEdgesData) {
val varControlFlowState = edgeData[variable] ?: VariableControlFlowState.create(isInitialized = false)
val varControlFlowState = edgeData[variable]
?: getDefaultValueForInitializers(variable, instruction, blockScopeVariableInfo)
initState = initState?.merge(varControlFlowState.initState) ?: varControlFlowState.initState
if (!varControlFlowState.isDeclared) {
isDeclared = false
@@ -16,7 +16,7 @@ L0:
v(val f = { x: Int -> val y = x + a use(a) }) INIT: in: {a=ID} out: {a=ID, f=D}
mark({ x: Int -> val y = x + a use(a) }) INIT: in: {a=ID, f=D} out: {a=ID, f=D}
jmp?(L2)
d({ x: Int -> val y = x + a use(a) }) INIT: in: {a=I?, f=-} out: {a=I?, f=-} USE: in: {a=READ} out: {a=READ}
d({ x: Int -> val y = x + a use(a) }) INIT: in: {a=I, f=I?} out: {a=I, f=I?} USE: in: {a=READ} out: {a=READ}
L2 [after local declaration]:
r({ x: Int -> val y = x + a use(a) }) -> <v1> INIT: in: {a=ID, f=D} out: {a=ID, f=D}
w(f|<v1>) INIT: in: {a=ID, f=D} out: {a=ID, f=ID}
@@ -54,7 +54,7 @@ L4:
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {a=I?, f=-, x=I?} out: {a=I?, f=-, x=I?} USE: in: {} out: {}
<SINK> INIT: in: {a=I, f=I?, x=I?} out: {a=I, f=I?, x=I?} USE: in: {} out: {}
=====================
== use ==
fun use(vararg a: Any?) = a
@@ -24,12 +24,12 @@ fun foo() {
}
---------------------
L0:
1 <START> INIT: in: {} out: {} USE: in: {} out: {}
1 <START> INIT: in: {} out: {} USE: in: {} out: {}
2 mark({ var v: Any bar { v.hashCode() } })
v(var v: Any) INIT: in: {} out: {v=D}
mark({ v.hashCode() }) INIT: in: {v=D} out: {v=D}
jmp?(L2)
d({ v.hashCode() }) INIT: in: {v=-} out: {v=-} USE: in: {v=READ} out: {v=READ}
d({ v.hashCode() }) INIT: in: {v=I?} out: {v=I?} USE: in: {v=READ} out: {v=READ}
L2 [after local declaration]:
r({ v.hashCode() }) -> <v0> INIT: in: {v=D} out: {v=D}
mark(bar { v.hashCode() })
@@ -39,7 +39,7 @@ L1:
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
<SINK> USE: in: {} out: {}
=====================
== anonymous_0 ==
{ v.hashCode() }
@@ -47,8 +47,8 @@ sink:
L3:
3 <START> INIT: in: {v=D} out: {v=D}
4 mark(v.hashCode())
mark(v.hashCode()) USE: in: {v=READ} out: {v=READ}
r(v) -> <v0> USE: in: {} out: {v=READ}
mark(v.hashCode()) USE: in: {v=READ} out: {v=READ}
r(v) -> <v0> USE: in: {} out: {v=READ}
mark(hashCode())
call(hashCode(), hashCode|<v0>) -> <v1>
L4:
@@ -56,5 +56,5 @@ L4:
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {v=-} out: {v=-} USE: in: {} out: {}
<SINK> INIT: in: {v=I?} out: {v=I?} USE: in: {} out: {}
=====================
+14 -14
View File
@@ -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() {}) INIT: in: {f=I?, x=I?} out: {f=I?, x=I?}
d(fun bar() {}) INIT: in: {f=I, x=I} out: {f=I, x=I}
L7 [after local declaration]:
L10 [finish finally]:
2 jmp(error) INIT: in: {f=ID, x=I?} out: {f=ID, x=I?}
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() {}) INIT: in: {f=I?, x=I?} out: {f=I?, x=I?}
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> INIT: in: {f=ID, x=I?} out: {f=ID, x=I?}
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> INIT: in: {f=I?, x=I?} out: {f=I?, x=I?} 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=I?, x=I?} out: {f=I?, 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=I?, x=I?} out: {f=I?, x=I?} USE: in: {} out: {}
<SINK> INIT: in: {f=I, x=I} out: {f=I, x=I} USE: in: {} out: {}
=====================
@@ -0,0 +1,485 @@
== println ==
fun println(obj: Any?) {}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(obj: Any?) INIT: in: {} out: {obj=D}
magic[FAKE_INITIALIZER](obj: Any?) -> <v0> INIT: in: {obj=D} out: {obj=D}
w(obj|<v0>) INIT: in: {obj=D} out: {obj=ID}
2 mark({}) INIT: in: {obj=ID} out: {obj=ID}
read (Unit)
L1:
1 <END>
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {obj=I?} out: {obj=I?} USE: in: {} out: {}
=====================
== Demo0 ==
class Demo0 {
private val some = object {
fun foo() {
println(state) // Ok
}
}
private var state: Boolean = true
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(private val some = object { fun foo() { println(state) // Ok } }) INIT: in: {} out: {some=D}
mark(object { fun foo() { println(state) // Ok } }) INIT: in: {some=D} out: {some=D}
jmp?(L2)
d(fun foo() { println(state) // Ok }) INIT: in: {some=I?} out: {some=I?} USE: in: {state=READ} out: {state=READ}
L2 [after local declaration]:
r(object { fun foo() { println(state) // Ok } }) -> <v0> INIT: in: {some=D} out: {some=D}
w(some|<v0>) INIT: in: {some=D} out: {some=ID}
v(private var state: Boolean = true) INIT: in: {some=ID} out: {some=ID, state=D}
r(true) -> <v1> INIT: in: {some=ID, state=D} out: {some=ID, state=D}
w(state|<v1>) INIT: in: {some=ID, state=D} out: {some=ID, state=ID}
L1:
<END> INIT: in: {some=ID, state=ID} out: {some=ID, state=ID}
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {some=I?, state=I?} out: {some=I?, state=I?} USE: in: {} out: {}
=====================
== foo ==
fun foo() {
println(state) // Ok
}
---------------------
L3:
2 <START> INIT: in: {some=D} out: {some=D}
3 mark({ println(state) // Ok })
magic[IMPLICIT_RECEIVER](state) -> <v0> USE: in: {state=READ} out: {state=READ}
r(state|<v0>) -> <v1> USE: in: {} out: {state=READ}
mark(println(state))
call(println(state), println|<v1>) -> <v2>
L4:
2 <END>
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {some=I?} out: {some=I?} USE: in: {} out: {}
=====================
== Demo1 ==
class Demo1 {
private val some = object {
fun foo() {
if (state)
state = true
println(state) // must be initialized
}
}
private var state: Boolean = true
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(private val some = object { fun foo() { if (state) state = true println(state) // must be initialized } }) INIT: in: {} out: {some=D}
mark(object { fun foo() { if (state) state = true println(state) // must be initialized } }) INIT: in: {some=D} out: {some=D}
jmp?(L2)
d(fun foo() { if (state) state = true println(state) // must be initialized }) INIT: in: {some=I?, state=I} out: {some=I?, state=I} USE: in: {state=READ} out: {state=READ}
L2 [after local declaration]:
r(object { fun foo() { if (state) state = true println(state) // must be initialized } }) -> <v0> INIT: in: {some=D} out: {some=D}
w(some|<v0>) INIT: in: {some=D} out: {some=ID}
v(private var state: Boolean = true) INIT: in: {some=ID} out: {some=ID, state=D}
r(true) -> <v1> INIT: in: {some=ID, state=D} out: {some=ID, state=D}
w(state|<v1>) INIT: in: {some=ID, state=D} out: {some=ID, state=ID}
L1:
<END> INIT: in: {some=ID, state=ID} out: {some=ID, state=ID}
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {some=I?, state=I?} out: {some=I?, state=I?} USE: in: {} out: {}
=====================
== foo ==
fun foo() {
if (state)
state = true
println(state) // must be initialized
}
---------------------
L3:
2 <START> INIT: in: {some=D} out: {some=D}
3 mark({ if (state) state = true println(state) // must be initialized })
mark(if (state) state = true)
magic[IMPLICIT_RECEIVER](state) -> <v0>
r(state|<v0>) -> <v1>
jf(L5|<v1>) USE: in: {state=READ} out: {state=READ}
magic[IMPLICIT_RECEIVER](state) -> <v2>
r(true) -> <v3> USE: in: {state=WRITTEN_AFTER_READ} out: {state=WRITTEN_AFTER_READ}
w(state|<v2>, <v3>) INIT: in: {some=D} out: {some=D, state=I} USE: in: {state=READ} out: {state=WRITTEN_AFTER_READ}
jmp(L6) INIT: in: {some=D, state=I} out: {some=D, state=I}
L5 [else branch]:
read (Unit) INIT: in: {some=D} out: {some=D}
L6 ['if' expression result]:
merge(if (state) state = true|!<v4>) -> <v5> INIT: in: {some=D, state=I} out: {some=D, state=I}
magic[IMPLICIT_RECEIVER](state) -> <v6> USE: in: {state=READ} out: {state=READ}
r(state|<v6>) -> <v7> USE: in: {} out: {state=READ}
mark(println(state))
call(println(state), println|<v7>) -> <v8>
L4:
2 <END>
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {some=I?, state=I} out: {some=I?, state=I} USE: in: {} out: {}
=====================
== Demo1A ==
class Demo1A {
fun foo() {
if (state)
state = true
println(state) // Ok
}
private var state: Boolean = true
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(private var state: Boolean = true) INIT: in: {} out: {state=D}
r(true) -> <v0> INIT: in: {state=D} out: {state=D}
w(state|<v0>) INIT: in: {state=D} out: {state=ID}
L1:
<END> INIT: in: {state=ID} out: {state=ID}
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {state=I?} out: {state=I?} USE: in: {} out: {}
=====================
== foo ==
fun foo() {
if (state)
state = true
println(state) // Ok
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
2 mark({ if (state) state = true println(state) // Ok })
mark(if (state) state = true)
magic[IMPLICIT_RECEIVER](state) -> <v0>
r(state|<v0>) -> <v1>
jf(L2|<v1>) USE: in: {state=READ} out: {state=READ}
magic[IMPLICIT_RECEIVER](state) -> <v2>
r(true) -> <v3> USE: in: {state=WRITTEN_AFTER_READ} out: {state=WRITTEN_AFTER_READ}
w(state|<v2>, <v3>) INIT: in: {} out: {state=I} USE: in: {state=READ} out: {state=WRITTEN_AFTER_READ}
jmp(L3) INIT: in: {state=I} out: {state=I}
L2 [else branch]:
read (Unit) INIT: in: {} out: {}
L3 ['if' expression result]:
merge(if (state) state = true|!<v4>) -> <v5> INIT: in: {state=I} out: {state=I}
magic[IMPLICIT_RECEIVER](state) -> <v6> USE: in: {state=READ} out: {state=READ}
r(state|<v6>) -> <v7> USE: in: {} out: {state=READ}
mark(println(state))
call(println(state), println|<v7>) -> <v8>
L1:
1 <END>
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {state=I} out: {state=I} USE: in: {} out: {}
=====================
== Demo2 ==
class Demo2 {
private val some = object {
fun foo() {
if (state)
state = true
else
state = false
println(state) // OK
}
}
private var state: Boolean = true
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(private val some = object { fun foo() { if (state) state = true else state = false println(state) // OK } }) INIT: in: {} out: {some=D}
mark(object { fun foo() { if (state) state = true else state = false println(state) // OK } }) INIT: in: {some=D} out: {some=D}
jmp?(L2)
d(fun foo() { if (state) state = true else state = false println(state) // OK }) INIT: in: {some=I?, state=I} out: {some=I?, state=I} USE: in: {state=READ} out: {state=READ}
L2 [after local declaration]:
r(object { fun foo() { if (state) state = true else state = false println(state) // OK } }) -> <v0> INIT: in: {some=D} out: {some=D}
w(some|<v0>) INIT: in: {some=D} out: {some=ID}
v(private var state: Boolean = true) INIT: in: {some=ID} out: {some=ID, state=D}
r(true) -> <v1> INIT: in: {some=ID, state=D} out: {some=ID, state=D}
w(state|<v1>) INIT: in: {some=ID, state=D} out: {some=ID, state=ID}
L1:
<END> INIT: in: {some=ID, state=ID} out: {some=ID, state=ID}
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {some=I?, state=I?} out: {some=I?, state=I?} USE: in: {} out: {}
=====================
== foo ==
fun foo() {
if (state)
state = true
else
state = false
println(state) // OK
}
---------------------
L3:
2 <START> INIT: in: {some=D} out: {some=D}
3 mark({ if (state) state = true else state = false println(state) // OK })
mark(if (state) state = true else state = false)
magic[IMPLICIT_RECEIVER](state) -> <v0> USE: in: {state=READ} out: {state=READ}
r(state|<v0>) -> <v1> USE: in: {state=WRITTEN_AFTER_READ} out: {state=READ}
jf(L5|<v1>)
magic[IMPLICIT_RECEIVER](state) -> <v2>
r(true) -> <v3> USE: in: {state=WRITTEN_AFTER_READ} out: {state=WRITTEN_AFTER_READ}
w(state|<v2>, <v3>) INIT: in: {some=D} out: {some=D, state=I} USE: in: {state=READ} out: {state=WRITTEN_AFTER_READ}
jmp(L6) INIT: in: {some=D, state=I} out: {some=D, state=I} USE: in: {state=READ} out: {state=READ}
L5 [else branch]:
magic[IMPLICIT_RECEIVER](state) -> <v4> INIT: in: {some=D} out: {some=D}
r(false) -> <v5> USE: in: {state=WRITTEN_AFTER_READ} out: {state=WRITTEN_AFTER_READ}
w(state|<v4>, <v5>) INIT: in: {some=D} out: {some=D, state=I} USE: in: {state=READ} out: {state=WRITTEN_AFTER_READ}
L6 ['if' expression result]:
merge(if (state) state = true else state = false|!<v6>, !<v7>) -> <v8> INIT: in: {some=D, state=I} out: {some=D, state=I}
magic[IMPLICIT_RECEIVER](state) -> <v9> USE: in: {state=READ} out: {state=READ}
r(state|<v9>) -> <v10> USE: in: {} out: {state=READ}
mark(println(state))
call(println(state), println|<v10>) -> <v11>
L4:
2 <END>
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {some=I?, state=I} out: {some=I?, state=I} USE: in: {} out: {}
=====================
== Demo3 ==
class Demo3 {
private val some = run {
if (state)
state = true
println(state) // OK
}
private var state: Boolean = true
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(private val some = run { if (state) state = true println(state) // OK }) INIT: in: {} out: {some=D}
magic[IMPLICIT_RECEIVER](run { if (state) state = true println(state) // OK }) -> <v0> INIT: in: {some=D} out: {some=D}
mark({ if (state) state = true println(state) // OK })
jmp?(L2)
d({ if (state) state = true println(state) // OK }) INIT: in: {some=I?} out: {some=I?} USE: in: {state=READ} out: {state=READ}
L2 [after local declaration]:
r({ if (state) state = true println(state) // OK }) -> <v1> INIT: in: {some=D} out: {some=D}
mark(run { if (state) state = true println(state) // OK })
call(run { if (state) state = true println(state) // OK }, run|<v0>, <v1>) -> <v2>
w(some|<v2>) INIT: in: {some=D} out: {some=ID}
v(private var state: Boolean = true) INIT: in: {some=ID} out: {some=ID, state=D}
r(true) -> <v3> INIT: in: {some=ID, state=D} out: {some=ID, state=D}
w(state|<v3>) INIT: in: {some=ID, state=D} out: {some=ID, state=ID}
L1:
<END> INIT: in: {some=ID, state=ID} out: {some=ID, state=ID}
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {some=I?, state=I?} out: {some=I?, state=I?} USE: in: {} out: {}
=====================
== anonymous_0 ==
{
if (state)
state = true
println(state) // OK
}
---------------------
L3:
2 <START> INIT: in: {some=D} out: {some=D}
3 mark(if (state) state = true println(state))
mark(if (state) state = true)
magic[IMPLICIT_RECEIVER](state) -> <v0>
r(state|<v0>) -> <v1>
jf(L5|<v1>) USE: in: {state=READ} out: {state=READ}
magic[IMPLICIT_RECEIVER](state) -> <v2>
r(true) -> <v3> USE: in: {state=WRITTEN_AFTER_READ} out: {state=WRITTEN_AFTER_READ}
w(state|<v2>, <v3>) USE: in: {state=READ} out: {state=WRITTEN_AFTER_READ}
jmp(L6)
L5 [else branch]:
read (Unit)
L6 ['if' expression result]:
merge(if (state) state = true|!<v4>) -> <v5>
magic[IMPLICIT_RECEIVER](state) -> <v6> USE: in: {state=READ} out: {state=READ}
r(state|<v6>) -> <v7> USE: in: {} out: {state=READ}
mark(println(state))
call(println(state), println|<v7>) -> <v8>
L4:
2 <END>
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {some=I?} out: {some=I?} USE: in: {} out: {}
=====================
== exec ==
fun <T> exec(f: () -> T): T = f()
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(f: () -> T) INIT: in: {} out: {f=D}
magic[FAKE_INITIALIZER](f: () -> T) -> <v0> INIT: in: {f=D} out: {f=D}
w(f|<v0>) INIT: in: {f=D} out: {f=ID} USE: in: {f=READ} out: {f=READ}
r(f) -> <v1> INIT: in: {f=ID} out: {f=ID} USE: in: {} out: {f=READ}
mark(f())
call(f(), invoke|<v1>) -> <v2>
ret(*|<v2>) L1
L1:
<END>
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {f=I?} out: {f=I?} USE: in: {} out: {}
=====================
== Demo4 ==
class Demo4 {
private val some = exec {
if (state)
state = true
println(state) // must be initialized
}
private var state: Boolean = true
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(private val some = exec { if (state) state = true println(state) // must be initialized }) INIT: in: {} out: {some=D}
mark({ if (state) state = true println(state) // must be initialized }) INIT: in: {some=D} out: {some=D}
jmp?(L2)
d({ if (state) state = true println(state) // must be initialized }) INIT: in: {some=I?, state=I} out: {some=I?, state=I} USE: in: {state=READ} out: {state=READ}
L2 [after local declaration]:
r({ if (state) state = true println(state) // must be initialized }) -> <v0> INIT: in: {some=D} out: {some=D}
mark(exec { if (state) state = true println(state) // must be initialized })
call(exec { if (state) state = true println(state) // must be initialized }, exec|<v0>) -> <v1>
w(some|<v1>) INIT: in: {some=D} out: {some=ID}
v(private var state: Boolean = true) INIT: in: {some=ID} out: {some=ID, state=D}
r(true) -> <v2> INIT: in: {some=ID, state=D} out: {some=ID, state=D}
w(state|<v2>) INIT: in: {some=ID, state=D} out: {some=ID, state=ID}
L1:
<END> INIT: in: {some=ID, state=ID} out: {some=ID, state=ID}
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {some=I?, state=I?} out: {some=I?, state=I?} USE: in: {} out: {}
=====================
== anonymous_1 ==
{
if (state)
state = true
println(state) // must be initialized
}
---------------------
L3:
2 <START> INIT: in: {some=D} out: {some=D}
3 mark(if (state) state = true println(state))
mark(if (state) state = true)
magic[IMPLICIT_RECEIVER](state) -> <v0>
r(state|<v0>) -> <v1>
jf(L5|<v1>) USE: in: {state=READ} out: {state=READ}
magic[IMPLICIT_RECEIVER](state) -> <v2>
r(true) -> <v3> USE: in: {state=WRITTEN_AFTER_READ} out: {state=WRITTEN_AFTER_READ}
w(state|<v2>, <v3>) INIT: in: {some=D} out: {some=D, state=I} USE: in: {state=READ} out: {state=WRITTEN_AFTER_READ}
jmp(L6) INIT: in: {some=D, state=I} out: {some=D, state=I}
L5 [else branch]:
read (Unit) INIT: in: {some=D} out: {some=D}
L6 ['if' expression result]:
merge(if (state) state = true|!<v4>) -> <v5> INIT: in: {some=D, state=I} out: {some=D, state=I}
magic[IMPLICIT_RECEIVER](state) -> <v6> USE: in: {state=READ} out: {state=READ}
r(state|<v6>) -> <v7> USE: in: {} out: {state=READ}
mark(println(state))
call(println(state), println|<v7>) -> <v8>
L4:
2 <END>
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {some=I?, state=I} out: {some=I?, state=I} USE: in: {} out: {}
=====================
== Demo5 ==
class Demo5 {
private var state: Boolean = true
private val some = object {
fun foo() {
if (state)
state = true
println(state) // OK
}
}
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(private var state: Boolean = true) INIT: in: {} out: {state=D}
r(true) -> <v0> INIT: in: {state=D} out: {state=D}
w(state|<v0>) INIT: in: {state=D} out: {state=ID}
v(private val some = object { fun foo() { if (state) state = true println(state) // OK } }) INIT: in: {state=ID} out: {some=D, state=ID}
mark(object { fun foo() { if (state) state = true println(state) // OK } }) INIT: in: {some=D, state=ID} out: {some=D, state=ID}
jmp?(L2)
d(fun foo() { if (state) state = true println(state) // OK }) INIT: in: {some=I?, state=I} out: {some=I?, state=I} USE: in: {state=READ} out: {state=READ}
L2 [after local declaration]:
r(object { fun foo() { if (state) state = true println(state) // OK } }) -> <v1> INIT: in: {some=D, state=ID} out: {some=D, state=ID}
w(some|<v1>) INIT: in: {some=D, state=ID} out: {some=ID, state=ID}
L1:
<END> INIT: in: {some=ID, state=ID} out: {some=ID, state=ID}
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {some=I?, state=I?} out: {some=I?, state=I?} USE: in: {} out: {}
=====================
== foo ==
fun foo() {
if (state)
state = true
println(state) // OK
}
---------------------
L3:
2 <START> INIT: in: {some=D, state=ID} out: {some=D, state=ID}
3 mark({ if (state) state = true println(state) // OK })
mark(if (state) state = true)
magic[IMPLICIT_RECEIVER](state) -> <v0>
r(state|<v0>) -> <v1>
jf(L5|<v1>) USE: in: {state=READ} out: {state=READ}
magic[IMPLICIT_RECEIVER](state) -> <v2>
r(true) -> <v3> USE: in: {state=WRITTEN_AFTER_READ} out: {state=WRITTEN_AFTER_READ}
w(state|<v2>, <v3>) USE: in: {state=READ} out: {state=WRITTEN_AFTER_READ}
jmp(L6)
L5 [else branch]:
read (Unit)
L6 ['if' expression result]:
merge(if (state) state = true|!<v4>) -> <v5>
magic[IMPLICIT_RECEIVER](state) -> <v6> USE: in: {state=READ} out: {state=READ}
r(state|<v6>) -> <v7> USE: in: {} out: {state=READ}
mark(println(state))
call(println(state), println|<v7>) -> <v8>
L4:
2 <END>
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {some=I?, state=I} out: {some=I?, state=I} USE: in: {} out: {}
=====================
@@ -0,0 +1,87 @@
fun println(obj: Any?) {}
class Demo0 {
private val some = object {
fun foo() {
println(state) // Ok
}
}
private var state: Boolean = true
}
class Demo1 {
private val some = object {
fun foo() {
if (state)
state = true
println(state) // must be initialized
}
}
private var state: Boolean = true
}
class Demo1A {
fun foo() {
if (state)
state = true
println(state) // Ok
}
private var state: Boolean = true
}
class Demo2 {
private val some = object {
fun foo() {
if (state)
state = true
else
state = false
println(state) // OK
}
}
private var state: Boolean = true
}
class Demo3 {
private val some = run {
if (state)
state = true
println(state) // OK
}
private var state: Boolean = true
}
fun <T> exec(f: () -> T): T = f()
class Demo4 {
private val some = exec {
if (state)
state = true
println(state) // must be initialized
}
private var state: Boolean = true
}
class Demo5 {
private var state: Boolean = true
private val some = object {
fun foo() {
if (state)
state = true
println(state) // OK
}
}
}
@@ -0,0 +1,255 @@
== println ==
fun println(obj: Any?) {}
---------------------
<v0>: * NEW: magic[FAKE_INITIALIZER](obj: Any?) -> <v0>
=====================
== Demo0 ==
class Demo0 {
private val some = object {
fun foo() {
println(state) // Ok
}
}
private var state: Boolean = true
}
---------------------
object { fun foo() { println(state) // Ok } } <v0>: <no name provided> NEW: r(object { fun foo() { println(state) // Ok } }) -> <v0>
true <v1>: Boolean NEW: r(true) -> <v1>
=====================
== foo ==
fun foo() {
println(state) // Ok
}
---------------------
<v0>: Demo0 NEW: magic[IMPLICIT_RECEIVER](state) -> <v0>
state <v1>: * NEW: r(state|<v0>) -> <v1>
println(state) <v2>: * NEW: call(println(state), println|<v1>) -> <v2>
{ println(state) // Ok } <v2>: * COPY
=====================
== Demo1 ==
class Demo1 {
private val some = object {
fun foo() {
if (state)
state = true
println(state) // must be initialized
}
}
private var state: Boolean = true
}
---------------------
object { fun foo() { if (state) state = true println(state) // must be initialized } } <v0>: <no name provided> NEW: r(object { fun foo() { if (state) state = true println(state) // must be initialized } }) -> <v0>
true <v1>: Boolean NEW: r(true) -> <v1>
=====================
== foo ==
fun foo() {
if (state)
state = true
println(state) // must be initialized
}
---------------------
<v0>: Demo1 NEW: magic[IMPLICIT_RECEIVER](state) -> <v0>
<v2>: Demo1 NEW: magic[IMPLICIT_RECEIVER](state) -> <v2>
<v6>: Demo1 NEW: magic[IMPLICIT_RECEIVER](state) -> <v6>
state <v1>: Boolean NEW: r(state|<v0>) -> <v1>
true <v3>: Boolean NEW: r(true) -> <v3>
state = true !<v4>: *
if (state) state = true <v5>: * NEW: merge(if (state) state = true|!<v4>) -> <v5>
state <v7>: * NEW: r(state|<v6>) -> <v7>
println(state) <v8>: * NEW: call(println(state), println|<v7>) -> <v8>
{ if (state) state = true println(state) // must be initialized } <v8>: * COPY
=====================
== Demo1A ==
class Demo1A {
fun foo() {
if (state)
state = true
println(state) // Ok
}
private var state: Boolean = true
}
---------------------
true <v0>: Boolean NEW: r(true) -> <v0>
=====================
== foo ==
fun foo() {
if (state)
state = true
println(state) // Ok
}
---------------------
<v0>: Demo1A NEW: magic[IMPLICIT_RECEIVER](state) -> <v0>
<v2>: Demo1A NEW: magic[IMPLICIT_RECEIVER](state) -> <v2>
<v6>: Demo1A NEW: magic[IMPLICIT_RECEIVER](state) -> <v6>
state <v1>: Boolean NEW: r(state|<v0>) -> <v1>
true <v3>: Boolean NEW: r(true) -> <v3>
state = true !<v4>: *
if (state) state = true <v5>: * NEW: merge(if (state) state = true|!<v4>) -> <v5>
state <v7>: * NEW: r(state|<v6>) -> <v7>
println(state) <v8>: * NEW: call(println(state), println|<v7>) -> <v8>
{ if (state) state = true println(state) // Ok } <v8>: * COPY
=====================
== Demo2 ==
class Demo2 {
private val some = object {
fun foo() {
if (state)
state = true
else
state = false
println(state) // OK
}
}
private var state: Boolean = true
}
---------------------
object { fun foo() { if (state) state = true else state = false println(state) // OK } } <v0>: <no name provided> NEW: r(object { fun foo() { if (state) state = true else state = false println(state) // OK } }) -> <v0>
true <v1>: Boolean NEW: r(true) -> <v1>
=====================
== foo ==
fun foo() {
if (state)
state = true
else
state = false
println(state) // OK
}
---------------------
<v0>: Demo2 NEW: magic[IMPLICIT_RECEIVER](state) -> <v0>
<v2>: Demo2 NEW: magic[IMPLICIT_RECEIVER](state) -> <v2>
<v4>: Demo2 NEW: magic[IMPLICIT_RECEIVER](state) -> <v4>
<v9>: Demo2 NEW: magic[IMPLICIT_RECEIVER](state) -> <v9>
state <v1>: Boolean NEW: r(state|<v0>) -> <v1>
true <v3>: Boolean NEW: r(true) -> <v3>
state = true !<v6>: *
false <v5>: Boolean NEW: r(false) -> <v5>
state = false !<v7>: *
if (state) state = true else state = false <v8>: * NEW: merge(if (state) state = true else state = false|!<v6>, !<v7>) -> <v8>
state <v10>: * NEW: r(state|<v9>) -> <v10>
println(state) <v11>: * NEW: call(println(state), println|<v10>) -> <v11>
{ if (state) state = true else state = false println(state) // OK } <v11>: * COPY
=====================
== Demo3 ==
class Demo3 {
private val some = run {
if (state)
state = true
println(state) // OK
}
private var state: Boolean = true
}
---------------------
<v0>: Demo3 NEW: magic[IMPLICIT_RECEIVER](run { if (state) state = true println(state) // OK }) -> <v0>
{ if (state) state = true println(state) // OK } <v1>: {<: Demo3.() -> Unit} NEW: r({ if (state) state = true println(state) // OK }) -> <v1>
run { if (state) state = true println(state) // OK } <v2>: Unit NEW: call(run { if (state) state = true println(state) // OK }, run|<v0>, <v1>) -> <v2>
true <v3>: Boolean NEW: r(true) -> <v3>
=====================
== anonymous_0 ==
{
if (state)
state = true
println(state) // OK
}
---------------------
<v0>: Demo3 NEW: magic[IMPLICIT_RECEIVER](state) -> <v0>
<v2>: Demo3 NEW: magic[IMPLICIT_RECEIVER](state) -> <v2>
<v6>: Demo3 NEW: magic[IMPLICIT_RECEIVER](state) -> <v6>
state <v1>: Boolean NEW: r(state|<v0>) -> <v1>
true <v3>: Boolean NEW: r(true) -> <v3>
state = true !<v4>: *
if (state) state = true <v5>: * NEW: merge(if (state) state = true|!<v4>) -> <v5>
state <v7>: * NEW: r(state|<v6>) -> <v7>
println(state) <v8>: * NEW: call(println(state), println|<v7>) -> <v8>
if (state) state = true println(state) <v8>: * COPY
=====================
== exec ==
fun <T> exec(f: () -> T): T = f()
---------------------
<v0>: {<: () -> T} NEW: magic[FAKE_INITIALIZER](f: () -> T) -> <v0>
f <v1>: {<: () -> T} NEW: r(f) -> <v1>
f() <v2>: {<: T} NEW: call(f(), invoke|<v1>) -> <v2>
=====================
== Demo4 ==
class Demo4 {
private val some = exec {
if (state)
state = true
println(state) // must be initialized
}
private var state: Boolean = true
}
---------------------
{ if (state) state = true println(state) // must be initialized } <v0>: {<: () -> Unit} NEW: r({ if (state) state = true println(state) // must be initialized }) -> <v0>
exec { if (state) state = true println(state) // must be initialized } <v1>: Unit NEW: call(exec { if (state) state = true println(state) // must be initialized }, exec|<v0>) -> <v1>
true <v2>: Boolean NEW: r(true) -> <v2>
=====================
== anonymous_1 ==
{
if (state)
state = true
println(state) // must be initialized
}
---------------------
<v0>: Demo4 NEW: magic[IMPLICIT_RECEIVER](state) -> <v0>
<v2>: Demo4 NEW: magic[IMPLICIT_RECEIVER](state) -> <v2>
<v6>: Demo4 NEW: magic[IMPLICIT_RECEIVER](state) -> <v6>
state <v1>: Boolean NEW: r(state|<v0>) -> <v1>
true <v3>: Boolean NEW: r(true) -> <v3>
state = true !<v4>: *
if (state) state = true <v5>: * NEW: merge(if (state) state = true|!<v4>) -> <v5>
state <v7>: * NEW: r(state|<v6>) -> <v7>
println(state) <v8>: * NEW: call(println(state), println|<v7>) -> <v8>
if (state) state = true println(state) <v8>: * COPY
=====================
== Demo5 ==
class Demo5 {
private var state: Boolean = true
private val some = object {
fun foo() {
if (state)
state = true
println(state) // OK
}
}
}
---------------------
true <v0>: Boolean NEW: r(true) -> <v0>
object { fun foo() { if (state) state = true println(state) // OK } } <v1>: <no name provided> NEW: r(object { fun foo() { if (state) state = true println(state) // OK } }) -> <v1>
=====================
== foo ==
fun foo() {
if (state)
state = true
println(state) // OK
}
---------------------
<v0>: Demo5 NEW: magic[IMPLICIT_RECEIVER](state) -> <v0>
<v2>: Demo5 NEW: magic[IMPLICIT_RECEIVER](state) -> <v2>
<v6>: Demo5 NEW: magic[IMPLICIT_RECEIVER](state) -> <v6>
state <v1>: Boolean NEW: r(state|<v0>) -> <v1>
true <v3>: Boolean NEW: r(true) -> <v3>
state = true !<v4>: *
if (state) state = true <v5>: * NEW: merge(if (state) state = true|!<v4>) -> <v5>
state <v7>: * NEW: r(state|<v6>) -> <v7>
println(state) <v8>: * NEW: call(println(state), println|<v7>) -> <v8>
{ if (state) state = true println(state) // OK } <v8>: * COPY
=====================
@@ -10,7 +10,7 @@ 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 }) INIT: in: {sum=-} out: {sum=-} USE: in: {sum=READ} out: {sum=READ}
d({ x: Int -> sum(x - 1) + x }) INIT: in: {sum=I?} out: {sum=I?} USE: in: {sum=READ} out: {sum=READ}
L2 [after local declaration]:
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}
@@ -32,15 +32,15 @@ L3:
magic[FAKE_INITIALIZER](x: Int) -> <v0> INIT: in: {sum=D, x=D} out: {sum=D, x=D}
w(x|<v0>) INIT: in: {sum=D, x=D} out: {sum=D, x=ID}
3 mark(sum(x - 1) + x) INIT: in: {sum=D, x=ID} out: {sum=D, x=ID}
magic[IMPLICIT_RECEIVER](sum) -> <v1> USE: in: {sum=READ, x=READ} out: {sum=READ, x=READ}
r(sum|<v1>) -> <v2> USE: in: {x=READ} out: {sum=READ, x=READ}
magic[IMPLICIT_RECEIVER](sum) -> <v1> USE: in: {sum=READ, x=READ} out: {sum=READ, x=READ}
r(sum|<v1>) -> <v2> USE: in: {x=READ} out: {sum=READ, x=READ}
r(x) -> <v3>
r(1) -> <v4>
mark(x - 1)
call(x - 1, minus|<v3>, <v4>) -> <v5>
mark(sum(x - 1))
call(sum(x - 1), invoke|<v2>, <v5>) -> <v6> USE: in: {x=READ} out: {x=READ}
r(x) -> <v7> USE: in: {} out: {x=READ}
call(sum(x - 1), invoke|<v2>, <v5>) -> <v6> USE: in: {x=READ} out: {x=READ}
r(x) -> <v7> USE: in: {} out: {x=READ}
mark(sum(x - 1) + x)
call(sum(x - 1) + x, plus|<v6>, <v7>) -> <v8>
2 ret(*|<v8>) L4
@@ -49,7 +49,7 @@ L4:
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {sum=-, x=I?} out: {sum=-, x=I?} USE: in: {} out: {}
<SINK> INIT: in: {sum=I?, x=I?} out: {sum=I?, x=I?} USE: in: {} out: {}
=====================
== A ==
open class A(val a: A)
@@ -92,7 +92,7 @@ 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 }) INIT: in: {obj=-} out: {obj=-} USE: in: {obj=READ} out: {obj=READ}
d(fun foo() { val y = obj }) INIT: in: {obj=I?} out: {obj=I?} 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> INIT: in: {obj=D} out: {obj=D}
w(obj|<v5>) INIT: in: {obj=D} out: {obj=ID}
@@ -120,7 +120,7 @@ L4:
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {obj=-} out: {obj=-} USE: in: {} out: {}
<SINK> INIT: in: {obj=I?} out: {obj=I?} USE: in: {} out: {}
=====================
== TestOther ==
class TestOther {
@@ -19,7 +19,7 @@ L0:
v(val f = { x: Int -> val a = x + b }) INIT: in: {b=ID} out: {b=ID, f=D}
mark({ x: Int -> val a = x + b }) INIT: in: {b=ID, f=D} out: {b=ID, f=D}
jmp?(L2)
d({ x: Int -> val a = x + b }) INIT: in: {b=I?, f=-} out: {b=I?, f=-} USE: in: {b=READ} out: {b=READ}
d({ x: Int -> val a = x + b }) INIT: in: {b=I, f=I?} out: {b=I, f=I?} USE: in: {b=READ} out: {b=READ}
L2 [after local declaration]:
r({ x: Int -> val a = x + b }) -> <v2> INIT: in: {b=ID, f=D} out: {b=ID, f=D}
w(f|<v2>) INIT: in: {b=ID, f=D} out: {b=ID, f=ID}
@@ -54,5 +54,5 @@ L4:
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {b=I?, f=-, x=I?} out: {b=I?, f=-, x=I?} USE: in: {} out: {}
<SINK> INIT: in: {b=I, f=I?, x=I?} out: {b=I, f=I?, x=I?} USE: in: {} out: {}
=====================
@@ -27,10 +27,10 @@ L0:
r(x|<v2>) -> <v3>
w(a|<v3>) INIT: in: {a=D, x=ID} out: {a=ID, x=ID}
2 jmp?(L3) INIT: in: {x=ID} out: {x=ID}
d(fun foo() { val b = x }) INIT: in: {x=I?} out: {x=I?} USE: in: {x=READ} out: {x=READ}
d(fun foo() { val b = x }) INIT: in: {x=I} out: {x=I} USE: in: {x=READ} out: {x=READ}
L2 [after local class]:
L3 [after local declaration]:
mark("after")
mark("after") INIT: in: {x=I?} out: {x=I?}
r("after") -> <v4>
L1:
1 <END> INIT: in: {} out: {}
@@ -56,5 +56,5 @@ L5:
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {x=I?} out: {x=I?} USE: in: {} out: {}
<SINK> INIT: in: {x=I} out: {x=I} USE: in: {} out: {}
=====================
@@ -17,7 +17,7 @@ L0:
r(1) -> <v1> INIT: in: {b=D} out: {b=D}
w(b|<v1>) INIT: in: {b=D} out: {b=ID}
jmp?(L2) INIT: in: {b=ID} out: {b=ID}
d(fun local(x: Int) { val a = x + b }) INIT: in: {b=I?} out: {b=I?} USE: in: {b=READ} out: {b=READ}
d(fun local(x: Int) { val a = x + b }) INIT: in: {b=I} out: {b=I} USE: in: {b=READ} out: {b=READ}
L2 [after local declaration]:
mark("after") INIT: in: {b=ID} out: {b=ID}
r("after") -> <v2>
@@ -50,5 +50,5 @@ L4:
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {b=I?, x=I?} out: {b=I?, x=I?} USE: in: {} out: {}
<SINK> INIT: in: {b=I, x=I?} out: {b=I, x=I?} USE: in: {} out: {}
=====================
@@ -15,7 +15,7 @@ L0:
r(1) -> <v1> INIT: in: {b=D} out: {b=D}
w(b|<v1>) INIT: in: {b=D} out: {b=ID}
jmp?(L2) INIT: in: {b=ID} out: {b=ID}
d(fun local(x: Int) = x + b) INIT: in: {b=I?} out: {b=I?} USE: in: {b=READ} out: {b=READ}
d(fun local(x: Int) = x + b) INIT: in: {b=I} out: {b=I} USE: in: {b=READ} out: {b=READ}
L2 [after local declaration]:
mark("after") INIT: in: {b=ID} out: {b=ID}
r("after") -> <v2>
@@ -44,5 +44,5 @@ L4:
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {b=I?, x=I?} out: {b=I?, x=I?} USE: in: {} out: {}
<SINK> INIT: in: {b=I, x=I?} out: {b=I, x=I?} USE: in: {} out: {}
=====================
@@ -24,7 +24,7 @@ L0:
r(1) -> <v1> INIT: in: {bar=D, x=D} out: {bar=D, x=D}
w(x|<v1>) INIT: in: {bar=D, x=D} out: {bar=D, x=ID}
2 jmp?(L2) INIT: in: {bar=D} out: {bar=D}
d(fun foo() { val a = 2 }) INIT: in: {bar=-} out: {bar=-}
d(fun foo() { val a = 2 }) INIT: in: {bar=I?} out: {bar=I?}
L2 [after local declaration]:
r(object { init { val x = 1 } fun foo() { val a = 2 } }) -> <v2> INIT: in: {bar=D} out: {bar=D}
w(bar|<v2>) INIT: in: {bar=D} out: {bar=ID}
@@ -53,5 +53,5 @@ L4:
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {bar=-} out: {bar=-} USE: in: {} out: {}
<SINK> INIT: in: {bar=I?} out: {bar=I?} USE: in: {} out: {}
=====================
@@ -17,10 +17,10 @@ L0:
jmp?(L2)
v(var a : Int get() { return field } set(v: Int) { field = v }) INIT: in: {} out: {a=D}
jmp?(L3) INIT: in: {a=D} out: {a=D} USE: in: {field=ONLY_WRITTEN_NEVER_READ, field=READ} out: {field=ONLY_WRITTEN_NEVER_READ, field=READ}
d(get() { return field }) INIT: in: {a=-} out: {a=-} USE: in: {field=READ} out: {field=READ}
d(get() { return field }) INIT: in: {a=I?} out: {a=I?} USE: in: {field=READ} out: {field=READ}
L3 [after local declaration]:
jmp?(L6) INIT: in: {a=D} out: {a=D}
d(set(v: Int) { field = v }) INIT: in: {a=-, field=I?} out: {a=-, field=I?} USE: in: {field=ONLY_WRITTEN_NEVER_READ} out: {field=ONLY_WRITTEN_NEVER_READ}
d(set(v: Int) { field = v }) INIT: in: {a=I?, field=I} out: {a=I?, field=I} USE: in: {field=ONLY_WRITTEN_NEVER_READ} out: {field=ONLY_WRITTEN_NEVER_READ}
L1:
L2 [after local class]:
L6 [after local declaration]:
@@ -28,7 +28,7 @@ L6 [after local declaration]:
error:
<ERROR>
sink:
<SINK> INIT: in: {field=I?} out: {field=I?} USE: in: {} out: {}
<SINK> INIT: in: {field=I} out: {field=I} USE: in: {} out: {}
=====================
== get_a ==
get() {
@@ -37,15 +37,15 @@ get() {
---------------------
L4:
3 <START> INIT: in: {a=D} out: {a=D}
4 mark({ return field }) USE: in: {field=READ} out: {field=READ}
r(field) -> <v0> USE: in: {} out: {field=READ}
4 mark({ return field }) USE: in: {field=READ} out: {field=READ}
r(field) -> <v0> USE: in: {} out: {field=READ}
ret(*|<v0>) L5
L5:
3 <END>
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {a=-} out: {a=-} USE: in: {} out: {}
<SINK> INIT: in: {a=I?} out: {a=I?} USE: in: {} out: {}
=====================
== set_a ==
set(v: Int) {
@@ -65,5 +65,5 @@ L8:
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {a=-, field=I?, v=I?} out: {a=-, field=I?, v=I?} USE: in: {} out: {}
<SINK> INIT: in: {a=I?, field=I, v=I?} out: {a=I?, field=I, v=I?} USE: in: {} out: {}
=====================
@@ -0,0 +1,87 @@
fun println(obj: Any?) = obj
class Demo0 {
private val some = object {
fun foo() {
println(state)
}
}
private var state: Boolean = true
}
class Demo1 {
private val some = object {
fun foo() {
if (state)
state = true
println(state)
}
}
private var state: Boolean = true
}
class Demo1A {
fun foo() {
if (state)
state = true
println(state)
}
private var state: Boolean = true
}
class Demo2 {
private val some = object {
fun foo() {
if (state)
state = true
else
state = false
println(state)
}
}
private var state: Boolean = true
}
class Demo3 {
private val some = run {
if (state)
state = true
println(state)
}
private var state: Boolean = true
}
fun <T> exec(f: () -> T): T = f()
class Demo4 {
private val some = exec {
if (state)
state = true
println(state)
}
private var state: Boolean = true
}
class Demo5 {
private var state: Boolean = true
private val some = object {
fun foo() {
if (state)
state = true
println(state)
}
}
}
@@ -0,0 +1,67 @@
package
public fun </*0*/ T> exec(/*0*/ f: () -> T): T
public fun println(/*0*/ obj: kotlin.Any?): kotlin.Any?
public final class Demo0 {
public constructor Demo0()
private final val some: Demo0.some.<no name provided>
private final var state: kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class Demo1 {
public constructor Demo1()
private final val some: Demo1.some.<no name provided>
private final var state: kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class Demo1A {
public constructor Demo1A()
private final var state: kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class Demo2 {
public constructor Demo2()
private final val some: Demo2.some.<no name provided>
private final var state: kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class Demo3 {
public constructor Demo3()
private final val some: kotlin.Any?
private final var state: kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class Demo4 {
public constructor Demo4()
private final val some: kotlin.Any?
private final var state: kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class Demo5 {
public constructor Demo5()
private final val some: Demo5.some.<no name provided>
private final var state: kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -130,6 +130,12 @@ public class DataFlowTestGenerated extends AbstractDataFlowTest {
doTest(fileName);
}
@TestMetadata("localObjectInConstructor.kt")
public void testLocalObjectInConstructor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/localObjectInConstructor.kt");
doTest(fileName);
}
@TestMetadata("referenceToPropertyInitializer.kt")
public void testReferenceToPropertyInitializer() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/referenceToPropertyInitializer.kt");
@@ -888,6 +888,12 @@ public class PseudoValueTestGenerated extends AbstractPseudoValueTest {
doTest(fileName);
}
@TestMetadata("localObjectInConstructor.kt")
public void testLocalObjectInConstructor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/localObjectInConstructor.kt");
doTest(fileName);
}
@TestMetadata("referenceToPropertyInitializer.kt")
public void testReferenceToPropertyInitializer() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/referenceToPropertyInitializer.kt");
@@ -3600,6 +3600,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("localObjectInConstructor.kt")
public void testLocalObjectInConstructor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/localObjectInConstructor.kt");
doTest(fileName);
}
@TestMetadata("nestedTryFinally.kt")
public void testNestedTryFinally() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlFlowAnalysis/nestedTryFinally.kt");