xref: /aosp_15_r20/external/cronet/third_party/libc++/src/test/libcxx/atomics/atomics.align/align.pass.cpp (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // UNSUPPORTED: c++03
10 // REQUIRES: has-1024-bit-atomics
11 // ADDITIONAL_COMPILE_FLAGS: -Wno-psabi
12 // ... since C++20 std::__atomic_base initializes, so we get a warning about an
13 // ABI change for vector variants since the constructor code for that is
14 // different if one were to compile with architecture-specific vector
15 // extensions enabled.
16 // This however isn't ABI breaking as it was impossible for any code to trigger
17 // this without using libc++ internals.
18 
19 // GCC currently fails because it needs -fabi-version=6 to fix mangling of
20 // std::atomic when used with __attribute__((vector(X))).
21 // XFAIL: gcc
22 
23 // This fails on PowerPC, as the LLIArr2 and Padding structs do not have
24 // adequate alignment, despite these types returning true for the query of
25 // being lock-free. This is an issue that occurs when linking in the
26 // PowerPC GNU libatomic library into the test.
27 // XFAIL: target=powerpc{{.*}}le-unknown-linux-gnu
28 
29 // <atomic>
30 
31 // Verify that the content of atomic<T> is properly aligned if the type is
32 // lock-free. This can't be observed through the atomic<T> API. It is
33 // nonetheless required for correctness of the implementation: lock-free implies
34 // that ISA instructions are used, and these instructions assume "suitable
35 // alignment". Supported architectures all require natural alignment for
36 // lock-freedom (e.g. load-linked / store-conditional, or cmpxchg).
37 
38 #include <atomic>
39 #include <cassert>
40 #include <cstddef>
41 
42 template <typename T>
43 struct atomic_test : public std::__atomic_base<T> {
atomic_testatomic_test44   atomic_test() {
45     if (this->is_lock_free()) {
46       using AtomicImpl = decltype(this->__a_);
47       assert(alignof(AtomicImpl) >= sizeof(AtomicImpl) &&
48              "expected natural alignment for lock-free type");
49     }
50   }
51 };
52 
main(int,char **)53 int main(int, char**) {
54 
55 // structs and unions can't be defined in the template invocation.
56 // Work around this with a typedef.
57 #define CHECK_ALIGNMENT(T)                                                     \
58   do {                                                                         \
59     typedef T type;                                                            \
60     atomic_test<type> t;                                                       \
61   } while (0)
62 
63   CHECK_ALIGNMENT(bool);
64   CHECK_ALIGNMENT(char);
65   CHECK_ALIGNMENT(signed char);
66   CHECK_ALIGNMENT(unsigned char);
67   CHECK_ALIGNMENT(char16_t);
68   CHECK_ALIGNMENT(char32_t);
69 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
70   CHECK_ALIGNMENT(wchar_t);
71 #endif
72   CHECK_ALIGNMENT(short);
73   CHECK_ALIGNMENT(unsigned short);
74   CHECK_ALIGNMENT(int);
75   CHECK_ALIGNMENT(unsigned int);
76   CHECK_ALIGNMENT(long);
77   CHECK_ALIGNMENT(unsigned long);
78   CHECK_ALIGNMENT(long long);
79   CHECK_ALIGNMENT(unsigned long long);
80   CHECK_ALIGNMENT(std::nullptr_t);
81   CHECK_ALIGNMENT(void *);
82   CHECK_ALIGNMENT(float);
83   CHECK_ALIGNMENT(double);
84   CHECK_ALIGNMENT(long double);
85   CHECK_ALIGNMENT(int __attribute__((vector_size(1 * sizeof(int)))));
86   CHECK_ALIGNMENT(int __attribute__((vector_size(2 * sizeof(int)))));
87   CHECK_ALIGNMENT(int __attribute__((vector_size(4 * sizeof(int)))));
88   CHECK_ALIGNMENT(int __attribute__((vector_size(16 * sizeof(int)))));
89   CHECK_ALIGNMENT(int __attribute__((vector_size(32 * sizeof(int)))));
90   CHECK_ALIGNMENT(float __attribute__((vector_size(1 * sizeof(float)))));
91   CHECK_ALIGNMENT(float __attribute__((vector_size(2 * sizeof(float)))));
92   CHECK_ALIGNMENT(float __attribute__((vector_size(4 * sizeof(float)))));
93   CHECK_ALIGNMENT(float __attribute__((vector_size(16 * sizeof(float)))));
94   CHECK_ALIGNMENT(float __attribute__((vector_size(32 * sizeof(float)))));
95   CHECK_ALIGNMENT(double __attribute__((vector_size(1 * sizeof(double)))));
96   CHECK_ALIGNMENT(double __attribute__((vector_size(2 * sizeof(double)))));
97   CHECK_ALIGNMENT(double __attribute__((vector_size(4 * sizeof(double)))));
98   CHECK_ALIGNMENT(double __attribute__((vector_size(16 * sizeof(double)))));
99   CHECK_ALIGNMENT(double __attribute__((vector_size(32 * sizeof(double)))));
100   CHECK_ALIGNMENT(struct Empty {});
101   CHECK_ALIGNMENT(struct OneInt { int i; });
102   CHECK_ALIGNMENT(struct IntArr2 { int i[2]; });
103   CHECK_ALIGNMENT(struct FloatArr3 { float i[3]; });
104   CHECK_ALIGNMENT(struct LLIArr2 { long long int i[2]; });
105   CHECK_ALIGNMENT(struct LLIArr4 { long long int i[4]; });
106   CHECK_ALIGNMENT(struct LLIArr8 { long long int i[8]; });
107   CHECK_ALIGNMENT(struct LLIArr16 { long long int i[16]; });
108   CHECK_ALIGNMENT(struct Padding { char c; /* padding */ long long int i; });
109   CHECK_ALIGNMENT(union IntFloat { int i; float f; });
110   CHECK_ALIGNMENT(enum class StrongEnum { foo });
111 
112   return 0;
113 }
114