diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/breakContinuesInInlinedLambda.instructions b/compiler/testData/cfgVariablesWithStdLib/contracts/breakContinuesInInlinedLambda.instructions new file mode 100644 index 00000000000..f1a909118ad --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/breakContinuesInInlinedLambda.instructions @@ -0,0 +1,299 @@ +== myRun == +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} +--------------------- +L0: + 1 INIT: in: {} out: {} + v(block: () -> T) INIT: in: {} out: {} + magic[FAKE_INITIALIZER](block: () -> T) -> INIT: in: {} out: {} + w(block|) INIT: in: {} out: {} + 2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() }) INIT: in: {} out: {} + mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + jmp?(L2) + d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) +L2 [after local declaration]: + r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> + mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> + r(block) -> + mark(block()) + call(block(), invoke|) -> + ret(*|) L1 +L1: + 1 +error: + +sink: + USE: in: {} out: {} +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- +L3: + 3 INIT: in: {} out: {} + 4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> + r(block) -> + mark(InvocationKind.EXACTLY_ONCE) + r(EXACTLY_ONCE) -> + mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +L4: + 3 +error: + +sink: + USE: in: {} out: {} +===================== +== getBoolean == +fun getBoolean(): Boolean = false +--------------------- +L0: + 1 INIT: in: {} out: {} + r(false) -> + ret(*|) L1 +L1: + +error: + +sink: + USE: in: {} out: {} +===================== +== test == +fun test() { + val x: Int + + if (getBoolean()) + myRun { + while (getBoolean()) { + do { + myRun { + if (getBoolean()) { + x = 42 + } + else { + x = 43 + } + } + break + } while (getBoolean()) + myRun { x.inc() } + myRun { x = 42 } + break + } + x = 42 + } + else + myRun { + x = 42 + } + + x.inc() +} +--------------------- +L0: + 1 INIT: in: {} out: {} USE: in: {} out: {} + 2 mark({ val x: Int if (getBoolean()) myRun { while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 } else myRun { x = 42 } x.inc() }) + v(val x: Int) INIT: in: {} out: {x=D} + mark(if (getBoolean()) myRun { while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 } else myRun { x = 42 }) INIT: in: {x=D} out: {x=D} + mark(getBoolean()) + call(getBoolean(), getBoolean) -> + jf(L2|) + mark({ while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 }) + r({ while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 }) -> + mark(myRun { while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 }) + call(myRun { while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 }, myRun|) -> +L3 [before inlined declaration]: + inlined({ while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 }) INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} +L4 [after inlined declaration]: + jmp(L31) USE: in: {x=READ} out: {x=READ} +L2 [else branch]: + mark({ x = 42 }) INIT: in: {x=D} out: {x=D} + r({ x = 42 }) -> + mark(myRun { x = 42 }) + call(myRun { x = 42 }, myRun|) -> +L32 [before inlined declaration]: + inlined({ x = 42 }) INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} +L31 ['if' expression result]: +L33 [after inlined declaration]: + merge(if (getBoolean()) myRun { while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 } else myRun { x = 42 }|, ) -> + mark(x.inc()) USE: in: {x=READ} out: {x=READ} + r(x) -> USE: in: {} out: {x=READ} + mark(inc()) + call(inc(), inc|) -> +L1: + 1 INIT: in: {} out: {} +error: + +sink: + USE: in: {} out: {} +===================== +== inlined anonymous_1 == +{ + while (getBoolean()) { + do { + myRun { + if (getBoolean()) { + x = 42 + } + else { + x = 43 + } + } + break + } while (getBoolean()) + myRun { x.inc() } + myRun { x = 42 } + break + } + x = 42 + } +--------------------- +L5: + 3 INIT: in: {x=D} out: {x=D} + 4 mark(while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42) +L7 [loop entry point]: +L11 [condition entry point]: + mark(getBoolean()) + call(getBoolean(), getBoolean) -> + mark(while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break }) + jf(L8|) +L9 [body entry point]: + 5 mark({ do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break }) + 6 mark(do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean())) +L12 [loop entry point]: +L14 [body entry point]: + mark({ myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break }) + mark({ if (getBoolean()) { x = 42 } else { x = 43 } }) + r({ if (getBoolean()) { x = 42 } else { x = 43 } }) -> + mark(myRun { if (getBoolean()) { x = 42 } else { x = 43 } }) + call(myRun { if (getBoolean()) { x = 42 } else { x = 43 } }, myRun|) -> +L17 [before inlined declaration]: + inlined({ if (getBoolean()) { x = 42 } else { x = 43 } }) INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} +L18 [after inlined declaration]: + jmp(L13) USE: in: {x=READ} out: {x=READ} +L15 [body exit point]: +L16 [condition entry point]: +- mark(getBoolean()) +- call(getBoolean(), getBoolean) -> +- 5 jt(L12|) +L13 [loop exit point]: + read (Unit) INIT: in: {x=ID} out: {x=ID} + mark({ x.inc() }) + r({ x.inc() }) -> + mark(myRun { x.inc() }) + call(myRun { x.inc() }, myRun|) -> +L23 [before inlined declaration]: + inlined({ x.inc() }) USE: in: {x=READ} out: {x=READ} +L24 [after inlined declaration]: + mark({ x = 42 }) + r({ x = 42 }) -> + mark(myRun { x = 42 }) + call(myRun { x = 42 }, myRun|) -> +L27 [before inlined declaration]: + inlined({ x = 42 }) +L28 [after inlined declaration]: + jmp(L8) USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} +- 4 jmp(L7) +L8 [loop exit point]: +L10 [body exit point]: + read (Unit) INIT: in: {x=I?D} out: {x=I?D} + r(42) -> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} + w(x|) INIT: in: {x=I?D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ} +L6: + 3 INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ} +error: +- +sink: + INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ} +===================== +== inlined anonymous_2 == +{ + if (getBoolean()) { + x = 42 + } + else { + x = 43 + } + } +--------------------- +L19: + 7 INIT: in: {x=D} out: {x=D} + 8 mark(if (getBoolean()) { x = 42 } else { x = 43 }) + mark(if (getBoolean()) { x = 42 } else { x = 43 }) + mark(getBoolean()) + call(getBoolean(), getBoolean) -> + jf(L21|) + 9 mark({ x = 42 }) + r(42) -> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} + w(x|) INIT: in: {x=D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ} + 8 jmp(L22) INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ} +L21 [else branch]: + 9 mark({ x = 43 }) INIT: in: {x=D} out: {x=D} + r(43) -> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} + w(x|) INIT: in: {x=D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ} +L22 ['if' expression result]: + 8 merge(if (getBoolean()) { x = 42 } else { x = 43 }|!, !) -> INIT: in: {x=ID} out: {x=ID} +L20: + 7 USE: in: {x=READ} out: {x=READ} +error: +- +sink: + INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ} +===================== +== inlined anonymous_3 == +{ x.inc() } +--------------------- +L25: + 6 INIT: in: {x=ID} out: {x=ID} + 7 mark(x.inc()) + mark(x.inc()) USE: in: {x=READ} out: {x=READ} + r(x) -> USE: in: {x=WRITTEN_AFTER_READ} out: {x=READ} + mark(inc()) + call(inc(), inc|) -> + 6 ret(*|) L26 +L26: + USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} +error: +- +sink: + INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} +===================== +== inlined anonymous_4 == +{ x = 42 } +--------------------- +L29: + 6 INIT: in: {x=ID} out: {x=ID} + 7 mark(x = 42) + r(42) -> + w(x|) +L30: + 6 USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} +error: +- +sink: + INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} +===================== +== inlined anonymous_5 == +{ + x = 42 + } +--------------------- +L34: + 3 INIT: in: {x=D} out: {x=D} + 4 mark(x = 42) + r(42) -> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} + w(x|) INIT: in: {x=D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ} +L35: + 3 INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ} +error: +- +sink: + INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ} +===================== diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/breakContinuesInInlinedLambda.kt b/compiler/testData/cfgVariablesWithStdLib/contracts/breakContinuesInInlinedLambda.kt new file mode 100644 index 00000000000..c1362255a2b --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/breakContinuesInInlinedLambda.kt @@ -0,0 +1,43 @@ +// LANGUAGE_VERSION: 1.3 + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun getBoolean(): Boolean = false + +fun test() { + val x: Int + + if (getBoolean()) + myRun { + while (getBoolean()) { + do { + myRun { + if (getBoolean()) { + x = 42 + } + else { + x = 43 + } + } + break + } while (getBoolean()) + myRun { x.inc() } + myRun { x = 42 } + break + } + x = 42 + } + else + myRun { + x = 42 + } + + x.inc() +} \ No newline at end of file diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/breakContinuesInInlinedLambda.values b/compiler/testData/cfgVariablesWithStdLib/contracts/breakContinuesInInlinedLambda.values new file mode 100644 index 00000000000..517055654c9 --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/breakContinuesInInlinedLambda.values @@ -0,0 +1,157 @@ +== myRun == +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} +--------------------- + : {<: () -> T} NEW: magic[FAKE_INITIALIZER](block: () -> T) -> +{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> +contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> +block : {<: () -> T} NEW: r(block) -> +block() : {<: T} NEW: call(block(), invoke|) -> +return block() !: * +{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() } !: * COPY +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- + : {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> +block : {<: Function} NEW: r(block) -> +EXACTLY_ONCE : {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> +InvocationKind.EXACTLY_ONCE : {<: InvocationKind} COPY +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * COPY +===================== +== getBoolean == +fun getBoolean(): Boolean = false +--------------------- +false : Boolean NEW: r(false) -> +===================== +== test == +fun test() { + val x: Int + + if (getBoolean()) + myRun { + while (getBoolean()) { + do { + myRun { + if (getBoolean()) { + x = 42 + } + else { + x = 43 + } + } + break + } while (getBoolean()) + myRun { x.inc() } + myRun { x = 42 } + break + } + x = 42 + } + else + myRun { + x = 42 + } + + x.inc() +} +--------------------- +getBoolean() : Boolean NEW: call(getBoolean(), getBoolean) -> +{ while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 } : {<: () -> Unit} NEW: r({ while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 }) -> +myRun { while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 } : * NEW: call(myRun { while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 }, myRun|) -> +{ x = 42 } : {<: () -> Unit} NEW: r({ x = 42 }) -> +myRun { x = 42 } : * NEW: call(myRun { x = 42 }, myRun|) -> +if (getBoolean()) myRun { while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 } else myRun { x = 42 } : * NEW: merge(if (getBoolean()) myRun { while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 } else myRun { x = 42 }|, ) -> +x : Int NEW: r(x) -> +inc() : * NEW: call(inc(), inc|) -> +x.inc() : * COPY +{ val x: Int if (getBoolean()) myRun { while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 } else myRun { x = 42 } x.inc() } : * COPY +===================== +== inlined anonymous_1 == +{ + while (getBoolean()) { + do { + myRun { + if (getBoolean()) { + x = 42 + } + else { + x = 43 + } + } + break + } while (getBoolean()) + myRun { x.inc() } + myRun { x = 42 } + break + } + x = 42 + } +--------------------- +getBoolean() : Boolean NEW: call(getBoolean(), getBoolean) -> +{ if (getBoolean()) { x = 42 } else { x = 43 } } : {<: () -> Unit} NEW: r({ if (getBoolean()) { x = 42 } else { x = 43 } }) -> +myRun { if (getBoolean()) { x = 42 } else { x = 43 } } : * NEW: call(myRun { if (getBoolean()) { x = 42 } else { x = 43 } }, myRun|) -> +break !: * +{ myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } !: * COPY +getBoolean() : Boolean NEW: call(getBoolean(), getBoolean) -> +{ x.inc() } : {<: () -> Int} NEW: r({ x.inc() }) -> +myRun { x.inc() } : * NEW: call(myRun { x.inc() }, myRun|) -> +{ x = 42 } : {<: () -> Unit} NEW: r({ x = 42 }) -> +myRun { x = 42 } : * NEW: call(myRun { x = 42 }, myRun|) -> +break !: * +{ do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } !: * COPY +42 : Int NEW: r(42) -> +x = 42 !: * +while (getBoolean()) { do { myRun { if (getBoolean()) { x = 42 } else { x = 43 } } break } while (getBoolean()) myRun { x.inc() } myRun { x = 42 } break } x = 42 !: * COPY +===================== +== inlined anonymous_2 == +{ + if (getBoolean()) { + x = 42 + } + else { + x = 43 + } + } +--------------------- +getBoolean() : Boolean NEW: call(getBoolean(), getBoolean) -> +42 : Int NEW: r(42) -> +x = 42 !: * +{ x = 42 } !: * COPY +43 : Int NEW: r(43) -> +x = 43 !: * +{ x = 43 } !: * COPY +if (getBoolean()) { x = 42 } else { x = 43 } : * NEW: merge(if (getBoolean()) { x = 42 } else { x = 43 }|!, !) -> +if (getBoolean()) { x = 42 } else { x = 43 } : * COPY +===================== +== inlined anonymous_3 == +{ x.inc() } +--------------------- +x : Int NEW: r(x) -> +inc() : Int NEW: call(inc(), inc|) -> +x.inc() : Int COPY +x.inc() : Int COPY +===================== +== inlined anonymous_4 == +{ x = 42 } +--------------------- +42 : Int NEW: r(42) -> +x = 42 !: * +x = 42 !: * COPY +===================== +== inlined anonymous_5 == +{ + x = 42 + } +--------------------- +42 : Int NEW: r(42) -> +x = 42 !: * +x = 42 !: * COPY +===================== diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/inlinedLambdaAlwaysThrows.instructions b/compiler/testData/cfgVariablesWithStdLib/contracts/inlinedLambdaAlwaysThrows.instructions new file mode 100644 index 00000000000..14b3cec35b7 --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/inlinedLambdaAlwaysThrows.instructions @@ -0,0 +1,96 @@ +== myRun == +inline fun myRun(block: () -> Unit): Unit { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + block() +} +--------------------- +L0: + 1 INIT: in: {} out: {} + v(block: () -> Unit) INIT: in: {} out: {} + magic[FAKE_INITIALIZER](block: () -> Unit) -> INIT: in: {} out: {} + w(block|) INIT: in: {} out: {} + 2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block() }) INIT: in: {} out: {} + mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + jmp?(L2) + d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) +L2 [after local declaration]: + r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> + mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> + r(block) -> + mark(block()) + call(block(), invoke|) -> +L1: + 1 +error: + +sink: + USE: in: {} out: {} +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- +L3: + 3 INIT: in: {} out: {} + 4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> + r(block) -> + mark(InvocationKind.EXACTLY_ONCE) + r(EXACTLY_ONCE) -> + mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +L4: + 3 +error: + +sink: + USE: in: {} out: {} +===================== +== test == +fun test() { + myRun { throw java.lang.IllegalArgumentException() } + val x: Int = 42 +} +--------------------- +L0: + 1 INIT: in: {} out: {} + 2 mark({ myRun { throw java.lang.IllegalArgumentException() } val x: Int = 42 }) + mark({ throw java.lang.IllegalArgumentException() }) + r({ throw java.lang.IllegalArgumentException() }) -> + mark(myRun { throw java.lang.IllegalArgumentException() }) + call(myRun { throw java.lang.IllegalArgumentException() }, myRun|) -> +L2 [before inlined declaration]: + inlined({ throw java.lang.IllegalArgumentException() }) USE: in: {} out: {} +L3 [after inlined declaration]: +- v(val x: Int = 42) +- r(42) -> +- w(x|) +L1: + 1 INIT: in: {} out: {} +error: + +sink: + USE: in: {} out: {} +===================== +== inlined anonymous_1 == +{ throw java.lang.IllegalArgumentException() } +--------------------- +L4: + 3 INIT: in: {} out: {} + 4 mark(throw java.lang.IllegalArgumentException()) + mark(throw java.lang.IllegalArgumentException()) + mark(java.lang.IllegalArgumentException()) + mark(IllegalArgumentException()) + call(IllegalArgumentException(), ) -> + throw (throw java.lang.IllegalArgumentException()|) USE: in: {} out: {} +L5: +- 3 +error: + INIT: in: {} out: {} +sink: + USE: in: {} out: {} +===================== diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/inlinedLambdaAlwaysThrows.kt b/compiler/testData/cfgVariablesWithStdLib/contracts/inlinedLambdaAlwaysThrows.kt new file mode 100644 index 00000000000..d29b2fd8df8 --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/inlinedLambdaAlwaysThrows.kt @@ -0,0 +1,15 @@ +// LANGUAGE_VERSION: 1.3 + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> Unit): Unit { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + block() +} + +fun test() { + myRun { throw java.lang.IllegalArgumentException() } + val x: Int = 42 +} \ No newline at end of file diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/inlinedLambdaAlwaysThrows.values b/compiler/testData/cfgVariablesWithStdLib/contracts/inlinedLambdaAlwaysThrows.values new file mode 100644 index 00000000000..866758a0cf0 --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/inlinedLambdaAlwaysThrows.values @@ -0,0 +1,45 @@ +== myRun == +inline fun myRun(block: () -> Unit): Unit { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + block() +} +--------------------- + : {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> +{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> +contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> +block : {<: () -> Unit} NEW: r(block) -> +block() : * NEW: call(block(), invoke|) -> +{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block() } : * COPY +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- + : {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> +block : {<: Function} NEW: r(block) -> +EXACTLY_ONCE : {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> +InvocationKind.EXACTLY_ONCE : {<: InvocationKind} COPY +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * COPY +===================== +== test == +fun test() { + myRun { throw java.lang.IllegalArgumentException() } + val x: Int = 42 +} +--------------------- +{ throw java.lang.IllegalArgumentException() } : {<: () -> Unit} NEW: r({ throw java.lang.IllegalArgumentException() }) -> +myRun { throw java.lang.IllegalArgumentException() } : * NEW: call(myRun { throw java.lang.IllegalArgumentException() }, myRun|) -> +42 : Int NEW: r(42) -> +===================== +== inlined anonymous_1 == +{ throw java.lang.IllegalArgumentException() } +--------------------- +IllegalArgumentException() : {<: Throwable} NEW: call(IllegalArgumentException(), ) -> +java.lang.IllegalArgumentException() : {<: Throwable} COPY +throw java.lang.IllegalArgumentException() !: * +throw java.lang.IllegalArgumentException() !: * COPY +===================== diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/irrelevantUnknownClosure.instructions b/compiler/testData/cfgVariablesWithStdLib/contracts/irrelevantUnknownClosure.instructions new file mode 100644 index 00000000000..238702d0c4b --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/irrelevantUnknownClosure.instructions @@ -0,0 +1,145 @@ +== myRun == +inline fun myRun(block: () -> Unit): Unit { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} +--------------------- +L0: + 1 INIT: in: {} out: {} + v(block: () -> Unit) INIT: in: {} out: {} + magic[FAKE_INITIALIZER](block: () -> Unit) -> INIT: in: {} out: {} + w(block|) INIT: in: {} out: {} + 2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() }) INIT: in: {} out: {} + mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + jmp?(L2) + d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) +L2 [after local declaration]: + r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> + mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> + r(block) -> + mark(block()) + call(block(), invoke|) -> + ret(*|) L1 +L1: + 1 +error: + +sink: + USE: in: {} out: {} +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- +L3: + 3 INIT: in: {} out: {} + 4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> + r(block) -> + mark(InvocationKind.EXACTLY_ONCE) + r(EXACTLY_ONCE) -> + mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +L4: + 3 +error: + +sink: + USE: in: {} out: {} +===================== +== unknownRun == +inline fun unknownRun(block: () -> Unit) { block() } +--------------------- +L0: + 1 INIT: in: {} out: {} + v(block: () -> Unit) INIT: in: {} out: {} + magic[FAKE_INITIALIZER](block: () -> Unit) -> INIT: in: {} out: {} + w(block|) INIT: in: {} out: {} + 2 mark({ block() }) INIT: in: {} out: {} + r(block) -> + mark(block()) + call(block(), invoke|) -> +L1: + 1 +error: + +sink: + USE: in: {} out: {} +===================== +== foo == +fun foo() { + val x: Int + myRun { + unknownRun { println("shouldn't change anything") } + x = 42 + } + println(x) +} +--------------------- +L0: + 1 INIT: in: {} out: {} USE: in: {} out: {} + 2 mark({ val x: Int myRun { unknownRun { println("shouldn't change anything") } x = 42 } println(x) }) + v(val x: Int) INIT: in: {} out: {x=D} + mark({ unknownRun { println("shouldn't change anything") } x = 42 }) INIT: in: {x=D} out: {x=D} + r({ unknownRun { println("shouldn't change anything") } x = 42 }) -> + mark(myRun { unknownRun { println("shouldn't change anything") } x = 42 }) + call(myRun { unknownRun { println("shouldn't change anything") } x = 42 }, myRun|) -> +L2 [before inlined declaration]: + inlined({ unknownRun { println("shouldn't change anything") } x = 42 }) INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ} +L3 [after inlined declaration]: + r(x) -> USE: in: {} out: {x=READ} + mark(println(x)) + call(println(x), println|) -> +L1: + 1 INIT: in: {} out: {} +error: + +sink: + USE: in: {} out: {} +===================== +== inlined anonymous_1 == +{ + unknownRun { println("shouldn't change anything") } + x = 42 + } +--------------------- +L4: + 3 INIT: in: {x=D} out: {x=D} + 4 mark(unknownRun { println("shouldn't change anything") } x = 42) + mark({ println("shouldn't change anything") }) + jmp?(L6) + d({ println("shouldn't change anything") }) INIT: in: {x=I?} out: {x=I?} USE: in: {x=READ} out: {x=READ} +L6 [after local declaration]: + r({ println("shouldn't change anything") }) -> INIT: in: {x=D} out: {x=D} + mark(unknownRun { println("shouldn't change anything") }) + call(unknownRun { println("shouldn't change anything") }, unknownRun|) -> + r(42) -> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} + w(x|) INIT: in: {x=D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ} +L5: + 3 INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ} +error: +- +sink: + INIT: in: {x=I?} out: {x=I?} USE: in: {x=READ} out: {x=READ} +===================== +== anonymous_2 == +{ println("shouldn't change anything") } +--------------------- +L7: + 5 INIT: in: {x=D} out: {x=D} + 6 mark(println("shouldn't change anything")) + mark("shouldn't change anything") + r("shouldn't change anything") -> + mark(println("shouldn't change anything")) + call(println("shouldn't change anything"), println|) -> +L8: + 5 +error: + INIT: in: {} out: {} +sink: + INIT: in: {x=I?} out: {x=I?} USE: in: {x=READ} out: {x=READ} +===================== diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/irrelevantUnknownClosure.kt b/compiler/testData/cfgVariablesWithStdLib/contracts/irrelevantUnknownClosure.kt new file mode 100644 index 00000000000..871b8020b5c --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/irrelevantUnknownClosure.kt @@ -0,0 +1,21 @@ +// LANGUAGE_VERSION: 1.3 + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> Unit): Unit { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +inline fun unknownRun(block: () -> Unit) { block() } + +fun foo() { + val x: Int + myRun { + unknownRun { println("shouldn't change anything") } + x = 42 + } + println(x) +} \ No newline at end of file diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/irrelevantUnknownClosure.values b/compiler/testData/cfgVariablesWithStdLib/contracts/irrelevantUnknownClosure.values new file mode 100644 index 00000000000..f05b0dd6d5a --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/irrelevantUnknownClosure.values @@ -0,0 +1,71 @@ +== myRun == +inline fun myRun(block: () -> Unit): Unit { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} +--------------------- + : {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> +{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> +contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> +block : {<: () -> Unit} NEW: r(block) -> +block() : Unit NEW: call(block(), invoke|) -> +return block() !: * +{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() } !: * COPY +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- + : {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> +block : {<: Function} NEW: r(block) -> +EXACTLY_ONCE : {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> +InvocationKind.EXACTLY_ONCE : {<: InvocationKind} COPY +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * COPY +===================== +== unknownRun == +inline fun unknownRun(block: () -> Unit) { block() } +--------------------- + : {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> +block : {<: () -> Unit} NEW: r(block) -> +block() : * NEW: call(block(), invoke|) -> +{ block() } : * COPY +===================== +== foo == +fun foo() { + val x: Int + myRun { + unknownRun { println("shouldn't change anything") } + x = 42 + } + println(x) +} +--------------------- +{ unknownRun { println("shouldn't change anything") } x = 42 } : {<: () -> Unit} NEW: r({ unknownRun { println("shouldn't change anything") } x = 42 }) -> +myRun { unknownRun { println("shouldn't change anything") } x = 42 } : * NEW: call(myRun { unknownRun { println("shouldn't change anything") } x = 42 }, myRun|) -> +x : Int NEW: r(x) -> +println(x) : * NEW: call(println(x), println|) -> +{ val x: Int myRun { unknownRun { println("shouldn't change anything") } x = 42 } println(x) } : * COPY +===================== +== inlined anonymous_1 == +{ + unknownRun { println("shouldn't change anything") } + x = 42 + } +--------------------- +{ println("shouldn't change anything") } : {<: () -> Unit} NEW: r({ println("shouldn't change anything") }) -> +unknownRun { println("shouldn't change anything") } : * NEW: call(unknownRun { println("shouldn't change anything") }, unknownRun|) -> +42 : Int NEW: r(42) -> +x = 42 !: * +unknownRun { println("shouldn't change anything") } x = 42 !: * COPY +===================== +== anonymous_2 == +{ println("shouldn't change anything") } +--------------------- +"shouldn't change anything" : * NEW: r("shouldn't change anything") -> +println("shouldn't change anything") : * NEW: call(println("shouldn't change anything"), println|) -> +println("shouldn't change anything") : * COPY +===================== diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchFinally.instructions b/compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchFinally.instructions new file mode 100644 index 00000000000..4fba5291736 --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchFinally.instructions @@ -0,0 +1,339 @@ +== myRun == +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} +--------------------- +L0: + 1 INIT: in: {} out: {} + v(block: () -> T) INIT: in: {} out: {} + magic[FAKE_INITIALIZER](block: () -> T) -> INIT: in: {} out: {} + w(block|) INIT: in: {} out: {} + 2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() }) INIT: in: {} out: {} + mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + jmp?(L2) + d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) +L2 [after local declaration]: + r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> + mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> + r(block) -> + mark(block()) + call(block(), invoke|) -> + ret(*|) L1 +L1: + 1 +error: + +sink: + USE: in: {} out: {} +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- +L3: + 3 INIT: in: {} out: {} + 4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> + r(block) -> + mark(InvocationKind.EXACTLY_ONCE) + r(EXACTLY_ONCE) -> + mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +L4: + 3 +error: + +sink: + USE: in: {} out: {} +===================== +== innerComputation == +fun innerComputation(): Int = 42 +--------------------- +L0: + 1 INIT: in: {} out: {} + r(42) -> + ret(*|) L1 +L1: + +error: + +sink: + USE: in: {} out: {} +===================== +== outerComputation == +fun outerComputation(): Int = 52 +--------------------- +L0: + 1 INIT: in: {} out: {} + r(52) -> + ret(*|) L1 +L1: + +error: + +sink: + USE: in: {} out: {} +===================== +== log == +fun log() = Unit +--------------------- +L0: + 1 INIT: in: {} out: {} + r(Unit) -> + ret(*|) L1 +L1: + +error: + +sink: + USE: in: {} out: {} +===================== +== outerFinallyInitializes == +fun outerFinallyInitializes() { + val x: Int + + try { + myRun { + try { + x = innerComputation() + } catch (e: java.lang.Exception) { + log() + } + // possible reassignment if innerComputation finished + x = 42 + } + + // Definite reassignment here, cause can get here only if myRun finished + x = outerComputation() + } catch (e: java.lang.Exception) { + // can catch exception thrown by the inner, so x can be not initalized + log() + } finally { + // Possible reassignment (e.g. if everything finished) + x = 42 + } + + // Properly initialized + x.inc() +} +--------------------- +L0: + 1 INIT: in: {} out: {} USE: in: {} out: {} + 2 mark({ val x: Int try { myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 } // Definite reassignment here, cause can get here only if myRun finished x = outerComputation() } catch (e: java.lang.Exception) { // can catch exception thrown by the inner, so x can be not initalized log() } finally { // Possible reassignment (e.g. if everything finished) x = 42 } // Properly initialized x.inc() }) + v(val x: Int) INIT: in: {} out: {x=D} + mark(try { myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 } // Definite reassignment here, cause can get here only if myRun finished x = outerComputation() } catch (e: java.lang.Exception) { // can catch exception thrown by the inner, so x can be not initalized log() } finally { // Possible reassignment (e.g. if everything finished) x = 42 }) INIT: in: {x=D} out: {x=D} + jmp?(L2) + jmp?(L3) + 3 mark({ myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 } // Definite reassignment here, cause can get here only if myRun finished x = outerComputation() }) + mark({ try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 }) + r({ try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 }) -> + mark(myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 }) + call(myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 }, myRun|) -> +L4 [before inlined declaration]: + inlined({ try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 }) INIT: in: {x=ID} out: {x=ID} +L5 [after inlined declaration]: + mark(outerComputation()) + call(outerComputation(), outerComputation) -> + w(x|) + 2 jmp?(L2) + jmp?(L3) + jmp(L10) +L2 [onException]: + 3 v(e: java.lang.Exception) INIT: in: {x=I?D} out: {x=I?D} + magic[FAKE_INITIALIZER](e: java.lang.Exception) -> INIT: in: {x=I?D} out: {x=I?D} + w(e|) INIT: in: {x=I?D} out: {x=I?D} + 4 mark({ // can catch exception thrown by the inner, so x can be not initalized log() }) INIT: in: {x=I?D} out: {x=I?D} + mark(log()) + call(log(), log) -> + 3 jmp(L10) +L10 [afterCatches]: + 2 jmp(L11) USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} +L3 [onExceptionToFinallyBlock]: +L12 [start finally]: + 3 mark({ // Possible reassignment (e.g. if everything finished) x = 42 }) + r(42) -> USE: in: {x=ONLY_WRITTEN_NEVER_READ} out: {x=ONLY_WRITTEN_NEVER_READ} + w(x|) INIT: in: {x=I?D} out: {x=ID} USE: in: {} out: {x=ONLY_WRITTEN_NEVER_READ} +L13 [finish finally]: + 2 jmp(error) INIT: in: {x=ID} out: {x=ID} USE: in: {} out: {} +L11 [skipFinallyToErrorBlock]: +L14 [copy of L3, onExceptionToFinallyBlock]: + 3 mark({ // Possible reassignment (e.g. if everything finished) x = 42 }) INIT: in: {x=I?D} out: {x=I?D} + r(42) -> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} + w(x|) INIT: in: {x=I?D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ} + 2 merge(try { myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 } // Definite reassignment here, cause can get here only if myRun finished x = outerComputation() } catch (e: java.lang.Exception) { // can catch exception thrown by the inner, so x can be not initalized log() } finally { // Possible reassignment (e.g. if everything finished) x = 42 }|!, ) -> INIT: in: {x=ID} out: {x=ID} + mark(x.inc()) USE: in: {x=READ} out: {x=READ} + r(x) -> USE: in: {} out: {x=READ} + mark(inc()) + call(inc(), inc|) -> +L1: + 1 INIT: in: {} out: {} +error: + +sink: + USE: in: {} out: {} +===================== +== inlined anonymous_1 == +{ + try { + x = innerComputation() + } catch (e: java.lang.Exception) { + log() + } + // possible reassignment if innerComputation finished + x = 42 + } +--------------------- +L6: + 4 INIT: in: {x=D} out: {x=D} + 5 mark(try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42) + mark(try { x = innerComputation() } catch (e: java.lang.Exception) { log() }) + jmp?(L8) + 6 mark({ x = innerComputation() }) + mark(innerComputation()) + call(innerComputation(), innerComputation) -> + w(x|) INIT: in: {x=D} out: {x=ID} + 5 jmp?(L8) INIT: in: {x=ID} out: {x=ID} + jmp(L9) +L8 [onException]: + 6 v(e: java.lang.Exception) INIT: in: {x=I?D} out: {x=I?D} + magic[FAKE_INITIALIZER](e: java.lang.Exception) -> INIT: in: {x=I?D} out: {x=I?D} + w(e|) INIT: in: {x=I?D} out: {x=I?D} + 7 mark({ log() }) INIT: in: {x=I?D} out: {x=I?D} + mark(log()) + call(log(), log) -> + 6 jmp(L9) +L9 [afterCatches]: + 5 merge(try { x = innerComputation() } catch (e: java.lang.Exception) { log() }|!, ) -> + r(42) -> + w(x|) INIT: in: {x=I?D} out: {x=ID} +L7: + 4 INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} +error: +- +sink: + INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} +===================== +== innerFinalltInitializes == +fun innerFinalltInitializes() { + val x: Int + try { + myRun { + try { + innerComputation() + } catch (e: java.lang.Exception) { + log() + } finally { + x = 42 + } + } + + // Properly initialized + x.inc() + } catch (e: java.lang.Exception) { + log() + } + + // Still can be non-initialized (e.g. if x.inc() threw an exception) + x.inc() +} +--------------------- +L0: + 1 INIT: in: {} out: {} USE: in: {} out: {} + 2 mark({ val x: Int try { myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } } // Properly initialized x.inc() } catch (e: java.lang.Exception) { log() } // Still can be non-initialized (e.g. if x.inc() threw an exception) x.inc() }) + v(val x: Int) INIT: in: {} out: {x=D} + mark(try { myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } } // Properly initialized x.inc() } catch (e: java.lang.Exception) { log() }) INIT: in: {x=D} out: {x=D} + jmp?(L2) USE: in: {x=READ} out: {x=READ} + 3 mark({ myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } } // Properly initialized x.inc() }) + mark({ try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } }) + r({ try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } }) -> + mark(myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } }) + call(myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } }, myRun|) -> +L3 [before inlined declaration]: + inlined({ try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } }) INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} +L4 [after inlined declaration]: + mark(x.inc()) + r(x) -> + mark(inc()) + call(inc(), inc|) -> + 2 jmp?(L2) + jmp(L14) +L2 [onException]: + 3 v(e: java.lang.Exception) INIT: in: {x=I?D} out: {x=I?D} + magic[FAKE_INITIALIZER](e: java.lang.Exception) -> INIT: in: {x=I?D} out: {x=I?D} + w(e|) INIT: in: {x=I?D} out: {x=I?D} + 4 mark({ log() }) INIT: in: {x=I?D} out: {x=I?D} + mark(log()) + call(log(), log) -> + 3 jmp(L14) +L14 [afterCatches]: + 2 merge(try { myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } } // Properly initialized x.inc() } catch (e: java.lang.Exception) { log() }|, ) -> + mark(x.inc()) USE: in: {x=READ} out: {x=READ} + r(x) -> USE: in: {} out: {x=READ} + mark(inc()) + call(inc(), inc|) -> +L1: + 1 INIT: in: {} out: {} +error: + +sink: + USE: in: {} out: {} +===================== +== inlined anonymous_2 == +{ + try { + innerComputation() + } catch (e: java.lang.Exception) { + log() + } finally { + x = 42 + } + } +--------------------- +L5: + 4 INIT: in: {x=D} out: {x=D} + 5 mark(try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 }) + mark(try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 }) + jmp?(L7) + jmp?(L8) + 6 mark({ innerComputation() }) + mark(innerComputation()) + call(innerComputation(), innerComputation) -> + 5 jmp?(L7) + jmp?(L8) + jmp(L9) +L7 [onException]: + 6 v(e: java.lang.Exception) INIT: in: {x=D} out: {x=D} + magic[FAKE_INITIALIZER](e: java.lang.Exception) -> INIT: in: {x=D} out: {x=D} + w(e|) INIT: in: {x=D} out: {x=D} + 7 mark({ log() }) INIT: in: {x=D} out: {x=D} + mark(log()) + call(log(), log) -> + 6 jmp(L9) +L9 [afterCatches]: + 5 jmp(L10) +L8 [onExceptionToFinallyBlock]: +L11 [start finally]: + 6 mark({ x = 42 }) + r(42) -> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} + w(x|) INIT: in: {x=D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ} +L12 [finish finally]: + 5 jmp(error) INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ} +L10 [skipFinallyToErrorBlock]: +L13 [copy of L8, onExceptionToFinallyBlock]: + 6 mark({ x = 42 }) INIT: in: {x=D} out: {x=D} + r(42) -> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} + w(x|) INIT: in: {x=D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ} + 5 merge(try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 }|, ) -> INIT: in: {x=ID} out: {x=ID} + 4 ret(*|) L6 +L6: + +error: + +sink: + USE: in: {x=READ} out: {x=READ} +===================== diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchFinally.kt b/compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchFinally.kt new file mode 100644 index 00000000000..2f4ad7f5efa --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchFinally.kt @@ -0,0 +1,66 @@ +// LANGUAGE_VERSION: 1.3 + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun innerComputation(): Int = 42 +fun outerComputation(): Int = 52 + +fun log() = Unit + +fun outerFinallyInitializes() { + val x: Int + + try { + myRun { + try { + x = innerComputation() + } catch (e: java.lang.Exception) { + log() + } + // possible reassignment if innerComputation finished + x = 42 + } + + // Definite reassignment here, cause can get here only if myRun finished + x = outerComputation() + } catch (e: java.lang.Exception) { + // can catch exception thrown by the inner, so x can be not initalized + log() + } finally { + // Possible reassignment (e.g. if everything finished) + x = 42 + } + + // Properly initialized + x.inc() +} + +fun innerFinalltInitializes() { + val x: Int + try { + myRun { + try { + innerComputation() + } catch (e: java.lang.Exception) { + log() + } finally { + x = 42 + } + } + + // Properly initialized + x.inc() + } catch (e: java.lang.Exception) { + log() + } + + // Still can be non-initialized (e.g. if x.inc() threw an exception) + x.inc() +} \ No newline at end of file diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchFinally.values b/compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchFinally.values new file mode 100644 index 00000000000..7ee176e20e7 --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchFinally.values @@ -0,0 +1,172 @@ +== myRun == +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} +--------------------- + : {<: () -> T} NEW: magic[FAKE_INITIALIZER](block: () -> T) -> +{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> +contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> +block : {<: () -> T} NEW: r(block) -> +block() : {<: T} NEW: call(block(), invoke|) -> +return block() !: * +{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() } !: * COPY +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- + : {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> +block : {<: Function} NEW: r(block) -> +EXACTLY_ONCE : {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> +InvocationKind.EXACTLY_ONCE : {<: InvocationKind} COPY +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * COPY +===================== +== innerComputation == +fun innerComputation(): Int = 42 +--------------------- +42 : Int NEW: r(42) -> +===================== +== outerComputation == +fun outerComputation(): Int = 52 +--------------------- +52 : Int NEW: r(52) -> +===================== +== log == +fun log() = Unit +--------------------- +Unit : Unit NEW: r(Unit) -> +===================== +== outerFinallyInitializes == +fun outerFinallyInitializes() { + val x: Int + + try { + myRun { + try { + x = innerComputation() + } catch (e: java.lang.Exception) { + log() + } + // possible reassignment if innerComputation finished + x = 42 + } + + // Definite reassignment here, cause can get here only if myRun finished + x = outerComputation() + } catch (e: java.lang.Exception) { + // can catch exception thrown by the inner, so x can be not initalized + log() + } finally { + // Possible reassignment (e.g. if everything finished) + x = 42 + } + + // Properly initialized + x.inc() +} +--------------------- + : {<: Exception} NEW: magic[FAKE_INITIALIZER](e: java.lang.Exception) -> +{ try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 } : {<: () -> Unit} NEW: r({ try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 }) -> +myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 } : * NEW: call(myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 }, myRun|) -> +outerComputation() : Int NEW: call(outerComputation(), outerComputation) -> +x = outerComputation() !: * +{ myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 } // Definite reassignment here, cause can get here only if myRun finished x = outerComputation() } !: * COPY +log() : * NEW: call(log(), log) -> +{ // can catch exception thrown by the inner, so x can be not initalized log() } : * COPY +42 : Int NEW: r(42) -> +x = 42 !: * +{ // Possible reassignment (e.g. if everything finished) x = 42 } !: * COPY +try { myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 } // Definite reassignment here, cause can get here only if myRun finished x = outerComputation() } catch (e: java.lang.Exception) { // can catch exception thrown by the inner, so x can be not initalized log() } finally { // Possible reassignment (e.g. if everything finished) x = 42 } : * NEW: merge(try { myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 } // Definite reassignment here, cause can get here only if myRun finished x = outerComputation() } catch (e: java.lang.Exception) { // can catch exception thrown by the inner, so x can be not initalized log() } finally { // Possible reassignment (e.g. if everything finished) x = 42 }|!, ) -> +x : Int NEW: r(x) -> +inc() : * NEW: call(inc(), inc|) -> +x.inc() : * COPY +{ val x: Int try { myRun { try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 } // Definite reassignment here, cause can get here only if myRun finished x = outerComputation() } catch (e: java.lang.Exception) { // can catch exception thrown by the inner, so x can be not initalized log() } finally { // Possible reassignment (e.g. if everything finished) x = 42 } // Properly initialized x.inc() } : * COPY +===================== +== inlined anonymous_1 == +{ + try { + x = innerComputation() + } catch (e: java.lang.Exception) { + log() + } + // possible reassignment if innerComputation finished + x = 42 + } +--------------------- + : {<: Exception} NEW: magic[FAKE_INITIALIZER](e: java.lang.Exception) -> +innerComputation() : Int NEW: call(innerComputation(), innerComputation) -> +x = innerComputation() !: * +{ x = innerComputation() } !: * COPY +log() : * NEW: call(log(), log) -> +{ log() } : * COPY +try { x = innerComputation() } catch (e: java.lang.Exception) { log() } : * NEW: merge(try { x = innerComputation() } catch (e: java.lang.Exception) { log() }|!, ) -> +42 : Int NEW: r(42) -> +x = 42 !: * +try { x = innerComputation() } catch (e: java.lang.Exception) { log() } // possible reassignment if innerComputation finished x = 42 !: * COPY +===================== +== innerFinalltInitializes == +fun innerFinalltInitializes() { + val x: Int + try { + myRun { + try { + innerComputation() + } catch (e: java.lang.Exception) { + log() + } finally { + x = 42 + } + } + + // Properly initialized + x.inc() + } catch (e: java.lang.Exception) { + log() + } + + // Still can be non-initialized (e.g. if x.inc() threw an exception) + x.inc() +} +--------------------- + : {<: Exception} NEW: magic[FAKE_INITIALIZER](e: java.lang.Exception) -> +{ try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } } : {<: () -> Any} NEW: r({ try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } }) -> +myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } } : * NEW: call(myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } }, myRun|) -> +x : Int NEW: r(x) -> +inc() : * NEW: call(inc(), inc|) -> +x.inc() : * COPY +{ myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } } // Properly initialized x.inc() } : * COPY +log() : * NEW: call(log(), log) -> +{ log() } : * COPY +try { myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } } // Properly initialized x.inc() } catch (e: java.lang.Exception) { log() } : * NEW: merge(try { myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } } // Properly initialized x.inc() } catch (e: java.lang.Exception) { log() }|, ) -> +x : Int NEW: r(x) -> +inc() : * NEW: call(inc(), inc|) -> +x.inc() : * COPY +{ val x: Int try { myRun { try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } } // Properly initialized x.inc() } catch (e: java.lang.Exception) { log() } // Still can be non-initialized (e.g. if x.inc() threw an exception) x.inc() } : * COPY +===================== +== inlined anonymous_2 == +{ + try { + innerComputation() + } catch (e: java.lang.Exception) { + log() + } finally { + x = 42 + } + } +--------------------- + : {<: Exception} NEW: magic[FAKE_INITIALIZER](e: java.lang.Exception) -> +innerComputation() : {<: Any} NEW: call(innerComputation(), innerComputation) -> +{ innerComputation() } : {<: Any} COPY +log() : {<: Any} NEW: call(log(), log) -> +{ log() } : {<: Any} COPY +42 : Int NEW: r(42) -> +x = 42 !: * +{ x = 42 } !: * COPY +try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } : {<: Any} NEW: merge(try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 }|, ) -> +try { innerComputation() } catch (e: java.lang.Exception) { log() } finally { x = 42 } : {<: Any} COPY +===================== diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchs.instructions b/compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchs.instructions new file mode 100644 index 00000000000..16dfb704506 --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchs.instructions @@ -0,0 +1,211 @@ +== myRun == +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} +--------------------- +L0: + 1 INIT: in: {} out: {} + v(block: () -> T) INIT: in: {} out: {} + magic[FAKE_INITIALIZER](block: () -> T) -> INIT: in: {} out: {} + w(block|) INIT: in: {} out: {} + 2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() }) INIT: in: {} out: {} + mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + jmp?(L2) + d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) +L2 [after local declaration]: + r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> + mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> + r(block) -> + mark(block()) + call(block(), invoke|) -> + ret(*|) L1 +L1: + 1 +error: + +sink: + USE: in: {} out: {} +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- +L3: + 3 INIT: in: {} out: {} + 4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> + r(block) -> + mark(InvocationKind.EXACTLY_ONCE) + r(EXACTLY_ONCE) -> + mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +L4: + 3 +error: + +sink: + USE: in: {} out: {} +===================== +== innerComputation == +fun innerComputation(): Int = 42 +--------------------- +L0: + 1 INIT: in: {} out: {} + r(42) -> + ret(*|) L1 +L1: + +error: + +sink: + USE: in: {} out: {} +===================== +== outerComputation == +fun outerComputation(): Int = 52 +--------------------- +L0: + 1 INIT: in: {} out: {} + r(52) -> + ret(*|) L1 +L1: + +error: + +sink: + USE: in: {} out: {} +===================== +== innerTryCatchInitializes == +fun innerTryCatchInitializes() { + val x: Int + + try { + myRun { + try { + x = innerComputation() + x.inc() + } + catch (e: java.lang.Exception) { + /** Potential reassignment because x.inc() could threw */ + x = 42 + x.inc() + } + } + // Can get here only when inlined lambda exited properly, i.e. x is initialized + x.inc() + outerComputation() + + } catch (e: java.lang.Exception) { + // Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized) + // OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok) + // So, x=I? here + x.inc() + + // Potential reasignment + x = 42 + } + // Here x=I because outer try-catch either exited normally (x=I) or catched exception (x=I, with reassingment, though) + x.inc() +} +--------------------- +L0: + 1 INIT: in: {} out: {} USE: in: {} out: {} + 2 mark({ val x: Int try { myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } } // Can get here only when inlined lambda exited properly, i.e. x is initialized x.inc() outerComputation() } catch (e: java.lang.Exception) { // Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized) // OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok) // So, x=I? here x.inc() // Potential reasignment x = 42 } // Here x=I because outer try-catch either exited normally (x=I) or catched exception (x=I, with reassingment, though) x.inc() }) + v(val x: Int) INIT: in: {} out: {x=D} + mark(try { myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } } // Can get here only when inlined lambda exited properly, i.e. x is initialized x.inc() outerComputation() } catch (e: java.lang.Exception) { // Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized) // OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok) // So, x=I? here x.inc() // Potential reasignment x = 42 }) INIT: in: {x=D} out: {x=D} + jmp?(L2) USE: in: {x=READ} out: {x=READ} + 3 mark({ myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } } // Can get here only when inlined lambda exited properly, i.e. x is initialized x.inc() outerComputation() }) + mark({ try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } }) + r({ try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } }) -> + mark(myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } }) + call(myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } }, myRun|) -> +L3 [before inlined declaration]: + inlined({ try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } }) INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} +L4 [after inlined declaration]: + mark(x.inc()) + r(x) -> + mark(inc()) + call(inc(), inc|) -> + mark(outerComputation()) + call(outerComputation(), outerComputation) -> + 2 jmp?(L2) + jmp(L9) +L2 [onException]: + 3 v(e: java.lang.Exception) INIT: in: {x=I?D} out: {x=I?D} + magic[FAKE_INITIALIZER](e: java.lang.Exception) -> INIT: in: {x=I?D} out: {x=I?D} + w(e|) INIT: in: {x=I?D} out: {x=I?D} + 4 mark({ // Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized) // OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok) // So, x=I? here x.inc() // Potential reasignment x = 42 }) INIT: in: {x=I?D} out: {x=I?D} + mark(x.inc()) USE: in: {x=READ} out: {x=READ} + r(x) -> USE: in: {x=WRITTEN_AFTER_READ} out: {x=READ} + mark(inc()) + call(inc(), inc|) -> + r(42) -> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} + w(x|) INIT: in: {x=I?D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ} + 3 jmp(L9) INIT: in: {x=ID} out: {x=ID} +L9 [afterCatches]: + 2 merge(try { myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } } // Can get here only when inlined lambda exited properly, i.e. x is initialized x.inc() outerComputation() } catch (e: java.lang.Exception) { // Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized) // OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok) // So, x=I? here x.inc() // Potential reasignment x = 42 }|, !) -> + mark(x.inc()) USE: in: {x=READ} out: {x=READ} + r(x) -> USE: in: {} out: {x=READ} + mark(inc()) + call(inc(), inc|) -> +L1: + 1 INIT: in: {} out: {} +error: + +sink: + USE: in: {} out: {} +===================== +== inlined anonymous_1 == +{ + try { + x = innerComputation() + x.inc() + } + catch (e: java.lang.Exception) { + /** Potential reassignment because x.inc() could threw */ + x = 42 + x.inc() + } + } +--------------------- +L5: + 4 INIT: in: {x=D} out: {x=D} + 5 mark(try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() }) + mark(try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() }) + jmp?(L7) + 6 mark({ x = innerComputation() x.inc() }) + mark(innerComputation()) + call(innerComputation(), innerComputation) -> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} + w(x|) INIT: in: {x=D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ} + mark(x.inc()) INIT: in: {x=ID} out: {x=ID} + r(x) -> + mark(inc()) + call(inc(), inc|) -> + 5 jmp?(L7) + jmp(L8) USE: in: {x=READ} out: {x=READ} +L7 [onException]: + 6 v(e: java.lang.Exception) INIT: in: {x=I?D} out: {x=I?D} + magic[FAKE_INITIALIZER](e: java.lang.Exception) -> INIT: in: {x=I?D} out: {x=I?D} + w(e|) INIT: in: {x=I?D} out: {x=I?D} + 7 mark({ /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() }) INIT: in: {x=I?D} out: {x=I?D} + r(42) -> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} + w(x|) INIT: in: {x=I?D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ} + mark(x.inc()) INIT: in: {x=ID} out: {x=ID} + r(x) -> + mark(inc()) + call(inc(), inc|) -> + 6 jmp(L8) +L8 [afterCatches]: + 5 merge(try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() }|, ) -> + 4 ret(*|) L6 +L6: + USE: in: {x=READ} out: {x=READ} +error: +- +sink: + INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ} +===================== diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchs.kt b/compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchs.kt new file mode 100644 index 00000000000..118e52982f1 --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchs.kt @@ -0,0 +1,45 @@ +// LANGUAGE_VERSION: 1.3 + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun innerComputation(): Int = 42 +fun outerComputation(): Int = 52 + +fun innerTryCatchInitializes() { + val x: Int + + try { + myRun { + try { + x = innerComputation() + x.inc() + } + catch (e: java.lang.Exception) { + /** Potential reassignment because x.inc() could threw */ + x = 42 + x.inc() + } + } + // Can get here only when inlined lambda exited properly, i.e. x is initialized + x.inc() + outerComputation() + + } catch (e: java.lang.Exception) { + // Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized) + // OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok) + // So, x=I? here + x.inc() + + // Potential reasignment + x = 42 + } + // Here x=I because outer try-catch either exited normally (x=I) or catched exception (x=I, with reassingment, though) + x.inc() +} \ No newline at end of file diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchs.values b/compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchs.values new file mode 100644 index 00000000000..8dc018f2187 --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchs.values @@ -0,0 +1,118 @@ +== myRun == +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} +--------------------- + : {<: () -> T} NEW: magic[FAKE_INITIALIZER](block: () -> T) -> +{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> +contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> +block : {<: () -> T} NEW: r(block) -> +block() : {<: T} NEW: call(block(), invoke|) -> +return block() !: * +{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() } !: * COPY +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- + : {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> +block : {<: Function} NEW: r(block) -> +EXACTLY_ONCE : {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> +InvocationKind.EXACTLY_ONCE : {<: InvocationKind} COPY +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * COPY +===================== +== innerComputation == +fun innerComputation(): Int = 42 +--------------------- +42 : Int NEW: r(42) -> +===================== +== outerComputation == +fun outerComputation(): Int = 52 +--------------------- +52 : Int NEW: r(52) -> +===================== +== innerTryCatchInitializes == +fun innerTryCatchInitializes() { + val x: Int + + try { + myRun { + try { + x = innerComputation() + x.inc() + } + catch (e: java.lang.Exception) { + /** Potential reassignment because x.inc() could threw */ + x = 42 + x.inc() + } + } + // Can get here only when inlined lambda exited properly, i.e. x is initialized + x.inc() + outerComputation() + + } catch (e: java.lang.Exception) { + // Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized) + // OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok) + // So, x=I? here + x.inc() + + // Potential reasignment + x = 42 + } + // Here x=I because outer try-catch either exited normally (x=I) or catched exception (x=I, with reassingment, though) + x.inc() +} +--------------------- + : {<: Exception} NEW: magic[FAKE_INITIALIZER](e: java.lang.Exception) -> +{ try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } } : {<: () -> Int} NEW: r({ try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } }) -> +myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } } : * NEW: call(myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } }, myRun|) -> +x : Int NEW: r(x) -> +inc() : * NEW: call(inc(), inc|) -> +x.inc() : * COPY +outerComputation() : * NEW: call(outerComputation(), outerComputation) -> +{ myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } } // Can get here only when inlined lambda exited properly, i.e. x is initialized x.inc() outerComputation() } : * COPY +x : Int NEW: r(x) -> +inc() : * NEW: call(inc(), inc|) -> +x.inc() : * COPY +42 : Int NEW: r(42) -> +x = 42 !: * +{ // Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized) // OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok) // So, x=I? here x.inc() // Potential reasignment x = 42 } !: * COPY +try { myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } } // Can get here only when inlined lambda exited properly, i.e. x is initialized x.inc() outerComputation() } catch (e: java.lang.Exception) { // Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized) // OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok) // So, x=I? here x.inc() // Potential reasignment x = 42 } : * NEW: merge(try { myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } } // Can get here only when inlined lambda exited properly, i.e. x is initialized x.inc() outerComputation() } catch (e: java.lang.Exception) { // Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized) // OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok) // So, x=I? here x.inc() // Potential reasignment x = 42 }|, !) -> +x : Int NEW: r(x) -> +inc() : * NEW: call(inc(), inc|) -> +x.inc() : * COPY +{ val x: Int try { myRun { try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } } // Can get here only when inlined lambda exited properly, i.e. x is initialized x.inc() outerComputation() } catch (e: java.lang.Exception) { // Can get here if innerComputation() threw an exception that wasn't catched by the inner catch (x is not initialized) // OR if outerComputation() threw an exception (x is initialized because we reach outer computation only when inner finished ok) // So, x=I? here x.inc() // Potential reasignment x = 42 } // Here x=I because outer try-catch either exited normally (x=I) or catched exception (x=I, with reassingment, though) x.inc() } : * COPY +===================== +== inlined anonymous_1 == +{ + try { + x = innerComputation() + x.inc() + } + catch (e: java.lang.Exception) { + /** Potential reassignment because x.inc() could threw */ + x = 42 + x.inc() + } + } +--------------------- + : {<: Exception} NEW: magic[FAKE_INITIALIZER](e: java.lang.Exception) -> +innerComputation() : Int NEW: call(innerComputation(), innerComputation) -> +x : Int NEW: r(x) -> +inc() : Int NEW: call(inc(), inc|) -> +x.inc() : Int COPY +{ x = innerComputation() x.inc() } : Int COPY +42 : Int NEW: r(42) -> +x : Int NEW: r(x) -> +inc() : Int NEW: call(inc(), inc|) -> +x.inc() : Int COPY +{ /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } : Int COPY +try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } : Int NEW: merge(try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() }|, ) -> +try { x = innerComputation() x.inc() } catch (e: java.lang.Exception) { /** Potential reassignment because x.inc() could threw */ x = 42 x.inc() } : Int COPY +===================== diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/nonReturningInlinedLambda.instructions b/compiler/testData/cfgVariablesWithStdLib/contracts/nonReturningInlinedLambda.instructions new file mode 100644 index 00000000000..9286f3d6c8a --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/nonReturningInlinedLambda.instructions @@ -0,0 +1,148 @@ +== myRun == +inline fun myRun(block: () -> Unit): Unit { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} +--------------------- +L0: + 1 INIT: in: {} out: {} + v(block: () -> Unit) INIT: in: {} out: {} + magic[FAKE_INITIALIZER](block: () -> Unit) -> INIT: in: {} out: {} + w(block|) INIT: in: {} out: {} + 2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() }) INIT: in: {} out: {} + mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + jmp?(L2) + d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) +L2 [after local declaration]: + r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> + mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> + r(block) -> + mark(block()) + call(block(), invoke|) -> + ret(*|) L1 +L1: + 1 +error: + +sink: + USE: in: {} out: {} +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- +L3: + 3 INIT: in: {} out: {} + 4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> + r(block) -> + mark(InvocationKind.EXACTLY_ONCE) + r(EXACTLY_ONCE) -> + mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +L4: + 3 +error: + +sink: + USE: in: {} out: {} +===================== +== getBool == +fun getBool(): Boolean = false +--------------------- +L0: + 1 INIT: in: {} out: {} + r(false) -> + ret(*|) L1 +L1: + +error: + +sink: + USE: in: {} out: {} +===================== +== withLabeledReturn == +fun withLabeledReturn(y: Int) { + val x = myRun outer@ { + myRun { return@outer Unit } + println(y) + } + + println(y) + println(x) +} +--------------------- +L0: + 1 INIT: in: {} out: {} + v(y: Int) INIT: in: {} out: {} + magic[FAKE_INITIALIZER](y: Int) -> INIT: in: {} out: {} + w(y|) INIT: in: {} out: {} + 2 mark({ val x = myRun outer@ { myRun { return@outer Unit } println(y) } println(y) println(x) }) INIT: in: {} out: {} + v(val x = myRun outer@ { myRun { return@outer Unit } println(y) }) INIT: in: {} out: {} + mark(outer@ { myRun { return@outer Unit } println(y) }) INIT: in: {} out: {} + mark({ myRun { return@outer Unit } println(y) }) + r({ myRun { return@outer Unit } println(y) }) -> + mark(myRun outer@ { myRun { return@outer Unit } println(y) }) + call(myRun outer@ { myRun { return@outer Unit } println(y) }, myRun|) -> +L2 [before inlined declaration]: + inlined({ myRun { return@outer Unit } println(y) }) +L3 [after inlined declaration]: + w(x|) INIT: in: {} out: {} + r(y) -> INIT: in: {} out: {} + mark(println(y)) + call(println(y), println|) -> + r(x) -> + mark(println(x)) + call(println(x), println|) -> +L1: + 1 +error: + +sink: + USE: in: {} out: {} +===================== +== inlined anonymous_1 == +{ + myRun { return@outer Unit } + println(y) + } +--------------------- +L4: + 3 INIT: in: {} out: {} + 4 mark(myRun { return@outer Unit } println(y)) + mark({ return@outer Unit }) + r({ return@outer Unit }) -> + mark(myRun { return@outer Unit }) + call(myRun { return@outer Unit }, myRun|) -> +L6 [before inlined declaration]: + inlined({ return@outer Unit }) USE: in: {} out: {} +L7 [after inlined declaration]: +- r(y) -> +- mark(println(y)) +- call(println(y), println|) -> +L5: + 3 INIT: in: {} out: {} USE: in: {} out: {} +error: +- +sink: + INIT: in: {} out: {} USE: in: {} out: {} +===================== +== inlined anonymous_2 == +{ return@outer Unit } +--------------------- +L8: + 5 INIT: in: {} out: {} + 6 mark(return@outer Unit) + r(Unit) -> + ret(*|) L5 USE: in: {} out: {} +L9: +- 5 +error: +- +sink: +- +===================== diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/nonReturningInlinedLambda.kt b/compiler/testData/cfgVariablesWithStdLib/contracts/nonReturningInlinedLambda.kt new file mode 100644 index 00000000000..a75f1ca6fdd --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/nonReturningInlinedLambda.kt @@ -0,0 +1,22 @@ +// LANGUAGE_VERSION: 1.3 + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> Unit): Unit { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun getBool(): Boolean = false + +fun withLabeledReturn(y: Int) { + val x = myRun outer@ { + myRun { return@outer Unit } + println(y) + } + + println(y) + println(x) +} \ No newline at end of file diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/nonReturningInlinedLambda.values b/compiler/testData/cfgVariablesWithStdLib/contracts/nonReturningInlinedLambda.values new file mode 100644 index 00000000000..305f999d806 --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/nonReturningInlinedLambda.values @@ -0,0 +1,73 @@ +== myRun == +inline fun myRun(block: () -> Unit): Unit { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} +--------------------- + : {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> +{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> +contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> +block : {<: () -> Unit} NEW: r(block) -> +block() : Unit NEW: call(block(), invoke|) -> +return block() !: * +{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() } !: * COPY +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- + : {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> +block : {<: Function} NEW: r(block) -> +EXACTLY_ONCE : {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> +InvocationKind.EXACTLY_ONCE : {<: InvocationKind} COPY +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * COPY +===================== +== getBool == +fun getBool(): Boolean = false +--------------------- +false : Boolean NEW: r(false) -> +===================== +== withLabeledReturn == +fun withLabeledReturn(y: Int) { + val x = myRun outer@ { + myRun { return@outer Unit } + println(y) + } + + println(y) + println(x) +} +--------------------- + : Int NEW: magic[FAKE_INITIALIZER](y: Int) -> +{ myRun { return@outer Unit } println(y) } : {<: () -> Unit} NEW: r({ myRun { return@outer Unit } println(y) }) -> +outer@ { myRun { return@outer Unit } println(y) } : {<: () -> Unit} COPY +myRun outer@ { myRun { return@outer Unit } println(y) } : Unit NEW: call(myRun outer@ { myRun { return@outer Unit } println(y) }, myRun|) -> +y : Int NEW: r(y) -> +println(y) : * NEW: call(println(y), println|) -> +x : * NEW: r(x) -> +println(x) : * NEW: call(println(x), println|) -> +{ val x = myRun outer@ { myRun { return@outer Unit } println(y) } println(y) println(x) } : * COPY +===================== +== inlined anonymous_1 == +{ + myRun { return@outer Unit } + println(y) + } +--------------------- +{ return@outer Unit } : {<: () -> Unit} NEW: r({ return@outer Unit }) -> +myRun { return@outer Unit } : * NEW: call(myRun { return@outer Unit }, myRun|) -> +y : Int NEW: r(y) -> +println(y) : * NEW: call(println(y), println|) -> +myRun { return@outer Unit } println(y) : * COPY +===================== +== inlined anonymous_2 == +{ return@outer Unit } +--------------------- +Unit : Unit NEW: r(Unit) -> +return@outer Unit !: * +return@outer Unit !: * COPY +===================== diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/returnsAndCalls.instructions b/compiler/testData/cfgVariablesWithStdLib/contracts/returnsAndCalls.instructions new file mode 100644 index 00000000000..32436d6d65c --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/returnsAndCalls.instructions @@ -0,0 +1,243 @@ +== callsAndInverts == +fun callsAndInverts(b: Boolean, block: () -> Unit): Boolean { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + returns(true) implies (!b) + returns(false) implies b + } + + block() + return !b +} +--------------------- +L0: + 1 INIT: in: {} out: {} + v(b: Boolean) INIT: in: {} out: {} + magic[FAKE_INITIALIZER](b: Boolean) -> INIT: in: {} out: {} + w(b|) INIT: in: {} out: {} + v(block: () -> Unit) INIT: in: {} out: {} + magic[FAKE_INITIALIZER](block: () -> Unit) -> INIT: in: {} out: {} + w(block|) INIT: in: {} out: {} + 2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b } block() return !b }) INIT: in: {} out: {} + mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }) + jmp?(L2) + d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }) +L2 [after local declaration]: + r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }) -> + mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }) + call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }, contract|) -> + r(block) -> + mark(block()) + call(block(), invoke|) -> + r(b) -> + mark(!b) + call(!b, not|) -> + ret(*|) L1 +L1: + 1 +error: + +sink: + USE: in: {} out: {} +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + returns(true) implies (!b) + returns(false) implies b + } +--------------------- +L3: + 3 INIT: in: {} out: {} + 4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b) + magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> + r(block) -> + mark(InvocationKind.EXACTLY_ONCE) + r(EXACTLY_ONCE) -> + mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> + magic[IMPLICIT_RECEIVER](returns(true)) -> + r(true) -> + mark(returns(true)) + call(returns(true), returns|, ) -> + mark((!b)) + r(b) -> + mark(!b) + call(!b, not|) -> + mark(returns(true) implies (!b)) + call(returns(true) implies (!b), implies|, ) -> + magic[IMPLICIT_RECEIVER](returns(false)) -> + r(false) -> + mark(returns(false)) + call(returns(false), returns|, ) -> + r(b) -> + mark(returns(false) implies b) + call(returns(false) implies b, implies|, ) -> +L4: + 3 +error: + +sink: + USE: in: {} out: {} +===================== +== smartcastAndInitialization == +fun smartcastAndInitialization(x: Any?) { + val y: Int + + if (callsAndInverts(x !is String) { y = 42 }) { + println(y) + x.length + } + else { + println(y) + x.length + } + println(y) +} +--------------------- +L0: + 1 INIT: in: {} out: {} + v(x: Any?) INIT: in: {} out: {} + magic[FAKE_INITIALIZER](x: Any?) -> INIT: in: {} out: {} + w(x|) INIT: in: {} out: {} USE: in: {} out: {} + 2 mark({ val y: Int if (callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length } println(y) }) INIT: in: {} out: {} + v(val y: Int) INIT: in: {} out: {y=D} + mark(if (callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length }) INIT: in: {y=D} out: {y=D} + mark(x !is String) + r(x) -> + magic[IS](x !is String|) -> + mark({ y = 42 }) + r({ y = 42 }) -> + mark(callsAndInverts(x !is String) { y = 42 }) + call(callsAndInverts(x !is String) { y = 42 }, callsAndInverts|, ) -> +L2 [before inlined declaration]: + inlined({ y = 42 }) INIT: in: {y=ID} out: {y=ID} USE: in: {y=WRITTEN_AFTER_READ} out: {y=WRITTEN_AFTER_READ} +L3 [after inlined declaration]: + jf(L6|) + 3 mark({ println(y) x.length }) + r(y) -> + mark(println(y)) + call(println(y), println|) -> + magic[UNRESOLVED_CALL](DEBUG_INFO_SMARTCAST) -> + mark(!DEBUG_INFO_SMARTCAST) + call(!DEBUG_INFO_SMARTCAST, |) -> + 2 jmp(L7) +L6 [else branch]: + 3 mark({ println(y) x.length }) + r(y) -> + mark(println(y)) + call(println(y), println|) -> + mark(x.<) + r(x) -> + magic[UNSUPPORTED_ELEMENT](x.<|) -> +L7 ['if' expression result]: + 2 merge(if (callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length }|, ) -> USE: in: {y=READ} out: {y=READ} + r(y) -> USE: in: {} out: {y=READ} + mark(println(y)) + call(println(y), println|) -> +L1: + 1 INIT: in: {} out: {} +error: + +sink: + USE: in: {} out: {} +===================== +== inlined anonymous_1 == +{ y = 42 } +--------------------- +L4: + 3 INIT: in: {y=D} out: {y=D} + 4 mark(y = 42) + r(42) -> USE: in: {y=WRITTEN_AFTER_READ} out: {y=WRITTEN_AFTER_READ} + w(y|) INIT: in: {y=D} out: {y=ID} USE: in: {y=READ} out: {y=WRITTEN_AFTER_READ} +L5: + 3 INIT: in: {y=ID} out: {y=ID} USE: in: {y=READ} out: {y=READ} +error: +- +sink: + INIT: in: {y=ID} out: {y=ID} USE: in: {y=READ} out: {y=READ} +===================== +== inPresenceOfLazy == +fun inPresenceOfLazy(x: Any?, unknownBoolean: Boolean) { + val y: Int + + if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { + println(y) + x.length + } + else { + println(y) + x.length + } + println(y) +} +--------------------- +L0: + 1 INIT: in: {} out: {} + v(x: Any?) INIT: in: {} out: {} + magic[FAKE_INITIALIZER](x: Any?) -> INIT: in: {} out: {} + w(x|) INIT: in: {} out: {} + v(unknownBoolean: Boolean) INIT: in: {} out: {} + magic[FAKE_INITIALIZER](unknownBoolean: Boolean) -> INIT: in: {} out: {} + w(unknownBoolean|) INIT: in: {} out: {} USE: in: {} out: {} + 2 mark({ val y: Int if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length } println(y) }) INIT: in: {} out: {} + v(val y: Int) INIT: in: {} out: {y=D} + mark(if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length }) INIT: in: {y=D} out: {y=D} + r(unknownBoolean) -> + jf(L2|) USE: in: {y=READ} out: {y=READ} + mark(x !is String) + r(x) -> + magic[IS](x !is String|) -> + mark({ y = 42 }) + r({ y = 42 }) -> + mark(callsAndInverts(x !is String) { y = 42 }) + call(callsAndInverts(x !is String) { y = 42 }, callsAndInverts|, ) -> +L3 [before inlined declaration]: + inlined({ y = 42 }) INIT: in: {y=ID} out: {y=ID} USE: in: {y=WRITTEN_AFTER_READ} out: {y=WRITTEN_AFTER_READ} +L2 [result of boolean operation]: +L4 [after inlined declaration]: + magic[AND](unknownBoolean && callsAndInverts(x !is String) { y = 42 }|, ) -> INIT: in: {y=I?D} out: {y=I?D} + jf(L7|) + 3 mark({ println(y) x.length }) + r(y) -> + mark(println(y)) + call(println(y), println|) -> + magic[UNRESOLVED_CALL](DEBUG_INFO_SMARTCAST) -> + mark(!DEBUG_INFO_SMARTCAST) + call(!DEBUG_INFO_SMARTCAST, |) -> + 2 jmp(L8) +L7 [else branch]: + 3 mark({ println(y) x.length }) + r(y) -> + mark(println(y)) + call(println(y), println|) -> + mark(x.<) + r(x) -> + magic[UNSUPPORTED_ELEMENT](x.<|) -> +L8 ['if' expression result]: + 2 merge(if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length }|, ) -> USE: in: {y=READ} out: {y=READ} + r(y) -> USE: in: {} out: {y=READ} + mark(println(y)) + call(println(y), println|) -> +L1: + 1 INIT: in: {} out: {} +error: + +sink: + USE: in: {} out: {} +===================== +== inlined anonymous_2 == +{ y = 42 } +--------------------- +L5: + 3 INIT: in: {y=D} out: {y=D} + 4 mark(y = 42) + r(42) -> USE: in: {y=WRITTEN_AFTER_READ} out: {y=WRITTEN_AFTER_READ} + w(y|) INIT: in: {y=D} out: {y=ID} USE: in: {y=READ} out: {y=WRITTEN_AFTER_READ} +L6: + 3 INIT: in: {y=ID} out: {y=ID} USE: in: {y=READ} out: {y=READ} +error: +- +sink: + INIT: in: {y=ID} out: {y=ID} USE: in: {y=READ} out: {y=READ} +===================== diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/returnsAndCalls.kt b/compiler/testData/cfgVariablesWithStdLib/contracts/returnsAndCalls.kt new file mode 100644 index 00000000000..58be9e1e3d7 --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/returnsAndCalls.kt @@ -0,0 +1,44 @@ +// LANGUAGE_VERSION: 1.3 + +import kotlin.internal.contracts.* + +fun callsAndInverts(b: Boolean, block: () -> Unit): Boolean { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + returns(true) implies (!b) + returns(false) implies b + } + + block() + return !b +} + + + +fun smartcastAndInitialization(x: Any?) { + val y: Int + + if (callsAndInverts(x !is String) { y = 42 }) { + println(y) + x.length + } + else { + println(y) + x.length + } + println(y) +} + +fun inPresenceOfLazy(x: Any?, unknownBoolean: Boolean) { + val y: Int + + if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { + println(y) + x.length + } + else { + println(y) + x.length + } + println(y) +} \ No newline at end of file diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/returnsAndCalls.values b/compiler/testData/cfgVariablesWithStdLib/contracts/returnsAndCalls.values new file mode 100644 index 00000000000..35dcb7d6e1b --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/returnsAndCalls.values @@ -0,0 +1,136 @@ +== callsAndInverts == +fun callsAndInverts(b: Boolean, block: () -> Unit): Boolean { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + returns(true) implies (!b) + returns(false) implies b + } + + block() + return !b +} +--------------------- + : Boolean NEW: magic[FAKE_INITIALIZER](b: Boolean) -> + : {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> +{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b } : {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }) -> +contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b } : * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }, contract|) -> +block : {<: () -> Unit} NEW: r(block) -> +block() : * NEW: call(block(), invoke|) -> +b : Boolean NEW: r(b) -> +!b : Boolean NEW: call(!b, not|) -> +return !b !: * +{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b } block() return !b } !: * COPY +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + returns(true) implies (!b) + returns(false) implies b + } +--------------------- + : {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> + : {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](returns(false)) -> + : {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](returns(true)) -> +block : {<: Function} NEW: r(block) -> +EXACTLY_ONCE : {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> +InvocationKind.EXACTLY_ONCE : {<: InvocationKind} COPY +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +true : * NEW: r(true) -> +returns(true) : {<: SimpleEffect} NEW: call(returns(true), returns|, ) -> +b : Boolean NEW: r(b) -> +!b : Boolean NEW: call(!b, not|) -> +(!b) : Boolean COPY +returns(true) implies (!b) : * NEW: call(returns(true) implies (!b), implies|, ) -> +false : * NEW: r(false) -> +returns(false) : {<: SimpleEffect} NEW: call(returns(false), returns|, ) -> +b : Boolean NEW: r(b) -> +returns(false) implies b : * NEW: call(returns(false) implies b, implies|, ) -> +callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b : * COPY +===================== +== smartcastAndInitialization == +fun smartcastAndInitialization(x: Any?) { + val y: Int + + if (callsAndInverts(x !is String) { y = 42 }) { + println(y) + x.length + } + else { + println(y) + x.length + } + println(y) +} +--------------------- + : * NEW: magic[FAKE_INITIALIZER](x: Any?) -> +x : * NEW: r(x) -> +x !is String : Boolean NEW: magic[IS](x !is String|) -> +{ y = 42 } : {<: () -> Unit} NEW: r({ y = 42 }) -> +callsAndInverts(x !is String) { y = 42 } : Boolean NEW: call(callsAndInverts(x !is String) { y = 42 }, callsAndInverts|, ) -> +y : Int NEW: r(y) -> +println(y) : * NEW: call(println(y), println|) -> +DEBUG_INFO_SMARTCAST : * NEW: magic[UNRESOLVED_CALL](DEBUG_INFO_SMARTCAST) -> +!DEBUG_INFO_SMARTCAST : * NEW: call(!DEBUG_INFO_SMARTCAST, |) -> +{ println(y) x.length } : * COPY +y : Int NEW: r(y) -> +println(y) : * NEW: call(println(y), println|) -> +x : * NEW: r(x) -> +x.< : * NEW: magic[UNSUPPORTED_ELEMENT](x.<|) -> +{ println(y) x.length } : * COPY +if (callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length } : * NEW: merge(if (callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length }|, ) -> +y : Int NEW: r(y) -> +println(y) : * NEW: call(println(y), println|) -> +{ val y: Int if (callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length } println(y) } : * COPY +===================== +== inlined anonymous_1 == +{ y = 42 } +--------------------- +42 : Int NEW: r(42) -> +y = 42 !: * +y = 42 !: * COPY +===================== +== inPresenceOfLazy == +fun inPresenceOfLazy(x: Any?, unknownBoolean: Boolean) { + val y: Int + + if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { + println(y) + x.length + } + else { + println(y) + x.length + } + println(y) +} +--------------------- + : * NEW: magic[FAKE_INITIALIZER](x: Any?) -> + : Boolean NEW: magic[FAKE_INITIALIZER](unknownBoolean: Boolean) -> +unknownBoolean : Boolean NEW: r(unknownBoolean) -> +x : * NEW: r(x) -> +x !is String : Boolean NEW: magic[IS](x !is String|) -> +{ y = 42 } : {<: () -> Unit} NEW: r({ y = 42 }) -> +callsAndInverts(x !is String) { y = 42 } : Boolean NEW: call(callsAndInverts(x !is String) { y = 42 }, callsAndInverts|, ) -> +unknownBoolean && callsAndInverts(x !is String) { y = 42 } : Boolean NEW: magic[AND](unknownBoolean && callsAndInverts(x !is String) { y = 42 }|, ) -> +y : Int NEW: r(y) -> +println(y) : * NEW: call(println(y), println|) -> +DEBUG_INFO_SMARTCAST : * NEW: magic[UNRESOLVED_CALL](DEBUG_INFO_SMARTCAST) -> +!DEBUG_INFO_SMARTCAST : * NEW: call(!DEBUG_INFO_SMARTCAST, |) -> +{ println(y) x.length } : * COPY +y : Int NEW: r(y) -> +println(y) : * NEW: call(println(y), println|) -> +x : * NEW: r(x) -> +x.< : * NEW: magic[UNSUPPORTED_ELEMENT](x.<|) -> +{ println(y) x.length } : * COPY +if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length } : * NEW: merge(if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length }|, ) -> +y : Int NEW: r(y) -> +println(y) : * NEW: call(println(y), println|) -> +{ val y: Int if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length } println(y) } : * COPY +===================== +== inlined anonymous_2 == +{ y = 42 } +--------------------- +42 : Int NEW: r(42) -> +y = 42 !: * +y = 42 !: * COPY +===================== diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/throwIfNotCalled.instructions b/compiler/testData/cfgVariablesWithStdLib/contracts/throwIfNotCalled.instructions new file mode 100644 index 00000000000..79fc5243e55 --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/throwIfNotCalled.instructions @@ -0,0 +1,184 @@ +== myRun == +inline fun myRun(block: () -> Unit) { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + block() +} +--------------------- +L0: + 1 INIT: in: {} out: {} + v(block: () -> Unit) INIT: in: {} out: {} + magic[FAKE_INITIALIZER](block: () -> Unit) -> INIT: in: {} out: {} + w(block|) INIT: in: {} out: {} + 2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block() }) INIT: in: {} out: {} + mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + jmp?(L2) + d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) +L2 [after local declaration]: + r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> + mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> + r(block) -> + mark(block()) + call(block(), invoke|) -> +L1: + 1 +error: + +sink: + USE: in: {} out: {} +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- +L3: + 3 INIT: in: {} out: {} + 4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> + r(block) -> + mark(InvocationKind.EXACTLY_ONCE) + r(EXACTLY_ONCE) -> + mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +L4: + 3 +error: + +sink: + USE: in: {} out: {} +===================== +== unknownRun == +inline fun unknownRun(block: () -> T): T = block() +--------------------- +L0: + 1 INIT: in: {} out: {} + v(block: () -> T) INIT: in: {} out: {} + magic[FAKE_INITIALIZER](block: () -> T) -> INIT: in: {} out: {} + w(block|) INIT: in: {} out: {} + r(block) -> INIT: in: {} out: {} + mark(block()) + call(block(), invoke|) -> + ret(*|) L1 +L1: + +error: + +sink: + USE: in: {} out: {} +===================== +== throwIfNotCalled == +fun throwIfNotCalled() { + val x: Int + myRun outer@ { + unknownRun { + myRun { + x = 42 + return@outer + } + } + throw java.lang.IllegalArgumentException() + } + println(x) +} +--------------------- +L0: + 1 INIT: in: {} out: {} USE: in: {} out: {} + 2 mark({ val x: Int myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() } println(x) }) + v(val x: Int) INIT: in: {} out: {x=D} + mark(outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }) INIT: in: {x=D} out: {x=D} + mark({ unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }) + r({ unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }) -> + mark(myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }) + call(myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }, myRun|) -> +L2 [before inlined declaration]: + inlined({ unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }) INIT: in: {x=ID} out: {x=ID} USE: in: {x=ONLY_WRITTEN_NEVER_READ} out: {x=ONLY_WRITTEN_NEVER_READ} +L3 [after inlined declaration]: + mark(println(<) + magic[UNRESOLVED_CALL](println(<|!) -> +L1: + 1 INIT: in: {} out: {} +error: + +sink: + USE: in: {} out: {} +===================== +== inlined anonymous_1 == +{ + unknownRun { + myRun { + x = 42 + return@outer + } + } + throw java.lang.IllegalArgumentException() + } +--------------------- +L4: + 3 INIT: in: {x=D} out: {x=D} + 4 mark(unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException()) + mark({ myRun { x = 42 return@outer } }) + jmp?(L6) + d({ myRun { x = 42 return@outer } }) INIT: in: {} out: {} USE: in: {x=ONLY_WRITTEN_NEVER_READ} out: {x=ONLY_WRITTEN_NEVER_READ} +L6 [after local declaration]: + r({ myRun { x = 42 return@outer } }) -> INIT: in: {x=D} out: {x=D} + mark(unknownRun { myRun { x = 42 return@outer } }) + call(unknownRun { myRun { x = 42 return@outer } }, unknownRun|) -> + mark(throw java.lang.IllegalArgumentException()) + mark(java.lang.IllegalArgumentException()) + mark(IllegalArgumentException()) + call(IllegalArgumentException(), ) -> + throw (throw java.lang.IllegalArgumentException()|) +L5: + 3 INIT: in: {x=ID} out: {x=ID} +error: + INIT: in: {x=D} out: {x=D} +sink: + INIT: in: {x=I?} out: {x=I?} USE: in: {} out: {} +===================== +== anonymous_2 == +{ + myRun { + x = 42 + return@outer + } + } +--------------------- +L7: + 5 INIT: in: {x=D} out: {x=D} + 6 mark(myRun { x = 42 return@outer }) + mark({ x = 42 return@outer }) + r({ x = 42 return@outer }) -> + mark(myRun { x = 42 return@outer }) + call(myRun { x = 42 return@outer }, myRun|) -> +L9 [before inlined declaration]: + inlined({ x = 42 return@outer }) USE: in: {x=ONLY_WRITTEN_NEVER_READ} out: {x=ONLY_WRITTEN_NEVER_READ} +L8: +L10 [after inlined declaration]: + 5 INIT: in: {} out: {} +error: + +sink: + USE: in: {} out: {} +===================== +== inlined anonymous_3 == +{ + x = 42 + return@outer + } +--------------------- +L11: + 7 INIT: in: {x=D} out: {x=D} + 8 mark(x = 42 return@outer) + r(42) -> USE: in: {x=ONLY_WRITTEN_NEVER_READ} out: {x=ONLY_WRITTEN_NEVER_READ} + w(x|) INIT: in: {x=D} out: {x=ID} USE: in: {} out: {x=ONLY_WRITTEN_NEVER_READ} + ret L5 INIT: in: {x=ID} out: {x=ID} USE: in: {} out: {} +L12: +- 7 +error: +- +sink: +- +===================== diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/throwIfNotCalled.kt b/compiler/testData/cfgVariablesWithStdLib/contracts/throwIfNotCalled.kt new file mode 100644 index 00000000000..8b99500a805 --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/throwIfNotCalled.kt @@ -0,0 +1,26 @@ +// LANGUAGE_VERSION: 1.3 + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> Unit) { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + block() +} + +inline fun unknownRun(block: () -> T): T = block() + +fun throwIfNotCalled() { + val x: Int + myRun outer@ { + unknownRun { + myRun { + x = 42 + return@outer + } + } + throw java.lang.IllegalArgumentException() + } + println(x) +} \ No newline at end of file diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/throwIfNotCalled.values b/compiler/testData/cfgVariablesWithStdLib/contracts/throwIfNotCalled.values new file mode 100644 index 00000000000..66d7025dfd6 --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/throwIfNotCalled.values @@ -0,0 +1,96 @@ +== myRun == +inline fun myRun(block: () -> Unit) { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + block() +} +--------------------- + : {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> +{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> +contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> +block : {<: () -> Unit} NEW: r(block) -> +block() : * NEW: call(block(), invoke|) -> +{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block() } : * COPY +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- + : {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> +block : {<: Function} NEW: r(block) -> +EXACTLY_ONCE : {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> +InvocationKind.EXACTLY_ONCE : {<: InvocationKind} COPY +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * COPY +===================== +== unknownRun == +inline fun unknownRun(block: () -> T): T = block() +--------------------- + : {<: () -> T} NEW: magic[FAKE_INITIALIZER](block: () -> T) -> +block : {<: () -> T} NEW: r(block) -> +block() : {<: T} NEW: call(block(), invoke|) -> +===================== +== throwIfNotCalled == +fun throwIfNotCalled() { + val x: Int + myRun outer@ { + unknownRun { + myRun { + x = 42 + return@outer + } + } + throw java.lang.IllegalArgumentException() + } + println(x) +} +--------------------- +{ unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() } : {<: () -> Unit} NEW: r({ unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }) -> +outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() } : {<: () -> Unit} COPY +myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() } : * NEW: call(myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }, myRun|) -> +println !: * +println(< : * NEW: magic[UNRESOLVED_CALL](println(<|!) -> +{ val x: Int myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() } println(x) } : * COPY +===================== +== inlined anonymous_1 == +{ + unknownRun { + myRun { + x = 42 + return@outer + } + } + throw java.lang.IllegalArgumentException() + } +--------------------- +{ myRun { x = 42 return@outer } } : {<: () -> Unit} NEW: r({ myRun { x = 42 return@outer } }) -> +unknownRun { myRun { x = 42 return@outer } } : * NEW: call(unknownRun { myRun { x = 42 return@outer } }, unknownRun|) -> +IllegalArgumentException() : {<: Throwable} NEW: call(IllegalArgumentException(), ) -> +java.lang.IllegalArgumentException() : {<: Throwable} COPY +throw java.lang.IllegalArgumentException() !: * +unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() !: * COPY +===================== +== anonymous_2 == +{ + myRun { + x = 42 + return@outer + } + } +--------------------- +{ x = 42 return@outer } : {<: () -> Unit} NEW: r({ x = 42 return@outer }) -> +myRun { x = 42 return@outer } : * NEW: call(myRun { x = 42 return@outer }, myRun|) -> +myRun { x = 42 return@outer } : * COPY +===================== +== inlined anonymous_3 == +{ + x = 42 + return@outer + } +--------------------- +42 : Int NEW: r(42) -> +return@outer !: * +x = 42 return@outer !: * COPY +===================== diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/tryCatch.instructions b/compiler/testData/cfgVariablesWithStdLib/contracts/tryCatch.instructions new file mode 100644 index 00000000000..bbe95bebc24 --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/tryCatch.instructions @@ -0,0 +1,366 @@ +== myRun == +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} +--------------------- +L0: + 1 INIT: in: {} out: {} + v(block: () -> T) INIT: in: {} out: {} + magic[FAKE_INITIALIZER](block: () -> T) -> INIT: in: {} out: {} + w(block|) INIT: in: {} out: {} + 2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() }) INIT: in: {} out: {} + mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + jmp?(L2) + d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) +L2 [after local declaration]: + r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> + mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> + r(block) -> + mark(block()) + call(block(), invoke|) -> + ret(*|) L1 +L1: + 1 +error: + +sink: + USE: in: {} out: {} +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- +L3: + 3 INIT: in: {} out: {} + 4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> + r(block) -> + mark(InvocationKind.EXACTLY_ONCE) + r(EXACTLY_ONCE) -> + mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +L4: + 3 +error: + +sink: + USE: in: {} out: {} +===================== +== someComputation == +fun someComputation(): Int = 42 +--------------------- +L0: + 1 INIT: in: {} out: {} + r(42) -> + ret(*|) L1 +L1: + +error: + +sink: + USE: in: {} out: {} +===================== +== tryCatchInlined == +fun tryCatchInlined() { + val x: Int + + myRun { + try { + x = someComputation() + x.inc() + } + catch (e: java.lang.Exception) { + // I? + x.inc() + } + } + + // I? + x.inc() +} +--------------------- +L0: + 1 INIT: in: {} out: {} USE: in: {} out: {} + 2 mark({ val x: Int myRun { try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } } // I? x.inc() }) + v(val x: Int) INIT: in: {} out: {x=D} + mark({ try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } }) INIT: in: {x=D} out: {x=D} + r({ try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } }) -> + mark(myRun { try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } }) + call(myRun { try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } }, myRun|) -> +L2 [before inlined declaration]: + inlined({ try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } }) INIT: in: {x=I?D} out: {x=I?D} +L3 [after inlined declaration]: + mark(x.inc()) USE: in: {x=READ} out: {x=READ} + r(x) -> USE: in: {} out: {x=READ} + mark(inc()) + call(inc(), inc|) -> +L1: + 1 INIT: in: {} out: {} +error: + +sink: + USE: in: {} out: {} +===================== +== inlined anonymous_1 == +{ + try { + x = someComputation() + x.inc() + } + catch (e: java.lang.Exception) { + // I? + x.inc() + } + } +--------------------- +L4: + 3 INIT: in: {x=D} out: {x=D} + 4 mark(try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() }) + mark(try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() }) + jmp?(L6) USE: in: {x=READ} out: {x=READ} + 5 mark({ x = someComputation() x.inc() }) + mark(someComputation()) + call(someComputation(), someComputation) -> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} + w(x|) INIT: in: {x=D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ} + mark(x.inc()) INIT: in: {x=ID} out: {x=ID} + r(x) -> + mark(inc()) + call(inc(), inc|) -> + 4 jmp?(L6) + jmp(L7) +L6 [onException]: + 5 v(e: java.lang.Exception) INIT: in: {x=I?D} out: {x=I?D} + magic[FAKE_INITIALIZER](e: java.lang.Exception) -> INIT: in: {x=I?D} out: {x=I?D} + w(e|) INIT: in: {x=I?D} out: {x=I?D} + 6 mark({ // I? x.inc() }) INIT: in: {x=I?D} out: {x=I?D} + mark(x.inc()) + r(x) -> + mark(inc()) + call(inc(), inc|) -> + 5 jmp(L7) +L7 [afterCatches]: + 4 merge(try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() }|, ) -> + 3 ret(*|) L5 +L5: + USE: in: {x=READ} out: {x=READ} +error: +- +sink: + INIT: in: {x=I?D} out: {x=I?D} USE: in: {x=READ} out: {x=READ} +===================== +== possibleReassignmentInTryCatch == +fun possibleReassignmentInTryCatch() { + val x: Int + + myRun { + x = 42 + try { + x = someComputation() + x.inc() + } + catch (e: java.lang.Exception) { + // Possible reassignment + x = 42 + x.inc() + } + // Initialized + x.inc() + } + // Initialized + x.inc() +} +--------------------- +L0: + 1 INIT: in: {} out: {} USE: in: {} out: {} + 2 mark({ val x: Int myRun { x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() } // Initialized x.inc() }) + v(val x: Int) INIT: in: {} out: {x=D} + mark({ x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() }) INIT: in: {x=D} out: {x=D} + r({ x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() }) -> + mark(myRun { x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() }) + call(myRun { x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() }, myRun|) -> +L2 [before inlined declaration]: + inlined({ x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() }) INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} +L3 [after inlined declaration]: + mark(x.inc()) USE: in: {x=READ} out: {x=READ} + r(x) -> USE: in: {} out: {x=READ} + mark(inc()) + call(inc(), inc|) -> +L1: + 1 INIT: in: {} out: {} +error: + +sink: + USE: in: {} out: {} +===================== +== inlined anonymous_2 == +{ + x = 42 + try { + x = someComputation() + x.inc() + } + catch (e: java.lang.Exception) { + // Possible reassignment + x = 42 + x.inc() + } + // Initialized + x.inc() + } +--------------------- +L4: + 3 INIT: in: {x=D} out: {x=D} + 4 mark(x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc()) + r(42) -> + w(x|) INIT: in: {x=D} out: {x=ID} + mark(try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() }) INIT: in: {x=ID} out: {x=ID} + jmp?(L6) + 5 mark({ x = someComputation() x.inc() }) + mark(someComputation()) + call(someComputation(), someComputation) -> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} + w(x|) USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ} + mark(x.inc()) + r(x) -> + mark(inc()) + call(inc(), inc|) -> + 4 jmp?(L6) + jmp(L7) USE: in: {x=READ} out: {x=READ} +L6 [onException]: + 5 v(e: java.lang.Exception) INIT: in: {x=ID} out: {x=ID} + magic[FAKE_INITIALIZER](e: java.lang.Exception) -> INIT: in: {x=ID} out: {x=ID} + w(e|) INIT: in: {x=ID} out: {x=ID} + 6 mark({ // Possible reassignment x = 42 x.inc() }) INIT: in: {x=ID} out: {x=ID} + r(42) -> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} + w(x|) USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ} + mark(x.inc()) + r(x) -> + mark(inc()) + call(inc(), inc|) -> + 5 jmp(L7) +L7 [afterCatches]: + 4 merge(try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() }|, ) -> + mark(x.inc()) + r(x) -> + mark(inc()) + call(inc(), inc|) -> + 3 ret(*|) L5 +L5: + USE: in: {x=READ} out: {x=READ} +error: +- +sink: + INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ} +===================== +== tryCatchOuter == +fun tryCatchOuter() { + var x: Int + try { + myRun { + x = someComputation() + x.inc() + } + } + catch (e: java.lang.UnsupportedOperationException) { + myRun { x = 42 } + } + catch (e: java.lang.Exception) { + // do nothing + } + // I? because we can leave with last catch-clause which doesn't initialize x + x.inc() +} +--------------------- +L0: + 1 INIT: in: {} out: {} USE: in: {} out: {} + 2 mark({ var x: Int try { myRun { x = someComputation() x.inc() } } catch (e: java.lang.UnsupportedOperationException) { myRun { x = 42 } } catch (e: java.lang.Exception) { // do nothing } // I? because we can leave with last catch-clause which doesn't initialize x x.inc() }) + v(var x: Int) INIT: in: {} out: {x=D} + mark(try { myRun { x = someComputation() x.inc() } } catch (e: java.lang.UnsupportedOperationException) { myRun { x = 42 } } catch (e: java.lang.Exception) { // do nothing }) INIT: in: {x=D} out: {x=D} + jmp?(L2) USE: in: {x=READ} out: {x=READ} + 3 mark({ myRun { x = someComputation() x.inc() } }) + mark({ x = someComputation() x.inc() }) + r({ x = someComputation() x.inc() }) -> + mark(myRun { x = someComputation() x.inc() }) + call(myRun { x = someComputation() x.inc() }, myRun|) -> +L3 [before inlined declaration]: + inlined({ x = someComputation() x.inc() }) INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} +L4 [after inlined declaration]: + 2 jmp?(L2) + jmp(L7) +L2 [onException]: + jmp?(L8) INIT: in: {x=I?D} out: {x=I?D} USE: in: {x=READ} out: {x=READ} + 3 v(e: java.lang.UnsupportedOperationException) INIT: in: {x=I?D} out: {x=I?D} + magic[FAKE_INITIALIZER](e: java.lang.UnsupportedOperationException) -> INIT: in: {x=I?D} out: {x=I?D} + w(e|) INIT: in: {x=I?D} out: {x=I?D} + 4 mark({ myRun { x = 42 } }) INIT: in: {x=I?D} out: {x=I?D} + mark({ x = 42 }) + r({ x = 42 }) -> + mark(myRun { x = 42 }) + call(myRun { x = 42 }, myRun|) -> +L9 [before inlined declaration]: + inlined({ x = 42 }) INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} +L10 [after inlined declaration]: + 3 jmp(L7) +L8 [catch 0]: + v(e: java.lang.Exception) INIT: in: {x=I?D} out: {x=I?D} + magic[FAKE_INITIALIZER](e: java.lang.Exception) -> INIT: in: {x=I?D} out: {x=I?D} + w(e|) INIT: in: {x=I?D} out: {x=I?D} + 4 mark({ // do nothing }) INIT: in: {x=I?D} out: {x=I?D} + read (Unit) + 3 jmp(L7) +L7 [afterCatches]: + 2 merge(try { myRun { x = someComputation() x.inc() } } catch (e: java.lang.UnsupportedOperationException) { myRun { x = 42 } } catch (e: java.lang.Exception) { // do nothing }|, , !) -> + mark(x.inc()) USE: in: {x=READ} out: {x=READ} + r(x) -> USE: in: {} out: {x=READ} + mark(inc()) + call(inc(), inc|) -> +L1: + 1 INIT: in: {} out: {} +error: + +sink: + USE: in: {} out: {} +===================== +== inlined anonymous_3 == +{ + x = someComputation() + x.inc() + } +--------------------- +L5: + 4 INIT: in: {x=D} out: {x=D} + 5 mark(x = someComputation() x.inc()) + mark(someComputation()) + call(someComputation(), someComputation) -> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} + w(x|) INIT: in: {x=D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ} + mark(x.inc()) INIT: in: {x=ID} out: {x=ID} + r(x) -> + mark(inc()) + call(inc(), inc|) -> + 4 ret(*|) L6 +L6: + USE: in: {x=READ} out: {x=READ} +error: +- +sink: + INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ} +===================== +== inlined anonymous_4 == +{ x = 42 } +--------------------- +L11: + 5 INIT: in: {x=I?D} out: {x=I?D} + 6 mark(x = 42) + r(42) -> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} + w(x|) INIT: in: {x=I?D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ} +L12: + 5 INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ} +error: +- +sink: + INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ} +===================== diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/tryCatch.kt b/compiler/testData/cfgVariablesWithStdLib/contracts/tryCatch.kt new file mode 100644 index 00000000000..26981ef7131 --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/tryCatch.kt @@ -0,0 +1,71 @@ +// LANGUAGE_VERSION: 1.3 + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun someComputation(): Int = 42 + +fun tryCatchInlined() { + val x: Int + + myRun { + try { + x = someComputation() + x.inc() + } + catch (e: java.lang.Exception) { + // I? + x.inc() + } + } + + // I? + x.inc() +} + +fun possibleReassignmentInTryCatch() { + val x: Int + + myRun { + x = 42 + try { + x = someComputation() + x.inc() + } + catch (e: java.lang.Exception) { + // Possible reassignment + x = 42 + x.inc() + } + // Initialized + x.inc() + } + // Initialized + x.inc() +} + + + +fun tryCatchOuter() { + var x: Int + try { + myRun { + x = someComputation() + x.inc() + } + } + catch (e: java.lang.UnsupportedOperationException) { + myRun { x = 42 } + } + catch (e: java.lang.Exception) { + // do nothing + } + // I? because we can leave with last catch-clause which doesn't initialize x + x.inc() +} diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/tryCatch.values b/compiler/testData/cfgVariablesWithStdLib/contracts/tryCatch.values new file mode 100644 index 00000000000..3141d082df0 --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/tryCatch.values @@ -0,0 +1,200 @@ +== myRun == +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} +--------------------- + : {<: () -> T} NEW: magic[FAKE_INITIALIZER](block: () -> T) -> +{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> +contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> +block : {<: () -> T} NEW: r(block) -> +block() : {<: T} NEW: call(block(), invoke|) -> +return block() !: * +{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() } !: * COPY +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- + : {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> +block : {<: Function} NEW: r(block) -> +EXACTLY_ONCE : {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> +InvocationKind.EXACTLY_ONCE : {<: InvocationKind} COPY +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * COPY +===================== +== someComputation == +fun someComputation(): Int = 42 +--------------------- +42 : Int NEW: r(42) -> +===================== +== tryCatchInlined == +fun tryCatchInlined() { + val x: Int + + myRun { + try { + x = someComputation() + x.inc() + } + catch (e: java.lang.Exception) { + // I? + x.inc() + } + } + + // I? + x.inc() +} +--------------------- +{ try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } } : {<: () -> Int} NEW: r({ try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } }) -> +myRun { try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } } : * NEW: call(myRun { try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } }, myRun|) -> +x : Int NEW: r(x) -> +inc() : * NEW: call(inc(), inc|) -> +x.inc() : * COPY +{ val x: Int myRun { try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } } // I? x.inc() } : * COPY +===================== +== inlined anonymous_1 == +{ + try { + x = someComputation() + x.inc() + } + catch (e: java.lang.Exception) { + // I? + x.inc() + } + } +--------------------- + : {<: Exception} NEW: magic[FAKE_INITIALIZER](e: java.lang.Exception) -> +someComputation() : Int NEW: call(someComputation(), someComputation) -> +x : Int NEW: r(x) -> +inc() : Int NEW: call(inc(), inc|) -> +x.inc() : Int COPY +{ x = someComputation() x.inc() } : Int COPY +x : Int NEW: r(x) -> +inc() : Int NEW: call(inc(), inc|) -> +x.inc() : Int COPY +{ // I? x.inc() } : Int COPY +try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } : Int NEW: merge(try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() }|, ) -> +try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // I? x.inc() } : Int COPY +===================== +== possibleReassignmentInTryCatch == +fun possibleReassignmentInTryCatch() { + val x: Int + + myRun { + x = 42 + try { + x = someComputation() + x.inc() + } + catch (e: java.lang.Exception) { + // Possible reassignment + x = 42 + x.inc() + } + // Initialized + x.inc() + } + // Initialized + x.inc() +} +--------------------- +{ x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() } : {<: () -> Int} NEW: r({ x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() }) -> +myRun { x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() } : * NEW: call(myRun { x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() }, myRun|) -> +x : Int NEW: r(x) -> +inc() : * NEW: call(inc(), inc|) -> +x.inc() : * COPY +{ val x: Int myRun { x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() } // Initialized x.inc() } : * COPY +===================== +== inlined anonymous_2 == +{ + x = 42 + try { + x = someComputation() + x.inc() + } + catch (e: java.lang.Exception) { + // Possible reassignment + x = 42 + x.inc() + } + // Initialized + x.inc() + } +--------------------- + : {<: Exception} NEW: magic[FAKE_INITIALIZER](e: java.lang.Exception) -> +42 : Int NEW: r(42) -> +someComputation() : Int NEW: call(someComputation(), someComputation) -> +x : Int NEW: r(x) -> +inc() : * NEW: call(inc(), inc|) -> +x.inc() : * COPY +{ x = someComputation() x.inc() } : * COPY +42 : Int NEW: r(42) -> +x : Int NEW: r(x) -> +inc() : * NEW: call(inc(), inc|) -> +x.inc() : * COPY +{ // Possible reassignment x = 42 x.inc() } : * COPY +try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } : * NEW: merge(try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() }|, ) -> +x : Int NEW: r(x) -> +inc() : Int NEW: call(inc(), inc|) -> +x.inc() : Int COPY +x = 42 try { x = someComputation() x.inc() } catch (e: java.lang.Exception) { // Possible reassignment x = 42 x.inc() } // Initialized x.inc() : Int COPY +===================== +== tryCatchOuter == +fun tryCatchOuter() { + var x: Int + try { + myRun { + x = someComputation() + x.inc() + } + } + catch (e: java.lang.UnsupportedOperationException) { + myRun { x = 42 } + } + catch (e: java.lang.Exception) { + // do nothing + } + // I? because we can leave with last catch-clause which doesn't initialize x + x.inc() +} +--------------------- + : {<: UnsupportedOperationException} NEW: magic[FAKE_INITIALIZER](e: java.lang.UnsupportedOperationException) -> + : {<: Exception} NEW: magic[FAKE_INITIALIZER](e: java.lang.Exception) -> +{ x = someComputation() x.inc() } : {<: () -> Int} NEW: r({ x = someComputation() x.inc() }) -> +myRun { x = someComputation() x.inc() } : * NEW: call(myRun { x = someComputation() x.inc() }, myRun|) -> +{ myRun { x = someComputation() x.inc() } } : * COPY +{ x = 42 } : {<: () -> Unit} NEW: r({ x = 42 }) -> +myRun { x = 42 } : * NEW: call(myRun { x = 42 }, myRun|) -> +{ myRun { x = 42 } } : * COPY +{ // do nothing } !: * +try { myRun { x = someComputation() x.inc() } } catch (e: java.lang.UnsupportedOperationException) { myRun { x = 42 } } catch (e: java.lang.Exception) { // do nothing } : * NEW: merge(try { myRun { x = someComputation() x.inc() } } catch (e: java.lang.UnsupportedOperationException) { myRun { x = 42 } } catch (e: java.lang.Exception) { // do nothing }|, , !) -> +x : Int NEW: r(x) -> +inc() : * NEW: call(inc(), inc|) -> +x.inc() : * COPY +{ var x: Int try { myRun { x = someComputation() x.inc() } } catch (e: java.lang.UnsupportedOperationException) { myRun { x = 42 } } catch (e: java.lang.Exception) { // do nothing } // I? because we can leave with last catch-clause which doesn't initialize x x.inc() } : * COPY +===================== +== inlined anonymous_3 == +{ + x = someComputation() + x.inc() + } +--------------------- +someComputation() : Int NEW: call(someComputation(), someComputation) -> +x : Int NEW: r(x) -> +inc() : Int NEW: call(inc(), inc|) -> +x.inc() : Int COPY +x = someComputation() x.inc() : Int COPY +===================== +== inlined anonymous_4 == +{ x = 42 } +--------------------- +42 : Int NEW: r(42) -> +x = 42 !: * +x = 42 !: * COPY +===================== diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/tryCatchFinally.instructions b/compiler/testData/cfgVariablesWithStdLib/contracts/tryCatchFinally.instructions new file mode 100644 index 00000000000..14d5be0ad69 --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/tryCatchFinally.instructions @@ -0,0 +1,187 @@ +== myRun == +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} +--------------------- +L0: + 1 INIT: in: {} out: {} + v(block: () -> T) INIT: in: {} out: {} + magic[FAKE_INITIALIZER](block: () -> T) -> INIT: in: {} out: {} + w(block|) INIT: in: {} out: {} + 2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() }) INIT: in: {} out: {} + mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + jmp?(L2) + d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) +L2 [after local declaration]: + r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> + mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> + r(block) -> + mark(block()) + call(block(), invoke|) -> + ret(*|) L1 +L1: + 1 +error: + +sink: + USE: in: {} out: {} +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- +L3: + 3 INIT: in: {} out: {} + 4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> + r(block) -> + mark(InvocationKind.EXACTLY_ONCE) + r(EXACTLY_ONCE) -> + mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +L4: + 3 +error: + +sink: + USE: in: {} out: {} +===================== +== someComputation == +fun someComputation(): Int = 42 +--------------------- +L0: + 1 INIT: in: {} out: {} + r(42) -> + ret(*|) L1 +L1: + +error: + +sink: + USE: in: {} out: {} +===================== +== report == +fun report(x: Int) = Unit +--------------------- +L0: + 1 INIT: in: {} out: {} + v(x: Int) INIT: in: {} out: {} + magic[FAKE_INITIALIZER](x: Int) -> INIT: in: {} out: {} + w(x|) INIT: in: {} out: {} + r(Unit) -> INIT: in: {} out: {} + ret(*|) L1 +L1: + +error: + +sink: + USE: in: {} out: {} +===================== +== innerTryCatchFinally == +fun innerTryCatchFinally() { + val x: Int + + myRun { + try { + x = someComputation() + report(x) + } catch (e: java.lang.Exception) { + x = 42 + report(x) + } finally { + x = 0 + } + } + + x.inc() +} +--------------------- +L0: + 1 INIT: in: {} out: {} USE: in: {} out: {} + 2 mark({ val x: Int myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } } x.inc() }) + v(val x: Int) INIT: in: {} out: {x=D} + mark({ try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }) INIT: in: {x=D} out: {x=D} + r({ try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }) -> + mark(myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }) + call(myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }, myRun|) -> +L2 [before inlined declaration]: + inlined({ try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }) INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} +L3 [after inlined declaration]: + mark(x.inc()) USE: in: {x=READ} out: {x=READ} + r(x) -> USE: in: {} out: {x=READ} + mark(inc()) + call(inc(), inc|) -> +L1: + 1 INIT: in: {} out: {} +error: + +sink: + USE: in: {} out: {} +===================== +== inlined anonymous_1 == +{ + try { + x = someComputation() + report(x) + } catch (e: java.lang.Exception) { + x = 42 + report(x) + } finally { + x = 0 + } + } +--------------------- +L4: + 3 INIT: in: {x=D} out: {x=D} + 4 mark(try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 }) + mark(try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 }) + jmp?(L6) + jmp?(L7) + 5 mark({ x = someComputation() report(x) }) + mark(someComputation()) + call(someComputation(), someComputation) -> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} + w(x|) INIT: in: {x=D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ} + r(x) -> INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=READ} + mark(report(x)) + call(report(x), report|) -> + 4 jmp?(L6) + jmp?(L7) + jmp(L8) +L6 [onException]: + 5 v(e: java.lang.Exception) INIT: in: {x=I?D} out: {x=I?D} + magic[FAKE_INITIALIZER](e: java.lang.Exception) -> INIT: in: {x=I?D} out: {x=I?D} + w(e|) INIT: in: {x=I?D} out: {x=I?D} + 6 mark({ x = 42 report(x) }) INIT: in: {x=I?D} out: {x=I?D} + r(42) -> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} + w(x|) INIT: in: {x=I?D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ} + r(x) -> INIT: in: {x=ID} out: {x=ID} USE: in: {x=WRITTEN_AFTER_READ} out: {x=READ} + mark(report(x)) + call(report(x), report|) -> + 5 jmp(L8) +L8 [afterCatches]: + 4 jmp(L9) +L7 [onExceptionToFinallyBlock]: +L10 [start finally]: + 5 mark({ x = 0 }) INIT: in: {x=I?D} out: {x=I?D} + r(0) -> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} + w(x|) INIT: in: {x=I?D} out: {x=ID} USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ} +L11 [finish finally]: + 4 jmp(error) INIT: in: {x=ID} out: {x=ID} USE: in: {x=READ} out: {x=READ} +L9 [skipFinallyToErrorBlock]: +L12 [copy of L7, onExceptionToFinallyBlock]: + 5 mark({ x = 0 }) + r(0) -> USE: in: {x=WRITTEN_AFTER_READ} out: {x=WRITTEN_AFTER_READ} + w(x|) USE: in: {x=READ} out: {x=WRITTEN_AFTER_READ} + 4 merge(try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 }|, ) -> +L5: + 3 +error: + +sink: + USE: in: {x=READ} out: {x=READ} +===================== diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/tryCatchFinally.kt b/compiler/testData/cfgVariablesWithStdLib/contracts/tryCatchFinally.kt new file mode 100644 index 00000000000..447fbb14629 --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/tryCatchFinally.kt @@ -0,0 +1,32 @@ +// LANGUAGE_VERSION: 1.3 + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun someComputation(): Int = 42 + +fun report(x: Int) = Unit + +fun innerTryCatchFinally() { + val x: Int + + myRun { + try { + x = someComputation() + report(x) + } catch (e: java.lang.Exception) { + x = 42 + report(x) + } finally { + x = 0 + } + } + + x.inc() +} \ No newline at end of file diff --git a/compiler/testData/cfgVariablesWithStdLib/contracts/tryCatchFinally.values b/compiler/testData/cfgVariablesWithStdLib/contracts/tryCatchFinally.values new file mode 100644 index 00000000000..004544eb4a8 --- /dev/null +++ b/compiler/testData/cfgVariablesWithStdLib/contracts/tryCatchFinally.values @@ -0,0 +1,93 @@ +== myRun == +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} +--------------------- + : {<: () -> T} NEW: magic[FAKE_INITIALIZER](block: () -> T) -> +{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> +contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> +block : {<: () -> T} NEW: r(block) -> +block() : {<: T} NEW: call(block(), invoke|) -> +return block() !: * +{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() } !: * COPY +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- + : {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> +block : {<: Function} NEW: r(block) -> +EXACTLY_ONCE : {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> +InvocationKind.EXACTLY_ONCE : {<: InvocationKind} COPY +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * COPY +===================== +== someComputation == +fun someComputation(): Int = 42 +--------------------- +42 : Int NEW: r(42) -> +===================== +== report == +fun report(x: Int) = Unit +--------------------- + : Int NEW: magic[FAKE_INITIALIZER](x: Int) -> +Unit : Unit NEW: r(Unit) -> +===================== +== innerTryCatchFinally == +fun innerTryCatchFinally() { + val x: Int + + myRun { + try { + x = someComputation() + report(x) + } catch (e: java.lang.Exception) { + x = 42 + report(x) + } finally { + x = 0 + } + } + + x.inc() +} +--------------------- +{ try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } } : {<: () -> Unit} NEW: r({ try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }) -> +myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } } : * NEW: call(myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }, myRun|) -> +x : Int NEW: r(x) -> +inc() : * NEW: call(inc(), inc|) -> +x.inc() : * COPY +{ val x: Int myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } } x.inc() } : * COPY +===================== +== inlined anonymous_1 == +{ + try { + x = someComputation() + report(x) + } catch (e: java.lang.Exception) { + x = 42 + report(x) + } finally { + x = 0 + } + } +--------------------- + : {<: Exception} NEW: magic[FAKE_INITIALIZER](e: java.lang.Exception) -> +someComputation() : Int NEW: call(someComputation(), someComputation) -> +x : Int NEW: r(x) -> +report(x) : * NEW: call(report(x), report|) -> +{ x = someComputation() report(x) } : * COPY +42 : Int NEW: r(42) -> +x : Int NEW: r(x) -> +report(x) : * NEW: call(report(x), report|) -> +{ x = 42 report(x) } : * COPY +0 : Int NEW: r(0) -> +x = 0 !: * +{ x = 0 } !: * COPY +try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } : * NEW: merge(try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 }|, ) -> +try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } : * COPY +===================== diff --git a/compiler/testData/cfgWithStdLib/contracts/labeledReturns.instructions b/compiler/testData/cfgWithStdLib/contracts/labeledReturns.instructions new file mode 100644 index 00000000000..ae285d4db56 --- /dev/null +++ b/compiler/testData/cfgWithStdLib/contracts/labeledReturns.instructions @@ -0,0 +1,298 @@ +== myLet == +inline fun T.myLet(block: (T) -> R): R { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block(this) +} +--------------------- +L0: + 1 + v(block: (T) -> R) + magic[FAKE_INITIALIZER](block: (T) -> R) -> + w(block|) + 2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block(this) }) + mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + jmp?(L2) NEXT:[r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> , d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })] + d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) NEXT:[] +L2 [after local declaration]: + r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> PREV:[jmp?(L2)] + mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> + r(block) -> + r(this, ) -> + mark(block(this)) + call(block(this), invoke|, ) -> + ret(*|) L1 +L1: + 1 NEXT:[] +error: + PREV:[] +sink: + PREV:[, , d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })] +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- +L3: + 3 + 4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> + r(block) -> + mark(InvocationKind.EXACTLY_ONCE) + r(EXACTLY_ONCE) -> + mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +L4: + 3 NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== myRun == +inline fun myRun(block: () -> Unit) { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + block() +} +--------------------- +L0: + 1 + v(block: () -> Unit) + magic[FAKE_INITIALIZER](block: () -> Unit) -> + w(block|) + 2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block() }) + mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + jmp?(L2) NEXT:[r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> , d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })] + d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) NEXT:[] +L2 [after local declaration]: + r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> PREV:[jmp?(L2)] + mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> + r(block) -> + mark(block()) + call(block(), invoke|) -> +L1: + 1 NEXT:[] +error: + PREV:[] +sink: + PREV:[, , d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })] +===================== +== anonymous_1 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- +L3: + 3 + 4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> + r(block) -> + mark(InvocationKind.EXACTLY_ONCE) + r(EXACTLY_ONCE) -> + mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +L4: + 3 NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== unknownRun == +inline fun unknownRun(block: () -> Unit) = block() +--------------------- +L0: + 1 + v(block: () -> Unit) + magic[FAKE_INITIALIZER](block: () -> Unit) -> + w(block|) + r(block) -> + mark(block()) + call(block(), invoke|) -> + ret(*|) L1 +L1: + NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== getBool == +fun getBool(): Boolean = false +--------------------- +L0: + 1 + r(false) -> + ret(*|) L1 +L1: + NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== threeLayersReturn == +fun threeLayersReturn(x: Int?): Int? { + // Inner always jumps to outer + // And middle always calls inner + // So, in fact, middle never finished normally + // Hence 'y = 54' in middle is unreachable, and middle doesn't performs definite initalization + // Hence, outer doesn't performs definite initialization + val y: Int + myRun outer@ { + myRun middle@ { + x.myLet inner@ { + if (it == null) { + return@outer Unit + } + else { + return@outer Unit + } + } + } + // Possible to report unreachable here + y = 54 + } + return y.inc() +} +--------------------- +L0: + 1 + v(x: Int?) + magic[FAKE_INITIALIZER](x: Int?) -> + w(x|) + 2 mark({ // Inner always jumps to outer // And middle always calls inner // So, in fact, middle never finished normally // Hence 'y = 54' in middle is unreachable, and middle doesn't performs definite initalization // Hence, outer doesn't performs definite initialization val y: Int myRun outer@ { myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 } return y.inc() }) + v(val y: Int) + mark(outer@ { myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 }) + mark({ myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 }) + r({ myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 }) -> + mark(myRun outer@ { myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 }) + call(myRun outer@ { myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 }, myRun|) -> +L2 [before inlined declaration]: + inlined({ myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 }) +L3 [after inlined declaration]: + mark(y.inc()) + r(y) -> + mark(inc()) + call(inc(), inc|) -> + ret(*|) L1 +L1: + 1 NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== inlined anonymous_2 == +{ + myRun middle@ { + x.myLet inner@ { + if (it == null) { + return@outer Unit + } + else { + return@outer Unit + } + } + } + // Possible to report unreachable here + y = 54 + } +--------------------- +L4: + 3 + 4 mark(myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54) + mark(middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } }) + mark({ x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } }) + r({ x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } }) -> + mark(myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } }) + call(myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } }, myRun|) -> +L6 [before inlined declaration]: + inlined({ x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } }) NEXT:[] +L7 [after inlined declaration]: +- r(54) -> PREV:[] +- w(y|) PREV:[] +L5: + 3 NEXT:[] PREV:[ret(*|) L5, ret(*|) L5] +error: +- PREV:[] +sink: + PREV:[, inlined({ x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } })] +===================== +== inlined anonymous_3 == +{ + x.myLet inner@ { + if (it == null) { + return@outer Unit + } + else { + return@outer Unit + } + } + } +--------------------- +L8: + 5 + 6 mark(x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } }) + mark(x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } }) + r(x) -> + mark(inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } }) + mark({ if (it == null) { return@outer Unit } else { return@outer Unit } }) + r({ if (it == null) { return@outer Unit } else { return@outer Unit } }) -> + mark(myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } }) + call(myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } }, myLet|, ) +L10 [before inlined declaration]: + inlined({ if (it == null) { return@outer Unit } else { return@outer Unit } }) NEXT:[] +L11 [after inlined declaration]: +- jmp(error) NEXT:[] PREV:[] +- jmp(error) NEXT:[] PREV:[] +L9: +- 5 NEXT:[] PREV:[] +error: +- PREV:[] +sink: + PREV:[inlined({ if (it == null) { return@outer Unit } else { return@outer Unit } })] +===================== +== inlined anonymous_4 == +{ + if (it == null) { + return@outer Unit + } + else { + return@outer Unit + } + } +--------------------- +L12: + 7 + 8 mark(if (it == null) { return@outer Unit } else { return@outer Unit }) + mark(if (it == null) { return@outer Unit } else { return@outer Unit }) + r(it) -> + r(null) -> + mark(it == null) + call(it == null, equals|, ) -> + jf(L14|) NEXT:[mark({ return@outer Unit }), mark({ return@outer Unit })] + 9 mark({ return@outer Unit }) + r(Unit) -> + ret(*|) L5 NEXT:[] +- 8 jmp(L15) NEXT:[merge(if (it == null) { return@outer Unit } else { return@outer Unit }|!, !) -> ] PREV:[] +L14 [else branch]: + 9 mark({ return@outer Unit }) PREV:[jf(L14|)] + r(Unit) -> + ret(*|) L5 NEXT:[] +L15 ['if' expression result]: +- 8 merge(if (it == null) { return@outer Unit } else { return@outer Unit }|!, !) -> PREV:[] +- 7 ret(*|) L13 PREV:[] +L13: +- NEXT:[] PREV:[] +error: +- PREV:[] +sink: +- PREV:[] +===================== diff --git a/compiler/testData/cfgWithStdLib/contracts/labeledReturns.kt b/compiler/testData/cfgWithStdLib/contracts/labeledReturns.kt new file mode 100644 index 00000000000..a990d6a5ae0 --- /dev/null +++ b/compiler/testData/cfgWithStdLib/contracts/labeledReturns.kt @@ -0,0 +1,45 @@ +// LANGUAGE_VERSION: 1.3 + +import kotlin.internal.contracts.* + +inline fun T.myLet(block: (T) -> R): R { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block(this) +} + +inline fun myRun(block: () -> Unit) { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + block() +} + +inline fun unknownRun(block: () -> Unit) = block() + +fun getBool(): Boolean = false + +fun threeLayersReturn(x: Int?): Int? { + // Inner always jumps to outer + // And middle always calls inner + // So, in fact, middle never finished normally + // Hence 'y = 54' in middle is unreachable, and middle doesn't performs definite initalization + // Hence, outer doesn't performs definite initialization + val y: Int + myRun outer@ { + myRun middle@ { + x.myLet inner@ { + if (it == null) { + return@outer Unit + } + else { + return@outer Unit + } + } + } + // Possible to report unreachable here + y = 54 + } + return y.inc() +} \ No newline at end of file diff --git a/compiler/testData/cfgWithStdLib/contracts/labeledReturns.values b/compiler/testData/cfgWithStdLib/contracts/labeledReturns.values new file mode 100644 index 00000000000..da4bf06c5c8 --- /dev/null +++ b/compiler/testData/cfgWithStdLib/contracts/labeledReturns.values @@ -0,0 +1,168 @@ +== myLet == +inline fun T.myLet(block: (T) -> R): R { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block(this) +} +--------------------- + : {<: (T) -> R} NEW: magic[FAKE_INITIALIZER](block: (T) -> R) -> +{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> +contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> +block : {<: (T) -> R} NEW: r(block) -> +this : {<: T} COPY +this : {<: T} NEW: r(this, ) -> +block(this) : {<: R} NEW: call(block(this), invoke|, ) -> +return block(this) !: * +{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block(this) } !: * COPY +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- + : {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> +block : {<: Function} NEW: r(block) -> +EXACTLY_ONCE : {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> +InvocationKind.EXACTLY_ONCE : {<: InvocationKind} COPY +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * COPY +===================== +== myRun == +inline fun myRun(block: () -> Unit) { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + block() +} +--------------------- + : {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> +{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> +contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> +block : {<: () -> Unit} NEW: r(block) -> +block() : * NEW: call(block(), invoke|) -> +{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block() } : * COPY +===================== +== anonymous_1 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- + : {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> +block : {<: Function} NEW: r(block) -> +EXACTLY_ONCE : {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> +InvocationKind.EXACTLY_ONCE : {<: InvocationKind} COPY +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * COPY +===================== +== unknownRun == +inline fun unknownRun(block: () -> Unit) = block() +--------------------- + : {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> +block : {<: () -> Unit} NEW: r(block) -> +block() : Unit NEW: call(block(), invoke|) -> +===================== +== getBool == +fun getBool(): Boolean = false +--------------------- +false : Boolean NEW: r(false) -> +===================== +== threeLayersReturn == +fun threeLayersReturn(x: Int?): Int? { + // Inner always jumps to outer + // And middle always calls inner + // So, in fact, middle never finished normally + // Hence 'y = 54' in middle is unreachable, and middle doesn't performs definite initalization + // Hence, outer doesn't performs definite initialization + val y: Int + myRun outer@ { + myRun middle@ { + x.myLet inner@ { + if (it == null) { + return@outer Unit + } + else { + return@outer Unit + } + } + } + // Possible to report unreachable here + y = 54 + } + return y.inc() +} +--------------------- + : {<: Int?} NEW: magic[FAKE_INITIALIZER](x: Int?) -> +{ myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 } : {<: () -> Unit} NEW: r({ myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 }) -> +outer@ { myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 } : {<: () -> Unit} COPY +myRun outer@ { myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 } : * NEW: call(myRun outer@ { myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 }, myRun|) -> +y : Int NEW: r(y) -> +inc() : {<: Int?} NEW: call(inc(), inc|) -> +y.inc() : {<: Int?} COPY +return y.inc() !: * +{ // Inner always jumps to outer // And middle always calls inner // So, in fact, middle never finished normally // Hence 'y = 54' in middle is unreachable, and middle doesn't performs definite initalization // Hence, outer doesn't performs definite initialization val y: Int myRun outer@ { myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 } return y.inc() } !: * COPY +===================== +== inlined anonymous_2 == +{ + myRun middle@ { + x.myLet inner@ { + if (it == null) { + return@outer Unit + } + else { + return@outer Unit + } + } + } + // Possible to report unreachable here + y = 54 + } +--------------------- +{ x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } : {<: () -> Unit} NEW: r({ x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } }) -> +middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } : {<: () -> Unit} COPY +myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } : * NEW: call(myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } }, myRun|) -> +54 : Int NEW: r(54) -> +y = 54 !: * +myRun middle@ { x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } } // Possible to report unreachable here y = 54 !: * COPY +===================== +== inlined anonymous_3 == +{ + x.myLet inner@ { + if (it == null) { + return@outer Unit + } + else { + return@outer Unit + } + } + } +--------------------- +x : {<: Int?} NEW: r(x) -> +{ if (it == null) { return@outer Unit } else { return@outer Unit } } : {<: (Int?) -> Nothing} NEW: r({ if (it == null) { return@outer Unit } else { return@outer Unit } }) -> +inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } : {<: (Int?) -> Nothing} COPY +myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } !: * +x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } !: * COPY +x.myLet inner@ { if (it == null) { return@outer Unit } else { return@outer Unit } } !: * COPY +===================== +== inlined anonymous_4 == +{ + if (it == null) { + return@outer Unit + } + else { + return@outer Unit + } + } +--------------------- +it : * NEW: r(it) -> +null : * NEW: r(null) -> +it == null : Boolean NEW: call(it == null, equals|, ) -> +Unit : Unit NEW: r(Unit) -> +return@outer Unit !: * +{ return@outer Unit } !: * COPY +Unit : Unit NEW: r(Unit) -> +return@outer Unit !: * +{ return@outer Unit } !: * COPY +if (it == null) { return@outer Unit } else { return@outer Unit } : Nothing NEW: merge(if (it == null) { return@outer Unit } else { return@outer Unit }|!, !) -> +if (it == null) { return@outer Unit } else { return@outer Unit } : Nothing COPY +===================== diff --git a/compiler/testData/cfgWithStdLib/contracts/nonReturningInlinedLambda.instructions b/compiler/testData/cfgWithStdLib/contracts/nonReturningInlinedLambda.instructions new file mode 100644 index 00000000000..9c18e460691 --- /dev/null +++ b/compiler/testData/cfgWithStdLib/contracts/nonReturningInlinedLambda.instructions @@ -0,0 +1,148 @@ +== myRun == +inline fun myRun(block: () -> Unit): Unit { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} +--------------------- +L0: + 1 + v(block: () -> Unit) + magic[FAKE_INITIALIZER](block: () -> Unit) -> + w(block|) + 2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() }) + mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + jmp?(L2) NEXT:[r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> , d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })] + d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) NEXT:[] +L2 [after local declaration]: + r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> PREV:[jmp?(L2)] + mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> + r(block) -> + mark(block()) + call(block(), invoke|) -> + ret(*|) L1 +L1: + 1 NEXT:[] +error: + PREV:[] +sink: + PREV:[, , d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })] +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- +L3: + 3 + 4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> + r(block) -> + mark(InvocationKind.EXACTLY_ONCE) + r(EXACTLY_ONCE) -> + mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +L4: + 3 NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== getBool == +fun getBool(): Boolean = false +--------------------- +L0: + 1 + r(false) -> + ret(*|) L1 +L1: + NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== withLabeledReturn == +fun withLabeledReturn(y: Int) { + val x = myRun outer@ { + myRun { return@outer Unit } + println(y) + } + + println(y) + println(x) +} +--------------------- +L0: + 1 + v(y: Int) + magic[FAKE_INITIALIZER](y: Int) -> + w(y|) + 2 mark({ val x = myRun outer@ { myRun { return@outer Unit } println(y) } println(y) println(x) }) + v(val x = myRun outer@ { myRun { return@outer Unit } println(y) }) + mark(outer@ { myRun { return@outer Unit } println(y) }) + mark({ myRun { return@outer Unit } println(y) }) + r({ myRun { return@outer Unit } println(y) }) -> + mark(myRun outer@ { myRun { return@outer Unit } println(y) }) + call(myRun outer@ { myRun { return@outer Unit } println(y) }, myRun|) -> +L2 [before inlined declaration]: + inlined({ myRun { return@outer Unit } println(y) }) +L3 [after inlined declaration]: + w(x|) + r(y) -> + mark(println(y)) + call(println(y), println|) -> + r(x) -> + mark(println(x)) + call(println(x), println|) -> +L1: + 1 NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== inlined anonymous_1 == +{ + myRun { return@outer Unit } + println(y) + } +--------------------- +L4: + 3 + 4 mark(myRun { return@outer Unit } println(y)) + mark({ return@outer Unit }) + r({ return@outer Unit }) -> + mark(myRun { return@outer Unit }) + call(myRun { return@outer Unit }, myRun|) -> +L6 [before inlined declaration]: + inlined({ return@outer Unit }) NEXT:[] +L7 [after inlined declaration]: +- r(y) -> PREV:[] +- mark(println(y)) PREV:[] +- call(println(y), println|) -> PREV:[] +L5: + 3 NEXT:[] PREV:[ret(*|) L5] +error: +- PREV:[] +sink: + PREV:[, inlined({ return@outer Unit })] +===================== +== inlined anonymous_2 == +{ return@outer Unit } +--------------------- +L8: + 5 + 6 mark(return@outer Unit) + r(Unit) -> + ret(*|) L5 NEXT:[] +L9: +- 5 NEXT:[] PREV:[] +error: +- PREV:[] +sink: +- PREV:[] +===================== diff --git a/compiler/testData/cfgWithStdLib/contracts/nonReturningInlinedLambda.kt b/compiler/testData/cfgWithStdLib/contracts/nonReturningInlinedLambda.kt new file mode 100644 index 00000000000..a75f1ca6fdd --- /dev/null +++ b/compiler/testData/cfgWithStdLib/contracts/nonReturningInlinedLambda.kt @@ -0,0 +1,22 @@ +// LANGUAGE_VERSION: 1.3 + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> Unit): Unit { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun getBool(): Boolean = false + +fun withLabeledReturn(y: Int) { + val x = myRun outer@ { + myRun { return@outer Unit } + println(y) + } + + println(y) + println(x) +} \ No newline at end of file diff --git a/compiler/testData/cfgWithStdLib/contracts/nonReturningInlinedLambda.values b/compiler/testData/cfgWithStdLib/contracts/nonReturningInlinedLambda.values new file mode 100644 index 00000000000..305f999d806 --- /dev/null +++ b/compiler/testData/cfgWithStdLib/contracts/nonReturningInlinedLambda.values @@ -0,0 +1,73 @@ +== myRun == +inline fun myRun(block: () -> Unit): Unit { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} +--------------------- + : {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> +{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> +contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> +block : {<: () -> Unit} NEW: r(block) -> +block() : Unit NEW: call(block(), invoke|) -> +return block() !: * +{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() } !: * COPY +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- + : {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> +block : {<: Function} NEW: r(block) -> +EXACTLY_ONCE : {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> +InvocationKind.EXACTLY_ONCE : {<: InvocationKind} COPY +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * COPY +===================== +== getBool == +fun getBool(): Boolean = false +--------------------- +false : Boolean NEW: r(false) -> +===================== +== withLabeledReturn == +fun withLabeledReturn(y: Int) { + val x = myRun outer@ { + myRun { return@outer Unit } + println(y) + } + + println(y) + println(x) +} +--------------------- + : Int NEW: magic[FAKE_INITIALIZER](y: Int) -> +{ myRun { return@outer Unit } println(y) } : {<: () -> Unit} NEW: r({ myRun { return@outer Unit } println(y) }) -> +outer@ { myRun { return@outer Unit } println(y) } : {<: () -> Unit} COPY +myRun outer@ { myRun { return@outer Unit } println(y) } : Unit NEW: call(myRun outer@ { myRun { return@outer Unit } println(y) }, myRun|) -> +y : Int NEW: r(y) -> +println(y) : * NEW: call(println(y), println|) -> +x : * NEW: r(x) -> +println(x) : * NEW: call(println(x), println|) -> +{ val x = myRun outer@ { myRun { return@outer Unit } println(y) } println(y) println(x) } : * COPY +===================== +== inlined anonymous_1 == +{ + myRun { return@outer Unit } + println(y) + } +--------------------- +{ return@outer Unit } : {<: () -> Unit} NEW: r({ return@outer Unit }) -> +myRun { return@outer Unit } : * NEW: call(myRun { return@outer Unit }, myRun|) -> +y : Int NEW: r(y) -> +println(y) : * NEW: call(println(y), println|) -> +myRun { return@outer Unit } println(y) : * COPY +===================== +== inlined anonymous_2 == +{ return@outer Unit } +--------------------- +Unit : Unit NEW: r(Unit) -> +return@outer Unit !: * +return@outer Unit !: * COPY +===================== diff --git a/compiler/testData/cfgWithStdLib/contracts/returnsAndCalls.instructions b/compiler/testData/cfgWithStdLib/contracts/returnsAndCalls.instructions new file mode 100644 index 00000000000..e39fb1546e3 --- /dev/null +++ b/compiler/testData/cfgWithStdLib/contracts/returnsAndCalls.instructions @@ -0,0 +1,243 @@ +== callsAndInverts == +fun callsAndInverts(b: Boolean, block: () -> Unit): Boolean { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + returns(true) implies (!b) + returns(false) implies b + } + + block() + return !b +} +--------------------- +L0: + 1 + v(b: Boolean) + magic[FAKE_INITIALIZER](b: Boolean) -> + w(b|) + v(block: () -> Unit) + magic[FAKE_INITIALIZER](block: () -> Unit) -> + w(block|) + 2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b } block() return !b }) + mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }) + jmp?(L2) NEXT:[r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }) -> , d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b })] + d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }) NEXT:[] +L2 [after local declaration]: + r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }) -> PREV:[jmp?(L2)] + mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }) + call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }, contract|) -> + r(block) -> + mark(block()) + call(block(), invoke|) -> + r(b) -> + mark(!b) + call(!b, not|) -> + ret(*|) L1 +L1: + 1 NEXT:[] +error: + PREV:[] +sink: + PREV:[, , d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b })] +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + returns(true) implies (!b) + returns(false) implies b + } +--------------------- +L3: + 3 + 4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b) + magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> + r(block) -> + mark(InvocationKind.EXACTLY_ONCE) + r(EXACTLY_ONCE) -> + mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> + magic[IMPLICIT_RECEIVER](returns(true)) -> + r(true) -> + mark(returns(true)) + call(returns(true), returns|, ) -> + mark((!b)) + r(b) -> + mark(!b) + call(!b, not|) -> + mark(returns(true) implies (!b)) + call(returns(true) implies (!b), implies|, ) -> + magic[IMPLICIT_RECEIVER](returns(false)) -> + r(false) -> + mark(returns(false)) + call(returns(false), returns|, ) -> + r(b) -> + mark(returns(false) implies b) + call(returns(false) implies b, implies|, ) -> +L4: + 3 NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== smartcastAndInitialization == +fun smartcastAndInitialization(x: Any?) { + val y: Int + + if (callsAndInverts(x !is String) { y = 42 }) { + println(y) + x.length + } + else { + println(y) + x.length + } + println(y) +} +--------------------- +L0: + 1 + v(x: Any?) + magic[FAKE_INITIALIZER](x: Any?) -> + w(x|) + 2 mark({ val y: Int if (callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length } println(y) }) + v(val y: Int) + mark(if (callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length }) + mark(x !is String) + r(x) -> + magic[IS](x !is String|) -> + mark({ y = 42 }) + r({ y = 42 }) -> + mark(callsAndInverts(x !is String) { y = 42 }) + call(callsAndInverts(x !is String) { y = 42 }, callsAndInverts|, ) -> +L2 [before inlined declaration]: + inlined({ y = 42 }) +L3 [after inlined declaration]: + jf(L6|) NEXT:[mark({ println(y) x.length }), mark({ println(y) x.length })] + 3 mark({ println(y) x.length }) + r(y) -> + mark(println(y)) + call(println(y), println|) -> + magic[UNRESOLVED_CALL](DEBUG_INFO_SMARTCAST) -> + mark(!DEBUG_INFO_SMARTCAST) + call(!DEBUG_INFO_SMARTCAST, |) -> + 2 jmp(L7) NEXT:[merge(if (callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length }|, ) -> ] +L6 [else branch]: + 3 mark({ println(y) x.length }) PREV:[jf(L6|)] + r(y) -> + mark(println(y)) + call(println(y), println|) -> + mark(x.<) + r(x) -> + magic[UNSUPPORTED_ELEMENT](x.<|) -> +L7 ['if' expression result]: + 2 merge(if (callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length }|, ) -> PREV:[jmp(L7), magic[UNSUPPORTED_ELEMENT](x.<|) -> ] + r(y) -> + mark(println(y)) + call(println(y), println|) -> +L1: + 1 NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== inlined anonymous_1 == +{ y = 42 } +--------------------- +L4: + 3 + 4 mark(y = 42) + r(42) -> + w(y|) +L5: + 3 NEXT:[] +error: +- PREV:[] +sink: + PREV:[] +===================== +== inPresenceOfLazy == +fun inPresenceOfLazy(x: Any?, unknownBoolean: Boolean) { + val y: Int + + if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { + println(y) + x.length + } + else { + println(y) + x.length + } + println(y) +} +--------------------- +L0: + 1 + v(x: Any?) + magic[FAKE_INITIALIZER](x: Any?) -> + w(x|) + v(unknownBoolean: Boolean) + magic[FAKE_INITIALIZER](unknownBoolean: Boolean) -> + w(unknownBoolean|) + 2 mark({ val y: Int if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length } println(y) }) + v(val y: Int) + mark(if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length }) + r(unknownBoolean) -> + jf(L2|) NEXT:[magic[AND](unknownBoolean && callsAndInverts(x !is String) { y = 42 }|, ) -> , mark(x !is String)] + mark(x !is String) + r(x) -> + magic[IS](x !is String|) -> + mark({ y = 42 }) + r({ y = 42 }) -> + mark(callsAndInverts(x !is String) { y = 42 }) + call(callsAndInverts(x !is String) { y = 42 }, callsAndInverts|, ) -> +L3 [before inlined declaration]: + inlined({ y = 42 }) +L2 [result of boolean operation]: +L4 [after inlined declaration]: + magic[AND](unknownBoolean && callsAndInverts(x !is String) { y = 42 }|, ) -> PREV:[jf(L2|), inlined({ y = 42 })] + jf(L7|) NEXT:[mark({ println(y) x.length }), mark({ println(y) x.length })] + 3 mark({ println(y) x.length }) + r(y) -> + mark(println(y)) + call(println(y), println|) -> + magic[UNRESOLVED_CALL](DEBUG_INFO_SMARTCAST) -> + mark(!DEBUG_INFO_SMARTCAST) + call(!DEBUG_INFO_SMARTCAST, |) -> + 2 jmp(L8) NEXT:[merge(if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length }|, ) -> ] +L7 [else branch]: + 3 mark({ println(y) x.length }) PREV:[jf(L7|)] + r(y) -> + mark(println(y)) + call(println(y), println|) -> + mark(x.<) + r(x) -> + magic[UNSUPPORTED_ELEMENT](x.<|) -> +L8 ['if' expression result]: + 2 merge(if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length }|, ) -> PREV:[jmp(L8), magic[UNSUPPORTED_ELEMENT](x.<|) -> ] + r(y) -> + mark(println(y)) + call(println(y), println|) -> +L1: + 1 NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== inlined anonymous_2 == +{ y = 42 } +--------------------- +L5: + 3 + 4 mark(y = 42) + r(42) -> + w(y|) +L6: + 3 NEXT:[] +error: +- PREV:[] +sink: + PREV:[] +===================== diff --git a/compiler/testData/cfgWithStdLib/contracts/returnsAndCalls.kt b/compiler/testData/cfgWithStdLib/contracts/returnsAndCalls.kt new file mode 100644 index 00000000000..58be9e1e3d7 --- /dev/null +++ b/compiler/testData/cfgWithStdLib/contracts/returnsAndCalls.kt @@ -0,0 +1,44 @@ +// LANGUAGE_VERSION: 1.3 + +import kotlin.internal.contracts.* + +fun callsAndInverts(b: Boolean, block: () -> Unit): Boolean { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + returns(true) implies (!b) + returns(false) implies b + } + + block() + return !b +} + + + +fun smartcastAndInitialization(x: Any?) { + val y: Int + + if (callsAndInverts(x !is String) { y = 42 }) { + println(y) + x.length + } + else { + println(y) + x.length + } + println(y) +} + +fun inPresenceOfLazy(x: Any?, unknownBoolean: Boolean) { + val y: Int + + if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { + println(y) + x.length + } + else { + println(y) + x.length + } + println(y) +} \ No newline at end of file diff --git a/compiler/testData/cfgWithStdLib/contracts/returnsAndCalls.values b/compiler/testData/cfgWithStdLib/contracts/returnsAndCalls.values new file mode 100644 index 00000000000..35dcb7d6e1b --- /dev/null +++ b/compiler/testData/cfgWithStdLib/contracts/returnsAndCalls.values @@ -0,0 +1,136 @@ +== callsAndInverts == +fun callsAndInverts(b: Boolean, block: () -> Unit): Boolean { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + returns(true) implies (!b) + returns(false) implies b + } + + block() + return !b +} +--------------------- + : Boolean NEW: magic[FAKE_INITIALIZER](b: Boolean) -> + : {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> +{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b } : {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }) -> +contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b } : * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b }, contract|) -> +block : {<: () -> Unit} NEW: r(block) -> +block() : * NEW: call(block(), invoke|) -> +b : Boolean NEW: r(b) -> +!b : Boolean NEW: call(!b, not|) -> +return !b !: * +{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b } block() return !b } !: * COPY +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + returns(true) implies (!b) + returns(false) implies b + } +--------------------- + : {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> + : {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](returns(false)) -> + : {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](returns(true)) -> +block : {<: Function} NEW: r(block) -> +EXACTLY_ONCE : {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> +InvocationKind.EXACTLY_ONCE : {<: InvocationKind} COPY +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +true : * NEW: r(true) -> +returns(true) : {<: SimpleEffect} NEW: call(returns(true), returns|, ) -> +b : Boolean NEW: r(b) -> +!b : Boolean NEW: call(!b, not|) -> +(!b) : Boolean COPY +returns(true) implies (!b) : * NEW: call(returns(true) implies (!b), implies|, ) -> +false : * NEW: r(false) -> +returns(false) : {<: SimpleEffect} NEW: call(returns(false), returns|, ) -> +b : Boolean NEW: r(b) -> +returns(false) implies b : * NEW: call(returns(false) implies b, implies|, ) -> +callsInPlace(block, InvocationKind.EXACTLY_ONCE) returns(true) implies (!b) returns(false) implies b : * COPY +===================== +== smartcastAndInitialization == +fun smartcastAndInitialization(x: Any?) { + val y: Int + + if (callsAndInverts(x !is String) { y = 42 }) { + println(y) + x.length + } + else { + println(y) + x.length + } + println(y) +} +--------------------- + : * NEW: magic[FAKE_INITIALIZER](x: Any?) -> +x : * NEW: r(x) -> +x !is String : Boolean NEW: magic[IS](x !is String|) -> +{ y = 42 } : {<: () -> Unit} NEW: r({ y = 42 }) -> +callsAndInverts(x !is String) { y = 42 } : Boolean NEW: call(callsAndInverts(x !is String) { y = 42 }, callsAndInverts|, ) -> +y : Int NEW: r(y) -> +println(y) : * NEW: call(println(y), println|) -> +DEBUG_INFO_SMARTCAST : * NEW: magic[UNRESOLVED_CALL](DEBUG_INFO_SMARTCAST) -> +!DEBUG_INFO_SMARTCAST : * NEW: call(!DEBUG_INFO_SMARTCAST, |) -> +{ println(y) x.length } : * COPY +y : Int NEW: r(y) -> +println(y) : * NEW: call(println(y), println|) -> +x : * NEW: r(x) -> +x.< : * NEW: magic[UNSUPPORTED_ELEMENT](x.<|) -> +{ println(y) x.length } : * COPY +if (callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length } : * NEW: merge(if (callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length }|, ) -> +y : Int NEW: r(y) -> +println(y) : * NEW: call(println(y), println|) -> +{ val y: Int if (callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length } println(y) } : * COPY +===================== +== inlined anonymous_1 == +{ y = 42 } +--------------------- +42 : Int NEW: r(42) -> +y = 42 !: * +y = 42 !: * COPY +===================== +== inPresenceOfLazy == +fun inPresenceOfLazy(x: Any?, unknownBoolean: Boolean) { + val y: Int + + if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { + println(y) + x.length + } + else { + println(y) + x.length + } + println(y) +} +--------------------- + : * NEW: magic[FAKE_INITIALIZER](x: Any?) -> + : Boolean NEW: magic[FAKE_INITIALIZER](unknownBoolean: Boolean) -> +unknownBoolean : Boolean NEW: r(unknownBoolean) -> +x : * NEW: r(x) -> +x !is String : Boolean NEW: magic[IS](x !is String|) -> +{ y = 42 } : {<: () -> Unit} NEW: r({ y = 42 }) -> +callsAndInverts(x !is String) { y = 42 } : Boolean NEW: call(callsAndInverts(x !is String) { y = 42 }, callsAndInverts|, ) -> +unknownBoolean && callsAndInverts(x !is String) { y = 42 } : Boolean NEW: magic[AND](unknownBoolean && callsAndInverts(x !is String) { y = 42 }|, ) -> +y : Int NEW: r(y) -> +println(y) : * NEW: call(println(y), println|) -> +DEBUG_INFO_SMARTCAST : * NEW: magic[UNRESOLVED_CALL](DEBUG_INFO_SMARTCAST) -> +!DEBUG_INFO_SMARTCAST : * NEW: call(!DEBUG_INFO_SMARTCAST, |) -> +{ println(y) x.length } : * COPY +y : Int NEW: r(y) -> +println(y) : * NEW: call(println(y), println|) -> +x : * NEW: r(x) -> +x.< : * NEW: magic[UNSUPPORTED_ELEMENT](x.<|) -> +{ println(y) x.length } : * COPY +if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length } : * NEW: merge(if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length }|, ) -> +y : Int NEW: r(y) -> +println(y) : * NEW: call(println(y), println|) -> +{ val y: Int if (unknownBoolean && callsAndInverts(x !is String) { y = 42 }) { println(y) x.length } else { println(y) x.length } println(y) } : * COPY +===================== +== inlined anonymous_2 == +{ y = 42 } +--------------------- +42 : Int NEW: r(42) -> +y = 42 !: * +y = 42 !: * COPY +===================== diff --git a/compiler/testData/cfgWithStdLib/contracts/throwIfNotCalled.instructions b/compiler/testData/cfgWithStdLib/contracts/throwIfNotCalled.instructions new file mode 100644 index 00000000000..fcb65b26fab --- /dev/null +++ b/compiler/testData/cfgWithStdLib/contracts/throwIfNotCalled.instructions @@ -0,0 +1,184 @@ +== myRun == +inline fun myRun(block: () -> Unit) { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + block() +} +--------------------- +L0: + 1 + v(block: () -> Unit) + magic[FAKE_INITIALIZER](block: () -> Unit) -> + w(block|) + 2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block() }) + mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + jmp?(L2) NEXT:[r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> , d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })] + d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) NEXT:[] +L2 [after local declaration]: + r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> PREV:[jmp?(L2)] + mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> + r(block) -> + mark(block()) + call(block(), invoke|) -> +L1: + 1 NEXT:[] +error: + PREV:[] +sink: + PREV:[, , d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })] +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- +L3: + 3 + 4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> + r(block) -> + mark(InvocationKind.EXACTLY_ONCE) + r(EXACTLY_ONCE) -> + mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +L4: + 3 NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== unknownRun == +inline fun unknownRun(block: () -> T): T = block() +--------------------- +L0: + 1 + v(block: () -> T) + magic[FAKE_INITIALIZER](block: () -> T) -> + w(block|) + r(block) -> + mark(block()) + call(block(), invoke|) -> + ret(*|) L1 +L1: + NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== throwIfNotCalled == +fun throwIfNotCalled() { + val x: Int + myRun outer@ { + unknownRun { + myRun { + x = 42 + return@outer + } + } + throw java.lang.IllegalArgumentException() + } + println(x) +} +--------------------- +L0: + 1 + 2 mark({ val x: Int myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() } println(x) }) + v(val x: Int) + mark(outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }) + mark({ unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }) + r({ unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }) -> + mark(myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }) + call(myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }, myRun|) -> +L2 [before inlined declaration]: + inlined({ unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }) +L3 [after inlined declaration]: + mark(println(<) + magic[UNRESOLVED_CALL](println(<|!) -> +L1: + 1 NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== inlined anonymous_1 == +{ + unknownRun { + myRun { + x = 42 + return@outer + } + } + throw java.lang.IllegalArgumentException() + } +--------------------- +L4: + 3 + 4 mark(unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException()) + mark({ myRun { x = 42 return@outer } }) + jmp?(L6) NEXT:[r({ myRun { x = 42 return@outer } }) -> , d({ myRun { x = 42 return@outer } })] + d({ myRun { x = 42 return@outer } }) NEXT:[] +L6 [after local declaration]: + r({ myRun { x = 42 return@outer } }) -> PREV:[jmp?(L6)] + mark(unknownRun { myRun { x = 42 return@outer } }) + call(unknownRun { myRun { x = 42 return@outer } }, unknownRun|) -> + mark(throw java.lang.IllegalArgumentException()) + mark(java.lang.IllegalArgumentException()) + mark(IllegalArgumentException()) + call(IllegalArgumentException(), ) -> + throw (throw java.lang.IllegalArgumentException()|) NEXT:[] +L5: + 3 NEXT:[] PREV:[ret L5] +error: + PREV:[throw (throw java.lang.IllegalArgumentException()|)] +sink: + PREV:[, , d({ myRun { x = 42 return@outer } })] +===================== +== anonymous_2 == +{ + myRun { + x = 42 + return@outer + } + } +--------------------- +L7: + 5 + 6 mark(myRun { x = 42 return@outer }) + mark({ x = 42 return@outer }) + r({ x = 42 return@outer }) -> + mark(myRun { x = 42 return@outer }) + call(myRun { x = 42 return@outer }, myRun|) -> +L9 [before inlined declaration]: + inlined({ x = 42 return@outer }) NEXT:[] +L8: +L10 [after inlined declaration]: + 5 NEXT:[] PREV:[] +error: + PREV:[] +sink: + PREV:[, , inlined({ x = 42 return@outer })] +===================== +== inlined anonymous_3 == +{ + x = 42 + return@outer + } +--------------------- +L11: + 7 + 8 mark(x = 42 return@outer) + r(42) -> + w(x|) + ret L5 NEXT:[] +L12: +- 7 NEXT:[] PREV:[] +error: +- PREV:[] +sink: +- PREV:[] +===================== diff --git a/compiler/testData/cfgWithStdLib/contracts/throwIfNotCalled.kt b/compiler/testData/cfgWithStdLib/contracts/throwIfNotCalled.kt new file mode 100644 index 00000000000..8b99500a805 --- /dev/null +++ b/compiler/testData/cfgWithStdLib/contracts/throwIfNotCalled.kt @@ -0,0 +1,26 @@ +// LANGUAGE_VERSION: 1.3 + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> Unit) { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + block() +} + +inline fun unknownRun(block: () -> T): T = block() + +fun throwIfNotCalled() { + val x: Int + myRun outer@ { + unknownRun { + myRun { + x = 42 + return@outer + } + } + throw java.lang.IllegalArgumentException() + } + println(x) +} \ No newline at end of file diff --git a/compiler/testData/cfgWithStdLib/contracts/throwIfNotCalled.values b/compiler/testData/cfgWithStdLib/contracts/throwIfNotCalled.values new file mode 100644 index 00000000000..66d7025dfd6 --- /dev/null +++ b/compiler/testData/cfgWithStdLib/contracts/throwIfNotCalled.values @@ -0,0 +1,96 @@ +== myRun == +inline fun myRun(block: () -> Unit) { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + block() +} +--------------------- + : {<: () -> Unit} NEW: magic[FAKE_INITIALIZER](block: () -> Unit) -> +{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> +contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> +block : {<: () -> Unit} NEW: r(block) -> +block() : * NEW: call(block(), invoke|) -> +{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block() } : * COPY +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- + : {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> +block : {<: Function} NEW: r(block) -> +EXACTLY_ONCE : {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> +InvocationKind.EXACTLY_ONCE : {<: InvocationKind} COPY +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * COPY +===================== +== unknownRun == +inline fun unknownRun(block: () -> T): T = block() +--------------------- + : {<: () -> T} NEW: magic[FAKE_INITIALIZER](block: () -> T) -> +block : {<: () -> T} NEW: r(block) -> +block() : {<: T} NEW: call(block(), invoke|) -> +===================== +== throwIfNotCalled == +fun throwIfNotCalled() { + val x: Int + myRun outer@ { + unknownRun { + myRun { + x = 42 + return@outer + } + } + throw java.lang.IllegalArgumentException() + } + println(x) +} +--------------------- +{ unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() } : {<: () -> Unit} NEW: r({ unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }) -> +outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() } : {<: () -> Unit} COPY +myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() } : * NEW: call(myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() }, myRun|) -> +println !: * +println(< : * NEW: magic[UNRESOLVED_CALL](println(<|!) -> +{ val x: Int myRun outer@ { unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() } println(x) } : * COPY +===================== +== inlined anonymous_1 == +{ + unknownRun { + myRun { + x = 42 + return@outer + } + } + throw java.lang.IllegalArgumentException() + } +--------------------- +{ myRun { x = 42 return@outer } } : {<: () -> Unit} NEW: r({ myRun { x = 42 return@outer } }) -> +unknownRun { myRun { x = 42 return@outer } } : * NEW: call(unknownRun { myRun { x = 42 return@outer } }, unknownRun|) -> +IllegalArgumentException() : {<: Throwable} NEW: call(IllegalArgumentException(), ) -> +java.lang.IllegalArgumentException() : {<: Throwable} COPY +throw java.lang.IllegalArgumentException() !: * +unknownRun { myRun { x = 42 return@outer } } throw java.lang.IllegalArgumentException() !: * COPY +===================== +== anonymous_2 == +{ + myRun { + x = 42 + return@outer + } + } +--------------------- +{ x = 42 return@outer } : {<: () -> Unit} NEW: r({ x = 42 return@outer }) -> +myRun { x = 42 return@outer } : * NEW: call(myRun { x = 42 return@outer }, myRun|) -> +myRun { x = 42 return@outer } : * COPY +===================== +== inlined anonymous_3 == +{ + x = 42 + return@outer + } +--------------------- +42 : Int NEW: r(42) -> +return@outer !: * +x = 42 return@outer !: * COPY +===================== diff --git a/compiler/testData/cfgWithStdLib/contracts/tryCatchFinally.instructions b/compiler/testData/cfgWithStdLib/contracts/tryCatchFinally.instructions new file mode 100644 index 00000000000..483ff596e01 --- /dev/null +++ b/compiler/testData/cfgWithStdLib/contracts/tryCatchFinally.instructions @@ -0,0 +1,187 @@ +== myRun == +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} +--------------------- +L0: + 1 + v(block: () -> T) + magic[FAKE_INITIALIZER](block: () -> T) -> + w(block|) + 2 mark({ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() }) + mark({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + jmp?(L2) NEXT:[r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> , d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })] + d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) NEXT:[] +L2 [after local declaration]: + r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> PREV:[jmp?(L2)] + mark(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) + call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> + r(block) -> + mark(block()) + call(block(), invoke|) -> + ret(*|) L1 +L1: + 1 NEXT:[] +error: + PREV:[] +sink: + PREV:[, , d({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) })] +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- +L3: + 3 + 4 mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> + r(block) -> + mark(InvocationKind.EXACTLY_ONCE) + r(EXACTLY_ONCE) -> + mark(callsInPlace(block, InvocationKind.EXACTLY_ONCE)) + call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +L4: + 3 NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== someComputation == +fun someComputation(): Int = 42 +--------------------- +L0: + 1 + r(42) -> + ret(*|) L1 +L1: + NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== report == +fun report(x: Int) = Unit +--------------------- +L0: + 1 + v(x: Int) + magic[FAKE_INITIALIZER](x: Int) -> + w(x|) + r(Unit) -> + ret(*|) L1 +L1: + NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== innerTryCatchFinally == +fun innerTryCatchFinally() { + val x: Int + + myRun { + try { + x = someComputation() + report(x) + } catch (e: java.lang.Exception) { + x = 42 + report(x) + } finally { + x = 0 + } + } + + x.inc() +} +--------------------- +L0: + 1 + 2 mark({ val x: Int myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } } x.inc() }) + v(val x: Int) + mark({ try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }) + r({ try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }) -> + mark(myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }) + call(myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }, myRun|) -> +L2 [before inlined declaration]: + inlined({ try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }) +L3 [after inlined declaration]: + mark(x.inc()) + r(x) -> + mark(inc()) + call(inc(), inc|) -> +L1: + 1 NEXT:[] +error: + PREV:[] +sink: + PREV:[, ] +===================== +== inlined anonymous_1 == +{ + try { + x = someComputation() + report(x) + } catch (e: java.lang.Exception) { + x = 42 + report(x) + } finally { + x = 0 + } + } +--------------------- +L4: + 3 + 4 mark(try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 }) + mark(try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 }) + jmp?(L6) NEXT:[v(e: java.lang.Exception), jmp?(L7)] + jmp?(L7) NEXT:[mark({ x = 0 }), mark({ x = someComputation() report(x) })] + 5 mark({ x = someComputation() report(x) }) + mark(someComputation()) + call(someComputation(), someComputation) -> + w(x|) + r(x) -> + mark(report(x)) + call(report(x), report|) -> + 4 jmp?(L6) NEXT:[v(e: java.lang.Exception), jmp?(L7)] + jmp?(L7) NEXT:[mark({ x = 0 }), jmp(L8)] + jmp(L8) NEXT:[jmp(L9)] +L6 [onException]: + 5 v(e: java.lang.Exception) PREV:[jmp?(L6), jmp?(L6)] + magic[FAKE_INITIALIZER](e: java.lang.Exception) -> + w(e|) + 6 mark({ x = 42 report(x) }) + r(42) -> + w(x|) + r(x) -> + mark(report(x)) + call(report(x), report|) -> + 5 jmp(L8) +L8 [afterCatches]: + 4 jmp(L9) NEXT:[mark({ x = 0 })] PREV:[jmp(L8), jmp(L8)] +L7 [onExceptionToFinallyBlock]: +L10 [start finally]: + 5 mark({ x = 0 }) PREV:[jmp?(L7), jmp?(L7)] + r(0) -> + w(x|) +L11 [finish finally]: + 4 jmp(error) NEXT:[] +L9 [skipFinallyToErrorBlock]: +L12 [copy of L7, onExceptionToFinallyBlock]: + 5 mark({ x = 0 }) PREV:[jmp(L9)] + r(0) -> + w(x|) + 4 merge(try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 }|, ) -> +L5: + 3 NEXT:[] +error: + PREV:[jmp(error)] +sink: + PREV:[, ] +===================== diff --git a/compiler/testData/cfgWithStdLib/contracts/tryCatchFinally.kt b/compiler/testData/cfgWithStdLib/contracts/tryCatchFinally.kt new file mode 100644 index 00000000000..447fbb14629 --- /dev/null +++ b/compiler/testData/cfgWithStdLib/contracts/tryCatchFinally.kt @@ -0,0 +1,32 @@ +// LANGUAGE_VERSION: 1.3 + +import kotlin.internal.contracts.* + +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} + +fun someComputation(): Int = 42 + +fun report(x: Int) = Unit + +fun innerTryCatchFinally() { + val x: Int + + myRun { + try { + x = someComputation() + report(x) + } catch (e: java.lang.Exception) { + x = 42 + report(x) + } finally { + x = 0 + } + } + + x.inc() +} \ No newline at end of file diff --git a/compiler/testData/cfgWithStdLib/contracts/tryCatchFinally.values b/compiler/testData/cfgWithStdLib/contracts/tryCatchFinally.values new file mode 100644 index 00000000000..004544eb4a8 --- /dev/null +++ b/compiler/testData/cfgWithStdLib/contracts/tryCatchFinally.values @@ -0,0 +1,93 @@ +== myRun == +inline fun myRun(block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } + return block() +} +--------------------- + : {<: () -> T} NEW: magic[FAKE_INITIALIZER](block: () -> T) -> +{ callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : {<: ContractBuilder.() -> Unit} NEW: r({ callsInPlace(block, InvocationKind.EXACTLY_ONCE) }) -> +contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } : * NEW: call(contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }, contract|) -> +block : {<: () -> T} NEW: r(block) -> +block() : {<: T} NEW: call(block(), invoke|) -> +return block() !: * +{ contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block() } !: * COPY +===================== +== anonymous_0 == +{ + callsInPlace(block, InvocationKind.EXACTLY_ONCE) + } +--------------------- + : {<: ContractBuilder} NEW: magic[IMPLICIT_RECEIVER](callsInPlace(block, InvocationKind.EXACTLY_ONCE)) -> +block : {<: Function} NEW: r(block) -> +EXACTLY_ONCE : {<: InvocationKind} NEW: r(EXACTLY_ONCE) -> +InvocationKind.EXACTLY_ONCE : {<: InvocationKind} COPY +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * NEW: call(callsInPlace(block, InvocationKind.EXACTLY_ONCE), callsInPlace|, , ) -> +callsInPlace(block, InvocationKind.EXACTLY_ONCE) : * COPY +===================== +== someComputation == +fun someComputation(): Int = 42 +--------------------- +42 : Int NEW: r(42) -> +===================== +== report == +fun report(x: Int) = Unit +--------------------- + : Int NEW: magic[FAKE_INITIALIZER](x: Int) -> +Unit : Unit NEW: r(Unit) -> +===================== +== innerTryCatchFinally == +fun innerTryCatchFinally() { + val x: Int + + myRun { + try { + x = someComputation() + report(x) + } catch (e: java.lang.Exception) { + x = 42 + report(x) + } finally { + x = 0 + } + } + + x.inc() +} +--------------------- +{ try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } } : {<: () -> Unit} NEW: r({ try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }) -> +myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } } : * NEW: call(myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } }, myRun|) -> +x : Int NEW: r(x) -> +inc() : * NEW: call(inc(), inc|) -> +x.inc() : * COPY +{ val x: Int myRun { try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } } x.inc() } : * COPY +===================== +== inlined anonymous_1 == +{ + try { + x = someComputation() + report(x) + } catch (e: java.lang.Exception) { + x = 42 + report(x) + } finally { + x = 0 + } + } +--------------------- + : {<: Exception} NEW: magic[FAKE_INITIALIZER](e: java.lang.Exception) -> +someComputation() : Int NEW: call(someComputation(), someComputation) -> +x : Int NEW: r(x) -> +report(x) : * NEW: call(report(x), report|) -> +{ x = someComputation() report(x) } : * COPY +42 : Int NEW: r(42) -> +x : Int NEW: r(x) -> +report(x) : * NEW: call(report(x), report|) -> +{ x = 42 report(x) } : * COPY +0 : Int NEW: r(0) -> +x = 0 !: * +{ x = 0 } !: * COPY +try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } : * NEW: merge(try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 }|, ) -> +try { x = someComputation() report(x) } catch (e: java.lang.Exception) { x = 42 report(x) } finally { x = 0 } : * COPY +===================== diff --git a/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java index 6edf498e592..f08ef47454d 100644 --- a/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java @@ -28,776 +28,827 @@ import java.util.regex.Pattern; /** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") -@TestMetadata("compiler/testData/cfg") -@TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) public class ControlFlowTestGenerated extends AbstractControlFlowTest { - public void testAllFilesPresentInCfg() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); - } - - @TestMetadata("compiler/testData/cfg/arrays") + @TestMetadata("compiler/testData/cfg") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) - public static class Arrays extends AbstractControlFlowTest { - public void testAllFilesPresentInArrays() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/arrays"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + public static class Cfg extends AbstractControlFlowTest { + public void testAllFilesPresentInCfg() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); } - @TestMetadata("ArrayAccess.kt") - public void testArrayAccess() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/arrays/ArrayAccess.kt"); - doTest(fileName); - } - - @TestMetadata("arrayAccessExpression.kt") - public void testArrayAccessExpression() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/arrays/arrayAccessExpression.kt"); - doTest(fileName); - } - - @TestMetadata("arrayInc.kt") - public void testArrayInc() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/arrays/arrayInc.kt"); - doTest(fileName); - } - - @TestMetadata("arrayIncUnresolved.kt") - public void testArrayIncUnresolved() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/arrays/arrayIncUnresolved.kt"); - doTest(fileName); - } - - @TestMetadata("ArrayOfFunctions.kt") - public void testArrayOfFunctions() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/arrays/ArrayOfFunctions.kt"); - doTest(fileName); - } - - @TestMetadata("arraySet.kt") - public void testArraySet() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/arrays/arraySet.kt"); - doTest(fileName); - } - - @TestMetadata("arraySetNoRHS.kt") - public void testArraySetNoRHS() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/arrays/arraySetNoRHS.kt"); - doTest(fileName); - } - - @TestMetadata("arraySetPlusAssign.kt") - public void testArraySetPlusAssign() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/arrays/arraySetPlusAssign.kt"); - doTest(fileName); - } - - @TestMetadata("arraySetPlusAssignUnresolved.kt") - public void testArraySetPlusAssignUnresolved() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/arrays/arraySetPlusAssignUnresolved.kt"); - doTest(fileName); - } - - @TestMetadata("arraySetUnresolved.kt") - public void testArraySetUnresolved() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/arrays/arraySetUnresolved.kt"); - doTest(fileName); - } - } - - @TestMetadata("compiler/testData/cfg/basic") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class Basic extends AbstractControlFlowTest { - public void testAllFilesPresentInBasic() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/basic"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); - } - - @TestMetadata("Basic.kt") - public void testBasic() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/basic/Basic.kt"); - doTest(fileName); - } - - @TestMetadata("EmptyFunction.kt") - public void testEmptyFunction() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/basic/EmptyFunction.kt"); - doTest(fileName); - } - - @TestMetadata("ShortFunction.kt") - public void testShortFunction() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/basic/ShortFunction.kt"); - doTest(fileName); - } - } - - @TestMetadata("compiler/testData/cfg/bugs") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class Bugs extends AbstractControlFlowTest { - public void testAllFilesPresentInBugs() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/bugs"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); - } - - @TestMetadata("jumpToOuterScope.kt") - public void testJumpToOuterScope() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/bugs/jumpToOuterScope.kt"); - doTest(fileName); - } - - @TestMetadata("kt10105.kt") - public void testKt10105() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/bugs/kt10105.kt"); - doTest(fileName); - } - - @TestMetadata("kt7761.kt") - public void testKt7761() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/bugs/kt7761.kt"); - doTest(fileName); - } - - @TestMetadata("setWithTypeMismatch.kt") - public void testSetWithTypeMismatch() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/bugs/setWithTypeMismatch.kt"); - doTest(fileName); - } - - @TestMetadata("unresolvedInvokeOnResolvedVar.kt") - public void testUnresolvedInvokeOnResolvedVar() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/bugs/unresolvedInvokeOnResolvedVar.kt"); - doTest(fileName); - } - } - - @TestMetadata("compiler/testData/cfg/controlStructures") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class ControlStructures extends AbstractControlFlowTest { - public void testAllFilesPresentInControlStructures() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/controlStructures"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); - } - - @TestMetadata("breakContinueInTryFinally.kt") - public void testBreakContinueInTryFinally() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/breakContinueInTryFinally.kt"); - doTest(fileName); - } - - @TestMetadata("breakInsideLocal.kt") - public void testBreakInsideLocal() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/breakInsideLocal.kt"); - doTest(fileName); - } - - @TestMetadata("continueInDoWhile.kt") - public void testContinueInDoWhile() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/continueInDoWhile.kt"); - doTest(fileName); - } - - @TestMetadata("continueInFor.kt") - public void testContinueInFor() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/continueInFor.kt"); - doTest(fileName); - } - - @TestMetadata("continueInWhile.kt") - public void testContinueInWhile() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/continueInWhile.kt"); - doTest(fileName); - } - - @TestMetadata("Finally.kt") - public void testFinally() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/Finally.kt"); - doTest(fileName); - } - - @TestMetadata("FinallyTestCopy.kt") - public void testFinallyTestCopy() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/FinallyTestCopy.kt"); - doTest(fileName); - } - - @TestMetadata("For.kt") - public void testFor() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/For.kt"); - doTest(fileName); - } - - @TestMetadata("If.kt") - public void testIf() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/If.kt"); - doTest(fileName); - } - - @TestMetadata("incorrectIndex.kt") - public void testIncorrectIndex() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/incorrectIndex.kt"); - doTest(fileName); - } - - @TestMetadata("InfiniteLoops.kt") - public void testInfiniteLoops() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/InfiniteLoops.kt"); - doTest(fileName); - } - - @TestMetadata("localAndNonlocalReturnsWithFinally.kt") - public void testLocalAndNonlocalReturnsWithFinally() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/localAndNonlocalReturnsWithFinally.kt"); - doTest(fileName); - } - - @TestMetadata("localFunctionInFinally.kt") - public void testLocalFunctionInFinally() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/localFunctionInFinally.kt"); - doTest(fileName); - } - - @TestMetadata("OnlyWhileInFunctionBody.kt") - public void testOnlyWhileInFunctionBody() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.kt"); - doTest(fileName); - } - - @TestMetadata("returnsInWhen.kt") - public void testReturnsInWhen() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/returnsInWhen.kt"); - doTest(fileName); - } - - @TestMetadata("whenConditions.kt") - public void testWhenConditions() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/whenConditions.kt"); - doTest(fileName); - } - - @TestMetadata("whenExhaustive.kt") - public void testWhenExhaustive() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/whenExhaustive.kt"); - doTest(fileName); - } - } - - @TestMetadata("compiler/testData/cfg/conventions") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class Conventions extends AbstractControlFlowTest { - public void testAllFilesPresentInConventions() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/conventions"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); - } - - @TestMetadata("bothReceivers.kt") - public void testBothReceivers() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/conventions/bothReceivers.kt"); - doTest(fileName); - } - - @TestMetadata("equals.kt") - public void testEquals() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/conventions/equals.kt"); - doTest(fileName); - } - - @TestMetadata("incrementAtTheEnd.kt") - public void testIncrementAtTheEnd() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/conventions/incrementAtTheEnd.kt"); - doTest(fileName); - } - - @TestMetadata("invoke.kt") - public void testInvoke() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/conventions/invoke.kt"); - doTest(fileName); - } - - @TestMetadata("notEqual.kt") - public void testNotEqual() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/conventions/notEqual.kt"); - doTest(fileName); - } - } - - @TestMetadata("compiler/testData/cfg/deadCode") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class DeadCode extends AbstractControlFlowTest { - public void testAllFilesPresentInDeadCode() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/deadCode"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); - } - - @TestMetadata("DeadCode.kt") - public void testDeadCode() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/deadCode/DeadCode.kt"); - doTest(fileName); - } - - @TestMetadata("notLocalReturn.kt") - public void testNotLocalReturn() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/deadCode/notLocalReturn.kt"); - doTest(fileName); - } - - @TestMetadata("returnInElvis.kt") - public void testReturnInElvis() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/deadCode/returnInElvis.kt"); - doTest(fileName); - } - - @TestMetadata("stringTemplate.kt") - public void testStringTemplate() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/deadCode/stringTemplate.kt"); - doTest(fileName); - } - - @TestMetadata("throwInLambda.kt") - public void testThrowInLambda() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/deadCode/throwInLambda.kt"); - doTest(fileName); - } - } - - @TestMetadata("compiler/testData/cfg/declarations") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class Declarations extends AbstractControlFlowTest { - public void testAllFilesPresentInDeclarations() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/declarations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); - } - - @TestMetadata("compiler/testData/cfg/declarations/classesAndObjects") + @TestMetadata("compiler/testData/cfg/arrays") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) - public static class ClassesAndObjects extends AbstractControlFlowTest { - public void testAllFilesPresentInClassesAndObjects() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/declarations/classesAndObjects"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + public static class Arrays extends AbstractControlFlowTest { + public void testAllFilesPresentInArrays() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/arrays"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); } - @TestMetadata("AnonymousInitializers.kt") - public void testAnonymousInitializers() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/classesAndObjects/AnonymousInitializers.kt"); + @TestMetadata("ArrayAccess.kt") + public void testArrayAccess() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/arrays/ArrayAccess.kt"); doTest(fileName); } - @TestMetadata("delegationByExpression.kt") - public void testDelegationByExpression() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/classesAndObjects/delegationByExpression.kt"); + @TestMetadata("arrayAccessExpression.kt") + public void testArrayAccessExpression() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/arrays/arrayAccessExpression.kt"); doTest(fileName); } - @TestMetadata("delegationBySuperCall.kt") - public void testDelegationBySuperCall() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/classesAndObjects/delegationBySuperCall.kt"); + @TestMetadata("arrayInc.kt") + public void testArrayInc() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/arrays/arrayInc.kt"); doTest(fileName); } - @TestMetadata("EnumEntryRefersCompanion.kt") - public void testEnumEntryRefersCompanion() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/classesAndObjects/EnumEntryRefersCompanion.kt"); + @TestMetadata("arrayIncUnresolved.kt") + public void testArrayIncUnresolved() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/arrays/arrayIncUnresolved.kt"); doTest(fileName); } - @TestMetadata("ObjectEnumQualifiers.kt") - public void testObjectEnumQualifiers() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/classesAndObjects/ObjectEnumQualifiers.kt"); + @TestMetadata("ArrayOfFunctions.kt") + public void testArrayOfFunctions() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/arrays/ArrayOfFunctions.kt"); doTest(fileName); } - @TestMetadata("QualifierReceiverWithOthers.kt") - public void testQualifierReceiverWithOthers() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/classesAndObjects/QualifierReceiverWithOthers.kt"); + @TestMetadata("arraySet.kt") + public void testArraySet() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/arrays/arraySet.kt"); + doTest(fileName); + } + + @TestMetadata("arraySetNoRHS.kt") + public void testArraySetNoRHS() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/arrays/arraySetNoRHS.kt"); + doTest(fileName); + } + + @TestMetadata("arraySetPlusAssign.kt") + public void testArraySetPlusAssign() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/arrays/arraySetPlusAssign.kt"); + doTest(fileName); + } + + @TestMetadata("arraySetPlusAssignUnresolved.kt") + public void testArraySetPlusAssignUnresolved() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/arrays/arraySetPlusAssignUnresolved.kt"); + doTest(fileName); + } + + @TestMetadata("arraySetUnresolved.kt") + public void testArraySetUnresolved() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/arrays/arraySetUnresolved.kt"); doTest(fileName); } } - @TestMetadata("compiler/testData/cfg/declarations/functionLiterals") + @TestMetadata("compiler/testData/cfg/basic") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) - public static class FunctionLiterals extends AbstractControlFlowTest { - public void testAllFilesPresentInFunctionLiterals() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/declarations/functionLiterals"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + public static class Basic extends AbstractControlFlowTest { + public void testAllFilesPresentInBasic() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/basic"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); } - @TestMetadata("unusedFunctionLiteral.kt") - public void testUnusedFunctionLiteral() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/functionLiterals/unusedFunctionLiteral.kt"); + @TestMetadata("Basic.kt") + public void testBasic() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/basic/Basic.kt"); + doTest(fileName); + } + + @TestMetadata("EmptyFunction.kt") + public void testEmptyFunction() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/basic/EmptyFunction.kt"); + doTest(fileName); + } + + @TestMetadata("ShortFunction.kt") + public void testShortFunction() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/basic/ShortFunction.kt"); doTest(fileName); } } - @TestMetadata("compiler/testData/cfg/declarations/functions") + @TestMetadata("compiler/testData/cfg/bugs") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Bugs extends AbstractControlFlowTest { + public void testAllFilesPresentInBugs() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/bugs"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("jumpToOuterScope.kt") + public void testJumpToOuterScope() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/bugs/jumpToOuterScope.kt"); + doTest(fileName); + } + + @TestMetadata("kt10105.kt") + public void testKt10105() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/bugs/kt10105.kt"); + doTest(fileName); + } + + @TestMetadata("kt7761.kt") + public void testKt7761() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/bugs/kt7761.kt"); + doTest(fileName); + } + + @TestMetadata("setWithTypeMismatch.kt") + public void testSetWithTypeMismatch() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/bugs/setWithTypeMismatch.kt"); + doTest(fileName); + } + + @TestMetadata("unresolvedInvokeOnResolvedVar.kt") + public void testUnresolvedInvokeOnResolvedVar() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/bugs/unresolvedInvokeOnResolvedVar.kt"); + doTest(fileName); + } + } + + @TestMetadata("compiler/testData/cfg/controlStructures") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ControlStructures extends AbstractControlFlowTest { + public void testAllFilesPresentInControlStructures() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/controlStructures"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("breakContinueInTryFinally.kt") + public void testBreakContinueInTryFinally() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/breakContinueInTryFinally.kt"); + doTest(fileName); + } + + @TestMetadata("breakInsideLocal.kt") + public void testBreakInsideLocal() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/breakInsideLocal.kt"); + doTest(fileName); + } + + @TestMetadata("continueInDoWhile.kt") + public void testContinueInDoWhile() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/continueInDoWhile.kt"); + doTest(fileName); + } + + @TestMetadata("continueInFor.kt") + public void testContinueInFor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/continueInFor.kt"); + doTest(fileName); + } + + @TestMetadata("continueInWhile.kt") + public void testContinueInWhile() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/continueInWhile.kt"); + doTest(fileName); + } + + @TestMetadata("Finally.kt") + public void testFinally() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/Finally.kt"); + doTest(fileName); + } + + @TestMetadata("FinallyTestCopy.kt") + public void testFinallyTestCopy() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/FinallyTestCopy.kt"); + doTest(fileName); + } + + @TestMetadata("For.kt") + public void testFor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/For.kt"); + doTest(fileName); + } + + @TestMetadata("If.kt") + public void testIf() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/If.kt"); + doTest(fileName); + } + + @TestMetadata("incorrectIndex.kt") + public void testIncorrectIndex() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/incorrectIndex.kt"); + doTest(fileName); + } + + @TestMetadata("InfiniteLoops.kt") + public void testInfiniteLoops() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/InfiniteLoops.kt"); + doTest(fileName); + } + + @TestMetadata("localAndNonlocalReturnsWithFinally.kt") + public void testLocalAndNonlocalReturnsWithFinally() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/localAndNonlocalReturnsWithFinally.kt"); + doTest(fileName); + } + + @TestMetadata("localFunctionInFinally.kt") + public void testLocalFunctionInFinally() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/localFunctionInFinally.kt"); + doTest(fileName); + } + + @TestMetadata("OnlyWhileInFunctionBody.kt") + public void testOnlyWhileInFunctionBody() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/OnlyWhileInFunctionBody.kt"); + doTest(fileName); + } + + @TestMetadata("returnsInWhen.kt") + public void testReturnsInWhen() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/returnsInWhen.kt"); + doTest(fileName); + } + + @TestMetadata("whenConditions.kt") + public void testWhenConditions() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/whenConditions.kt"); + doTest(fileName); + } + + @TestMetadata("whenExhaustive.kt") + public void testWhenExhaustive() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/whenExhaustive.kt"); + doTest(fileName); + } + } + + @TestMetadata("compiler/testData/cfg/conventions") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Conventions extends AbstractControlFlowTest { + public void testAllFilesPresentInConventions() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/conventions"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("bothReceivers.kt") + public void testBothReceivers() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/conventions/bothReceivers.kt"); + doTest(fileName); + } + + @TestMetadata("equals.kt") + public void testEquals() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/conventions/equals.kt"); + doTest(fileName); + } + + @TestMetadata("incrementAtTheEnd.kt") + public void testIncrementAtTheEnd() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/conventions/incrementAtTheEnd.kt"); + doTest(fileName); + } + + @TestMetadata("invoke.kt") + public void testInvoke() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/conventions/invoke.kt"); + doTest(fileName); + } + + @TestMetadata("notEqual.kt") + public void testNotEqual() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/conventions/notEqual.kt"); + doTest(fileName); + } + } + + @TestMetadata("compiler/testData/cfg/deadCode") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class DeadCode extends AbstractControlFlowTest { + public void testAllFilesPresentInDeadCode() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/deadCode"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("DeadCode.kt") + public void testDeadCode() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/deadCode/DeadCode.kt"); + doTest(fileName); + } + + @TestMetadata("notLocalReturn.kt") + public void testNotLocalReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/deadCode/notLocalReturn.kt"); + doTest(fileName); + } + + @TestMetadata("returnInElvis.kt") + public void testReturnInElvis() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/deadCode/returnInElvis.kt"); + doTest(fileName); + } + + @TestMetadata("stringTemplate.kt") + public void testStringTemplate() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/deadCode/stringTemplate.kt"); + doTest(fileName); + } + + @TestMetadata("throwInLambda.kt") + public void testThrowInLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/deadCode/throwInLambda.kt"); + doTest(fileName); + } + } + + @TestMetadata("compiler/testData/cfg/declarations") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Declarations extends AbstractControlFlowTest { + public void testAllFilesPresentInDeclarations() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/declarations"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("compiler/testData/cfg/declarations/classesAndObjects") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ClassesAndObjects extends AbstractControlFlowTest { + public void testAllFilesPresentInClassesAndObjects() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/declarations/classesAndObjects"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("AnonymousInitializers.kt") + public void testAnonymousInitializers() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/classesAndObjects/AnonymousInitializers.kt"); + doTest(fileName); + } + + @TestMetadata("delegationByExpression.kt") + public void testDelegationByExpression() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/classesAndObjects/delegationByExpression.kt"); + doTest(fileName); + } + + @TestMetadata("delegationBySuperCall.kt") + public void testDelegationBySuperCall() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/classesAndObjects/delegationBySuperCall.kt"); + doTest(fileName); + } + + @TestMetadata("EnumEntryRefersCompanion.kt") + public void testEnumEntryRefersCompanion() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/classesAndObjects/EnumEntryRefersCompanion.kt"); + doTest(fileName); + } + + @TestMetadata("ObjectEnumQualifiers.kt") + public void testObjectEnumQualifiers() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/classesAndObjects/ObjectEnumQualifiers.kt"); + doTest(fileName); + } + + @TestMetadata("QualifierReceiverWithOthers.kt") + public void testQualifierReceiverWithOthers() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/classesAndObjects/QualifierReceiverWithOthers.kt"); + doTest(fileName); + } + } + + @TestMetadata("compiler/testData/cfg/declarations/functionLiterals") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class FunctionLiterals extends AbstractControlFlowTest { + public void testAllFilesPresentInFunctionLiterals() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/declarations/functionLiterals"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("unusedFunctionLiteral.kt") + public void testUnusedFunctionLiteral() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/functionLiterals/unusedFunctionLiteral.kt"); + doTest(fileName); + } + } + + @TestMetadata("compiler/testData/cfg/declarations/functions") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Functions extends AbstractControlFlowTest { + public void testAllFilesPresentInFunctions() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/declarations/functions"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("anonymousFunctionInBlock.kt") + public void testAnonymousFunctionInBlock() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/functions/anonymousFunctionInBlock.kt"); + doTest(fileName); + } + + @TestMetadata("FailFunction.kt") + public void testFailFunction() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/functions/FailFunction.kt"); + doTest(fileName); + } + + @TestMetadata("functionAsExpression.kt") + public void testFunctionAsExpression() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/functions/functionAsExpression.kt"); + doTest(fileName); + } + + @TestMetadata("namedFunctionInBlock.kt") + public void testNamedFunctionInBlock() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/functions/namedFunctionInBlock.kt"); + doTest(fileName); + } + + @TestMetadata("typeParameter.kt") + public void testTypeParameter() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/functions/typeParameter.kt"); + doTest(fileName); + } + } + + @TestMetadata("compiler/testData/cfg/declarations/local") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Local extends AbstractControlFlowTest { + public void testAllFilesPresentInLocal() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/declarations/local"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("localClass.kt") + public void testLocalClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/localClass.kt"); + doTest(fileName); + } + + @TestMetadata("LocalDeclarations.kt") + public void testLocalDeclarations() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/LocalDeclarations.kt"); + doTest(fileName); + } + + @TestMetadata("localDelegatedVal.kt") + public void testLocalDelegatedVal() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/localDelegatedVal.kt"); + doTest(fileName); + } + + @TestMetadata("localFunction.kt") + public void testLocalFunction() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/localFunction.kt"); + doTest(fileName); + } + + @TestMetadata("localProperty.kt") + public void testLocalProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/localProperty.kt"); + doTest(fileName); + } + + @TestMetadata("ObjectExpression.kt") + public void testObjectExpression() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/ObjectExpression.kt"); + doTest(fileName); + } + } + + @TestMetadata("compiler/testData/cfg/declarations/multiDeclaration") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class MultiDeclaration extends AbstractControlFlowTest { + public void testAllFilesPresentInMultiDeclaration() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/declarations/multiDeclaration"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("MultiDecl.kt") + public void testMultiDecl() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/multiDeclaration/MultiDecl.kt"); + doTest(fileName); + } + + @TestMetadata("multiDeclarationWithError.kt") + public void testMultiDeclarationWithError() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/multiDeclaration/multiDeclarationWithError.kt"); + doTest(fileName); + } + } + + @TestMetadata("compiler/testData/cfg/declarations/properties") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Properties extends AbstractControlFlowTest { + public void testAllFilesPresentInProperties() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/declarations/properties"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("DelegatedProperty.kt") + public void testDelegatedProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/properties/DelegatedProperty.kt"); + doTest(fileName); + } + + @TestMetadata("unreachableDelegation.kt") + public void testUnreachableDelegation() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/properties/unreachableDelegation.kt"); + doTest(fileName); + } + } + } + + @TestMetadata("compiler/testData/cfg/expressions") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Expressions extends AbstractControlFlowTest { + public void testAllFilesPresentInExpressions() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/expressions"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("assignmentToThis.kt") + public void testAssignmentToThis() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/assignmentToThis.kt"); + doTest(fileName); + } + + @TestMetadata("Assignments.kt") + public void testAssignments() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/Assignments.kt"); + doTest(fileName); + } + + @TestMetadata("callableReferences.kt") + public void testCallableReferences() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/callableReferences.kt"); + doTest(fileName); + } + + @TestMetadata("casts.kt") + public void testCasts() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/casts.kt"); + doTest(fileName); + } + + @TestMetadata("chainedQualifiedExpression.kt") + public void testChainedQualifiedExpression() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/chainedQualifiedExpression.kt"); + doTest(fileName); + } + + @TestMetadata("expressionAsFunction.kt") + public void testExpressionAsFunction() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/expressionAsFunction.kt"); + doTest(fileName); + } + + @TestMetadata("incdec.kt") + public void testIncdec() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/incdec.kt"); + doTest(fileName); + } + + @TestMetadata("invalidVariableCall.kt") + public void testInvalidVariableCall() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/invalidVariableCall.kt"); + doTest(fileName); + } + + @TestMetadata("labeledExpression.kt") + public void testLabeledExpression() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/labeledExpression.kt"); + doTest(fileName); + } + + @TestMetadata("LazyBooleans.kt") + public void testLazyBooleans() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/LazyBooleans.kt"); + doTest(fileName); + } + + @TestMetadata("nothingExpr.kt") + public void testNothingExpr() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/nothingExpr.kt"); + doTest(fileName); + } + + @TestMetadata("parenthesizedSelector.kt") + public void testParenthesizedSelector() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/parenthesizedSelector.kt"); + doTest(fileName); + } + + @TestMetadata("propertySafeCall.kt") + public void testPropertySafeCall() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/propertySafeCall.kt"); + doTest(fileName); + } + + @TestMetadata("qualifiedExpressionWithoutSelector.kt") + public void testQualifiedExpressionWithoutSelector() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/qualifiedExpressionWithoutSelector.kt"); + doTest(fileName); + } + + @TestMetadata("ReturnFromExpression.kt") + public void testReturnFromExpression() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/ReturnFromExpression.kt"); + doTest(fileName); + } + + @TestMetadata("thisExpression.kt") + public void testThisExpression() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/thisExpression.kt"); + doTest(fileName); + } + + @TestMetadata("unresolvedCall.kt") + public void testUnresolvedCall() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/unresolvedCall.kt"); + doTest(fileName); + } + + @TestMetadata("unresolvedCalls.kt") + public void testUnresolvedCalls() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/unresolvedCalls.kt"); + doTest(fileName); + } + + @TestMetadata("unresolvedCallsWithReceiver.kt") + public void testUnresolvedCallsWithReceiver() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/unresolvedCallsWithReceiver.kt"); + doTest(fileName); + } + + @TestMetadata("unresolvedProperty.kt") + public void testUnresolvedProperty() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/unresolvedProperty.kt"); + doTest(fileName); + } + + @TestMetadata("unresolvedWriteLHS.kt") + public void testUnresolvedWriteLHS() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/unresolvedWriteLHS.kt"); + doTest(fileName); + } + + @TestMetadata("unsupportedReturns.kt") + public void testUnsupportedReturns() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/unsupportedReturns.kt"); + doTest(fileName); + } + + @TestMetadata("unusedExpressionSimpleName.kt") + public void testUnusedExpressionSimpleName() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/unusedExpressionSimpleName.kt"); + doTest(fileName); + } + } + + @TestMetadata("compiler/testData/cfg/functions") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) public static class Functions extends AbstractControlFlowTest { public void testAllFilesPresentInFunctions() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/declarations/functions"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/functions"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); } - @TestMetadata("anonymousFunctionInBlock.kt") - public void testAnonymousFunctionInBlock() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/functions/anonymousFunctionInBlock.kt"); + @TestMetadata("DefaultValuesForArguments.kt") + public void testDefaultValuesForArguments() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/functions/DefaultValuesForArguments.kt"); doTest(fileName); } - @TestMetadata("FailFunction.kt") - public void testFailFunction() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/functions/FailFunction.kt"); - doTest(fileName); - } - - @TestMetadata("functionAsExpression.kt") - public void testFunctionAsExpression() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/functions/functionAsExpression.kt"); - doTest(fileName); - } - - @TestMetadata("namedFunctionInBlock.kt") - public void testNamedFunctionInBlock() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/functions/namedFunctionInBlock.kt"); - doTest(fileName); - } - - @TestMetadata("typeParameter.kt") - public void testTypeParameter() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/functions/typeParameter.kt"); + @TestMetadata("unmappedArgs.kt") + public void testUnmappedArgs() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/functions/unmappedArgs.kt"); doTest(fileName); } } - @TestMetadata("compiler/testData/cfg/declarations/local") + @TestMetadata("compiler/testData/cfg/secondaryConstructors") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) - public static class Local extends AbstractControlFlowTest { - public void testAllFilesPresentInLocal() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/declarations/local"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + public static class SecondaryConstructors extends AbstractControlFlowTest { + public void testAllFilesPresentInSecondaryConstructors() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/secondaryConstructors"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); } - @TestMetadata("localClass.kt") - public void testLocalClass() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/localClass.kt"); + @TestMetadata("withPrimary.kt") + public void testWithPrimary() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/secondaryConstructors/withPrimary.kt"); doTest(fileName); } - @TestMetadata("LocalDeclarations.kt") - public void testLocalDeclarations() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/LocalDeclarations.kt"); + @TestMetadata("withPrimarySuper.kt") + public void testWithPrimarySuper() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/secondaryConstructors/withPrimarySuper.kt"); doTest(fileName); } - @TestMetadata("localDelegatedVal.kt") - public void testLocalDelegatedVal() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/localDelegatedVal.kt"); + @TestMetadata("withReturn.kt") + public void testWithReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/secondaryConstructors/withReturn.kt"); doTest(fileName); } - @TestMetadata("localFunction.kt") - public void testLocalFunction() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/localFunction.kt"); + @TestMetadata("withoutPrimary.kt") + public void testWithoutPrimary() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/secondaryConstructors/withoutPrimary.kt"); doTest(fileName); } - @TestMetadata("localProperty.kt") - public void testLocalProperty() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/localProperty.kt"); - doTest(fileName); - } - - @TestMetadata("ObjectExpression.kt") - public void testObjectExpression() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/local/ObjectExpression.kt"); + @TestMetadata("withoutPrimarySuper.kt") + public void testWithoutPrimarySuper() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/secondaryConstructors/withoutPrimarySuper.kt"); doTest(fileName); } } - @TestMetadata("compiler/testData/cfg/declarations/multiDeclaration") + @TestMetadata("compiler/testData/cfg/tailCalls") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) - public static class MultiDeclaration extends AbstractControlFlowTest { - public void testAllFilesPresentInMultiDeclaration() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/declarations/multiDeclaration"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + public static class TailCalls extends AbstractControlFlowTest { + public void testAllFilesPresentInTailCalls() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/tailCalls"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); } - @TestMetadata("MultiDecl.kt") - public void testMultiDecl() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/multiDeclaration/MultiDecl.kt"); + @TestMetadata("finally.kt") + public void testFinally() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/tailCalls/finally.kt"); doTest(fileName); } - @TestMetadata("multiDeclarationWithError.kt") - public void testMultiDeclarationWithError() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/multiDeclaration/multiDeclarationWithError.kt"); + @TestMetadata("finallyWithReturn.kt") + public void testFinallyWithReturn() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/tailCalls/finallyWithReturn.kt"); + doTest(fileName); + } + + @TestMetadata("sum.kt") + public void testSum() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/tailCalls/sum.kt"); + doTest(fileName); + } + + @TestMetadata("try.kt") + public void testTry() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/tailCalls/try.kt"); + doTest(fileName); + } + + @TestMetadata("tryCatchFinally.kt") + public void testTryCatchFinally() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/tailCalls/tryCatchFinally.kt"); doTest(fileName); } } + } - @TestMetadata("compiler/testData/cfg/declarations/properties") + @TestMetadata("compiler/testData/cfgWithStdLib") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class CfgWithStdLib extends AbstractControlFlowTest { + public void testAllFilesPresentInCfgWithStdLib() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfgWithStdLib"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("compiler/testData/cfgWithStdLib/contracts") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) - public static class Properties extends AbstractControlFlowTest { - public void testAllFilesPresentInProperties() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/declarations/properties"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + public static class Contracts extends AbstractControlFlowTest { + public void testAllFilesPresentInContracts() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfgWithStdLib/contracts"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); } - @TestMetadata("DelegatedProperty.kt") - public void testDelegatedProperty() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/properties/DelegatedProperty.kt"); - doTest(fileName); + @TestMetadata("labeledReturns.kt") + public void testLabeledReturns() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgWithStdLib/contracts/labeledReturns.kt"); + doTestWithStdLib(fileName); } - @TestMetadata("unreachableDelegation.kt") - public void testUnreachableDelegation() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/declarations/properties/unreachableDelegation.kt"); - doTest(fileName); + @TestMetadata("nonReturningInlinedLambda.kt") + public void testNonReturningInlinedLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgWithStdLib/contracts/nonReturningInlinedLambda.kt"); + doTestWithStdLib(fileName); } - } - } - @TestMetadata("compiler/testData/cfg/expressions") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class Expressions extends AbstractControlFlowTest { - public void testAllFilesPresentInExpressions() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/expressions"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); - } + @TestMetadata("returnsAndCalls.kt") + public void testReturnsAndCalls() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgWithStdLib/contracts/returnsAndCalls.kt"); + doTestWithStdLib(fileName); + } - @TestMetadata("assignmentToThis.kt") - public void testAssignmentToThis() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/assignmentToThis.kt"); - doTest(fileName); - } + @TestMetadata("throwIfNotCalled.kt") + public void testThrowIfNotCalled() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgWithStdLib/contracts/throwIfNotCalled.kt"); + doTestWithStdLib(fileName); + } - @TestMetadata("Assignments.kt") - public void testAssignments() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/Assignments.kt"); - doTest(fileName); - } - - @TestMetadata("callableReferences.kt") - public void testCallableReferences() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/callableReferences.kt"); - doTest(fileName); - } - - @TestMetadata("casts.kt") - public void testCasts() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/casts.kt"); - doTest(fileName); - } - - @TestMetadata("chainedQualifiedExpression.kt") - public void testChainedQualifiedExpression() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/chainedQualifiedExpression.kt"); - doTest(fileName); - } - - @TestMetadata("expressionAsFunction.kt") - public void testExpressionAsFunction() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/expressionAsFunction.kt"); - doTest(fileName); - } - - @TestMetadata("incdec.kt") - public void testIncdec() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/incdec.kt"); - doTest(fileName); - } - - @TestMetadata("invalidVariableCall.kt") - public void testInvalidVariableCall() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/invalidVariableCall.kt"); - doTest(fileName); - } - - @TestMetadata("labeledExpression.kt") - public void testLabeledExpression() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/labeledExpression.kt"); - doTest(fileName); - } - - @TestMetadata("LazyBooleans.kt") - public void testLazyBooleans() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/LazyBooleans.kt"); - doTest(fileName); - } - - @TestMetadata("nothingExpr.kt") - public void testNothingExpr() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/nothingExpr.kt"); - doTest(fileName); - } - - @TestMetadata("parenthesizedSelector.kt") - public void testParenthesizedSelector() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/parenthesizedSelector.kt"); - doTest(fileName); - } - - @TestMetadata("propertySafeCall.kt") - public void testPropertySafeCall() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/propertySafeCall.kt"); - doTest(fileName); - } - - @TestMetadata("qualifiedExpressionWithoutSelector.kt") - public void testQualifiedExpressionWithoutSelector() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/qualifiedExpressionWithoutSelector.kt"); - doTest(fileName); - } - - @TestMetadata("ReturnFromExpression.kt") - public void testReturnFromExpression() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/ReturnFromExpression.kt"); - doTest(fileName); - } - - @TestMetadata("thisExpression.kt") - public void testThisExpression() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/thisExpression.kt"); - doTest(fileName); - } - - @TestMetadata("unresolvedCall.kt") - public void testUnresolvedCall() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/unresolvedCall.kt"); - doTest(fileName); - } - - @TestMetadata("unresolvedCalls.kt") - public void testUnresolvedCalls() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/unresolvedCalls.kt"); - doTest(fileName); - } - - @TestMetadata("unresolvedCallsWithReceiver.kt") - public void testUnresolvedCallsWithReceiver() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/unresolvedCallsWithReceiver.kt"); - doTest(fileName); - } - - @TestMetadata("unresolvedProperty.kt") - public void testUnresolvedProperty() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/unresolvedProperty.kt"); - doTest(fileName); - } - - @TestMetadata("unresolvedWriteLHS.kt") - public void testUnresolvedWriteLHS() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/unresolvedWriteLHS.kt"); - doTest(fileName); - } - - @TestMetadata("unsupportedReturns.kt") - public void testUnsupportedReturns() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/unsupportedReturns.kt"); - doTest(fileName); - } - - @TestMetadata("unusedExpressionSimpleName.kt") - public void testUnusedExpressionSimpleName() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/expressions/unusedExpressionSimpleName.kt"); - doTest(fileName); - } - } - - @TestMetadata("compiler/testData/cfg/functions") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class Functions extends AbstractControlFlowTest { - public void testAllFilesPresentInFunctions() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/functions"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); - } - - @TestMetadata("DefaultValuesForArguments.kt") - public void testDefaultValuesForArguments() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/functions/DefaultValuesForArguments.kt"); - doTest(fileName); - } - - @TestMetadata("unmappedArgs.kt") - public void testUnmappedArgs() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/functions/unmappedArgs.kt"); - doTest(fileName); - } - } - - @TestMetadata("compiler/testData/cfg/secondaryConstructors") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class SecondaryConstructors extends AbstractControlFlowTest { - public void testAllFilesPresentInSecondaryConstructors() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/secondaryConstructors"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); - } - - @TestMetadata("withPrimary.kt") - public void testWithPrimary() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/secondaryConstructors/withPrimary.kt"); - doTest(fileName); - } - - @TestMetadata("withPrimarySuper.kt") - public void testWithPrimarySuper() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/secondaryConstructors/withPrimarySuper.kt"); - doTest(fileName); - } - - @TestMetadata("withReturn.kt") - public void testWithReturn() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/secondaryConstructors/withReturn.kt"); - doTest(fileName); - } - - @TestMetadata("withoutPrimary.kt") - public void testWithoutPrimary() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/secondaryConstructors/withoutPrimary.kt"); - doTest(fileName); - } - - @TestMetadata("withoutPrimarySuper.kt") - public void testWithoutPrimarySuper() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/secondaryConstructors/withoutPrimarySuper.kt"); - doTest(fileName); - } - } - - @TestMetadata("compiler/testData/cfg/tailCalls") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class TailCalls extends AbstractControlFlowTest { - public void testAllFilesPresentInTailCalls() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg/tailCalls"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); - } - - @TestMetadata("finally.kt") - public void testFinally() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/tailCalls/finally.kt"); - doTest(fileName); - } - - @TestMetadata("finallyWithReturn.kt") - public void testFinallyWithReturn() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/tailCalls/finallyWithReturn.kt"); - doTest(fileName); - } - - @TestMetadata("sum.kt") - public void testSum() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/tailCalls/sum.kt"); - doTest(fileName); - } - - @TestMetadata("try.kt") - public void testTry() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/tailCalls/try.kt"); - doTest(fileName); - } - - @TestMetadata("tryCatchFinally.kt") - public void testTryCatchFinally() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg/tailCalls/tryCatchFinally.kt"); - doTest(fileName); + @TestMetadata("tryCatchFinally.kt") + public void testTryCatchFinally() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgWithStdLib/contracts/tryCatchFinally.kt"); + doTestWithStdLib(fileName); + } } } } diff --git a/compiler/tests/org/jetbrains/kotlin/cfg/DataFlowTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/cfg/DataFlowTestGenerated.java index c2fd4f85086..2f7ba44e25e 100644 --- a/compiler/tests/org/jetbrains/kotlin/cfg/DataFlowTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/cfg/DataFlowTestGenerated.java @@ -28,218 +28,299 @@ import java.util.regex.Pattern; /** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") -@TestMetadata("compiler/testData/cfg-variables") -@TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) public class DataFlowTestGenerated extends AbstractDataFlowTest { - public void testAllFilesPresentInCfg_variables() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg-variables"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); - } - - @TestMetadata("compiler/testData/cfg-variables/basic") + @TestMetadata("compiler/testData/cfg-variables") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) - public static class Basic extends AbstractDataFlowTest { - public void testAllFilesPresentInBasic() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg-variables/basic"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + public static class Cfg_variables extends AbstractDataFlowTest { + public void testAllFilesPresentInCfg_variables() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg-variables"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); } - @TestMetadata("ExhaustiveInitialization.kt") - public void testExhaustiveInitialization() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/ExhaustiveInitialization.kt"); - doTest(fileName); + @TestMetadata("compiler/testData/cfg-variables/basic") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Basic extends AbstractDataFlowTest { + public void testAllFilesPresentInBasic() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg-variables/basic"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("ExhaustiveInitialization.kt") + public void testExhaustiveInitialization() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/ExhaustiveInitialization.kt"); + doTest(fileName); + } + + @TestMetadata("IfWithUninitialized.kt") + public void testIfWithUninitialized() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/IfWithUninitialized.kt"); + doTest(fileName); + } + + @TestMetadata("InitializedNotDeclared.kt") + public void testInitializedNotDeclared() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/InitializedNotDeclared.kt"); + doTest(fileName); + } + + @TestMetadata("UsageInFunctionLiteral.kt") + public void testUsageInFunctionLiteral() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.kt"); + doTest(fileName); + } + + @TestMetadata("UseUninitializedInLambda.kt") + public void testUseUninitializedInLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/UseUninitializedInLambda.kt"); + doTest(fileName); + } + + @TestMetadata("VariablesInitialization.kt") + public void testVariablesInitialization() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/VariablesInitialization.kt"); + doTest(fileName); + } + + @TestMetadata("VariablesUsage.kt") + public void testVariablesUsage() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/VariablesUsage.kt"); + doTest(fileName); + } } - @TestMetadata("IfWithUninitialized.kt") - public void testIfWithUninitialized() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/IfWithUninitialized.kt"); - doTest(fileName); + @TestMetadata("compiler/testData/cfg-variables/bugs") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Bugs extends AbstractDataFlowTest { + public void testAllFilesPresentInBugs() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg-variables/bugs"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("doWhileAssignment.kt") + public void testDoWhileAssignment() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/doWhileAssignment.kt"); + doTest(fileName); + } + + @TestMetadata("doWhileNotDefined.kt") + public void testDoWhileNotDefined() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/doWhileNotDefined.kt"); + doTest(fileName); + } + + @TestMetadata("initializationInLocalClass.kt") + public void testInitializationInLocalClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/initializationInLocalClass.kt"); + doTest(fileName); + } + + @TestMetadata("kt10243.kt") + public void testKt10243() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/kt10243.kt"); + doTest(fileName); + } + + @TestMetadata("kt4764.kt") + public void testKt4764() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/kt4764.kt"); + doTest(fileName); + } + + @TestMetadata("kt5469.kt") + public void testKt5469() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/kt5469.kt"); + doTest(fileName); + } + + @TestMetadata("kt9825.kt") + public void testKt9825() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/kt9825.kt"); + 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"); + doTest(fileName); + } + + @TestMetadata("varInitializationInIf.kt") + public void testVarInitializationInIf() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/varInitializationInIf.kt"); + doTest(fileName); + } + + @TestMetadata("varInitializationInIfInCycle.kt") + public void testVarInitializationInIfInCycle() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/varInitializationInIfInCycle.kt"); + doTest(fileName); + } } - @TestMetadata("InitializedNotDeclared.kt") - public void testInitializedNotDeclared() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/InitializedNotDeclared.kt"); - doTest(fileName); - } + @TestMetadata("compiler/testData/cfg-variables/lexicalScopes") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class LexicalScopes extends AbstractDataFlowTest { + public void testAllFilesPresentInLexicalScopes() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg-variables/lexicalScopes"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } - @TestMetadata("UsageInFunctionLiteral.kt") - public void testUsageInFunctionLiteral() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.kt"); - doTest(fileName); - } + @TestMetadata("doWhileScope.kt") + public void testDoWhileScope() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/doWhileScope.kt"); + doTest(fileName); + } - @TestMetadata("UseUninitializedInLambda.kt") - public void testUseUninitializedInLambda() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/UseUninitializedInLambda.kt"); - doTest(fileName); - } + @TestMetadata("forScope.kt") + public void testForScope() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/forScope.kt"); + doTest(fileName); + } - @TestMetadata("VariablesInitialization.kt") - public void testVariablesInitialization() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/VariablesInitialization.kt"); - doTest(fileName); - } + @TestMetadata("functionLiteralScope.kt") + public void testFunctionLiteralScope() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/functionLiteralScope.kt"); + doTest(fileName); + } - @TestMetadata("VariablesUsage.kt") - public void testVariablesUsage() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/basic/VariablesUsage.kt"); - doTest(fileName); + @TestMetadata("ifScope.kt") + public void testIfScope() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/ifScope.kt"); + doTest(fileName); + } + + @TestMetadata("localClass.kt") + public void testLocalClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/localClass.kt"); + doTest(fileName); + } + + @TestMetadata("localFunctionScope.kt") + public void testLocalFunctionScope() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/localFunctionScope.kt"); + doTest(fileName); + } + + @TestMetadata("localFunctionScopeWithoutBody.kt") + public void testLocalFunctionScopeWithoutBody() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/localFunctionScopeWithoutBody.kt"); + doTest(fileName); + } + + @TestMetadata("localObject.kt") + public void testLocalObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/localObject.kt"); + doTest(fileName); + } + + @TestMetadata("objectLiteralScope.kt") + public void testObjectLiteralScope() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/objectLiteralScope.kt"); + doTest(fileName); + } + + @TestMetadata("propertyAccessorScope.kt") + public void testPropertyAccessorScope() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/propertyAccessorScope.kt"); + doTest(fileName); + } + + @TestMetadata("tryScope.kt") + public void testTryScope() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/tryScope.kt"); + doTest(fileName); + } + + @TestMetadata("whileScope.kt") + public void testWhileScope() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/whileScope.kt"); + doTest(fileName); + } } } - @TestMetadata("compiler/testData/cfg-variables/bugs") + @TestMetadata("compiler/testData/cfgVariablesWithStdLib") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) - public static class Bugs extends AbstractDataFlowTest { - public void testAllFilesPresentInBugs() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg-variables/bugs"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + public static class CfgVariablesWithStdLib extends AbstractDataFlowTest { + public void testAllFilesPresentInCfgVariablesWithStdLib() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfgVariablesWithStdLib"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); } - @TestMetadata("doWhileAssignment.kt") - public void testDoWhileAssignment() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/doWhileAssignment.kt"); - doTest(fileName); - } + @TestMetadata("compiler/testData/cfgVariablesWithStdLib/contracts") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Contracts extends AbstractDataFlowTest { + public void testAllFilesPresentInContracts() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfgVariablesWithStdLib/contracts"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } - @TestMetadata("doWhileNotDefined.kt") - public void testDoWhileNotDefined() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/doWhileNotDefined.kt"); - doTest(fileName); - } + @TestMetadata("breakContinuesInInlinedLambda.kt") + public void testBreakContinuesInInlinedLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/breakContinuesInInlinedLambda.kt"); + doTestWithStdLib(fileName); + } - @TestMetadata("initializationInLocalClass.kt") - public void testInitializationInLocalClass() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/initializationInLocalClass.kt"); - doTest(fileName); - } + @TestMetadata("inlinedLambdaAlwaysThrows.kt") + public void testInlinedLambdaAlwaysThrows() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/inlinedLambdaAlwaysThrows.kt"); + doTestWithStdLib(fileName); + } - @TestMetadata("kt10243.kt") - public void testKt10243() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/kt10243.kt"); - doTest(fileName); - } + @TestMetadata("irrelevantUnknownClosure.kt") + public void testIrrelevantUnknownClosure() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/irrelevantUnknownClosure.kt"); + doTestWithStdLib(fileName); + } - @TestMetadata("kt4764.kt") - public void testKt4764() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/kt4764.kt"); - doTest(fileName); - } + @TestMetadata("nestedTryCatchFinally.kt") + public void testNestedTryCatchFinally() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchFinally.kt"); + doTestWithStdLib(fileName); + } - @TestMetadata("kt5469.kt") - public void testKt5469() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/kt5469.kt"); - doTest(fileName); - } + @TestMetadata("nestedTryCatchs.kt") + public void testNestedTryCatchs() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchs.kt"); + doTestWithStdLib(fileName); + } - @TestMetadata("kt9825.kt") - public void testKt9825() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/kt9825.kt"); - doTest(fileName); - } + @TestMetadata("nonReturningInlinedLambda.kt") + public void testNonReturningInlinedLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/nonReturningInlinedLambda.kt"); + doTestWithStdLib(fileName); + } - @TestMetadata("localObjectInConstructor.kt") - public void testLocalObjectInConstructor() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/localObjectInConstructor.kt"); - doTest(fileName); - } + @TestMetadata("returnsAndCalls.kt") + public void testReturnsAndCalls() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/returnsAndCalls.kt"); + doTestWithStdLib(fileName); + } - @TestMetadata("referenceToPropertyInitializer.kt") - public void testReferenceToPropertyInitializer() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/referenceToPropertyInitializer.kt"); - doTest(fileName); - } + @TestMetadata("throwIfNotCalled.kt") + public void testThrowIfNotCalled() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/throwIfNotCalled.kt"); + doTestWithStdLib(fileName); + } - @TestMetadata("varInitializationInIf.kt") - public void testVarInitializationInIf() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/varInitializationInIf.kt"); - doTest(fileName); - } + @TestMetadata("tryCatch.kt") + public void testTryCatch() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/tryCatch.kt"); + doTestWithStdLib(fileName); + } - @TestMetadata("varInitializationInIfInCycle.kt") - public void testVarInitializationInIfInCycle() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/bugs/varInitializationInIfInCycle.kt"); - doTest(fileName); - } - } - - @TestMetadata("compiler/testData/cfg-variables/lexicalScopes") - @TestDataPath("$PROJECT_ROOT") - @RunWith(JUnit3RunnerWithInners.class) - public static class LexicalScopes extends AbstractDataFlowTest { - public void testAllFilesPresentInLexicalScopes() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfg-variables/lexicalScopes"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); - } - - @TestMetadata("doWhileScope.kt") - public void testDoWhileScope() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/doWhileScope.kt"); - doTest(fileName); - } - - @TestMetadata("forScope.kt") - public void testForScope() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/forScope.kt"); - doTest(fileName); - } - - @TestMetadata("functionLiteralScope.kt") - public void testFunctionLiteralScope() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/functionLiteralScope.kt"); - doTest(fileName); - } - - @TestMetadata("ifScope.kt") - public void testIfScope() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/ifScope.kt"); - doTest(fileName); - } - - @TestMetadata("localClass.kt") - public void testLocalClass() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/localClass.kt"); - doTest(fileName); - } - - @TestMetadata("localFunctionScope.kt") - public void testLocalFunctionScope() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/localFunctionScope.kt"); - doTest(fileName); - } - - @TestMetadata("localFunctionScopeWithoutBody.kt") - public void testLocalFunctionScopeWithoutBody() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/localFunctionScopeWithoutBody.kt"); - doTest(fileName); - } - - @TestMetadata("localObject.kt") - public void testLocalObject() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/localObject.kt"); - doTest(fileName); - } - - @TestMetadata("objectLiteralScope.kt") - public void testObjectLiteralScope() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/objectLiteralScope.kt"); - doTest(fileName); - } - - @TestMetadata("propertyAccessorScope.kt") - public void testPropertyAccessorScope() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/propertyAccessorScope.kt"); - doTest(fileName); - } - - @TestMetadata("tryScope.kt") - public void testTryScope() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/tryScope.kt"); - doTest(fileName); - } - - @TestMetadata("whileScope.kt") - public void testWhileScope() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfg-variables/lexicalScopes/whileScope.kt"); - doTest(fileName); + @TestMetadata("tryCatchFinally.kt") + public void testTryCatchFinally() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/tryCatchFinally.kt"); + doTestWithStdLib(fileName); + } } } } diff --git a/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java index 30c02f1d0a8..1e0a3a7086d 100644 --- a/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java @@ -804,6 +804,54 @@ public class PseudoValueTestGenerated extends AbstractPseudoValueTest { } } + @TestMetadata("compiler/testData/cfgWithStdLib") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class CfgWithStdLib extends AbstractPseudoValueTest { + public void testAllFilesPresentInCfgWithStdLib() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfgWithStdLib"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("compiler/testData/cfgWithStdLib/contracts") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Contracts extends AbstractPseudoValueTest { + public void testAllFilesPresentInContracts() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfgWithStdLib/contracts"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("labeledReturns.kt") + public void testLabeledReturns() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgWithStdLib/contracts/labeledReturns.kt"); + doTestWithStdLib(fileName); + } + + @TestMetadata("nonReturningInlinedLambda.kt") + public void testNonReturningInlinedLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgWithStdLib/contracts/nonReturningInlinedLambda.kt"); + doTestWithStdLib(fileName); + } + + @TestMetadata("returnsAndCalls.kt") + public void testReturnsAndCalls() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgWithStdLib/contracts/returnsAndCalls.kt"); + doTestWithStdLib(fileName); + } + + @TestMetadata("throwIfNotCalled.kt") + public void testThrowIfNotCalled() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgWithStdLib/contracts/throwIfNotCalled.kt"); + doTestWithStdLib(fileName); + } + + @TestMetadata("tryCatchFinally.kt") + public void testTryCatchFinally() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgWithStdLib/contracts/tryCatchFinally.kt"); + doTestWithStdLib(fileName); + } + } + } + @TestMetadata("compiler/testData/cfg-variables") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) @@ -1019,4 +1067,82 @@ public class PseudoValueTestGenerated extends AbstractPseudoValueTest { } } } + + @TestMetadata("compiler/testData/cfgVariablesWithStdLib") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class CfgVariablesWithStdLib extends AbstractPseudoValueTest { + public void testAllFilesPresentInCfgVariablesWithStdLib() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfgVariablesWithStdLib"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("compiler/testData/cfgVariablesWithStdLib/contracts") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Contracts extends AbstractPseudoValueTest { + public void testAllFilesPresentInContracts() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cfgVariablesWithStdLib/contracts"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("breakContinuesInInlinedLambda.kt") + public void testBreakContinuesInInlinedLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/breakContinuesInInlinedLambda.kt"); + doTestWithStdLib(fileName); + } + + @TestMetadata("inlinedLambdaAlwaysThrows.kt") + public void testInlinedLambdaAlwaysThrows() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/inlinedLambdaAlwaysThrows.kt"); + doTestWithStdLib(fileName); + } + + @TestMetadata("irrelevantUnknownClosure.kt") + public void testIrrelevantUnknownClosure() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/irrelevantUnknownClosure.kt"); + doTestWithStdLib(fileName); + } + + @TestMetadata("nestedTryCatchFinally.kt") + public void testNestedTryCatchFinally() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchFinally.kt"); + doTestWithStdLib(fileName); + } + + @TestMetadata("nestedTryCatchs.kt") + public void testNestedTryCatchs() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/nestedTryCatchs.kt"); + doTestWithStdLib(fileName); + } + + @TestMetadata("nonReturningInlinedLambda.kt") + public void testNonReturningInlinedLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/nonReturningInlinedLambda.kt"); + doTestWithStdLib(fileName); + } + + @TestMetadata("returnsAndCalls.kt") + public void testReturnsAndCalls() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/returnsAndCalls.kt"); + doTestWithStdLib(fileName); + } + + @TestMetadata("throwIfNotCalled.kt") + public void testThrowIfNotCalled() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/throwIfNotCalled.kt"); + doTestWithStdLib(fileName); + } + + @TestMetadata("tryCatch.kt") + public void testTryCatch() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/tryCatch.kt"); + doTestWithStdLib(fileName); + } + + @TestMetadata("tryCatchFinally.kt") + public void testTryCatchFinally() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cfgVariablesWithStdLib/contracts/tryCatchFinally.kt"); + doTestWithStdLib(fileName); + } + } + } }