[clang] Handle __declspec() attributes in using
[llvm-project.git] / clang / test / CodeGenCXX / volatile-1.cpp
blobeefcc574e92ce41bc18c74f3cab242c8748425f5
1 // RUN: %clang_cc1 -Wno-unused-value -triple %itanium_abi_triple -emit-llvm %s -std=c++98 -o - | FileCheck %s
2 // RUN: %clang_cc1 -Wno-unused-value -triple %itanium_abi_triple -emit-llvm %s -std=c++11 -o - | FileCheck -check-prefix=CHECK -check-prefix=CHECK11 %s
4 // CHECK: @i = {{(dso_local )?}}global [[INT:i[0-9]+]] 0
5 volatile int i, j, k;
6 volatile int ar[5];
7 volatile char c;
8 // CHECK: @ci = {{(dso_local )?}}global [[CINT:.*]] zeroinitializer
9 volatile _Complex int ci;
10 volatile struct S {
11 #ifdef __cplusplus
12 void operator =(volatile struct S&o) volatile;
13 #endif
14 int i;
15 } a, b;
17 //void operator =(volatile struct S&o1, volatile struct S&o2) volatile;
18 int printf(const char *, ...);
21 // CHECK: define {{.*}}void @{{.*}}test
22 void test() {
24 asm("nop"); // CHECK: call void asm
26 // should not load in C++98
28 // CHECK11-NEXT: load volatile [[INT]], ptr @i
30 (float)(ci);
31 // CHECK-NEXT: load volatile [[INT]], ptr @ci
32 // CHECK-NEXT: load volatile [[INT]], ptr getelementptr inbounds ([[CINT]], ptr @ci, i32 0, i32 1)
33 // CHECK-NEXT: sitofp [[INT]]
35 // These are not uses in C++98:
36 // [expr.static.cast]p6:
37 // The lvalue-to-rvalue . . . conversions are not applied to the expression.
38 (void)ci;
39 // CHECK11-NEXT: load volatile [[INT]], ptr @ci
40 // CHECK11-NEXT: load volatile [[INT]], ptr getelementptr inbounds ([[CINT]], ptr @ci, i32 0, i32 1)
42 (void)a;
44 (void)(ci=ci);
45 // CHECK-NEXT: [[R:%.*]] = load volatile [[INT]], ptr @ci
46 // CHECK-NEXT: [[I:%.*]] = load volatile [[INT]], ptr getelementptr inbounds ([[CINT]], ptr @ci, i32 0, i32 1)
47 // CHECK-NEXT: store volatile [[INT]] [[R]], ptr @ci
48 // CHECK-NEXT: store volatile [[INT]] [[I]], ptr getelementptr inbounds ([[CINT]], ptr @ci, i32 0, i32 1)
50 (void)(i=j);
51 // CHECK-NEXT: [[T:%.*]] = load volatile [[INT]], ptr @j
52 // CHECK-NEXT: store volatile [[INT]] [[T]], ptr @i
54 ci+=ci;
55 // CHECK-NEXT: [[R1:%.*]] = load volatile [[INT]], ptr @ci
56 // CHECK-NEXT: [[I1:%.*]] = load volatile [[INT]], ptr getelementptr inbounds ([[CINT]], ptr @ci, i32 0, i32 1)
57 // CHECK-NEXT: [[R2:%.*]] = load volatile [[INT]], ptr @ci
58 // CHECK-NEXT: [[I2:%.*]] = load volatile [[INT]], ptr getelementptr inbounds ([[CINT]], ptr @ci, i32 0, i32 1)
59 // Not sure why they're ordered this way.
60 // CHECK-NEXT: [[R:%.*]] = add [[INT]] [[R2]], [[R1]]
61 // CHECK-NEXT: [[I:%.*]] = add [[INT]] [[I2]], [[I1]]
62 // CHECK-NEXT: store volatile [[INT]] [[R]], ptr @ci
63 // CHECK-NEXT: store volatile [[INT]] [[I]], ptr getelementptr inbounds ([[CINT]], ptr @ci, i32 0, i32 1)
65 // Note that C++ requires an extra load volatile over C from the LHS of the '+'.
66 (ci += ci) + ci;
67 // CHECK-NEXT: [[R1:%.*]] = load volatile [[INT]], ptr @ci
68 // CHECK-NEXT: [[I1:%.*]] = load volatile [[INT]], ptr getelementptr inbounds ([[CINT]], ptr @ci, i32 0, i32 1)
69 // CHECK-NEXT: [[R2:%.*]] = load volatile [[INT]], ptr @ci
70 // CHECK-NEXT: [[I2:%.*]] = load volatile [[INT]], ptr getelementptr inbounds ([[CINT]], ptr @ci, i32 0, i32 1)
71 // CHECK-NEXT: [[R:%.*]] = add [[INT]] [[R2]], [[R1]]
72 // CHECK-NEXT: [[I:%.*]] = add [[INT]] [[I2]], [[I1]]
73 // CHECK-NEXT: store volatile [[INT]] [[R]], ptr @ci
74 // CHECK-NEXT: store volatile [[INT]] [[I]], ptr getelementptr inbounds ([[CINT]], ptr @ci, i32 0, i32 1)
75 // CHECK-NEXT: [[R1:%.*]] = load volatile [[INT]], ptr @ci
76 // CHECK-NEXT: [[I1:%.*]] = load volatile [[INT]], ptr getelementptr inbounds ([[CINT]], ptr @ci, i32 0, i32 1)
77 // CHECK-NEXT: [[R2:%.*]] = load volatile [[INT]], ptr @ci
78 // CHECK-NEXT: [[I2:%.*]] = load volatile [[INT]], ptr getelementptr inbounds ([[CINT]], ptr @ci, i32 0, i32 1)
79 // These additions can be elided.
80 // CHECK-NEXT: add [[INT]] [[R1]], [[R2]]
81 // CHECK-NEXT: add [[INT]] [[I1]], [[I2]]
83 asm("nop"); // CHECK-NEXT: call void asm
85 // Extra load volatile in C++.
86 (i += j) + k;
87 // CHECK-NEXT: load volatile
88 // CHECK-NEXT: load volatile
89 // CHECK-NEXT: add nsw [[INT]]
90 // CHECK-NEXT: store volatile
91 // CHECK-NEXT: load volatile
92 // CHECK-NEXT: load volatile
93 // CHECK-NEXT: add nsw [[INT]]
95 asm("nop"); // CHECK-NEXT: call void asm
97 // Extra load volatile in C++.
98 (i += j) + 1;
99 // CHECK-NEXT: load volatile
100 // CHECK-NEXT: load volatile
101 // CHECK-NEXT: add nsw [[INT]]
102 // CHECK-NEXT: store volatile
103 // CHECK-NEXT: load volatile
104 // CHECK-NEXT: add nsw [[INT]]
106 asm("nop"); // CHECK-NEXT: call void asm
108 ci+ci;
109 // CHECK-NEXT: load volatile
110 // CHECK-NEXT: load volatile
111 // CHECK-NEXT: load volatile
112 // CHECK-NEXT: load volatile
113 // CHECK-NEXT: add [[INT]]
114 // CHECK-NEXT: add [[INT]]
116 __real i;
118 +ci;
119 // CHECK-NEXT: load volatile
120 // CHECK-NEXT: load volatile
122 asm("nop"); // CHECK-NEXT: call void asm
124 (void)(i=i);
125 // CHECK-NEXT: load volatile
126 // CHECK-NEXT: store volatile
128 (float)(i=i);
129 // CHECK-NEXT: load volatile
130 // CHECK-NEXT: store volatile
131 // CHECK-NEXT: load volatile
132 // CHECK-NEXT: sitofp
134 (void)i; // This is now a load in C++11
135 // CHECK11-NEXT: load volatile
137 i=i;
138 // CHECK-NEXT: load volatile
139 // CHECK-NEXT: store volatile
141 // Extra load volatile in C++.
142 i=i=i;
143 // CHECK-NEXT: load volatile
144 // CHECK-NEXT: store volatile
145 // CHECK-NEXT: load volatile
146 // CHECK-NEXT: store volatile
148 (void)__builtin_choose_expr(0, i=i, j=j);
149 // CHECK-NEXT: load volatile
150 // CHECK-NEXT: store volatile
152 k ? (i=i) : (j=j);
153 // CHECK-NEXT: load volatile
154 // CHECK-NEXT: icmp
155 // CHECK-NEXT: br i1
156 // CHECK: load volatile
157 // CHECK-NEXT: store volatile
158 // CHECK-NEXT: br label
159 // CHECK: load volatile
160 // CHECK-NEXT: store volatile
161 // CHECK-NEXT: br label
162 // CHECK: phi
164 (void)(i,(i=i)); // first i is also a load in C++11
165 // CHECK11-NEXT: load volatile
166 // CHECK-NEXT: load volatile
167 // CHECK-NEXT: store volatile
169 i=i,k; // k is also a load in C++11
170 // CHECK-NEXT: load volatile [[INT]], ptr @i
171 // CHECK-NEXT: store volatile {{.*}}, ptr @i
172 // CHECK11-NEXT: load volatile [[INT]], ptr @k
174 (i=j,k=j);
175 // CHECK-NEXT: load volatile [[INT]], ptr @j
176 // CHECK-NEXT: store volatile {{.*}}, ptr @i
177 // CHECK-NEXT: load volatile [[INT]], ptr @j
178 // CHECK-NEXT: store volatile {{.*}}, ptr @k
180 (i=j,k); // k is also a load in C++11
181 // CHECK-NEXT: load volatile [[INT]], ptr @j
182 // CHECK-NEXT: store volatile {{.*}}, ptr @i
183 // CHECK11-NEXT: load volatile [[INT]], ptr @k
185 (i,j); // i and j both are loads in C++11
186 // CHECK11-NEXT: load volatile [[INT]], ptr @i
187 // CHECK11-NEXT: load volatile [[INT]], ptr @j
189 // Extra load in C++.
190 i=c=k;
191 // CHECK-NEXT: load volatile
192 // CHECK-NEXT: trunc
193 // CHECK-NEXT: store volatile
194 // CHECK-NEXT: load volatile
195 // CHECK-NEXT: sext
196 // CHECK-NEXT: store volatile
198 i+=k;
199 // CHECK-NEXT: load volatile
200 // CHECK-NEXT: load volatile
201 // CHECK-NEXT: add nsw [[INT]]
202 // CHECK-NEXT: store volatile
204 ci; // ci is a load in C++11
205 // CHECK11-NEXT: load volatile {{.*}} @ci
206 // CHECK11-NEXT: load volatile {{.*}} @ci, i32 0, i32 1
208 asm("nop"); // CHECK-NEXT: call void asm
210 (int)ci;
211 // CHECK-NEXT: load volatile {{.*}} @ci
212 // CHECK-NEXT: load volatile {{.*}} @ci, i32 0, i32 1
214 (bool)ci;
215 // CHECK-NEXT: load volatile {{.*}} @ci
216 // CHECK-NEXT: load volatile {{.*}} @ci, i32 0, i32 1
217 // CHECK-NEXT: icmp ne
218 // CHECK-NEXT: icmp ne
219 // CHECK-NEXT: or i1
221 ci=ci;
222 // CHECK-NEXT: load volatile
223 // CHECK-NEXT: load volatile
224 // CHECK-NEXT: store volatile
225 // CHECK-NEXT: store volatile
227 asm("nop"); // CHECK-NEXT: call void asm
229 // Extra load in C++.
230 ci=ci=ci;
231 // CHECK-NEXT: load volatile
232 // CHECK-NEXT: load volatile
233 // CHECK-NEXT: store volatile
234 // CHECK-NEXT: store volatile
235 // CHECK-NEXT: load volatile
236 // CHECK-NEXT: load volatile
237 // CHECK-NEXT: store volatile
238 // CHECK-NEXT: store volatile
240 __imag ci = __imag ci = __imag ci;
241 // CHECK-NEXT: [[T:%.*]] = load volatile [[INT]], ptr getelementptr inbounds ([[CINT]], ptr @ci, i32 0, i32 1)
242 // CHECK-NEXT: store volatile [[INT]] [[T]], ptr getelementptr inbounds ([[CINT]], ptr @ci, i32 0, i32 1)
243 // CHECK-NEXT: [[T:%.*]] = load volatile [[INT]], ptr getelementptr inbounds ([[CINT]], ptr @ci, i32 0, i32 1)
244 // CHECK-NEXT: store volatile [[INT]] [[T]], ptr getelementptr inbounds ([[CINT]], ptr @ci, i32 0, i32 1)
246 __real (i = j);
247 // CHECK-NEXT: load volatile
248 // CHECK-NEXT: store volatile
250 __imag i;
252 // ============================================================
253 // FIXME: Test cases we get wrong.
255 // A use. We load all of a into a copy of a, then load i. gcc forgets to do
256 // the assignment.
257 // (a = a).i;
259 // ============================================================
260 // Test cases where we intentionally differ from gcc, due to suspected bugs in
261 // gcc.
263 // Not a use. gcc forgets to do the assignment.
264 // CHECK-NEXT: call {{.*}}void
265 ((a=a),a);
267 // Not a use. gcc gets this wrong, it doesn't emit the copy!
268 // CHECK-NEXT: call {{.*}}void
269 (void)(a=a);
271 // Not a use. gcc got this wrong in 4.2 and omitted the side effects
272 // entirely, but it is fixed in 4.4.0.
273 __imag (i = j);
274 // CHECK-NEXT: load volatile
275 // CHECK-NEXT: store volatile
277 // C++ does an extra load here. Note that we have to do full loads.
278 (float)(ci=ci);
279 // CHECK-NEXT: load volatile
280 // CHECK-NEXT: load volatile
281 // CHECK-NEXT: store volatile
282 // CHECK-NEXT: store volatile
283 // CHECK-NEXT: load volatile
284 // CHECK-NEXT: load volatile
285 // CHECK-NEXT: sitofp
287 // Not a use, bug? gcc treats this as not a use, that's probably a
288 // bug due to tree folding ignoring volatile.
289 (int)(ci=ci);
290 // CHECK-NEXT: load volatile
291 // CHECK-NEXT: load volatile
292 // CHECK-NEXT: store volatile
293 // CHECK-NEXT: store volatile
294 // CHECK-NEXT: load volatile
295 // CHECK-NEXT: load volatile
297 // A use.
298 (float)(i=i);
299 // CHECK-NEXT: load volatile
300 // CHECK-NEXT: store volatile
301 // CHECK-NEXT: load volatile
302 // CHECK-NEXT: sitofp
304 // A use. gcc treats this as not a use, that's probably a bug due to tree
305 // folding ignoring volatile.
306 (int)(i=i);
307 // CHECK-NEXT: load volatile
308 // CHECK-NEXT: store volatile
309 // CHECK-NEXT: load volatile
311 // A use.
312 -(i=j);
313 // CHECK-NEXT: load volatile
314 // CHECK-NEXT: store volatile
315 // CHECK-NEXT: load volatile
316 // CHECK-NEXT: sub
318 // A use. gcc treats this a not a use, that's probably a bug due to tree
319 // folding ignoring volatile.
320 +(i=k);
321 // CHECK-NEXT: load volatile
322 // CHECK-NEXT: store volatile
323 // CHECK-NEXT: load volatile
325 // A use. gcc treats this a not a use, that's probably a bug due to tree
326 // folding ignoring volatile.
327 __real (ci=ci);
328 // CHECK-NEXT: load volatile
329 // CHECK-NEXT: load volatile
330 // CHECK-NEXT: store volatile
331 // CHECK-NEXT: store volatile
333 // A use.
334 i + 0;
335 // CHECK-NEXT: load volatile
336 // CHECK-NEXT: add
338 // A use.
339 (i=j) + i;
340 // CHECK-NEXT: load volatile
341 // CHECK-NEXT: store volatile
342 // CHECK-NEXT: load volatile
343 // CHECK-NEXT: load volatile
344 // CHECK-NEXT: add
346 // A use. gcc treats this as not a use, that's probably a bug due to tree
347 // folding ignoring volatile.
348 (i=j) + 0;
349 // CHECK-NEXT: load volatile
350 // CHECK-NEXT: store volatile
351 // CHECK-NEXT: load volatile
352 // CHECK-NEXT: add
354 (i,j)=k; // i is also a load in C++11
355 // CHECK-NEXT: load volatile [[INT]], ptr @k
356 // CHECK11-NEXT: load volatile [[INT]], ptr @i
357 // CHECK-NEXT: store volatile {{.*}}, ptr @j
359 (j=k,i)=i;
360 // CHECK-NEXT: load volatile [[INT]], ptr @i
361 // CHECK-NEXT: load volatile [[INT]], ptr @k
362 // CHECK-NEXT: store volatile {{.*}}, ptr @j
363 // CHECK-NEXT: store volatile {{.*}}, ptr @i
365 // CHECK-NEXT: ret void