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