1 // RUN: %clang_cc1 -triple x86_64-linux-gnu -DALIGN_BUILTIN=__builtin_align_down -DRETURNS_BOOL=0 %s -fsyntax-only -verify -Wpedantic 2 // RUN: %clang_cc1 -triple x86_64-linux-gnu -DALIGN_BUILTIN=__builtin_align_up -DRETURNS_BOOL=0 %s -fsyntax-only -verify -Wpedantic 3 // RUN: %clang_cc1 -triple x86_64-linux-gnu -DALIGN_BUILTIN=__builtin_is_aligned -DRETURNS_BOOL=1 %s -fsyntax-only -verify -Wpedantic 4 5 struct Aggregate { 6 int i; 7 int j; 8 }; 9 enum Enum { EnumValue1, 10 EnumValue2 }; 11 typedef __SIZE_TYPE__ size_t; 12 13 void test_parameter_types(char *ptr, size_t size) { 14 struct Aggregate agg; 15 enum Enum e = EnumValue2; 16 _Bool b = 0; 17 18 // The first parameter can be any pointer or integer type: 19 (void)ALIGN_BUILTIN(ptr, 4); 20 (void)ALIGN_BUILTIN(size, 2); 21 (void)ALIGN_BUILTIN(12345, 2); 22 (void)ALIGN_BUILTIN(agg, 2); // expected-error {{operand of type 'struct Aggregate' where arithmetic or pointer type is required}} 23 (void)ALIGN_BUILTIN(e, 2); // expected-error {{operand of type 'enum Enum' where arithmetic or pointer type is required}} 24 (void)ALIGN_BUILTIN(b, 2); // expected-error {{operand of type '_Bool' where arithmetic or pointer type is required}} 25 (void)ALIGN_BUILTIN((int)e, 2); // but with a cast it is fine 26 (void)ALIGN_BUILTIN((int)b, 2); // but with a cast it is fine 27 28 // The second parameter must be an integer type (but not enum or _Bool): 29 (void)ALIGN_BUILTIN(ptr, size); 30 (void)ALIGN_BUILTIN(ptr, ptr); // expected-error {{used type 'char *' where integer is required}} 31 (void)ALIGN_BUILTIN(ptr, agg); // expected-error {{used type 'struct Aggregate' where integer is required}} 32 (void)ALIGN_BUILTIN(ptr, b); // expected-error {{used type '_Bool' where integer is required}} 33 (void)ALIGN_BUILTIN(ptr, e); // expected-error {{used type 'enum Enum' where integer is required}} 34 (void)ALIGN_BUILTIN(ptr, (int)e); // but with a cast enums are fine 35 (void)ALIGN_BUILTIN(ptr, (int)b); // but with a cast booleans are fine 36 37 (void)ALIGN_BUILTIN(ptr, size); 38 (void)ALIGN_BUILTIN(size, size); 39 } 40 41 void test_result_unused(int i, int align) { 42 // -Wunused-result does not trigger for macros so we can't use ALIGN_BUILTIN() 43 // but need to explicitly call each function. 44 __builtin_align_up(i, align); // expected-warning{{ignoring return value of function declared with const attribute}} 45 __builtin_align_down(i, align); // expected-warning{{ignoring return value of function declared with const attribute}} 46 __builtin_is_aligned(i, align); // expected-warning{{ignoring return value of function declared with const attribute}} 47 ALIGN_BUILTIN(i, align); // no warning here 48 } 49 50 #define check_same_type(type1, type2) __builtin_types_compatible_p(type1, type2) && __builtin_types_compatible_p(type1 *, type2 *) 51 52 void test_return_type(void *ptr, int i, long l) { 53 char array[32]; 54 __extension__ typedef typeof(ALIGN_BUILTIN(ptr, 4)) result_type_ptr; 55 __extension__ typedef typeof(ALIGN_BUILTIN(i, 4)) result_type_int; 56 __extension__ typedef typeof(ALIGN_BUILTIN(l, 4)) result_type_long; 57 __extension__ typedef typeof(ALIGN_BUILTIN(array, 4)) result_type_char_array; 58 #if RETURNS_BOOL 59 _Static_assert(check_same_type(_Bool, result_type_ptr), "Should return bool"); 60 _Static_assert(check_same_type(_Bool, result_type_int), "Should return bool"); 61 _Static_assert(check_same_type(_Bool, result_type_long), "Should return bool"); 62 _Static_assert(check_same_type(_Bool, result_type_char_array), "Should return bool"); 63 #else 64 _Static_assert(check_same_type(void *, result_type_ptr), "Should return void*"); 65 _Static_assert(check_same_type(int, result_type_int), "Should return int"); 66 _Static_assert(check_same_type(long, result_type_long), "Should return long"); 67 // Check that we can use the alignment builtins on on array types (result should decay) 68 _Static_assert(check_same_type(char *, result_type_char_array), 69 "Using the builtins on an array should yield the decayed type"); 70 #endif 71 } 72 73 void test_invalid_alignment_values(char *ptr, long *longptr, size_t align) { 74 int x = 1; 75 (void)ALIGN_BUILTIN(ptr, 2); 76 (void)ALIGN_BUILTIN(longptr, 1024); 77 (void)ALIGN_BUILTIN(x, 32); 78 79 (void)ALIGN_BUILTIN(ptr, 0); // expected-error {{requested alignment must be 1 or greater}} 80 (void)ALIGN_BUILTIN(ptr, 1); 81 #if RETURNS_BOOL 82 // expected-warning@-2 {{checking whether a value is aligned to 1 byte is always true}} 83 #else 84 // expected-warning@-4 {{aligning a value to 1 byte is a no-op}} 85 #endif 86 (void)ALIGN_BUILTIN(ptr, 3); // expected-error {{requested alignment is not a power of 2}} 87 (void)ALIGN_BUILTIN(x, 7); // expected-error {{requested alignment is not a power of 2}} 88 89 // check the maximum range for smaller types: 90 __UINT8_TYPE__ c = ' '; 91 92 (void)ALIGN_BUILTIN(c, 128); // this is fine 93 (void)ALIGN_BUILTIN(c, 256); // expected-error {{requested alignment must be 128 or smaller}} 94 (void)ALIGN_BUILTIN(x, 1ULL << 31); // this is also fine 95 (void)ALIGN_BUILTIN(x, 1LL << 31); // this is also fine 96 __INT32_TYPE__ i32 = 3; 97 __UINT32_TYPE__ u32 = 3; 98 // Maximum is the same for int32 and uint32 99 (void)ALIGN_BUILTIN(i32, 1ULL << 32); // expected-error {{requested alignment must be 2147483648 or smaller}} 100 (void)ALIGN_BUILTIN(u32, 1ULL << 32); // expected-error {{requested alignment must be 2147483648 or smaller}} 101 (void)ALIGN_BUILTIN(ptr, ((__int128)1) << 65); // expected-error {{requested alignment must be 9223372036854775808 or smaller}} 102 (void)ALIGN_BUILTIN(longptr, ((__int128)1) << 65); // expected-error {{requested alignment must be 9223372036854775808 or smaller}} 103 104 const int bad_align = 8 + 1; 105 (void)ALIGN_BUILTIN(ptr, bad_align); // expected-error {{requested alignment is not a power of 2}} 106 } 107 108 // Check that it can be used in constant expressions: 109 void constant_expression(int x) { 110 _Static_assert(__builtin_is_aligned(1024, 512), ""); 111 _Static_assert(!__builtin_is_aligned(256, 512ULL), ""); 112 _Static_assert(__builtin_align_up(33, 32) == 64, ""); 113 _Static_assert(__builtin_align_down(33, 32) == 32, ""); 114 115 // But not if one of the arguments isn't constant: 116 _Static_assert(ALIGN_BUILTIN(33, x) != 100, ""); // expected-error {{static_assert expression is not an integral constant expression}} 117 _Static_assert(ALIGN_BUILTIN(x, 4) != 100, ""); // expected-error {{static_assert expression is not an integral constant expression}} 118 } 119 120 // Check that it is a constant expression that can be assigned to globals: 121 int global1 = __builtin_align_down(33, 8); 122 int global2 = __builtin_align_up(33, 8); 123 _Bool global3 = __builtin_is_aligned(33, 8); 124 125 extern void test_ptr(char *c); 126 char *test_array_and_fnptr(void) { 127 char buf[1024]; 128 // The builtins should also work on arrays (decaying the return type) 129 (void)(ALIGN_BUILTIN(buf, 16)); 130 // But not on functions and function pointers: 131 (void)(ALIGN_BUILTIN(test_array_and_fnptr, 16)); // expected-error{{operand of type 'char *(void)' where arithmetic or pointer type is required}} 132 (void)(ALIGN_BUILTIN(&test_array_and_fnptr, 16)); // expected-error{{operand of type 'char *(*)(void)' where arithmetic or pointer type is required}} 133 } 134