Hi! Here's a patch co-authored by Martin and I. It adds support for array parameters in _Countof, which will enable writing safer code that only specifies array bounds in function calls when strictly necessary, reducing the chances for mistakes.
Here's an example program that never specifies bounds except in the function prototypes and wrapper macros that insert _Countof() calls. Once those are correct, which is easier than guaranteeing correctness of all callers, the bounds are correct. alx@devuan:~/tmp$ cat present.c | nl -ba 1 #include <stddef.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 5 #define MALLOCARRAY(n, T) ((typeof(T) (*)[n]) reallocarray(NULL, n, sizeof(T))) 6 7 #define F(a) f(_Countof(a), a) 8 #define G(a) g(_Countof(a), a) 9 #define H(a) h(_Countof(a), a) 10 #define I(a) i(_Countof(a), a) 11 #define P(a) p(_Countof(a), a) 12 13 void f(size_t n, int a[n]); 14 void g(size_t n, int a[n]); 15 void h(size_t n, int a[n]); 16 void i(size_t n, int a[n]); 17 void p(size_t n, int a[n]); 18 19 int 20 main(void) 21 { 22 int (*ap)[7] = MALLOCARRAY(7, int); 23 24 F(*ap); 25 P(*ap); 26 } 27 28 void f(size_t n, int a[n]) { G(a); } 29 void g(size_t n, int a[n]) { H(a); } 30 void h(size_t n, int a[n]) { I(a); } 31 void i(size_t n, int a[n]) 32 { 33 for (size_t j = 0; j < _Countof(a); j++) 34 a[j] = j; 35 } 36 void p(size_t n, int a[n]) 37 { 38 for (size_t j = 0; j < _Countof(a); j++) 39 printf("%d\n", a[j]); 40 } alx@devuan:~/tmp$ /opt/local/gnu/gcc/countof_ap/bin/gcc -Wall -Wextra present.c alx@devuan:~/tmp$ ./a.out 0 1 2 3 4 5 6 Of course, programmers sometimes need to pass a slice of an array, which is still a point where mistakes can be made, but the mistake surface is much smaller. This has passed regression testing on my amd64 computer: alx@devuan:/srv/alx/src/gnu/gcc/countof_ap$ git log --oneline gnu/master..cap1 b5e67c7fb806 (HEAD -> countof_ap, tag: cap1) c: Add support for array parameters in _Co> alx@devuan:/srv/alx/src/gnu/gcc/countof_ap$ git reset gnu/master --h HEAD is now at a440b382e432 tree-optimization/121514 - ICE with recent VN improvement alx@devuan:/srv/alx/src/gnu/gcc/countof_ap$ mkdir ../cap1 alx@devuan:/srv/alx/src/gnu/gcc/countof_ap$ cd ../cap1 alx@devuan:/srv/alx/src/gnu/gcc/cap1$ /bin/time ../countof_ap/configure --disable-multilib --prefix=/opt/local/gnu/gcc/cap1 |& ts -s | tail -n 3; echo $? 00:00:02 config.status: creating Makefile 00:00:02 1.60user 0.41system 0:01.68elapsed 119%CPU (0avgtext+0avgdata 58188maxresident)k 00:00:02 0inputs+8512outputs (0major+296952minor)pagefaults 0swaps 0 alx@devuan:/srv/alx/src/gnu/gcc/cap1$ /bin/time make -j12 bootstrap |& ts -s | tail -n 3; echo $? 00:29:03 make[1]: Leaving directory '/srv/alx/src/gnu/gcc/cap1' 00:29:03 14854.54user 351.05system 29:03.04elapsed 872%CPU (0avgtext+0avgdata 1491724maxresident)k 00:29:03 7432inputs+48894016outputs (1057major+125712628minor)pagefaults 0swaps 0 alx@devuan:/srv/alx/src/gnu/gcc/cap1$ /bin/time make check |& ts -s | tail -n 3; echo $?06:54:30 make[1]: Leaving directory '/srv/alx/src/gnu/gcc/cap1' 06:54:30 22580.22user 2458.85system 6:54:30elapsed 100%CPU (0avgtext+0avgdata 1041248maxresident)k 06:54:30 747704inputs+49565368outputs (3254major+1065983823minor)pagefaults 0swaps 0 alx@devuan:/srv/alx/src/gnu/gcc/cap1$ cd ../countof_ap/ alx@devuan:/srv/alx/src/gnu/gcc/countof_ap$ git merge --ff-only cap1 Updating a440b382e432..b5e67c7fb806 Fast-forward gcc/c/c-typeck.cc | 50 +++++++++++++++++++---- gcc/doc/extend.texi | 11 +++++ gcc/testsuite/gcc.dg/countof-compile.c | 8 +--- gcc/testsuite/gcc.dg/countof-param-compile.c | 76 +++++++++++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/countof-param-pedantic.c | 11 +++++ gcc/testsuite/gcc.dg/countof-param.c | 25 ++++++++++++ 6 files changed, 166 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/countof-param-compile.c create mode 100644 gcc/testsuite/gcc.dg/countof-param-pedantic.c create mode 100644 gcc/testsuite/gcc.dg/countof-param.c alx@devuan:/srv/alx/src/gnu/gcc/countof_ap$ cd .. alx@devuan:/srv/alx/src/gnu/gcc$ mv cap1/ cap1_b4 alx@devuan:/srv/alx/src/gnu/gcc$ mkdir cap1 alx@devuan:/srv/alx/src/gnu/gcc$ cd cap1 alx@devuan:/srv/alx/src/gnu/gcc/cap1$ /bin/time ../countof_ap/configure --disable-multilib --prefix=/opt/local/gnu/gcc/cap1 |& ts -s | tail -n 3; echo $? 00:00:01 config.status: creating Makefile 00:00:01 1.51user 0.29system 0:01.51elapsed 119%CPU (0avgtext+0avgdata 58188maxresident)k 00:00:01 5360inputs+8512outputs (0major+294355minor)pagefaults 0swaps 0 alx@devuan:/srv/alx/src/gnu/gcc/cap1$ /bin/time make -j12 bootstrap |& ts -s | tail -n 3; echo $? 00:28:39 make[1]: Leaving directory '/srv/alx/src/gnu/gcc/cap1' 00:28:39 14724.90user 348.58system 28:39.00elapsed 876%CPU (0avgtext+0avgdata 1491500maxresident)k 00:28:39 9792inputs+48912704outputs (474major+127163137minor)pagefaults 0swaps 0 alx@devuan:/srv/alx/src/gnu/gcc/cap1$ /bin/time make check |& ts -s | tail -n 3; echo $? 07:10:04 make[1]: Leaving directory '/srv/alx/src/gnu/gcc/cap1' 07:10:04 23505.49user 2504.21system 7:10:03elapsed 100%CPU (0avgtext+0avgdata 1040928maxresident)k 07:10:04 125624inputs+49566296outputs (3531major+1091343152minor)pagefaults 0swaps 0 alx@devuan:/srv/alx/src/gnu/gcc/cap1$ find -type f | grep '\.sum$' | while read f; do diff -u ../cap1_b4/$f <(cat $f | sed s,/home/,/srv/,); done --- ../cap1_b4/./x86_64-pc-linux-gnu/libitm/testsuite/libitm.sum 2025-08-12 22:05:07.371228042 +0200 +++ /dev/fd/63 2025-08-14 10:09:07.738374420 +0200 @@ -1,4 +1,4 @@ -Test run by alx on Tue Aug 12 22:05:05 2025 +Test run by alx on Thu Aug 14 06:17:05 2025 Native configuration is x86_64-pc-linux-gnu === libitm tests === --- ../cap1_b4/./x86_64-pc-linux-gnu/libatomic/testsuite/libatomic.sum 2025-08-12 22:05:09.188035238 +0200 +++ /dev/fd/63 2025-08-14 10:09:07.742374460 +0200 @@ -1,4 +1,4 @@ -Test run by alx on Tue Aug 12 22:05:07 2025 +Test run by alx on Thu Aug 14 06:17:07 2025 Native configuration is x86_64-pc-linux-gnu === libatomic tests === --- ../cap1_b4/./x86_64-pc-linux-gnu/libgomp/testsuite/libgomp.sum 2025-08-12 22:05:05.247204895 +0200 +++ /dev/fd/63 2025-08-14 10:09:07.742374460 +0200 @@ -1,4 +1,4 @@ -Test run by alx on Tue Aug 12 21:49:34 2025 +Test run by alx on Thu Aug 14 06:01:52 2025 Native configuration is x86_64-pc-linux-gnu === libgomp tests === --- ../cap1_b4/./x86_64-pc-linux-gnu/libstdc++-v3/testsuite/libstdc++.sum 2025-08-12 21:49:12.806400698 +0200 +++ /dev/fd/63 2025-08-14 10:09:07.754374580 +0200 @@ -1,4 +1,4 @@ -Test run by alx on Tue Aug 12 18:21:51 2025 +Test run by alx on Thu Aug 14 02:17:17 2025 Native configuration is x86_64-pc-linux-gnu === libstdc++ tests === --- ../cap1_b4/./gcc/testsuite/objc/objc.sum 2025-08-12 18:21:24.478438464 +0200 +++ /dev/fd/63 2025-08-14 10:09:07.762374660 +0200 @@ -1,4 +1,4 @@ -Test run by alx on Tue Aug 12 18:20:26 2025 +Test run by alx on Thu Aug 14 02:15:58 2025 Native configuration is x86_64-pc-linux-gnu === objc tests === --- ../cap1_b4/./gcc/testsuite/g++/g++.sum 2025-08-12 17:45:03.165753359 +0200 +++ /dev/fd/63 2025-08-14 10:09:07.766374700 +0200 @@ -1,4 +1,4 @@ -Test run by alx on Tue Aug 12 16:47:58 2025 +Test run by alx on Thu Aug 14 00:43:52 2025 Native configuration is x86_64-pc-linux-gnu === g++ tests === --- ../cap1_b4/./gcc/testsuite/gcc/gcc.sum 2025-08-12 16:47:57.835002964 +0200 +++ /dev/fd/63 2025-08-14 10:09:07.842375460 +0200 @@ -1,4 +1,4 @@ -Test run by alx on Tue Aug 12 15:10:43 2025 +Test run by alx on Wed Aug 13 23:07:08 2025 Native configuration is x86_64-pc-linux-gnu === gcc tests === @@ -81811,26 +81811,47 @@ PASS: gcc.dg/countof-compat.c (test for warnings, line 8) PASS: gcc.dg/countof-compat.c (test for excess errors) PASS: gcc.dg/countof-compile.c (test for errors, line 23) -PASS: gcc.dg/countof-compile.c (test for errors, line 27) -PASS: gcc.dg/countof-compile.c (test for errors, line 38) -PASS: gcc.dg/countof-compile.c (test for errors, line 46) +PASS: gcc.dg/countof-compile.c (test for errors, line 34) +PASS: gcc.dg/countof-compile.c (test for errors, line 40) +PASS: gcc.dg/countof-compile.c (test for errors, line 58) +PASS: gcc.dg/countof-compile.c (test for errors, line 61) PASS: gcc.dg/countof-compile.c (test for errors, line 64) -PASS: gcc.dg/countof-compile.c (test for errors, line 67) -PASS: gcc.dg/countof-compile.c (test for errors, line 70) +PASS: gcc.dg/countof-compile.c (test for errors, line 76) +PASS: gcc.dg/countof-compile.c (test for errors, line 77) +PASS: gcc.dg/countof-compile.c (test for errors, line 78) +PASS: gcc.dg/countof-compile.c (test for errors, line 79) +PASS: gcc.dg/countof-compile.c (test for errors, line 80) +PASS: gcc.dg/countof-compile.c (test for errors, line 81) PASS: gcc.dg/countof-compile.c (test for errors, line 82) PASS: gcc.dg/countof-compile.c (test for errors, line 83) PASS: gcc.dg/countof-compile.c (test for errors, line 84) -PASS: gcc.dg/countof-compile.c (test for errors, line 85) -PASS: gcc.dg/countof-compile.c (test for errors, line 86) -PASS: gcc.dg/countof-compile.c (test for errors, line 87) PASS: gcc.dg/countof-compile.c (test for errors, line 88) -PASS: gcc.dg/countof-compile.c (test for errors, line 89) -PASS: gcc.dg/countof-compile.c (test for errors, line 90) -PASS: gcc.dg/countof-compile.c (test for errors, line 94) -PASS: gcc.dg/countof-compile.c (test for errors, line 114) -PASS: gcc.dg/countof-compile.c (test for errors, line 123) +PASS: gcc.dg/countof-compile.c (test for errors, line 108) +PASS: gcc.dg/countof-compile.c (test for errors, line 117) PASS: gcc.dg/countof-compile.c (test for excess errors) PASS: gcc.dg/countof-no-compat.c (test for excess errors) +PASS: gcc.dg/countof-param-compile.c (test for errors, line 20) +PASS: gcc.dg/countof-param-compile.c (test for errors, line 21) +PASS: gcc.dg/countof-param-compile.c (test for errors, line 22) +PASS: gcc.dg/countof-param-compile.c (test for errors, line 30) +PASS: gcc.dg/countof-param-compile.c (test for errors, line 33) +PASS: gcc.dg/countof-param-compile.c (test for errors, line 34) +PASS: gcc.dg/countof-param-compile.c (test for errors, line 39) +PASS: gcc.dg/countof-param-compile.c (test for errors, line 40) +PASS: gcc.dg/countof-param-compile.c (test for errors, line 41) +PASS: gcc.dg/countof-param-compile.c (test for errors, line 45) +PASS: gcc.dg/countof-param-compile.c (test for errors, line 49) +PASS: gcc.dg/countof-param-compile.c (test for errors, line 75) +PASS: gcc.dg/countof-param-compile.c (test for excess errors) +PASS: gcc.dg/countof-param-pedantic.c (test for warnings, line 9) +PASS: gcc.dg/countof-param-pedantic.c (test for warnings, line 10) +PASS: gcc.dg/countof-param-pedantic.c (test for excess errors) +PASS: gcc.dg/countof-param.c (test for warnings, line 9) +PASS: gcc.dg/countof-param.c (test for warnings, line 10) +PASS: gcc.dg/countof-param.c (test for warnings, line 15) +PASS: gcc.dg/countof-param.c (test for warnings, line 16) +PASS: gcc.dg/countof-param.c (test for excess errors) +PASS: gcc.dg/countof-param.c execution test PASS: gcc.dg/countof-pedantic-errors.c (test for errors, line 8) PASS: gcc.dg/countof-pedantic-errors.c (test for excess errors) PASS: gcc.dg/countof-pedantic.c (test for warnings, line 8) @@ -218959,7 +218980,7 @@ === gcc Summary === -# of expected passes 212922 +# of expected passes 212943 # of unexpected failures 528 # of unexpected successes 2 # of expected failures 1478 --- ../cap1_b4/./gcc/testsuite/gfortran/gfortran.sum 2025-08-12 18:20:25.729779170 +0200 +++ /dev/fd/63 2025-08-14 10:09:07.942376461 +0200 @@ -1,4 +1,4 @@ -Test run by alx on Tue Aug 12 17:45:03 2025 +Test run by alx on Thu Aug 14 01:40:28 2025 Native configuration is x86_64-pc-linux-gnu === gfortran tests === Have a lovely day! Alex Martin Uecker (1): c: Add support for array parameters in _Countof gcc/c/c-typeck.cc | 50 ++++++++++-- gcc/doc/extend.texi | 11 +++ gcc/testsuite/gcc.dg/countof-compile.c | 8 +- gcc/testsuite/gcc.dg/countof-param-compile.c | 76 +++++++++++++++++++ gcc/testsuite/gcc.dg/countof-param-pedantic.c | 11 +++ gcc/testsuite/gcc.dg/countof-param.c | 25 ++++++ 6 files changed, 166 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/countof-param-compile.c create mode 100644 gcc/testsuite/gcc.dg/countof-param-pedantic.c create mode 100644 gcc/testsuite/gcc.dg/countof-param.c Range-diff against v0: -: ------------ > 1: b5e67c7fb806 c: Add support for array parameters in _Countof base-commit: a440b382e43203857de9195eb526c4a16f21ceb1 -- 2.50.1