604 lines
14 KiB
Plaintext
604 lines
14 KiB
Plaintext
-- Test cases for data flow analysis.
|
|
|
|
[case testSimple_MaybeDefined]
|
|
def f(a: int) -> None:
|
|
x = 1
|
|
if x == a:
|
|
y = 1
|
|
else:
|
|
z = 1
|
|
[out]
|
|
def f(a):
|
|
a, x :: int
|
|
r0 :: native_int
|
|
r1, r2, r3 :: bit
|
|
y, z :: int
|
|
L0:
|
|
x = 2
|
|
r0 = x & 1
|
|
r1 = r0 != 0
|
|
if r1 goto L1 else goto L2 :: bool
|
|
L1:
|
|
r2 = CPyTagged_IsEq_(x, a)
|
|
if r2 goto L3 else goto L4 :: bool
|
|
L2:
|
|
r3 = x == a
|
|
if r3 goto L3 else goto L4 :: bool
|
|
L3:
|
|
y = 2
|
|
goto L5
|
|
L4:
|
|
z = 2
|
|
L5:
|
|
return 1
|
|
(0, 0) {a} {a, x}
|
|
(0, 1) {a, x} {a, x}
|
|
(0, 2) {a, x} {a, x}
|
|
(0, 3) {a, x} {a, x}
|
|
(1, 0) {a, x} {a, x}
|
|
(1, 1) {a, x} {a, x}
|
|
(2, 0) {a, x} {a, x}
|
|
(2, 1) {a, x} {a, x}
|
|
(3, 0) {a, x} {a, x, y}
|
|
(3, 1) {a, x, y} {a, x, y}
|
|
(4, 0) {a, x} {a, x, z}
|
|
(4, 1) {a, x, z} {a, x, z}
|
|
(5, 0) {a, x, y, z} {a, x, y, z}
|
|
|
|
[case testSimple_Liveness]
|
|
def f(a: int) -> int:
|
|
x = 1
|
|
if x == 1:
|
|
return a
|
|
else:
|
|
return x
|
|
[out]
|
|
def f(a):
|
|
a, x :: int
|
|
r0 :: bit
|
|
L0:
|
|
x = 2
|
|
r0 = x == 2
|
|
if r0 goto L1 else goto L2 :: bool
|
|
L1:
|
|
return a
|
|
L2:
|
|
return x
|
|
L3:
|
|
unreachable
|
|
(0, 0) {a} {a, x}
|
|
(0, 1) {a, x} {a, r0, x}
|
|
(0, 2) {a, r0, x} {a, x}
|
|
(1, 0) {a} {}
|
|
(2, 0) {x} {}
|
|
(3, 0) {} {}
|
|
|
|
[case testSpecial_Liveness]
|
|
def f() -> int:
|
|
x = 1
|
|
y = 1
|
|
x = 2
|
|
return x
|
|
[out]
|
|
def f():
|
|
x, y :: int
|
|
L0:
|
|
x = 2
|
|
y = 2
|
|
x = 4
|
|
return x
|
|
(0, 0) {} {}
|
|
(0, 1) {} {}
|
|
(0, 2) {} {x}
|
|
(0, 3) {x} {}
|
|
|
|
[case testSpecial2_Liveness]
|
|
def f(a: int) -> int:
|
|
a = 1
|
|
a = 2
|
|
a = 3
|
|
return a
|
|
[out]
|
|
def f(a):
|
|
a :: int
|
|
L0:
|
|
a = 2
|
|
a = 4
|
|
a = 6
|
|
return a
|
|
(0, 0) {} {}
|
|
(0, 1) {} {}
|
|
(0, 2) {} {a}
|
|
(0, 3) {a} {}
|
|
|
|
[case testSimple_MustDefined]
|
|
def f(a: int) -> None:
|
|
if a == 1:
|
|
y = 1
|
|
x = 2
|
|
else:
|
|
x = 2
|
|
[out]
|
|
def f(a):
|
|
a :: int
|
|
r0 :: bit
|
|
y, x :: int
|
|
L0:
|
|
r0 = a == 2
|
|
if r0 goto L1 else goto L2 :: bool
|
|
L1:
|
|
y = 2
|
|
x = 4
|
|
goto L3
|
|
L2:
|
|
x = 4
|
|
L3:
|
|
return 1
|
|
(0, 0) {a} {a}
|
|
(0, 1) {a} {a}
|
|
(1, 0) {a} {a, y}
|
|
(1, 1) {a, y} {a, x, y}
|
|
(1, 2) {a, x, y} {a, x, y}
|
|
(2, 0) {a} {a, x}
|
|
(2, 1) {a, x} {a, x}
|
|
(3, 0) {a, x} {a, x}
|
|
|
|
[case testTwoArgs_MustDefined]
|
|
def f(x: int, y: int) -> int:
|
|
return x
|
|
[out]
|
|
def f(x, y):
|
|
x, y :: int
|
|
L0:
|
|
return x
|
|
(0, 0) {x, y} {x, y}
|
|
|
|
[case testLoop_MustDefined]
|
|
def f(n: int) -> None:
|
|
while n < 5:
|
|
n = n + 1
|
|
m = n
|
|
[out]
|
|
def f(n):
|
|
n :: int
|
|
r0 :: native_int
|
|
r1, r2, r3 :: bit
|
|
r4, m :: int
|
|
L0:
|
|
L1:
|
|
r0 = n & 1
|
|
r1 = r0 != 0
|
|
if r1 goto L2 else goto L3 :: bool
|
|
L2:
|
|
r2 = CPyTagged_IsLt_(n, 10)
|
|
if r2 goto L4 else goto L5 :: bool
|
|
L3:
|
|
r3 = n < 10 :: signed
|
|
if r3 goto L4 else goto L5 :: bool
|
|
L4:
|
|
r4 = CPyTagged_Add(n, 2)
|
|
n = r4
|
|
m = n
|
|
goto L1
|
|
L5:
|
|
return 1
|
|
(0, 0) {n} {n}
|
|
(1, 0) {n} {n}
|
|
(1, 1) {n} {n}
|
|
(1, 2) {n} {n}
|
|
(2, 0) {n} {n}
|
|
(2, 1) {n} {n}
|
|
(3, 0) {n} {n}
|
|
(3, 1) {n} {n}
|
|
(4, 0) {n} {n}
|
|
(4, 1) {n} {n}
|
|
(4, 2) {n} {m, n}
|
|
(4, 3) {m, n} {m, n}
|
|
(5, 0) {n} {n}
|
|
|
|
[case testMultiPass_Liveness]
|
|
def f(n: int) -> None:
|
|
x = 1
|
|
y = 1
|
|
while n < 1:
|
|
n = y
|
|
while n < 2:
|
|
n = 1
|
|
n = x
|
|
[out]
|
|
def f(n):
|
|
n, x, y :: int
|
|
r0 :: native_int
|
|
r1, r2, r3 :: bit
|
|
r4 :: native_int
|
|
r5, r6, r7 :: bit
|
|
L0:
|
|
x = 2
|
|
y = 2
|
|
L1:
|
|
r0 = n & 1
|
|
r1 = r0 != 0
|
|
if r1 goto L2 else goto L3 :: bool
|
|
L2:
|
|
r2 = CPyTagged_IsLt_(n, 2)
|
|
if r2 goto L4 else goto L10 :: bool
|
|
L3:
|
|
r3 = n < 2 :: signed
|
|
if r3 goto L4 else goto L10 :: bool
|
|
L4:
|
|
n = y
|
|
L5:
|
|
r4 = n & 1
|
|
r5 = r4 != 0
|
|
if r5 goto L6 else goto L7 :: bool
|
|
L6:
|
|
r6 = CPyTagged_IsLt_(n, 4)
|
|
if r6 goto L8 else goto L9 :: bool
|
|
L7:
|
|
r7 = n < 4 :: signed
|
|
if r7 goto L8 else goto L9 :: bool
|
|
L8:
|
|
n = 2
|
|
n = x
|
|
goto L5
|
|
L9:
|
|
goto L1
|
|
L10:
|
|
return 1
|
|
(0, 0) {n} {n, x}
|
|
(0, 1) {n, x} {n, x, y}
|
|
(0, 2) {n, x, y} {n, x, y}
|
|
(1, 0) {n, x, y} {n, r0, x, y}
|
|
(1, 1) {n, r0, x, y} {n, r1, x, y}
|
|
(1, 2) {n, r1, x, y} {n, x, y}
|
|
(2, 0) {n, x, y} {r2, x, y}
|
|
(2, 1) {r2, x, y} {x, y}
|
|
(3, 0) {n, x, y} {r3, x, y}
|
|
(3, 1) {r3, x, y} {x, y}
|
|
(4, 0) {x, y} {n, x, y}
|
|
(4, 1) {n, x, y} {n, x, y}
|
|
(5, 0) {n, x, y} {n, r4, x, y}
|
|
(5, 1) {n, r4, x, y} {n, r5, x, y}
|
|
(5, 2) {n, r5, x, y} {n, x, y}
|
|
(6, 0) {n, x, y} {n, r6, x, y}
|
|
(6, 1) {n, r6, x, y} {n, x, y}
|
|
(7, 0) {n, x, y} {n, r7, x, y}
|
|
(7, 1) {n, r7, x, y} {n, x, y}
|
|
(8, 0) {x, y} {x, y}
|
|
(8, 1) {x, y} {n, x, y}
|
|
(8, 2) {n, x, y} {n, x, y}
|
|
(9, 0) {n, x, y} {n, x, y}
|
|
(10, 0) {} {}
|
|
|
|
[case testCall_Liveness]
|
|
def f(x: int) -> int:
|
|
a = f(1)
|
|
return f(a) + a
|
|
[out]
|
|
def f(x):
|
|
x, r0, a, r1, r2, r3 :: int
|
|
L0:
|
|
r0 = f(2)
|
|
if is_error(r0) goto L3 (error at f:2) else goto L1
|
|
L1:
|
|
a = r0
|
|
r1 = f(a)
|
|
if is_error(r1) goto L3 (error at f:3) else goto L2
|
|
L2:
|
|
r2 = CPyTagged_Add(r1, a)
|
|
return r2
|
|
L3:
|
|
r3 = <error> :: int
|
|
return r3
|
|
(0, 0) {} {r0}
|
|
(0, 1) {r0} {r0}
|
|
(1, 0) {r0} {a}
|
|
(1, 1) {a} {a, r1}
|
|
(1, 2) {a, r1} {a, r1}
|
|
(2, 0) {a, r1} {r2}
|
|
(2, 1) {r2} {}
|
|
(3, 0) {} {r3}
|
|
(3, 1) {r3} {}
|
|
|
|
[case testLoop_MaybeDefined]
|
|
def f(a: int) -> None:
|
|
while a < a:
|
|
while a < a:
|
|
y = a
|
|
x = a
|
|
[out]
|
|
def f(a):
|
|
a :: int
|
|
r0 :: native_int
|
|
r1 :: bit
|
|
r2 :: native_int
|
|
r3, r4, r5 :: bit
|
|
r6 :: native_int
|
|
r7 :: bit
|
|
r8 :: native_int
|
|
r9, r10, r11 :: bit
|
|
y, x :: int
|
|
L0:
|
|
L1:
|
|
r0 = a & 1
|
|
r1 = r0 != 0
|
|
if r1 goto L3 else goto L2 :: bool
|
|
L2:
|
|
r2 = a & 1
|
|
r3 = r2 != 0
|
|
if r3 goto L3 else goto L4 :: bool
|
|
L3:
|
|
r4 = CPyTagged_IsLt_(a, a)
|
|
if r4 goto L5 else goto L12 :: bool
|
|
L4:
|
|
r5 = a < a :: signed
|
|
if r5 goto L5 else goto L12 :: bool
|
|
L5:
|
|
L6:
|
|
r6 = a & 1
|
|
r7 = r6 != 0
|
|
if r7 goto L8 else goto L7 :: bool
|
|
L7:
|
|
r8 = a & 1
|
|
r9 = r8 != 0
|
|
if r9 goto L8 else goto L9 :: bool
|
|
L8:
|
|
r10 = CPyTagged_IsLt_(a, a)
|
|
if r10 goto L10 else goto L11 :: bool
|
|
L9:
|
|
r11 = a < a :: signed
|
|
if r11 goto L10 else goto L11 :: bool
|
|
L10:
|
|
y = a
|
|
goto L6
|
|
L11:
|
|
x = a
|
|
goto L1
|
|
L12:
|
|
return 1
|
|
(0, 0) {a} {a}
|
|
(1, 0) {a, x, y} {a, x, y}
|
|
(1, 1) {a, x, y} {a, x, y}
|
|
(1, 2) {a, x, y} {a, x, y}
|
|
(2, 0) {a, x, y} {a, x, y}
|
|
(2, 1) {a, x, y} {a, x, y}
|
|
(2, 2) {a, x, y} {a, x, y}
|
|
(3, 0) {a, x, y} {a, x, y}
|
|
(3, 1) {a, x, y} {a, x, y}
|
|
(4, 0) {a, x, y} {a, x, y}
|
|
(4, 1) {a, x, y} {a, x, y}
|
|
(5, 0) {a, x, y} {a, x, y}
|
|
(6, 0) {a, x, y} {a, x, y}
|
|
(6, 1) {a, x, y} {a, x, y}
|
|
(6, 2) {a, x, y} {a, x, y}
|
|
(7, 0) {a, x, y} {a, x, y}
|
|
(7, 1) {a, x, y} {a, x, y}
|
|
(7, 2) {a, x, y} {a, x, y}
|
|
(8, 0) {a, x, y} {a, x, y}
|
|
(8, 1) {a, x, y} {a, x, y}
|
|
(9, 0) {a, x, y} {a, x, y}
|
|
(9, 1) {a, x, y} {a, x, y}
|
|
(10, 0) {a, x, y} {a, x, y}
|
|
(10, 1) {a, x, y} {a, x, y}
|
|
(11, 0) {a, x, y} {a, x, y}
|
|
(11, 1) {a, x, y} {a, x, y}
|
|
(12, 0) {a, x, y} {a, x, y}
|
|
|
|
[case testTrivial_BorrowedArgument]
|
|
def f(a: int, b: int) -> int:
|
|
return b
|
|
[out]
|
|
def f(a, b):
|
|
a, b :: int
|
|
L0:
|
|
return b
|
|
(0, 0) {a, b} {a, b}
|
|
|
|
[case testSimple_BorrowedArgument]
|
|
def f(a: int) -> int:
|
|
b = a
|
|
a = 1
|
|
return a
|
|
[out]
|
|
def f(a):
|
|
a, b :: int
|
|
L0:
|
|
b = a
|
|
a = 2
|
|
return a
|
|
(0, 0) {a} {a}
|
|
(0, 1) {a} {}
|
|
(0, 2) {} {}
|
|
|
|
[case testConditional_BorrowedArgument]
|
|
def f(a: int) -> int:
|
|
if a == a:
|
|
x = 2
|
|
a = 1
|
|
else:
|
|
x = 1
|
|
return x
|
|
[out]
|
|
def f(a):
|
|
a :: int
|
|
r0 :: native_int
|
|
r1, r2, r3 :: bit
|
|
x :: int
|
|
L0:
|
|
r0 = a & 1
|
|
r1 = r0 != 0
|
|
if r1 goto L1 else goto L2 :: bool
|
|
L1:
|
|
r2 = CPyTagged_IsEq_(a, a)
|
|
if r2 goto L3 else goto L4 :: bool
|
|
L2:
|
|
r3 = a == a
|
|
if r3 goto L3 else goto L4 :: bool
|
|
L3:
|
|
x = 4
|
|
a = 2
|
|
goto L5
|
|
L4:
|
|
x = 2
|
|
L5:
|
|
return x
|
|
(0, 0) {a} {a}
|
|
(0, 1) {a} {a}
|
|
(0, 2) {a} {a}
|
|
(1, 0) {a} {a}
|
|
(1, 1) {a} {a}
|
|
(2, 0) {a} {a}
|
|
(2, 1) {a} {a}
|
|
(3, 0) {a} {a}
|
|
(3, 1) {a} {}
|
|
(3, 2) {} {}
|
|
(4, 0) {a} {a}
|
|
(4, 1) {a} {a}
|
|
(5, 0) {} {}
|
|
|
|
[case testLoop_BorrowedArgument]
|
|
def f(a: int) -> int:
|
|
sum = 0
|
|
i = 0
|
|
while i <= a:
|
|
sum = sum + i
|
|
i = i + 1
|
|
return sum
|
|
[out]
|
|
def f(a):
|
|
a, sum, i :: int
|
|
r0 :: native_int
|
|
r1 :: bit
|
|
r2 :: native_int
|
|
r3, r4, r5 :: bit
|
|
r6, r7 :: int
|
|
L0:
|
|
sum = 0
|
|
i = 0
|
|
L1:
|
|
r0 = i & 1
|
|
r1 = r0 != 0
|
|
if r1 goto L3 else goto L2 :: bool
|
|
L2:
|
|
r2 = a & 1
|
|
r3 = r2 != 0
|
|
if r3 goto L3 else goto L4 :: bool
|
|
L3:
|
|
r4 = CPyTagged_IsLt_(a, i)
|
|
if r4 goto L6 else goto L5 :: bool
|
|
L4:
|
|
r5 = i <= a :: signed
|
|
if r5 goto L5 else goto L6 :: bool
|
|
L5:
|
|
r6 = CPyTagged_Add(sum, i)
|
|
sum = r6
|
|
r7 = CPyTagged_Add(i, 2)
|
|
i = r7
|
|
goto L1
|
|
L6:
|
|
return sum
|
|
(0, 0) {a} {a}
|
|
(0, 1) {a} {a}
|
|
(0, 2) {a} {a}
|
|
(1, 0) {a} {a}
|
|
(1, 1) {a} {a}
|
|
(1, 2) {a} {a}
|
|
(2, 0) {a} {a}
|
|
(2, 1) {a} {a}
|
|
(2, 2) {a} {a}
|
|
(3, 0) {a} {a}
|
|
(3, 1) {a} {a}
|
|
(4, 0) {a} {a}
|
|
(4, 1) {a} {a}
|
|
(5, 0) {a} {a}
|
|
(5, 1) {a} {a}
|
|
(5, 2) {a} {a}
|
|
(5, 3) {a} {a}
|
|
(5, 4) {a} {a}
|
|
(6, 0) {a} {a}
|
|
|
|
[case testError]
|
|
def f(x: List[int]) -> None: pass # E: Name "List" is not defined \
|
|
# N: Did you forget to import it from "typing"? (Suggestion: "from typing import List")
|
|
|
|
[case testExceptUndefined_Liveness]
|
|
def lol(x: object) -> int:
|
|
try:
|
|
st = id(x)
|
|
except Exception:
|
|
return -1
|
|
return st + 1
|
|
[out]
|
|
def lol(x):
|
|
x :: object
|
|
r0, st :: int
|
|
r1 :: tuple[object, object, object]
|
|
r2 :: object
|
|
r3 :: str
|
|
r4 :: object
|
|
r5, r6 :: bit
|
|
r7, r8 :: int
|
|
L0:
|
|
L1:
|
|
r0 = CPyTagged_Id(x)
|
|
st = r0
|
|
goto L10
|
|
L2:
|
|
r1 = CPy_CatchError()
|
|
r2 = builtins :: module
|
|
r3 = 'Exception'
|
|
r4 = CPyObject_GetAttr(r2, r3)
|
|
if is_error(r4) goto L8 (error at lol:4) else goto L3
|
|
L3:
|
|
r5 = CPy_ExceptionMatches(r4)
|
|
if r5 goto L4 else goto L5 :: bool
|
|
L4:
|
|
CPy_RestoreExcInfo(r1)
|
|
return -2
|
|
L5:
|
|
CPy_Reraise()
|
|
if not 0 goto L8 else goto L6 :: bool
|
|
L6:
|
|
unreachable
|
|
L7:
|
|
CPy_RestoreExcInfo(r1)
|
|
goto L10
|
|
L8:
|
|
CPy_RestoreExcInfo(r1)
|
|
r6 = CPy_KeepPropagating()
|
|
if not r6 goto L11 else goto L9 :: bool
|
|
L9:
|
|
unreachable
|
|
L10:
|
|
r7 = CPyTagged_Add(st, 2)
|
|
return r7
|
|
L11:
|
|
r8 = <error> :: int
|
|
return r8
|
|
(0, 0) {x} {x}
|
|
(1, 0) {x} {r0}
|
|
(1, 1) {r0} {st}
|
|
(1, 2) {st} {st}
|
|
(2, 0) {} {r1}
|
|
(2, 1) {r1} {r1, r2}
|
|
(2, 2) {r1, r2} {r1, r2, r3}
|
|
(2, 3) {r1, r2, r3} {r1, r4}
|
|
(2, 4) {r1, r4} {r1, r4}
|
|
(3, 0) {r1, r4} {r1, r5}
|
|
(3, 1) {r1, r5} {r1}
|
|
(4, 0) {r1} {}
|
|
(4, 1) {} {}
|
|
(5, 0) {r1} {r1}
|
|
(5, 1) {r1} {r1}
|
|
(6, 0) {} {}
|
|
(7, 0) {r1, st} {st}
|
|
(7, 1) {st} {st}
|
|
(8, 0) {r1} {}
|
|
(8, 1) {} {r6}
|
|
(8, 2) {r6} {}
|
|
(9, 0) {} {}
|
|
(10, 0) {st} {r7}
|
|
(10, 1) {r7} {}
|
|
(11, 0) {} {r8}
|
|
(11, 1) {r8} {}
|