]>
Commit | Line | Data |
---|---|---|
267bac10 JM |
1 | /* Test for _Atomic in C11. Test of valid code. See c11-atomic-2.c |
2 | for more exhaustive tests of assignment cases. */ | |
3 | /* { dg-do compile } */ | |
4 | /* { dg-options "-std=c11 -pedantic-errors" } */ | |
5 | ||
6 | /* The use of _Atomic as a qualifier, and of _Atomic (type-name), give | |
7 | the same type. */ | |
8 | extern _Atomic int a; | |
9 | extern _Atomic (int) a; | |
10 | extern int *_Atomic b; | |
11 | extern _Atomic (int *) b; | |
12 | extern void f (int [_Atomic]); | |
13 | extern void f (int *_Atomic); | |
14 | ||
15 | /* _Atomic may be applied to arbitrary types, with or without other | |
16 | qualifiers, and assignments may be made as with non-atomic | |
17 | types. Structure and union elements may be atomic. */ | |
18 | _Atomic int ai1, ai2; | |
19 | int i1; | |
20 | volatile _Atomic long double ald1; | |
21 | const _Atomic long double ald2; | |
22 | long double ld1; | |
23 | _Atomic _Complex double acd1, acd2; | |
24 | _Complex double d1; | |
25 | _Atomic volatile _Bool ab1; | |
26 | int *p; | |
27 | int *_Atomic restrict ap; | |
28 | struct s { char c[1000]; }; | |
29 | _Atomic struct s as1; | |
30 | struct s s1; | |
31 | struct t { _Atomic int i; }; | |
32 | _Atomic struct t at1; | |
33 | _Atomic struct t *atp1; | |
34 | struct t t1; | |
35 | union u { char c[1000]; }; | |
36 | _Atomic union u au1; | |
37 | union u u1; | |
38 | union v { _Atomic int i; }; | |
39 | _Atomic union v av1; | |
40 | union v v1; | |
41 | ||
42 | void | |
43 | func (_Atomic volatile long al1) | |
44 | { | |
45 | ai1 = ai2; | |
46 | ai1 = i1; | |
47 | i1 = ai2; | |
48 | ai1 = ald2; | |
49 | ald1 = d1; | |
50 | ld1 = acd2; | |
51 | acd1 += ab1; | |
52 | acd2 /= ai1; | |
53 | p = ap; | |
54 | ap = p; | |
55 | ab1 = p; | |
56 | as1 = s1; | |
57 | s1 = as1; | |
58 | at1 = t1; | |
59 | t1 = at1; | |
60 | /* It's unclear whether the undefined behavior (6.5.2.3#5) for | |
61 | accessing elements of atomic structures and unions is at | |
62 | translation or execution time; presume here that it's at | |
63 | execution time. */ | |
64 | t1.i = at1.i; | |
65 | at1.i = t1.i; | |
66 | atp1->i = t1.i; | |
67 | au1 = u1; | |
68 | u1 = au1; | |
69 | av1 = v1; | |
70 | v1 = av1; | |
71 | v1.i = av1.i; | |
72 | av1.i = v1.i; | |
73 | /* _Atomic is valid on register variables, even if not particularly | |
74 | useful. */ | |
75 | register _Atomic volatile int ra1 = 1, ra2 = 2; | |
76 | ra1 = ra2; | |
77 | ra2 = ra1; | |
78 | /* And on parameters. */ | |
79 | al1 = ra1; | |
80 | ra2 = al1; | |
81 | } | |
82 | ||
83 | /* A function may return an atomic type. */ | |
84 | _Atomic int | |
85 | func2 (int i) | |
86 | { | |
87 | return i; | |
88 | } | |
89 | ||
90 | /* Casts may specify atomic type. */ | |
91 | int | |
92 | func3 (int i) | |
93 | { | |
94 | return func2 ((_Atomic long) i); | |
95 | } | |
96 | ||
97 | /* The _Atomic void type is valid. */ | |
98 | _Atomic void *avp; | |
99 | ||
100 | /* An array of atomic elements is valid (the elements being atomic, | |
101 | not the array). */ | |
102 | _Atomic int aa[10]; | |
103 | int | |
104 | func4 (void) | |
105 | { | |
106 | return aa[2]; | |
107 | } | |
108 | ||
109 | /* Increment and decrement are valid for atomic types when they are | |
110 | valid for non-atomic types. */ | |
111 | void | |
112 | func5 (void) | |
113 | { | |
114 | ald1++; | |
115 | ald1--; | |
116 | ++ald1; | |
117 | --ald1; | |
118 | ai1++; | |
119 | ai1--; | |
120 | ++ai1; | |
121 | --ai1; | |
122 | ab1++; | |
123 | ab1--; | |
124 | ++ab1; | |
125 | --ab1; | |
126 | ap++; | |
127 | ap--; | |
128 | ++ap; | |
129 | --ap; | |
130 | } | |
131 | ||
132 | /* Compound literals may have atomic type. */ | |
133 | _Atomic int *aiclp = &(_Atomic int) { 1 }; | |
134 | ||
135 | /* Test unary & and *. */ | |
136 | void | |
137 | func6 (void) | |
138 | { | |
139 | int i = *aiclp; | |
140 | _Atomic int *p = &ai2; | |
141 | } | |
142 | ||
143 | /* Casts to atomic type are valid (although the _Atomic has little | |
144 | effect because the result is an rvalue). */ | |
145 | int i2 = (_Atomic int) 1.0; | |
146 | ||
147 | /* For pointer subtraction and comparisons, _Atomic does not count as | |
148 | a qualifier. Likewise for conditional expressions. */ | |
149 | _Atomic int *xaip1; | |
150 | volatile _Atomic int *xaip2; | |
151 | void *xvp1; | |
152 | ||
153 | void | |
154 | func7 (void) | |
155 | { | |
156 | int r; | |
157 | r = xaip1 - xaip2; | |
158 | r = xaip1 < xaip2; | |
159 | r = xaip1 > xaip2; | |
160 | r = xaip1 <= xaip2; | |
161 | r = xaip1 >= xaip2; | |
162 | r = xaip1 == xaip2; | |
163 | r = xaip1 != xaip2; | |
164 | r = xaip1 == xvp1; | |
165 | r = xaip1 != xvp1; | |
166 | r = xvp1 == xaip1; | |
167 | r = xvp1 != xaip1; | |
168 | r = xaip1 == 0; | |
169 | r = ((void *) 0) == xaip2; | |
170 | (void) (r ? xaip1 : xaip2); | |
171 | (void) (r ? xvp1 : xaip2); | |
172 | (void) (r ? xaip2 : xvp1); | |
173 | (void) (r ? xaip1 : 0); | |
174 | (void) (r ? 0 : xaip1); | |
175 | /* The result of a conditional expression between a pointer to | |
176 | qualified or unqualified (but not atomic) void, and a pointer to | |
177 | an atomic type, is a pointer to appropriately qualified, not | |
178 | atomic, void. As such, it is valid to use further in conditional | |
179 | expressions with other pointer types. */ | |
180 | (void) (r ? xaip1 : (r ? xaip1 : xvp1)); | |
181 | } | |
182 | ||
183 | /* Pointer += and -= integer is valid. */ | |
184 | void | |
185 | func8 (void) | |
186 | { | |
187 | b += 1; | |
188 | b -= 2ULL; | |
189 | ap += 3; | |
190 | } | |
191 | ||
192 | /* Various other cases of simple assignment are valid (some already | |
193 | tested above). */ | |
194 | void | |
195 | func9 (void) | |
196 | { | |
197 | ap = 0; | |
198 | ap = (void *) 0; | |
199 | xvp1 = atp1; | |
200 | atp1 = xvp1; | |
201 | } | |
202 | ||
203 | /* Test compatibility of function types in cases where _Atomic matches | |
204 | (see c11-atomic-3.c for corresponding cases where it doesn't | |
205 | match). */ | |
206 | void fc0a (int const); | |
207 | void fc0a (int); | |
208 | void fc0b (int _Atomic); | |
209 | void fc0b (int _Atomic); | |
210 | void fc1a (int); | |
211 | void | |
212 | fc1a (x) | |
213 | volatile int x; | |
214 | { | |
215 | } | |
216 | void fc1b (_Atomic int); | |
217 | void | |
218 | fc1b (x) | |
219 | volatile _Atomic int x; | |
220 | { | |
221 | } | |
222 | void | |
223 | fc2a (x) | |
224 | const int x; | |
225 | { | |
226 | } | |
227 | void fc2a (int); /* { dg-warning "follows non-prototype" } */ | |
228 | void | |
229 | fc2b (x) | |
230 | _Atomic int x; | |
231 | { | |
232 | } | |
233 | void fc2b (_Atomic int); /* { dg-warning "follows non-prototype" } */ | |
234 | void fc3a (int); | |
235 | void | |
236 | fc3a (x) | |
237 | volatile short x; | |
238 | { | |
239 | } | |
240 | void fc3b (_Atomic int); | |
241 | void | |
242 | fc3b (x) | |
243 | _Atomic short x; | |
244 | { | |
245 | } | |
246 | void | |
247 | fc4a (x) | |
248 | const short x; | |
249 | { | |
250 | } | |
251 | void fc4a (int); /* { dg-warning "follows non-prototype" } */ | |
252 | void | |
253 | fc4b (x) | |
254 | _Atomic short x; | |
255 | { | |
256 | } | |
257 | void fc4b (_Atomic int); /* { dg-warning "follows non-prototype" } */ | |
258 | ||
259 | /* Test cases involving C_MAYBE_CONST_EXPR work. */ | |
260 | void | |
261 | func10 (_Atomic int *p) | |
262 | { | |
263 | p[0 / 0] = 1; /* { dg-warning "division by zero" } */ | |
264 | p[0 / 0] += 1; /* { dg-warning "division by zero" } */ | |
265 | *p = 0 / 0; /* { dg-warning "division by zero" } */ | |
266 | *p += 0 / 0; /* { dg-warning "division by zero" } */ | |
267 | } |