llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Alejandro Colomar (alejandro-colomar) <details> <summary>Changes</summary> Link: <https://github.com/llvm/llvm-project/issues/102836> Link: <https://github.com/llvm/llvm-project/pull/133125> Cc: @<!-- -->AaronBallman I haven't yet tried to run these tests. I've pasted and adapted them from the ones I wrote for my own implementation. (I have a few more, which I'll adapt once I know I adapted these correctly.) --- Revisions: <details> <summary>v2</summary> - Fix some expected diagnostics - Use `global_num` instead of `errno`. ``` $ git range-diff main gh/countof_tests countof_tests 1: fe746be5715d ! 1: a651447d3fac Add more tests for _Countof @@ Commit message Link: <https://github.com/llvm/llvm-project/issues/102836> Link: <https://github.com/llvm/llvm-project/pull/133125> + Cc: Aaron Ballman <aaron@<!-- -->aaronballman.com> Signed-off-by: Alejandro Colomar <alx@<!-- -->kernel.org> ## clang/test/C/C2y/n3369.c ## @@ clang/test/C/C2y/n3369.c: void test_with_function_param(int array[12], int (*arr (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)]); -+void test_func_fix_var(int i, char (*a)[3][i], int (*x)[_Countof(*a)]); -+void test_func_fix_uns(int i, char (*a)[3][*], int (*x)[_Countof(*a)]); ++void test_func_fix_fix(int i, char (*a)[3][5], int (*x)[_Countof(*a)]); // expected-note {{passing argument to parameter}} ++void test_func_fix_var(int i, char (*a)[3][i], int (*x)[_Countof(*a)]); // expected-note {{passing argument to parameter}} ++void test_func_fix_uns(int i, char (*a)[3][*], int (*x)[_Countof(*a)]); // 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); -+ test_func_fix_fix(5, &c35, &i5); // expected-error {{incompatible-pointer-types}} ++ test_func_fix_fix(5, &c35, &i5); // expected-error {{incompatible pointer types passing}} + test_func_fix_var(5, &c35, &i3); -+ test_func_fix_var(5, &c35, &i5); // expected-error {{incompatible-pointer-types}} ++ test_func_fix_var(5, &c35, &i5); // expected-error {{incompatible pointer types passing}} + test_func_fix_uns(5, &c35, &i3); -+ test_func_fix_uns(5, &c35, &i5); // expected-error {{incompatible-pointer-types}} ++ test_func_fix_uns(5, &c35, &i5); // expected-error {{incompatible pointer types passing}} +} + void test_multidimensional_arrays() { @@ clang/test/C/C2y/n3369.c: void test_unspecified_array_length() { } +void test_completed_array() { -+ int a[] = {1, 2, errno}; ++ int a[] = {1, 2, global_num}; + static_assert(_Countof(a) == 3); +} + ``` </details> <details> <summary>v2b</summary> - Fix expected diagnostic messages ``` $ git range-diff main gh/countof_tests countof_tests 1: a651447d3fac ! 1: 6c5c502ca376 Add more tests for _Countof @@ clang/test/C/C2y/n3369.c: void test_with_function_param(int array[12], int (*arr + int i5[5]; + char c35[3][5]; + test_func_fix_fix(5, &c35, &i3); -+ test_func_fix_fix(5, &c35, &i5); // expected-error {{incompatible pointer types passing}} ++ test_func_fix_fix(5, &c35, &i5); // expected-error {{incompatible pointer types passing 'int (*)[5]' to parameter of type 'int (*)[3]'}} + test_func_fix_var(5, &c35, &i3); -+ test_func_fix_var(5, &c35, &i5); // expected-error {{incompatible pointer types passing}} ++ test_func_fix_var(5, &c35, &i5); // expected-error {{incompatible pointer types passing 'int (*)[5]' to parameter of type 'int (*)[3]'}} + test_func_fix_uns(5, &c35, &i3); -+ test_func_fix_uns(5, &c35, &i5); // expected-error {{incompatible pointer types passing}} ++ test_func_fix_uns(5, &c35, &i5); // expected-error {{incompatible pointer types passing 'int (*)[5]' to parameter of type 'int (*)[3]'}} +} + void test_multidimensional_arrays() { ``` </details> <details> <summary>v2c</summary> - Fix expected diagnostic type ``` $ git range-diff main gh/countof_tests countof_tests 1: 6c5c502ca376 ! 1: b8f95e71efec Add more tests for _Countof @@ clang/test/C/C2y/n3369.c: void test_with_function_param(int array[12], int (*arr + int i5[5]; + char c35[3][5]; + test_func_fix_fix(5, &c35, &i3); -+ test_func_fix_fix(5, &c35, &i5); // expected-error {{incompatible pointer types passing 'int (*)[5]' to parameter of type 'int (*)[3]'}} ++ test_func_fix_fix(5, &c35, &i5); // expected-warning {{incompatible pointer types passing 'int (*)[5]' to parameter of type 'int (*)[3]'}} + test_func_fix_var(5, &c35, &i3); -+ test_func_fix_var(5, &c35, &i5); // expected-error {{incompatible pointer types passing 'int (*)[5]' to parameter of type 'int (*)[3]'}} ++ test_func_fix_var(5, &c35, &i5); // expected-warning {{incompatible pointer types passing 'int (*)[5]' to parameter of type 'int (*)[3]'}} + test_func_fix_uns(5, &c35, &i3); -+ test_func_fix_uns(5, &c35, &i5); // expected-error {{incompatible pointer types passing 'int (*)[5]' to parameter of type 'int (*)[3]'}} ++ test_func_fix_uns(5, &c35, &i5); // expected-warning {{incompatible pointer types passing 'int (*)[5]' to parameter of type 'int (*)[3]'}} +} + void test_multidimensional_arrays() { ``` </details> <details> <summary>v2d</summary> - Fix expected diagnostics. ``` $ git range-diff main gh/countof_tests countof_tests 1: b8f95e71efec ! 1: eb63ad49de45 Add more tests for _Countof @@ clang/test/C/C2y/n3369.c: void test_typedefs() { 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]; // 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); @@ clang/test/C/C2y/n3369.c: void test_compound_literals() { } + +static int test_f1(); -+static int test_f2(); // expected-warning {{never defined}} ++static int test_f2(); // expected-warning {{function 'f' has internal linkage but is not defined}} + +void test_symbols() { + int a[global_num][global_num]; ``` </details> <details> <summary>v2e</summary> - Add comment about symbols. - tfix ``` $ git range-diff main gh/countof_tests countof_tests 1: eb63ad49de45 ! 1: 3660f83ad4be Add more tests for _Countof @@ clang/test/C/C2y/n3369.c: void test_compound_literals() { 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(); // expected-warning {{function 'f' has internal linkage but is not defined}} ++static int test_f2(); // expected-warning {{function 'test_f2' has internal linkage but is not defined}} + +void test_symbols() { + int a[global_num][global_num]; ``` </details> <details> <summary>v3</summary> - Change `expected-warning` into a FIXME note (pre-existing false negative). - Add _Generic() code suggested by @<!-- -->frederick-vs-ja . ``` $ git range-diff main..@{u} main@{u}..HEAD 1: 3660f83ad4be ! 1: d393955db896 Add more tests for _Countof @@ clang/test/C/C2y/n3369.c: void test_with_function_param(int array[12], int (*arr (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)]); // expected-note {{passing argument to parameter}} -+void test_func_fix_var(int i, char (*a)[3][i], int (*x)[_Countof(*a)]); // expected-note {{passing argument to parameter}} -+void test_func_fix_uns(int i, char (*a)[3][*], int (*x)[_Countof(*a)]); // expected-note {{passing argument to parameter}} ++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]; @@ clang/test/C/C2y/n3369.c: void test_compound_literals() { + * a VLA. + */ +static int test_f1(); -+static int test_f2(); // expected-warning {{function 'test_f2' has internal linkage but is not defined}} ++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]; ``` </details> <details> <summary>v3b</summary> - Rebase ``` $ git range-diff main..@{u} main@{u}..HEAD 1: d393955db896 = 1: 923856a504d8 Add more tests for _Countof ``` </details> <details> <summary>v3c</summary> - Add missing parameter. ``` $ git range-diff main..@{u} main@{u}..HEAD 1: 923856a504d8 ! 1: f4f1f5661b0b Add more tests for _Countof @@ Commit message ## clang/test/C/C2y/n3369.c ## @@ + #error "Expected to have _Countof support" #endif ++#define NULL ((void *) 0) ++ int global_array[12]; +int global_multi_array[12][34]; +int global_num; @@ clang/test/C/C2y/n3369.c: void test_with_function_param(int array[12], int (*arr + int i3[3]; + int i5[5]; + char c35[3][5]; -+ test_func_fix_fix(5, &c35, &i3); -+ test_func_fix_fix(5, &c35, &i5); // expected-warning {{incompatible pointer types passing 'int (*)[5]' to parameter of type 'int (*)[3]'}} -+ test_func_fix_var(5, &c35, &i3); -+ test_func_fix_var(5, &c35, &i5); // expected-warning {{incompatible pointer types passing 'int (*)[5]' to parameter of type 'int (*)[3]'}} -+ test_func_fix_uns(5, &c35, &i3); -+ test_func_fix_uns(5, &c35, &i5); // expected-warning {{incompatible pointer types passing 'int (*)[5]' to parameter of type 'int (*)[3]'}} ++ 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() { ``` </details> --- Full diff: https://github.com/llvm/llvm-project/pull/133333.diff 1 Files Affected: - (modified) clang/test/C/C2y/n3369.c (+51-1) ``````````diff diff --git a/clang/test/C/C2y/n3369.c b/clang/test/C/C2y/n3369.c index 389828b52b6a2..db26040d8cf44 100644 --- a/clang/test/C/C2y/n3369.c +++ b/clang/test/C/C2y/n3369.c @@ -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}} @@ -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) { @@ -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); @@ -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)); @@ -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() { @@ -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()]); +} `````````` </details> https://github.com/llvm/llvm-project/pull/133333 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits