// #target: macos-x64

fn int hello(int x)
{
    return x + 1;
}

extern fn int printf(char *c, ...);

fn int? tester()
{
    printf("In tester\n");
    return 222;
}

faultdef A;

fn void test1()
{
    int? a = 11;
    if (try int b = a && try int c = tester())
    {
        printf("%d\n", hello(b));
        printf("%d\n", c);
    }
}
fn void main()
{
    test1();
}

fn void test2()
{
    int? a;
    if (try int b = a && hello(b))
    {
        hello(b + 1);
    }
}

/* #expect: try_with_unwrapper.ll


define i32 @try_with_unwrapper.hello(i32 %0) #0 {
entry:
  %add = add i32 %0, 1
  ret i32 %add
}


declare i32 @printf(ptr, ...) #0


define i64 @try_with_unwrapper.tester(ptr %0) #0 {
entry:
  %reterr = alloca i64, align 8
  %1 = call i32 (ptr, ...) @printf(ptr @.str)
  store i32 222, ptr %0, align 4
  ret i64 0
}


define void @try_with_unwrapper.test1() #0 {
entry:
  %a = alloca i32, align 4
  %a.f = alloca i64, align 8
  %b = alloca i32, align 4
  %c = alloca i32, align 4
  %retparam = alloca i32, align 4
  store i32 11, ptr %a, align 4
  store i64 0, ptr %a.f, align 8
  store i32 0, ptr %b, align 4
  %optval = load i64, ptr %a.f, align 8
  %not_err = icmp eq i64 %optval, 0
  %0 = call i1 @llvm.expect.i1(i1 %not_err, i1 true)
  br i1 %0, label %after_check, label %catch_landing

after_check:                                      ; preds = %entry
  %1 = load i32, ptr %a, align 4
  store i32 %1, ptr %b, align 4
  br label %phi_try_catch

catch_landing:                                    ; preds = %entry
  br label %phi_try_catch

phi_try_catch:                                    ; preds = %catch_landing, %after_check
  %val = phi i1 [ true, %after_check ], [ false, %catch_landing ]
  br i1 %val, label %chain_next, label %fail_chain

chain_next:                                       ; preds = %phi_try_catch
  store i32 0, ptr %c, align 4
  %2 = call i64 @try_with_unwrapper.tester(ptr %retparam)
  %not_err1 = icmp eq i64 %2, 0
  %3 = call i1 @llvm.expect.i1(i1 %not_err1, i1 true)
  br i1 %3, label %after_check2, label %catch_landing3

after_check2:                                     ; preds = %chain_next
  %4 = load i32, ptr %retparam, align 4
  store i32 %4, ptr %c, align 4
  br label %phi_try_catch4

catch_landing3:                                   ; preds = %chain_next
  br label %phi_try_catch4

phi_try_catch4:                                   ; preds = %catch_landing3, %after_check2
  %val5 = phi i1 [ true, %after_check2 ], [ false, %catch_landing3 ]
  br i1 %val5, label %chain_next6, label %fail_chain

chain_next6:                                      ; preds = %phi_try_catch4
  br label %end_chain

fail_chain:                                       ; preds = %phi_try_catch4, %phi_try_catch
  br label %end_chain

end_chain:                                        ; preds = %fail_chain, %chain_next6
  %chain.phi = phi i1 [ true, %chain_next6 ], [ false, %fail_chain ]
  br i1 %chain.phi, label %if.then, label %if.exit

if.then:                                          ; preds = %end_chain
  %5 = load i32, ptr %b, align 4
  %6 = call i32 @try_with_unwrapper.hello(i32 %5)
  %7 = call i32 (ptr, ...) @printf(ptr @.str.1, i32 %6)
  %8 = load i32, ptr %c, align 4
  %9 = call i32 (ptr, ...) @printf(ptr @.str.2, i32 %8)
  br label %if.exit

if.exit:                                          ; preds = %if.then, %end_chain
  ret void
}



define void @try_with_unwrapper.test2() #0 {
entry:
  %a = alloca i32, align 4
  %a.f = alloca i64, align 8
  %b = alloca i32, align 4
  store i64 0, ptr %a.f, align 8
  store i32 0, ptr %a, align 4
  store i32 0, ptr %b, align 4
  %optval = load i64, ptr %a.f, align 8
  %not_err = icmp eq i64 %optval, 0
  %0 = call i1 @llvm.expect.i1(i1 %not_err, i1 true)
  br i1 %0, label %after_check, label %catch_landing

after_check:                                      ; preds = %entry
  %1 = load i32, ptr %a, align 4
  store i32 %1, ptr %b, align 4
  br label %phi_try_catch

catch_landing:                                    ; preds = %entry
  br label %phi_try_catch

phi_try_catch:                                    ; preds = %catch_landing, %after_check
  %val = phi i1 [ true, %after_check ], [ false, %catch_landing ]
  br i1 %val, label %chain_next, label %fail_chain

chain_next:                                       ; preds = %phi_try_catch
  %2 = load i32, ptr %b, align 4
  %3 = call i32 @try_with_unwrapper.hello(i32 %2)
  %i2b = icmp ne i32 %3, 0
  br i1 %i2b, label %chain_next1, label %fail_chain

chain_next1:                                      ; preds = %chain_next
  br label %end_chain

fail_chain:                                       ; preds = %chain_next, %phi_try_catch
  br label %end_chain

end_chain:                                        ; preds = %fail_chain, %chain_next1
  %chain.phi = phi i1 [ true, %chain_next1 ], [ false, %fail_chain ]
  br i1 %chain.phi, label %if.then, label %if.exit

if.then:                                          ; preds = %end_chain
  %4 = load i32, ptr %b, align 4
  %add = add i32 %4, 1
  %5 = call i32 @try_with_unwrapper.hello(i32 %add)
  br label %if.exit

if.exit:                                          ; preds = %if.then, %end_chain
  ret void
}

