// #target: macos-x64

module test;
struct Foo
{
    int x, y;
}

faultdef FOO;

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

fn void main()
{
    int? z = 2;
    Foo*? w = &&(Foo){ z, 0 };
    (void)printf("%d\n", w.x);
    z = FOO~;
    w = &&(Foo){ z, 0 };
    (void)printf("Not visible: %d\n", w.x);
}

/* #expect: test.ll

%Foo = type { i32, i32 }

@"$ct.test.Foo" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8
@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
@test.FOO = linkonce constant %"char[]" { ptr @test.FOO.nameof, i64 9 }, align 8
@test.FOO.nameof = internal constant [10 x i8] c"test::FOO\00", align 1
@.str.1 = private unnamed_addr constant [17 x i8] c"Not visible: %d\0A\00", align 1

; Function Attrs:
declare i32 @printf(ptr, ...) #0

; Function Attrs:
define void @test.main() #0 {
entry:
  %z = alloca i32, align 4
  %z.f = alloca i64, align 8
  %w = alloca ptr, align 8
  %w.f = alloca i64, align 8
  %literal = alloca %Foo, align 4
  %literal5 = alloca %Foo, align 4
  store i32 2, ptr %z, align 4
  store i64 0, ptr %z.f, align 8
  %optval = load i64, ptr %z.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 %assign_optional

assign_optional:                                  ; preds = %entry
  store i64 %optval, ptr %w.f, align 8
  br label %after_assign

after_check:                                      ; preds = %entry
  %1 = load i32, ptr %z, align 4
  store i32 %1, ptr %literal, align 4
  %ptradd = getelementptr inbounds i8, ptr %literal, i64 4
  store i32 0, ptr %ptradd, align 4
  store ptr %literal, ptr %w, align 8
  store i64 0, ptr %w.f, align 8
  br label %after_assign

after_assign:                                     ; preds = %after_check, %assign_optional
  %optval1 = load i64, ptr %w.f, align 8
  %not_err2 = icmp eq i64 %optval1, 0
  %2 = call i1 @llvm.expect.i1(i1 %not_err2, i1 true)
  br i1 %2, label %after_check3, label %voiderr

after_check3:                                     ; preds = %after_assign
  %3 = load ptr, ptr %w, align 8
  %4 = load i32, ptr %3, align 4
  %5 = call i32 (ptr, ...) @printf(ptr @.str, i32 %4)
  br label %voiderr

voiderr:                                          ; preds = %after_check3, %after_assign
  store i64 ptrtoint (ptr @test.FOO to i64), ptr %z.f, align 8
  br label %after_check4

after_check4:                                     ; preds = %voiderr
  %optval6 = load i64, ptr %z.f, align 8
  %not_err7 = icmp eq i64 %optval6, 0
  %6 = call i1 @llvm.expect.i1(i1 %not_err7, i1 true)
  br i1 %6, label %after_check9, label %assign_optional8

assign_optional8:                                 ; preds = %after_check4
  store i64 %optval6, ptr %w.f, align 8
  br label %after_assign11

after_check9:                                     ; preds = %after_check4
  %7 = load i32, ptr %z, align 4
  store i32 %7, ptr %literal5, align 4
  %ptradd10 = getelementptr inbounds i8, ptr %literal5, i64 4
  store i32 0, ptr %ptradd10, align 4
  store ptr %literal5, ptr %w, align 8
  store i64 0, ptr %w.f, align 8
  br label %after_assign11

after_assign11:                                   ; preds = %after_check9, %assign_optional8
  %optval12 = load i64, ptr %w.f, align 8
  %not_err13 = icmp eq i64 %optval12, 0
  %8 = call i1 @llvm.expect.i1(i1 %not_err13, i1 true)
  br i1 %8, label %after_check14, label %voiderr15

after_check14:                                    ; preds = %after_assign11
  %9 = load ptr, ptr %w, align 8
  %10 = load i32, ptr %9, align 4
  %11 = call i32 (ptr, ...) @printf(ptr @.str.1, i32 %10)
  br label %voiderr15

voiderr15:                                        ; preds = %after_check14, %after_assign11
  ret void
}