# Test cases for unreachable expressions and statements

[case testUnreachableMemberExpr]
import sys

def f() -> None:
    y = sys.platform == "x" and sys.version_info > (3, 5)
[out]
def f():
    r0 :: object
    r1 :: str
    r2 :: object
    r3, r4 :: str
    r5 :: i32
    r6 :: bit
    r7 :: object
    r8, r9, r10 :: bit
    r11, r12 :: bool
    r13 :: object
    r14 :: str
    r15 :: object
    r16 :: tuple[int, int]
    r17, r18 :: object
    r19, y :: bool
L0:
    r0 = sys :: module
    r1 = 'platform'
    r2 = CPyObject_GetAttr(r0, r1)
    r3 = cast(str, r2)
    r4 = 'x'
    r5 = PyUnicode_Compare(r3, r4)
    r6 = r5 == -1
    if r6 goto L1 else goto L3 :: bool
L1:
    r7 = PyErr_Occurred()
    r8 = r7 != 0
    if r8 goto L2 else goto L3 :: bool
L2:
    r9 = CPy_KeepPropagating()
L3:
    r10 = r5 == 0
    if r10 goto L5 else goto L4 :: bool
L4:
    r11 = r10
    goto L6
L5:
    r12 = raise RuntimeError('mypyc internal error: should be unreachable')
    r13 = box(None, 1)
    r14 = 'version_info'
    r15 = CPyObject_GetAttr(r13, r14)
    r16 = (6, 10)
    r17 = box(tuple[int, int], r16)
    r18 = PyObject_RichCompare(r15, r17, 4)
    r19 = unbox(bool, r18)
    r11 = r19
L6:
    y = r11
    return 1

[case testUnreachableNameExpr]
import sys

def f() -> None:
    y = sys.platform == 'x' and foobar
[out]
def f():
    r0 :: object
    r1 :: str
    r2 :: object
    r3, r4 :: str
    r5 :: i32
    r6 :: bit
    r7 :: object
    r8, r9, r10 :: bit
    r11, r12 :: bool
    r13 :: object
    r14, y :: bool
L0:
    r0 = sys :: module
    r1 = 'platform'
    r2 = CPyObject_GetAttr(r0, r1)
    r3 = cast(str, r2)
    r4 = 'x'
    r5 = PyUnicode_Compare(r3, r4)
    r6 = r5 == -1
    if r6 goto L1 else goto L3 :: bool
L1:
    r7 = PyErr_Occurred()
    r8 = r7 != 0
    if r8 goto L2 else goto L3 :: bool
L2:
    r9 = CPy_KeepPropagating()
L3:
    r10 = r5 == 0
    if r10 goto L5 else goto L4 :: bool
L4:
    r11 = r10
    goto L6
L5:
    r12 = raise RuntimeError('mypyc internal error: should be unreachable')
    r13 = box(None, 1)
    r14 = unbox(bool, r13)
    r11 = r14
L6:
    y = r11
    return 1

[case testUnreachableStatementAfterReturn]
def f(x: bool) -> int:
    if x:
        return 1
        f(False)
    return 2
[out]
def f(x):
    x :: bool
L0:
    if x goto L1 else goto L2 :: bool
L1:
    return 2
L2:
    return 4

[case testUnreachableStatementAfterContinue]
def c() -> bool:
    return False

def f() -> None:
    n = True
    while n:
        if c():
            continue
            if int():
                f()
        n = False
[out]
def c():
L0:
    return 0
def f():
    n, r0 :: bool
L0:
    n = 1
L1:
    if n goto L2 else goto L5 :: bool
L2:
    r0 = c()
    if r0 goto L3 else goto L4 :: bool
L3:
    goto L1
L4:
    n = 0
    goto L1
L5:
    return 1

[case testUnreachableStatementAfterBreak]
def c() -> bool:
    return False

def f() -> None:
    n = True
    while n:
        if c():
            break
            if int():
                f()
        n = False
[out]
def c():
L0:
    return 0
def f():
    n, r0 :: bool
L0:
    n = 1
L1:
    if n goto L2 else goto L5 :: bool
L2:
    r0 = c()
    if r0 goto L3 else goto L4 :: bool
L3:
    goto L5
L4:
    n = 0
    goto L1
L5:
    return 1

[case testUnreachableStatementAfterRaise]
def f(x: bool) -> int:
    if x:
        raise ValueError()
        print('hello')
    return 2
[out]
def f(x):
    x :: bool
    r0 :: object
    r1 :: str
    r2, r3 :: object
L0:
    if x goto L1 else goto L2 :: bool
L1:
    r0 = builtins :: module
    r1 = 'ValueError'
    r2 = CPyObject_GetAttr(r0, r1)
    r3 = PyObject_CallFunctionObjArgs(r2, 0)
    CPy_Raise(r3)
    unreachable
L2:
    return 4

[case testUnreachableStatementAfterAssertFalse]
def f(x: bool) -> int:
    if x:
        assert False
        print('hello')
    return 2
[out]
def f(x):
    x, r0 :: bool
    r1 :: str
    r2 :: object
    r3 :: str
    r4, r5 :: object
L0:
    if x goto L1 else goto L4 :: bool
L1:
    if 0 goto L3 else goto L2 :: bool
L2:
    r0 = raise AssertionError
    unreachable
L3:
    r1 = 'hello'
    r2 = builtins :: module
    r3 = 'print'
    r4 = CPyObject_GetAttr(r2, r3)
    r5 = PyObject_CallFunctionObjArgs(r4, r1, 0)
L4:
    return 4
