1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
|
// RUN: %clang_cc1 -fsyntax-only -std=c2y -pedantic -Wall -Wno-comment -verify %s
// RUN: %clang_cc1 -fsyntax-only -std=c2y -pedantic -Wall -Wno-comment -fexperimental-new-constant-interpreter -verify %s
/* WG14 N3369: Clang 21
* _Lengthof operator
*
* Adds an operator to get the length of an array. Note that WG14 N3469 renamed
* this operator to _Countof.
*/
#if !__has_feature(c_countof)
#error "Expected to have _Countof support"
#endif
#if !__has_extension(c_countof)
// __has_extension returns true if __has_feature returns true.
#error "Expected to have _Countof support"
#endif
#define NULL ((void *) 0)
int global_array[12];
int global_multi_array[12][34];
int global_num;
void test_parsing_failures() {
(void)_Countof; // expected-error {{expected expression}}
(void)_Countof(; // expected-error {{expected expression}}
(void)_Countof(); // expected-error {{expected expression}}
(void)_Countof int; // expected-error {{expected expression}}
}
void test_semantic_failures() {
(void)_Countof(1); // expected-error {{'_Countof' requires an argument of array type; 'int' invalid}}
int non_array;
(void)_Countof non_array; // expected-error {{'_Countof' requires an argument of array type; 'int' invalid}}
(void)_Countof(int); // expected-error {{'_Countof' requires an argument of array type; 'int' invalid}}
(void)_Countof(test_semantic_failures); // expected-error {{invalid application of '_Countof' to a function type}}
(void)_Countof(struct S); // expected-error {{invalid application of '_Countof' to an incomplete type 'struct S'}} \
expected-note {{forward declaration of 'struct S'}}
struct T { int x; };
(void)_Countof(struct T); // expected-error {{'_Countof' requires an argument of array type; 'struct T' invalid}}
struct U { int x[3]; };
(void)_Countof(struct U); // expected-error {{'_Countof' requires an argument of array type; 'struct U' invalid}}
int a[3];
(void)_Countof(&a); // expected-error {{'_Countof' requires an argument of array type; 'int (*)[3]' invalid}}
int *p;
(void)_Countof(p); // expected-error {{'_Countof' requires an argument of array type; 'int *' invalid}}
}
void test_constant_expression_behavior(int n) {
static_assert(_Countof(global_array) == 12);
static_assert(_Countof global_array == 12);
static_assert(_Countof(int[12]) == 12);
// Use of a VLA makes it not a constant expression, same as with sizeof.
int array[n];
static_assert(_Countof(array)); // expected-error {{static assertion expression is not an integral constant expression}}
static_assert(sizeof(array)); // expected-error {{static assertion expression is not an integral constant expression}}
static_assert(_Countof(int[n]));// expected-error {{static assertion expression is not an integral constant expression}}
static_assert(sizeof(int[n])); // expected-error {{static assertion expression is not an integral constant expression}}
// Constant folding works the same way as sizeof, too.
const int m = 12;
int other_array[m];
static_assert(sizeof(other_array)); // expected-error {{static assertion expression is not an integral constant expression}}
static_assert(_Countof(other_array)); // expected-error {{static assertion expression is not an integral constant expression}}
static_assert(sizeof(int[m])); // expected-error {{static assertion expression is not an integral constant expression}}
static_assert(_Countof(int[m])); // expected-error {{static assertion expression is not an integral constant expression}}
// Note that this applies to each array dimension.
int another_array[n][7];
static_assert(_Countof(another_array)); // expected-error {{static assertion expression is not an integral constant expression}}
static_assert(_Countof(*another_array) == 7);
// Only the first dimension is needed for constant evaluation; other
// dimensions can be ignored.
int yet_another_array[7][n];
static_assert(_Countof(yet_another_array) == 7);
static_assert(_Countof(*yet_another_array)); // expected-error {{static assertion expression is not an integral constant expression}}
int one_more_time[n][n][7];
static_assert(_Countof(one_more_time)); // expected-error {{static assertion expression is not an integral constant expression}}
static_assert(_Countof(*one_more_time)); // expected-error {{static assertion expression is not an integral constant expression}}
static_assert(_Countof(**one_more_time) == 7);
}
void test_with_function_param(int array[12], int (*array_ptr)[12], int static_array[static 12]) {
(void)_Countof(array); // expected-error {{'_Countof' requires an argument of array type; 'int *' invalid}}
static_assert(_Countof(*array_ptr) == 12);
(void)_Countof(static_array); // expected-error {{'_Countof' requires an argument of array type; 'int *' invalid}}
}
void test_func_fix_fix(int i, char (*a)[3][5], int (*x)[_Countof(*a)], char (*)[_Generic(x, int (*)[3]: 1)]); // expected-note {{passing argument to parameter}}
void test_func_fix_var(int i, char (*a)[3][i], int (*x)[_Countof(*a)], char (*)[_Generic(x, int (*)[3]: 1)]); // expected-note {{passing argument to parameter}}
void test_func_fix_uns(int i, char (*a)[3][*], int (*x)[_Countof(*a)], char (*)[_Generic(x, int (*)[3]: 1)]); // expected-note {{passing argument to parameter}}
void test_funcs() {
int i3[3];
int i5[5];
char c35[3][5];
test_func_fix_fix(5, &c35, &i3, NULL);
test_func_fix_fix(5, &c35, &i5, NULL); // expected-warning {{incompatible pointer types passing 'int (*)[5]' to parameter of type 'int (*)[3]'}}
test_func_fix_var(5, &c35, &i3, NULL);
test_func_fix_var(5, &c35, &i5, NULL); // expected-warning {{incompatible pointer types passing 'int (*)[5]' to parameter of type 'int (*)[3]'}}
test_func_fix_uns(5, &c35, &i3, NULL);
test_func_fix_uns(5, &c35, &i5, NULL); // expected-warning {{incompatible pointer types passing 'int (*)[5]' to parameter of type 'int (*)[3]'}}
}
void test_multidimensional_arrays() {
int array[12][7];
static_assert(_Countof(array) == 12);
static_assert(_Countof(*array) == 7);
int mdarray[12][7][100][3];
static_assert(_Countof(mdarray) == 12);
static_assert(_Countof(*mdarray) == 7);
static_assert(_Countof(**mdarray) == 100);
static_assert(_Countof(***mdarray) == 3);
}
void test_unspecified_array_length() {
static_assert(_Countof(int[])); // expected-error {{invalid application of '_Countof' to an incomplete type 'int[]'}}
extern int x[][6][3];
static_assert(_Countof(x)); // expected-error {{invalid application of '_Countof' to an incomplete type 'int[][6][3]'}}
static_assert(_Countof(*x) == 6);
static_assert(_Countof(**x) == 3);
}
void test_completed_array() {
int a[] = {1, 2, global_num};
static_assert(_Countof(a) == 3);
}
// Test that the return type of _Countof is what you'd expect (size_t).
void test_return_type() {
static_assert(_Generic(typeof(_Countof global_array), typeof(sizeof(0)) : 1, default : 0));
}
// Test that _Countof is able to look through typedefs.
void test_typedefs() {
typedef int foo[12];
foo f;
static_assert(_Countof(foo) == 12);
static_assert(_Countof(f) == 12);
// Ensure multidimensional arrays also work.
foo x[100];
static_assert(_Generic(typeof(x), int[100][12] : 1, default : 0));
static_assert(_Countof(x) == 100);
static_assert(_Countof(*x) == 12);
}
void test_zero_size_arrays(int n) {
int array[0]; // expected-warning {{zero size arrays are an extension}}
static_assert(_Countof(array) == 0);
static_assert(_Countof(int[0]) == 0); // expected-warning {{zero size arrays are an extension}}
int multi_array[0][n]; // FIXME: Should trigger -Wzero-length-array
static_assert(_Countof(multi_array) == 0);
int another_one[0][3]; // expected-warning {{zero size arrays are an extension}}
static_assert(_Countof(another_one) == 0);
}
void test_struct_members() {
struct S {
int array[10];
} s;
static_assert(_Countof(s.array) == 10);
struct T {
int count;
int fam[];
} t;
static_assert(_Countof(t.fam)); // expected-error {{invalid application of '_Countof' to an incomplete type 'int[]'}}
}
void test_compound_literals() {
static_assert(_Countof((int[2]){}) == 2);
static_assert(_Countof((int[]){1, 2, 3, 4}) == 4);
}
/* We don't get a diagnostic for test_f1(), because it ends up unused
* as _Countof() results in an integer constant expression, which is not
* evaluated. However, test_f2() ends up being evaluated, since 'a' is
* a VLA.
*/
static int test_f1();
static int test_f2(); // FIXME: Should trigger function 'test_f2' has internal linkage but is not defined
void test_symbols() {
int a[global_num][global_num];
static_assert(_Countof(global_multi_array[test_f1()]) == 34);
(void)_Countof(a[test_f2()]);
}
|