|  | // RUN: %clang_cc1 %s -verify=expected,access -fsyntax-only | 
|  | // RUN: %clang_cc1 %s -std=c2x -verify=expected,access -fsyntax-only | 
|  | // RUN: %clang_cc1 %s -std=c2x -pedantic -verify=expected,access -fsyntax-only | 
|  | // RUN: %clang_cc1 %s -verify -fsyntax-only -Wno-atomic-access | 
|  |  | 
|  | _Atomic(unsigned int) data1; | 
|  | int _Atomic data2; | 
|  |  | 
|  | // Shift operations | 
|  |  | 
|  | int func_01 (int x) { | 
|  | return data1 << x; | 
|  | } | 
|  |  | 
|  | int func_02 (int x) { | 
|  | return x << data1; | 
|  | } | 
|  |  | 
|  | int func_03 (int x) { | 
|  | return data2 << x; | 
|  | } | 
|  |  | 
|  | int func_04 (int x) { | 
|  | return x << data2; | 
|  | } | 
|  |  | 
|  | int func_05 (void) { | 
|  | return data2 << data1; | 
|  | } | 
|  |  | 
|  | int func_06 (void) { | 
|  | return data1 << data2; | 
|  | } | 
|  |  | 
|  | void func_07 (int x) { | 
|  | data1 <<= x; | 
|  | } | 
|  |  | 
|  | void func_08 (int x) { | 
|  | data2 <<= x; | 
|  | } | 
|  |  | 
|  | void func_09 (int* xp) { | 
|  | *xp <<= data1; | 
|  | } | 
|  |  | 
|  | void func_10 (int* xp) { | 
|  | *xp <<= data2; | 
|  | } | 
|  |  | 
|  | int func_11 (int x) { | 
|  | return data1 == x; | 
|  | } | 
|  |  | 
|  | int func_12 (void) { | 
|  | return data1 < data2; | 
|  | } | 
|  |  | 
|  | int func_13 (int x, unsigned y) { | 
|  | return x ? data1 : y; | 
|  | } | 
|  |  | 
|  | int func_14 (void) { | 
|  | return data1 == 0; | 
|  | } | 
|  |  | 
|  | void func_15(void) { | 
|  | // Ensure that the result of an assignment expression properly strips the | 
|  | // _Atomic qualifier; Issue 48742. | 
|  | _Atomic int x; | 
|  | int y = (x = 2); | 
|  | int z = (int)(x = 2); | 
|  | y = (x = 2); | 
|  | z = (int)(x = 2); | 
|  | y = (x += 2); | 
|  |  | 
|  | _Static_assert(__builtin_types_compatible_p(__typeof__(x = 2), int), "incorrect"); | 
|  | _Static_assert(__builtin_types_compatible_p(__typeof__(x += 2), int), "incorrect"); | 
|  | } | 
|  |  | 
|  | // Ensure that member access of an atomic structure or union type is properly | 
|  | // diagnosed as being undefined behavior; Issue 54563. | 
|  | void func_16(void) { | 
|  | // LHS member access. | 
|  | _Atomic struct { int val; } x, *xp; | 
|  | x.val = 12;   // access-error {{accessing a member of an atomic structure or union is undefined behavior}} | 
|  | xp->val = 12; // access-error {{accessing a member of an atomic structure or union is undefined behavior}} | 
|  |  | 
|  | _Atomic union { | 
|  | int ival; | 
|  | float fval; | 
|  | } y, *yp; | 
|  | y.ival = 12;     // access-error {{accessing a member of an atomic structure or union is undefined behavior}} | 
|  | yp->fval = 1.2f; // access-error {{accessing a member of an atomic structure or union is undefined behavior}} | 
|  |  | 
|  | // RHS member access. | 
|  | int xval = x.val; // access-error {{accessing a member of an atomic structure or union is undefined behavior}} | 
|  | xval = xp->val;   // access-error {{accessing a member of an atomic structure or union is undefined behavior}} | 
|  | int yval = y.ival; // access-error {{accessing a member of an atomic structure or union is undefined behavior}} | 
|  | yval = yp->ival;   // access-error {{accessing a member of an atomic structure or union is undefined behavior}} | 
|  |  | 
|  | // Using the type specifier instead of the type qualifier. | 
|  | _Atomic(struct { int val; }) z; | 
|  | z.val = 12;       // access-error {{accessing a member of an atomic structure or union is undefined behavior}} | 
|  | int zval = z.val; // access-error {{accessing a member of an atomic structure or union is undefined behavior}} | 
|  |  | 
|  | // Don't diagnose in an unevaluated context, however. | 
|  | (void)sizeof(x.val); | 
|  | (void)sizeof(xp->val); | 
|  | (void)sizeof(y.ival); | 
|  | (void)sizeof(yp->ival); | 
|  | } | 
|  |  | 
|  | // Ensure that we correctly implement assignment constraints from C2x 6.5.16.1. | 
|  | void func_17(void) { | 
|  | // The left operand has atomic ... arithmetic type, and the right operand has | 
|  | // arithmetic type; | 
|  | _Atomic int i = 0; | 
|  | _Atomic float f = 0.0f; | 
|  |  | 
|  | // the left operand has an atomic ... version of a structure or union type | 
|  | // compatible with the type of the right operand; | 
|  | struct S { int i; } non_atomic_s; | 
|  | _Atomic struct S s = non_atomic_s; | 
|  |  | 
|  | union U { int i; float f; } non_atomic_u; | 
|  | _Atomic union U u = non_atomic_u; | 
|  |  | 
|  | // the left operand has atomic ... pointer type, and (considering the type | 
|  | // the left operand would have after lvalue conversion) both operands are | 
|  | // pointers to qualified or unqualified versions of compatible types, and the | 
|  | // type pointed to by the left operand has all the qualifiers of the type | 
|  | // pointed to by the right operand; | 
|  | const int *cip = 0; | 
|  | volatile const int *vcip = 0; | 
|  | const int * const cicp = 0; | 
|  | _Atomic(const int *) acip = cip; | 
|  | _Atomic(const int *) bad_acip = vcip; // expected-warning {{initializing '_Atomic(const int *)' with an expression of type 'const volatile int *' discards qualifiers}} | 
|  | _Atomic(const int *) acip2 = cicp; | 
|  | _Atomic(int *) aip = &i; // expected-warning {{incompatible pointer types initializing '_Atomic(int *)' with an expression of type '_Atomic(int) *'}} \ | 
|  |  | 
|  | // the left operand has atomic ... pointer type, and (considering the type | 
|  | // the left operand would have after lvalue conversion) one operand is a | 
|  | // pointer to an object type, and the other is a pointer to a qualified or | 
|  | // unqualified version of void, and the type pointed to by the left operand | 
|  | // has all the qualifiers of the type pointed to by the right operand; | 
|  | const void *cvp = 0; | 
|  | _Atomic(const int *) acip3 = cvp; | 
|  | _Atomic(const void *) acvip = cip; | 
|  | _Atomic(const int *) acip4 = vcip;   // expected-warning {{initializing '_Atomic(const int *)' with an expression of type 'const volatile int *' discards qualifiers}} | 
|  | _Atomic(const void *) acvip2 = vcip; // expected-warning {{initializing '_Atomic(const void *)' with an expression of type 'const volatile int *' discards qualifiers}} | 
|  | _Atomic(const int *) acip5 = cicp; | 
|  | _Atomic(const void *) acvip3 = cicp; | 
|  |  | 
|  | #if __STDC_VERSION__ >= 202000L | 
|  | // the left operand has an atomic ... version of the nullptr_t type and the | 
|  | // right operand is a null pointer constant or its type is nullptr_t | 
|  | typedef typeof(nullptr) nullptr_t; | 
|  | nullptr_t n; | 
|  | _Atomic nullptr_t cn2 = n; | 
|  | _Atomic nullptr_t cn3 = nullptr; | 
|  | #endif // __STDC_VERSION__ >= 202000L | 
|  |  | 
|  | // the left operand is an atomic ... pointer, and the right operand is a null | 
|  | // pointer constant or its type is nullptr_t; | 
|  | _Atomic(int *) aip2 = 0; | 
|  | #if __STDC_VERSION__ >= 202000L | 
|  | _Atomic(int *) ip2 = n; | 
|  | _Atomic(int *) ip3 = nullptr; | 
|  | _Atomic(const int *) ip4 = nullptr; | 
|  | #endif // __STDC_VERSION__ >= 202000L | 
|  | } | 
|  |  | 
|  | // Ensure that the assignment constraints also work at file scope. | 
|  | _Atomic int ai = 0; | 
|  | _Atomic float af = 0.0f; | 
|  | _Atomic(int *) aip1 = 0; | 
|  |  | 
|  | struct S { int a; } non_atomic_s; | 
|  | _Atomic struct S as = non_atomic_s; // expected-error {{initializer element is not a compile-time constant}} | 
|  |  | 
|  | const int *cip = 0; | 
|  | _Atomic(const int *) acip1 = cip; // expected-error {{initializer element is not a compile-time constant}} | 
|  |  | 
|  | const void *cvp = 0; | 
|  | _Atomic(const int *) acip2 = cvp; // expected-error {{initializer element is not a compile-time constant}} | 
|  |  | 
|  | #if __STDC_VERSION__ >= 202000L | 
|  | // the left operand has an atomic ... version of the nullptr_t type and the | 
|  | // right operand is a null pointer constant or its type is nullptr_t | 
|  | typedef typeof(nullptr) nullptr_t; | 
|  | nullptr_t n; | 
|  | _Atomic nullptr_t cn2 = n; // expected-error {{initializer element is not a compile-time constant}} | 
|  | _Atomic(int *) aip2 = nullptr; | 
|  | #endif // __STDC_VERSION__ >= 202000L | 
|  |  | 
|  | // FIXME: &ai is an address constant, so this should be accepted as an | 
|  | // initializer, but the bit-cast inserted due to the pointer conversion is | 
|  | // tripping up the test for whether the initializer is a constant expression. | 
|  | // The warning is correct but the error is not. | 
|  | _Atomic(int *) aip3 = &ai; /* expected-warning {{incompatible pointer types initializing '_Atomic(int *)' with an expression of type '_Atomic(int) *'}} | 
|  | expected-error {{initializer element is not a compile-time constant}} | 
|  | */ | 
|  |  | 
|  | // Test the behavior when converting the null pointer constant to an atomic | 
|  | // function pointer. | 
|  | _Atomic(int (*)(char)) afp = (void *)0; | 
|  |  | 
|  | void func_18(void) { | 
|  | // Ensure we can cast to atomic scalar types. | 
|  | data2 = (_Atomic int)0; | 
|  | (void)(_Atomic(int *))0; | 
|  |  | 
|  | // But that we correctly reject casts to atomic aggregate types. | 
|  | struct S { int a; } s; | 
|  | struct T { int a; }; | 
|  | (void)(_Atomic struct T)s; // expected-error {{used type 'struct T' where arithmetic or pointer type is required}} | 
|  | } |