xref: /llvm-project/clang/test/Sema/atomic-expr.c (revision e4f1ef85fd60c08c9ece4982fccf76e8101011b8)
1 // RUN: %clang_cc1 %s -verify=expected,access -fsyntax-only
2 // RUN: %clang_cc1 %s -std=c2x -verify=expected,access -fsyntax-only
3 // RUN: %clang_cc1 %s -std=c2x -pedantic -verify=expected,access -fsyntax-only
4 // RUN: %clang_cc1 %s -verify -fsyntax-only -Wno-atomic-access
5 // RUN: %clang_cc1 %s -verify=expected,access -fsyntax-only -fexperimental-new-constant-interpreter
6 // RUN: %clang_cc1 %s -std=c2x -verify=expected,access -fsyntax-only -fexperimental-new-constant-interpreter
7 // RUN: %clang_cc1 %s -std=c2x -pedantic -verify=expected,access -fsyntax-only -fexperimental-new-constant-interpreter
8 // RUN: %clang_cc1 %s -verify -fsyntax-only -Wno-atomic-access -fexperimental-new-constant-interpreter
9 
10 
11 _Atomic(unsigned int) data1;
12 int _Atomic data2;
13 
14 // Shift operations
15 
func_01(int x)16 int func_01 (int x) {
17   return data1 << x;
18 }
19 
func_02(int x)20 int func_02 (int x) {
21   return x << data1;
22 }
23 
func_03(int x)24 int func_03 (int x) {
25   return data2 << x;
26 }
27 
func_04(int x)28 int func_04 (int x) {
29   return x << data2;
30 }
31 
func_05(void)32 int func_05 (void) {
33   return data2 << data1;
34 }
35 
func_06(void)36 int func_06 (void) {
37   return data1 << data2;
38 }
39 
func_07(int x)40 void func_07 (int x) {
41   data1 <<= x;
42 }
43 
func_08(int x)44 void func_08 (int x) {
45   data2 <<= x;
46 }
47 
func_09(int * xp)48 void func_09 (int* xp) {
49   *xp <<= data1;
50 }
51 
func_10(int * xp)52 void func_10 (int* xp) {
53   *xp <<= data2;
54 }
55 
func_11(int x)56 int func_11 (int x) {
57   return data1 == x;
58 }
59 
func_12(void)60 int func_12 (void) {
61   return data1 < data2;
62 }
63 
func_13(int x,unsigned y)64 int func_13 (int x, unsigned y) {
65   return x ? data1 : y;
66 }
67 
func_14(void)68 int func_14 (void) {
69   return data1 == 0;
70 }
71 
func_15(void)72 void func_15(void) {
73   // Ensure that the result of an assignment expression properly strips the
74   // _Atomic qualifier; Issue 48742.
75   _Atomic int x;
76   int y = (x = 2);
77   int z = (int)(x = 2);
78   y = (x = 2);
79   z = (int)(x = 2);
80   y = (x += 2);
81 
82   _Static_assert(__builtin_types_compatible_p(__typeof__(x = 2), int), "incorrect");
83   _Static_assert(__builtin_types_compatible_p(__typeof__(x += 2), int), "incorrect");
84 }
85 
86 // Ensure that member access of an atomic structure or union type is properly
87 // diagnosed as being undefined behavior; Issue 54563.
func_16(void)88 void func_16(void) {
89   // LHS member access.
90   _Atomic struct { int val; } x, *xp;
91   x.val = 12;   // access-error {{accessing a member of an atomic structure or union is undefined behavior}}
92   xp->val = 12; // access-error {{accessing a member of an atomic structure or union is undefined behavior}}
93 
94   _Atomic union {
95     int ival;
96     float fval;
97   } y, *yp;
98   y.ival = 12;     // access-error {{accessing a member of an atomic structure or union is undefined behavior}}
99   yp->fval = 1.2f; // access-error {{accessing a member of an atomic structure or union is undefined behavior}}
100 
101   // RHS member access.
102   int xval = x.val; // access-error {{accessing a member of an atomic structure or union is undefined behavior}}
103   xval = xp->val;   // access-error {{accessing a member of an atomic structure or union is undefined behavior}}
104   int yval = y.ival; // access-error {{accessing a member of an atomic structure or union is undefined behavior}}
105   yval = yp->ival;   // access-error {{accessing a member of an atomic structure or union is undefined behavior}}
106 
107   // Using the type specifier instead of the type qualifier.
108   _Atomic(struct { int val; }) z;
109   z.val = 12;       // access-error {{accessing a member of an atomic structure or union is undefined behavior}}
110   int zval = z.val; // access-error {{accessing a member of an atomic structure or union is undefined behavior}}
111 
112   // Don't diagnose in an unevaluated context, however.
113   (void)sizeof(x.val);
114   (void)sizeof(xp->val);
115   (void)sizeof(y.ival);
116   (void)sizeof(yp->ival);
117 }
118 
119 // Ensure that we correctly implement assignment constraints from C2x 6.5.16.1.
func_17(void)120 void func_17(void) {
121   // The left operand has atomic ... arithmetic type, and the right operand has
122   // arithmetic type;
123   _Atomic int i = 0;
124   _Atomic float f = 0.0f;
125 
126   // the left operand has an atomic ... version of a structure or union type
127   // compatible with the type of the right operand;
128   struct S { int i; } non_atomic_s;
129   _Atomic struct S s = non_atomic_s;
130 
131   union U { int i; float f; } non_atomic_u;
132   _Atomic union U u = non_atomic_u;
133 
134   // the left operand has atomic ... pointer type, and (considering the type
135   // the left operand would have after lvalue conversion) both operands are
136   // pointers to qualified or unqualified versions of compatible types, and the
137   // type pointed to by the left operand has all the qualifiers of the type
138   // pointed to by the right operand;
139   const int *cip = 0;
140   volatile const int *vcip = 0;
141   const int * const cicp = 0;
142   _Atomic(const int *) acip = cip;
143   _Atomic(const int *) bad_acip = vcip; // expected-warning {{initializing '_Atomic(const int *)' with an expression of type 'const volatile int *' discards qualifiers}}
144   _Atomic(const int *) acip2 = cicp;
145   _Atomic(int *) aip = &i; // expected-warning {{incompatible pointer types initializing '_Atomic(int *)' with an expression of type '_Atomic(int) *'}} \
146 
147   // the left operand has atomic ... pointer type, and (considering the type
148   // the left operand would have after lvalue conversion) one operand is a
149   // pointer to an object type, and the other is a pointer to a qualified or
150   // unqualified version of void, and the type pointed to by the left operand
151   // has all the qualifiers of the type pointed to by the right operand;
152   const void *cvp = 0;
153   _Atomic(const int *) acip3 = cvp;
154   _Atomic(const void *) acvip = cip;
155   _Atomic(const int *) acip4 = vcip;   // expected-warning {{initializing '_Atomic(const int *)' with an expression of type 'const volatile int *' discards qualifiers}}
156   _Atomic(const void *) acvip2 = vcip; // expected-warning {{initializing '_Atomic(const void *)' with an expression of type 'const volatile int *' discards qualifiers}}
157   _Atomic(const int *) acip5 = cicp;
158   _Atomic(const void *) acvip3 = cicp;
159 
160 #if __STDC_VERSION__ >= 202311L
161   // the left operand has an atomic ... version of the nullptr_t type and the
162   // right operand is a null pointer constant or its type is nullptr_t
163   typedef typeof(nullptr) nullptr_t;
164   nullptr_t n;
165   _Atomic nullptr_t cn2 = n;
166   _Atomic nullptr_t cn3 = nullptr;
167 #endif // __STDC_VERSION__ >= 202311L
168 
169   // the left operand is an atomic ... pointer, and the right operand is a null
170   // pointer constant or its type is nullptr_t;
171   _Atomic(int *) aip2 = 0;
172 #if __STDC_VERSION__ >= 202311L
173   _Atomic(int *) ip2 = n;
174   _Atomic(int *) ip3 = nullptr;
175   _Atomic(const int *) ip4 = nullptr;
176 #endif // __STDC_VERSION__ >= 202311L
177 }
178 
179 // Ensure that the assignment constraints also work at file scope.
180 _Atomic int ai = 0;
181 _Atomic float af = 0.0f;
182 _Atomic(int *) aip1 = 0;
183 
184 struct S { int a; } non_atomic_s;
185 _Atomic struct S as = non_atomic_s; // expected-error {{initializer element is not a compile-time constant}}
186 
187 const int *cip = 0;
188 _Atomic(const int *) acip1 = cip; // expected-error {{initializer element is not a compile-time constant}}
189 
190 const void *cvp = 0;
191 _Atomic(const int *) acip2 = cvp; // expected-error {{initializer element is not a compile-time constant}}
192 
193 #if __STDC_VERSION__ >= 202311L
194   // the left operand has an atomic ... version of the nullptr_t type and the
195   // right operand is a null pointer constant or its type is nullptr_t
196   typedef typeof(nullptr) nullptr_t;
197   nullptr_t n;
198   _Atomic nullptr_t cn2 = n; // expected-error {{initializer element is not a compile-time constant}}
199   _Atomic(int *) aip2 = nullptr;
200 #endif // __STDC_VERSION__ >= 202311L
201 
202 // FIXME: &ai is an address constant, so this should be accepted as an
203 // initializer, but the bit-cast inserted due to the pointer conversion is
204 // tripping up the test for whether the initializer is a constant expression.
205 // The warning is correct but the error is not.
206 _Atomic(int *) aip3 = &ai; /* expected-warning {{incompatible pointer types initializing '_Atomic(int *)' with an expression of type '_Atomic(int) *'}}
207                               expected-error {{initializer element is not a compile-time constant}}
208                             */
209 
210 // Test the behavior when converting the null pointer constant to an atomic
211 // function pointer.
212 _Atomic(int (*)(char)) afp = (void *)0;
213 
func_18(void)214 void func_18(void) {
215   // Ensure we can cast to atomic scalar types.
216   data2 = (_Atomic int)0;
217   (void)(_Atomic(int *))0;
218 
219   // But that we correctly reject casts to atomic aggregate types.
220   struct S { int a; } s;
221   struct T { int a; };
222   (void)(_Atomic struct T)s; // expected-error {{used type 'struct T' where arithmetic or pointer type is required}}
223 }
224 
225 // Test if we can handle an _Atomic qualified integer in a switch statement.
func_19(void)226 void func_19(void) {
227   _Atomic int a = 0;
228   switch (a) { }
229 }
230