Skip to content

Add more tests for _Countof #133333

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 7, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 51 additions & 1 deletion clang/test/C/C2y/n3369.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@
#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}}
Expand All @@ -36,6 +40,12 @@ void test_semantic_failures() {
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) {
Expand Down Expand Up @@ -81,6 +91,22 @@ void test_with_function_param(int array[12], int (*array_ptr)[12], int static_ar
(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);
Expand All @@ -102,6 +128,11 @@ void test_unspecified_array_length() {
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));
Expand All @@ -121,10 +152,14 @@ void test_typedefs() {
static_assert(_Countof(*x) == 12);
}

void test_zero_size_arrays() {
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() {
Expand All @@ -144,3 +179,18 @@ 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()]);
}