[flang][cuda] Adapt ExternalNameConversion to work in gpu module (#117039)
[llvm-project.git] / clang / test / AST / ByteCode / builtin-align-cxx.cpp
bloba1edf307d6c479c57588237ee2934593d41b04bc
1 // C++-specific checks for the alignment builtins
2 // RUN: %clang_cc1 -triple=x86_64-unknown-unknown -std=c++11 %s -fsyntax-only -verify=expected,both -fexperimental-new-constant-interpreter
3 // RUN: %clang_cc1 -triple=x86_64-unknown-unknown -std=c++11 %s -fsyntax-only -verify=ref,both
5 // Check that we don't crash when using dependent types in __builtin_align:
6 template <typename a, a b>
7 void *c(void *d) { // both-note{{candidate template ignored}}
8 return __builtin_align_down(d, b);
11 struct x {};
12 x foo;
13 void test(void *value) {
14 c<int, 16>(value);
15 c<struct x, foo>(value); // both-error{{no matching function for call to 'c'}}
18 template <typename T, long Alignment, long ArraySize = 16>
19 void test_templated_arguments() {
20 T array[ArraySize]; // both-error{{variable has incomplete type 'fwddecl'}}
21 static_assert(__is_same(decltype(__builtin_align_up(array, Alignment)), T *), // both-error{{requested alignment is not a power of 2}}
22 "return type should be the decayed array type");
23 static_assert(__is_same(decltype(__builtin_align_down(array, Alignment)), T *),
24 "return type should be the decayed array type");
25 static_assert(__is_same(decltype(__builtin_is_aligned(array, Alignment)), bool),
26 "return type should be bool");
27 T *x1 = __builtin_align_up(array, Alignment);
28 T *x2 = __builtin_align_down(array, Alignment);
29 bool x3 = __builtin_align_up(array, Alignment);
32 void test() {
33 test_templated_arguments<int, 32>(); // fine
34 test_templated_arguments<struct fwddecl, 16>();
35 // both-note@-1{{in instantiation of function template specialization 'test_templated_arguments<fwddecl, 16L, 16L>'}}
36 // both-note@-2{{forward declaration of 'fwddecl'}}
37 test_templated_arguments<int, 7>(); // invalid alignment value
38 // both-note@-1{{in instantiation of function template specialization 'test_templated_arguments<int, 7L, 16L>'}}
41 template <typename T, long ArraySize>
42 void test_incorrect_alignment_without_instatiation(T value) {
43 int array[32];
44 static_assert(__is_same(decltype(__builtin_align_up(array, 31)), int *), // both-error{{requested alignment is not a power of 2}}
45 "return type should be the decayed array type");
46 static_assert(__is_same(decltype(__builtin_align_down(array, 7)), int *), // both-error{{requested alignment is not a power of 2}}
47 "return type should be the decayed array type");
48 static_assert(__is_same(decltype(__builtin_is_aligned(array, -1)), bool), // both-error{{requested alignment must be 1 or greater}}
49 "return type should be bool");
50 __builtin_align_up(array); // both-error{{too few arguments to function call, expected 2, have 1}}
51 __builtin_align_up(array, 31); // both-error{{requested alignment is not a power of 2}}
52 __builtin_align_down(array, 31); // both-error{{requested alignment is not a power of 2}}
53 __builtin_align_up(array, 31); // both-error{{requested alignment is not a power of 2}}
54 __builtin_align_up(value, 31); // This shouldn't want since the type is dependent
55 __builtin_align_up(value); // Same here
57 __builtin_align_up(array, sizeof(sizeof(value)) - 1); // both-error{{requested alignment is not a power of 2}}
58 __builtin_align_up(array, value); // no diagnostic as the alignment is value dependent.
59 (void)__builtin_align_up(array, ArraySize); // The same above here
62 // The original fix for the issue above broke some legitimate code.
63 // Here is a regression test:
64 typedef __SIZE_TYPE__ size_t;
65 void *allocate_impl(size_t size);
66 template <typename T>
67 T *allocate() {
68 constexpr size_t allocation_size =
69 __builtin_align_up(sizeof(T), sizeof(void *));
70 return static_cast<T *>(
71 __builtin_assume_aligned(allocate_impl(allocation_size), sizeof(void *)));
73 struct Foo {
74 int value;
76 void *test2() {
77 return allocate<struct Foo>();
80 // Check that pointers-to-members cannot be used:
81 class MemPtr {
82 public:
83 int data;
84 void func();
85 virtual void vfunc();
87 void test_member_ptr() {
88 __builtin_align_up(&MemPtr::data, 64); // both-error{{operand of type 'int MemPtr::*' where arithmetic or pointer type is required}}
89 __builtin_align_down(&MemPtr::func, 64); // both-error{{operand of type 'void (MemPtr::*)()' where arithmetic or pointer type is required}}
90 __builtin_is_aligned(&MemPtr::vfunc, 64); // both-error{{operand of type 'void (MemPtr::*)()' where arithmetic or pointer type is required}}
93 void test_references(Foo &i) {
94 // Check that the builtins look at the referenced type rather than the reference itself.
95 (void)__builtin_align_up(i, 64); // both-error{{operand of type 'Foo' where arithmetic or pointer type is required}}
96 (void)__builtin_align_up(static_cast<Foo &>(i), 64); // both-error{{operand of type 'Foo' where arithmetic or pointer type is required}}
97 (void)__builtin_align_up(static_cast<const Foo &>(i), 64); // both-error{{operand of type 'const Foo' where arithmetic or pointer type is required}}
98 (void)__builtin_align_up(static_cast<Foo &&>(i), 64); // both-error{{operand of type 'Foo' where arithmetic or pointer type is required}}
99 (void)__builtin_align_up(static_cast<const Foo &&>(i), 64); // both-error{{operand of type 'const Foo' where arithmetic or pointer type is required}}
100 (void)__builtin_align_up(&i, 64);
103 // Check that constexpr wrapper functions can be constant-evaluated.
104 template <typename T>
105 constexpr bool wrap_is_aligned(T ptr, long align) {
106 return __builtin_is_aligned(ptr, align);
107 // both-note@-1{{requested alignment -3 is not a positive power of two}}
108 // both-note@-2{{requested alignment 19 is not a positive power of two}}
109 // both-note@-3{{requested alignment must be 128 or less for type 'char'; 4194304 is invalid}}
111 template <typename T>
112 constexpr T wrap_align_up(T ptr, long align) {
113 return __builtin_align_up(ptr, align);
114 // both-note@-1{{requested alignment -2 is not a positive power of two}}
115 // both-note@-2{{requested alignment 18 is not a positive power of two}}
116 // both-note@-3{{requested alignment must be 2147483648 or less for type 'int'; 8589934592 is invalid}}
117 // both-error@-4{{operand of type 'bool' where arithmetic or pointer type is required}}
120 template <typename T>
121 constexpr T wrap_align_down(T ptr, long align) {
122 return __builtin_align_down(ptr, align);
123 // both-note@-1{{requested alignment -1 is not a positive power of two}}
124 // both-note@-2{{requested alignment 17 is not a positive power of two}}
125 // both-note@-3{{requested alignment must be 32768 or less for type 'short'; 1048576 is invalid}}
128 constexpr int a1 = wrap_align_up(22, 32);
129 static_assert(a1 == 32, "");
130 constexpr int a2 = wrap_align_down(22, 16);
131 static_assert(a2 == 16, "");
132 constexpr bool a3 = wrap_is_aligned(22, 32);
133 static_assert(!a3, "");
134 static_assert(wrap_align_down(wrap_align_up(22, 16), 32) == 32, "");
135 static_assert(wrap_is_aligned(wrap_align_down(wrap_align_up(22, 16), 32), 32), "");
136 static_assert(!wrap_is_aligned(wrap_align_down(wrap_align_up(22, 16), 32), 64), "");
138 constexpr long const_value(long l) { return l; }
139 // Check some invalid values during constant-evaluation
140 static_assert(wrap_align_down(1, const_value(-1)), ""); // both-error{{not an integral constant expression}}
141 // both-note@-1{{in call to}}
142 static_assert(wrap_align_up(1, const_value(-2)), ""); // both-error{{not an integral constant expression}}
143 // both-note@-1{{in call to}}
144 static_assert(wrap_is_aligned(1, const_value(-3)), ""); // both-error{{not an integral constant expression}}
145 // both-note@-1{{in call to}}
146 static_assert(wrap_align_down(1, const_value(17)), ""); // both-error{{not an integral constant expression}}
147 // both-note@-1{{in call to}}
148 static_assert(wrap_align_up(1, const_value(18)), ""); // both-error{{not an integral constant expression}}
149 // both-note@-1{{in call to}}
150 static_assert(wrap_is_aligned(1, const_value(19)), ""); // both-error{{not an integral constant expression}}
151 // both-note@-1{{in call to}}
153 // Check invalid values for smaller types:
154 static_assert(wrap_align_down(static_cast<short>(1), const_value(1 << 20)), ""); // both-error{{not an integral constant expression}}
155 // both-note@-1{{in call to }}
156 // Check invalid boolean type
157 static_assert(wrap_align_up(static_cast<int>(1), const_value(1ull << 33)), ""); // both-error{{not an integral constant expression}}
158 // both-note@-1{{in call to}}
159 static_assert(wrap_is_aligned(static_cast<char>(1), const_value(1 << 22)), ""); // both-error{{not an integral constant expression}}
160 // both-note@-1{{in call to}}
162 // Check invalid boolean type
163 static_assert(wrap_align_up(static_cast<bool>(1), const_value(1 << 21)), ""); // both-error{{not an integral constant expression}}
164 // both-note@-1{{in instantiation of function template specialization 'wrap_align_up<bool>' requested here}}
166 // Check constant evaluation for pointers:
167 _Alignas(32) char align32array[128];
168 static_assert(&align32array[0] == &align32array[0], "");
169 // __builtin_align_up/down can be constant evaluated as a no-op for values
170 // that are known to have greater alignment:
171 static_assert(__builtin_align_up(&align32array[0], 32) == &align32array[0], "");
172 static_assert(__builtin_align_up(&align32array[0], 4) == &align32array[0], "");
173 static_assert(__builtin_align_down(&align32array[0], 4) == __builtin_align_up(&align32array[0], 8), "");
174 // But it can not be evaluated if the alignment is greater than the minimum
175 // known alignment, since in that case the value might be the same if it happens
176 // to actually be aligned to 64 bytes at run time.
177 static_assert(&align32array[0] == __builtin_align_up(&align32array[0], 64), ""); // both-error{{not an integral constant expression}}
178 // both-note@-1{{cannot constant evaluate the result of adjusting alignment to 64}}
179 static_assert(__builtin_align_up(&align32array[0], 64) == __builtin_align_up(&align32array[0], 64), ""); // both-error{{not an integral constant expression}}
180 // both-note@-1{{cannot constant evaluate the result of adjusting alignment to 64}}
182 // However, we can compute in case the requested alignment is less than the
183 // base alignment:
184 static_assert(__builtin_align_up(&align32array[0], 4) == &align32array[0], "");
185 static_assert(__builtin_align_up(&align32array[1], 4) == &align32array[4], "");
186 static_assert(__builtin_align_up(&align32array[2], 4) == &align32array[4], "");
187 static_assert(__builtin_align_up(&align32array[3], 4) == &align32array[4], "");
188 static_assert(__builtin_align_up(&align32array[4], 4) == &align32array[4], "");
189 static_assert(__builtin_align_up(&align32array[5], 4) == &align32array[8], "");
190 static_assert(__builtin_align_up(&align32array[6], 4) == &align32array[8], "");
191 static_assert(__builtin_align_up(&align32array[7], 4) == &align32array[8], "");
192 static_assert(__builtin_align_up(&align32array[8], 4) == &align32array[8], "");
194 static_assert(__builtin_align_down(&align32array[0], 4) == &align32array[0], "");
195 static_assert(__builtin_align_down(&align32array[1], 4) == &align32array[0], "");
196 static_assert(__builtin_align_down(&align32array[2], 4) == &align32array[0], "");
197 static_assert(__builtin_align_down(&align32array[3], 4) == &align32array[0], "");
198 static_assert(__builtin_align_down(&align32array[4], 4) == &align32array[4], "");
199 static_assert(__builtin_align_down(&align32array[5], 4) == &align32array[4], "");
200 static_assert(__builtin_align_down(&align32array[6], 4) == &align32array[4], "");
201 static_assert(__builtin_align_down(&align32array[7], 4) == &align32array[4], "");
202 static_assert(__builtin_align_down(&align32array[8], 4) == &align32array[8], "");
204 // Achieving the same thing using casts to uintptr_t is not allowed:
205 static_assert((char *)((__UINTPTR_TYPE__)&align32array[7] & ~3) == &align32array[4], ""); // both-error{{not an integral constant expression}}
207 static_assert(__builtin_align_down(&align32array[1], 4) == &align32array[0], "");
208 static_assert(__builtin_align_down(&align32array[1], 64) == &align32array[0], ""); // both-error{{not an integral constant expression}}
209 // both-note@-1{{cannot constant evaluate the result of adjusting alignment to 64}}
211 // Add some checks for __builtin_is_aligned:
212 static_assert(__builtin_is_aligned(&align32array[0], 32), "");
213 static_assert(__builtin_is_aligned(&align32array[4], 4), "");
214 // We cannot constant evaluate whether the array is aligned to > 32 since this
215 // may well be true at run time.
216 static_assert(!__builtin_is_aligned(&align32array[0], 64), ""); // both-error{{not an integral constant expression}}
217 // both-note@-1{{cannot constant evaluate whether run-time alignment is at least 64}}
219 // However, if the alignment being checked is less than the minimum alignment of
220 // the base object we can check the low bits of the alignment:
221 static_assert(__builtin_is_aligned(&align32array[0], 4), "");
222 static_assert(!__builtin_is_aligned(&align32array[1], 4), "");
223 static_assert(!__builtin_is_aligned(&align32array[2], 4), "");
224 static_assert(!__builtin_is_aligned(&align32array[3], 4), "");
225 static_assert(__builtin_is_aligned(&align32array[4], 4), "");
227 // TODO: this should evaluate to true even though we can't evaluate the result
228 // of __builtin_align_up() to a concrete value
229 static_assert(__builtin_is_aligned(__builtin_align_up(&align32array[0], 64), 64), ""); // both-error{{not an integral constant expression}}
230 // both-note@-1{{cannot constant evaluate the result of adjusting alignment to 64}}
232 // Check different source and alignment type widths are handled correctly.
233 static_assert(!__builtin_is_aligned(static_cast<signed long>(7), static_cast<signed short>(4)), "");
234 static_assert(!__builtin_is_aligned(static_cast<signed short>(7), static_cast<signed long>(4)), "");
235 // Also check signed -- unsigned mismatch.
236 static_assert(!__builtin_is_aligned(static_cast<signed long>(7), static_cast<signed long>(4)), "");
237 static_assert(!__builtin_is_aligned(static_cast<unsigned long>(7), static_cast<unsigned long>(4)), "");
238 static_assert(!__builtin_is_aligned(static_cast<signed long>(7), static_cast<unsigned long>(4)), "");
239 static_assert(!__builtin_is_aligned(static_cast<unsigned long>(7), static_cast<signed long>(4)), "");
240 static_assert(!__builtin_is_aligned(static_cast<signed long>(7), static_cast<unsigned short>(4)), "");
241 static_assert(!__builtin_is_aligned(static_cast<unsigned short>(7), static_cast<signed long>(4)), "");
243 // Check the diagnostic message
244 _Alignas(void) char align_void_array[1]; // both-error {{invalid application of '_Alignas' to an incomplete type 'void'}}