]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/CodeGenCXX/trivial-auto-var-init.cpp
Vendor import of clang trunk r351319 (just before the release_80 branch
[FreeBSD/FreeBSD.git] / test / CodeGenCXX / trivial-auto-var-init.cpp
1 // RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks %s -emit-llvm -o - | FileCheck %s -check-prefix=UNINIT
2 // RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=pattern %s -emit-llvm -o - | FileCheck %s -check-prefix=PATTERN
3 // RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=zero %s -emit-llvm -o - | FileCheck %s -check-prefix=ZERO
4
5 // None of the synthesized globals should contain `undef`.
6 // PATTERN-NOT: undef
7 // ZERO-NOT: undef
8
9 template<typename T> void used(T &) noexcept;
10
11 extern "C" {
12
13 // UNINIT-LABEL:  test_selfinit(
14 // ZERO-LABEL:    test_selfinit(
15 // ZERO: store i32 0, i32* %self, align 4
16 // PATTERN-LABEL: test_selfinit(
17 // PATTERN: store i32 -1431655766, i32* %self, align 4
18 void test_selfinit() {
19   int self = self + 1;
20   used(self);
21 }
22
23 // UNINIT-LABEL:  test_block(
24 // ZERO-LABEL:    test_block(
25 // ZERO: store i32 0, i32* %block
26 // PATTERN-LABEL: test_block(
27 // PATTERN: store i32 -1431655766, i32* %block
28 void test_block() {
29   __block int block;
30   used(block);
31 }
32
33 // This type of code is currently not handled by zero / pattern initialization.
34 // The test will break when that is fixed.
35 // UNINIT-LABEL:  test_goto_unreachable_value(
36 // ZERO-LABEL:    test_goto_unreachable_value(
37 // ZERO-NOT: store {{.*}}%oops
38 // PATTERN-LABEL: test_goto_unreachable_value(
39 // PATTERN-NOT: store {{.*}}%oops
40 void test_goto_unreachable_value() {
41   goto jump;
42   int oops;
43  jump:
44   used(oops);
45 }
46
47 // This type of code is currently not handled by zero / pattern initialization.
48 // The test will break when that is fixed.
49 // UNINIT-LABEL:  test_goto(
50 // ZERO-LABEL:    test_goto(
51 // ZERO: if.then:
52 // ZERO: br label %jump
53 // ZERO: store i32 0, i32* %oops, align 4
54 // ZERO: br label %jump
55 // ZERO: jump:
56 // PATTERN-LABEL: test_goto(
57 // PATTERN: if.then:
58 // PATTERN: br label %jump
59 // PATTERN: store i32 -1431655766, i32* %oops, align 4
60 // PATTERN: br label %jump
61 // PATTERN: jump:
62 void test_goto(int i) {
63   if (i)
64     goto jump;
65   int oops;
66  jump:
67   used(oops);
68 }
69
70 // This type of code is currently not handled by zero / pattern initialization.
71 // The test will break when that is fixed.
72 // UNINIT-LABEL:  test_switch(
73 // ZERO-LABEL:    test_switch(
74 // ZERO:      sw.bb:
75 // ZERO-NEXT: store i32 0, i32* %oops, align 4
76 // ZERO:      sw.bb1:
77 // ZERO-NEXT: call void @{{.*}}used
78 // PATTERN-LABEL: test_switch(
79 // PATTERN:      sw.bb:
80 // PATTERN-NEXT: store i32 -1431655766, i32* %oops, align 4
81 // PATTERN:      sw.bb1:
82 // PATTERN-NEXT: call void @{{.*}}used
83 void test_switch(int i) {
84   switch (i) {
85   case 0:
86     int oops;
87     break;
88   case 1:
89     used(oops);
90   }
91 }
92
93 // UNINIT-LABEL:  test_vla(
94 // ZERO-LABEL:    test_vla(
95 // ZERO:  %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 4
96 // ZERO:  call void @llvm.memset{{.*}}(i8* align 16 %{{.*}}, i8 0, i64 %[[SIZE]], i1 false)
97 // PATTERN-LABEL: test_vla(
98 // PATTERN:  %vla.iszerosized = icmp eq i64 %{{.*}}, 0
99 // PATTERN:  br i1 %vla.iszerosized, label %vla-init.cont, label %vla-setup.loop
100 // PATTERN: vla-setup.loop:
101 // PATTERN:  %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 4
102 // PATTERN:  %vla.begin = bitcast i32* %vla to i8*
103 // PATTERN:  %vla.end = getelementptr inbounds i8, i8* %vla.begin, i64 %[[SIZE]]
104 // PATTERN:  br label %vla-init.loop
105 // PATTERN: vla-init.loop:
106 // PATTERN:  %vla.cur = phi i8* [ %vla.begin, %vla-setup.loop ], [ %vla.next, %vla-init.loop ]
107 // PATTERN:  call void @llvm.memcpy{{.*}} %vla.cur, {{.*}}@__const.test_vla.vla
108 // PATTERN:  %vla.next = getelementptr inbounds i8, i8* %vla.cur, i64 4
109 // PATTERN:  %vla-init.isdone = icmp eq i8* %vla.next, %vla.end
110 // PATTERN:  br i1 %vla-init.isdone, label %vla-init.cont, label %vla-init.loop
111 // PATTERN: vla-init.cont:
112 // PATTERN:  call void @{{.*}}used
113 void test_vla(int size) {
114   // Variable-length arrays can't have a zero size according to C11 6.7.6.2/5.
115   // Neither can they be negative-sized.
116   //
117   // We don't use the former fact because some code creates zero-sized VLAs and
118   // doesn't use them. clang makes these share locations with other stack
119   // values, which leads to initialization of the wrong values.
120   //
121   // We rely on the later fact because it generates better code.
122   //
123   // Both cases are caught by UBSan.
124   int vla[size];
125   int *ptr = vla;
126   used(ptr);
127 }
128
129 // UNINIT-LABEL:  test_struct_vla(
130 // ZERO-LABEL:    test_struct_vla(
131 // ZERO:  %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 16
132 // ZERO:  call void @llvm.memset{{.*}}(i8* align 16 %{{.*}}, i8 0, i64 %[[SIZE]], i1 false)
133 // PATTERN-LABEL: test_struct_vla(
134 // PATTERN:  %vla.iszerosized = icmp eq i64 %{{.*}}, 0
135 // PATTERN:  br i1 %vla.iszerosized, label %vla-init.cont, label %vla-setup.loop
136 // PATTERN: vla-setup.loop:
137 // PATTERN:  %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 16
138 // PATTERN:  %vla.begin = bitcast %struct.anon* %vla to i8*
139 // PATTERN:  %vla.end = getelementptr inbounds i8, i8* %vla.begin, i64 %[[SIZE]]
140 // PATTERN:  br label %vla-init.loop
141 // PATTERN: vla-init.loop:
142 // PATTERN:  %vla.cur = phi i8* [ %vla.begin, %vla-setup.loop ], [ %vla.next, %vla-init.loop ]
143 // PATTERN:  call void @llvm.memcpy{{.*}} %vla.cur, {{.*}}@__const.test_struct_vla.vla
144 // PATTERN:  %vla.next = getelementptr inbounds i8, i8* %vla.cur, i64 16
145 // PATTERN:  %vla-init.isdone = icmp eq i8* %vla.next, %vla.end
146 // PATTERN:  br i1 %vla-init.isdone, label %vla-init.cont, label %vla-init.loop
147 // PATTERN: vla-init.cont:
148 // PATTERN:  call void @{{.*}}used
149 void test_struct_vla(int size) {
150   // Same as above, but with a struct that doesn't just memcpy.
151   struct {
152     float f;
153     char c;
154     void *ptr;
155   } vla[size];
156   void *ptr = static_cast<void*>(vla);
157   used(ptr);
158 }
159
160 // UNINIT-LABEL:  test_zsa(
161 // ZERO-LABEL:    test_zsa(
162 // ZERO: %zsa = alloca [0 x i32], align 4
163 // ZERO-NOT: %zsa
164 // ZERO:  call void @{{.*}}used
165 // PATTERN-LABEL: test_zsa(
166 // PATTERN: %zsa = alloca [0 x i32], align 4
167 // PATTERN-NOT: %zsa
168 // PATTERN:  call void @{{.*}}used
169 void test_zsa(int size) {
170   // Technically not valid, but as long as clang accepts them we should do
171   // something sensible (i.e. not store to the zero-size array).
172   int zsa[0];
173   used(zsa);
174 }
175   
176 // UNINIT-LABEL:  test_huge_uninit(
177 // ZERO-LABEL:    test_huge_uninit(
178 // ZERO: call void @llvm.memset{{.*}}, i8 0, i64 65536,
179 // PATTERN-LABEL: test_huge_uninit(
180 // PATTERN: call void @llvm.memset{{.*}}, i8 -86, i64 65536,
181 void test_huge_uninit() {
182   // We can't emit this as an inline constant to a store instruction because
183   // SDNode hits an internal size limit.
184   char big[65536];
185   used(big);
186 }
187
188 // UNINIT-LABEL:  test_huge_small_init(
189 // ZERO-LABEL:    test_huge_small_init(
190 // ZERO: call void @llvm.memset{{.*}}, i8 0, i64 65536,
191 // ZERO: store i8 97,
192 // ZERO: store i8 98,
193 // ZERO: store i8 99,
194 // ZERO: store i8 100,
195 // PATTERN-LABEL: test_huge_small_init(
196 // PATTERN: call void @llvm.memset{{.*}}, i8 0, i64 65536,
197 // PATTERN: store i8 97,
198 // PATTERN: store i8 98,
199 // PATTERN: store i8 99,
200 // PATTERN: store i8 100,
201 void test_huge_small_init() {
202   char big[65536] = { 'a', 'b', 'c', 'd' };
203   used(big);
204 }
205
206 // UNINIT-LABEL:  test_huge_larger_init(
207 // ZERO-LABEL:    test_huge_larger_init(
208 // ZERO:  call void @llvm.memcpy{{.*}} @__const.test_huge_larger_init.big, {{.*}}, i64 65536,
209 // PATTERN-LABEL: test_huge_larger_init(
210 // PATTERN:  call void @llvm.memcpy{{.*}} @__const.test_huge_larger_init.big, {{.*}}, i64 65536,
211 void test_huge_larger_init() {
212   char big[65536] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
213   used(big);
214 }
215
216 } // extern "C"