1*67e74705SXin Li // RUN: %clang_cc1 -fms-extensions -emit-llvm -o - %s | FileCheck %s
2*67e74705SXin Li
3*67e74705SXin Li // CHECK: %struct.test = type { i32, %struct.nested2, i32 }
4*67e74705SXin Li // CHECK: %struct.nested2 = type { i32, %struct.nested1, i32 }
5*67e74705SXin Li // CHECK: %struct.nested1 = type { i32, i32 }
6*67e74705SXin Li typedef struct nested1 {
7*67e74705SXin Li int a1;
8*67e74705SXin Li int b1;
9*67e74705SXin Li } NESTED1;
10*67e74705SXin Li
11*67e74705SXin Li struct nested2 {
12*67e74705SXin Li int a;
13*67e74705SXin Li NESTED1;
14*67e74705SXin Li int b;
15*67e74705SXin Li };
16*67e74705SXin Li
17*67e74705SXin Li struct test {
18*67e74705SXin Li int x;
19*67e74705SXin Li struct nested2;
20*67e74705SXin Li int y;
21*67e74705SXin Li };
22*67e74705SXin Li
23*67e74705SXin Li
foo()24*67e74705SXin Li void foo()
25*67e74705SXin Li {
26*67e74705SXin Li // CHECK: %var = alloca %struct.test, align 4
27*67e74705SXin Li struct test var;
28*67e74705SXin Li
29*67e74705SXin Li // CHECK: getelementptr inbounds %struct.test, %struct.test* %var, i32 0, i32 1
30*67e74705SXin Li // CHECK-NEXT: getelementptr inbounds %struct.nested2, %struct.nested2* %{{.*}}, i32 0, i32 0
31*67e74705SXin Li // CHECK-NEXT: load i32, i32* %{{.*}}, align 4
32*67e74705SXin Li var.a;
33*67e74705SXin Li
34*67e74705SXin Li // CHECK-NEXT: getelementptr inbounds %struct.test, %struct.test* %var, i32 0, i32 1
35*67e74705SXin Li // CHECK-NEXT: getelementptr inbounds %struct.nested2, %struct.nested2* %{{.*}}, i32 0, i32 2
36*67e74705SXin Li // CHECK-NEXT: load i32, i32* %{{.*}}, align 4
37*67e74705SXin Li var.b;
38*67e74705SXin Li
39*67e74705SXin Li // CHECK-NEXT: getelementptr inbounds %struct.test, %struct.test* %var, i32 0, i32 1
40*67e74705SXin Li // CHECK-NEXT: getelementptr inbounds %struct.nested2, %struct.nested2* %{{.*}}, i32 0, i32 1
41*67e74705SXin Li // CHECK-NEXT: getelementptr inbounds %struct.nested1, %struct.nested1* %{{.*}}, i32 0, i32 0
42*67e74705SXin Li // CHECK-NEXT: load i32, i32* %{{.*}}, align 4
43*67e74705SXin Li var.a1;
44*67e74705SXin Li
45*67e74705SXin Li // CHECK-NEXT: getelementptr inbounds %struct.test, %struct.test* %{{.*}}var, i32 0, i32 1
46*67e74705SXin Li // CHECK-NEXT: getelementptr inbounds %struct.nested2, %struct.nested2* %{{.*}}, i32 0, i32 1
47*67e74705SXin Li // CHECK-NEXT: getelementptr inbounds %struct.nested1, %struct.nested1* %{{.*}}, i32 0, i32 1
48*67e74705SXin Li // CHECK-NEXT: load i32, i32* %{{.*}}, align 4
49*67e74705SXin Li var.b1;
50*67e74705SXin Li
51*67e74705SXin Li // CHECK-NEXT: getelementptr inbounds %struct.test, %struct.test* %var, i32 0, i32 0
52*67e74705SXin Li // CHECK-NEXT: load i32, i32* %{{.*}}, align 4
53*67e74705SXin Li var.x;
54*67e74705SXin Li
55*67e74705SXin Li // CHECK-NEXT: getelementptr inbounds %struct.test, %struct.test* %var, i32 0, i32 2
56*67e74705SXin Li // CHECK-NEXT: load i32, i32* %{{.*}}, align 4
57*67e74705SXin Li var.y;
58*67e74705SXin Li }
59*67e74705SXin Li
foo2(struct test * var)60*67e74705SXin Li void foo2(struct test* var)
61*67e74705SXin Li {
62*67e74705SXin Li // CHECK: alloca %struct.test*, align
63*67e74705SXin Li // CHECK-NEXT: store %struct.test* %var, %struct.test** %{{.*}}, align
64*67e74705SXin Li // CHECK-NEXT: load %struct.test*, %struct.test** %{{.*}}, align
65*67e74705SXin Li // CHECK-NEXT: getelementptr inbounds %struct.test, %struct.test* %{{.*}}, i32 0, i32 1
66*67e74705SXin Li // CHECK-NEXT: getelementptr inbounds %struct.nested2, %struct.nested2* %{{.*}}, i32 0, i32 0
67*67e74705SXin Li // CHECK-NEXT: load i32, i32* %{{.*}}, align 4
68*67e74705SXin Li var->a;
69*67e74705SXin Li
70*67e74705SXin Li // CHECK-NEXT: load %struct.test*, %struct.test** %{{.*}}, align
71*67e74705SXin Li // CHECK-NEXT: getelementptr inbounds %struct.test, %struct.test* %{{.*}}, i32 0, i32 1
72*67e74705SXin Li // CHECK-NEXT: getelementptr inbounds %struct.nested2, %struct.nested2* %{{.*}}, i32 0, i32 2
73*67e74705SXin Li // CHECK-NEXT: load i32, i32* %{{.*}}, align 4
74*67e74705SXin Li var->b;
75*67e74705SXin Li
76*67e74705SXin Li // CHECK-NEXT: load %struct.test*, %struct.test** %{{.*}}, align
77*67e74705SXin Li // CHECK-NEXT: getelementptr inbounds %struct.test, %struct.test* %{{.*}}, i32 0, i32 1
78*67e74705SXin Li // CHECK-NEXT: getelementptr inbounds %struct.nested2, %struct.nested2* %{{.*}}, i32 0, i32 1
79*67e74705SXin Li // CHECK-NEXT: getelementptr inbounds %struct.nested1, %struct.nested1* %{{.*}}, i32 0, i32 0
80*67e74705SXin Li // CHECK-NEXT: load i32, i32* %{{.*}}, align 4
81*67e74705SXin Li var->a1;
82*67e74705SXin Li
83*67e74705SXin Li // CHECK-NEXT: load %struct.test*, %struct.test** %{{.*}}, align
84*67e74705SXin Li // CHECK-NEXT: getelementptr inbounds %struct.test, %struct.test* %{{.*}}, i32 0, i32 1
85*67e74705SXin Li // CHECK-NEXT: getelementptr inbounds %struct.nested2, %struct.nested2* %{{.*}}, i32 0, i32 1
86*67e74705SXin Li // CHECK-NEXT: getelementptr inbounds %struct.nested1, %struct.nested1* %{{.*}}, i32 0, i32 1
87*67e74705SXin Li // CHECK-NEXT: load i32, i32* %{{.*}}, align 4
88*67e74705SXin Li var->b1;
89*67e74705SXin Li
90*67e74705SXin Li // CHECK-NEXT: load %struct.test*, %struct.test** %{{.*}}, align
91*67e74705SXin Li // CHECK-NEXT: getelementptr inbounds %struct.test, %struct.test* %{{.*}}, i32 0, i32 0
92*67e74705SXin Li // CHECK-NEXT: load i32, i32* %{{.*}}, align 4
93*67e74705SXin Li var->x;
94*67e74705SXin Li
95*67e74705SXin Li // CHECK-NEXT: load %struct.test*, %struct.test** %{{.*}}, align
96*67e74705SXin Li // CHECK-NEXT: getelementptr inbounds %struct.test, %struct.test* %{{.*}}, i32 0, i32 2
97*67e74705SXin Li // CHECK-NEXT: load i32, i32* %{{.*}}, align 4
98*67e74705SXin Li var->y;
99*67e74705SXin Li }
100