Hi Martin, On Thu, Aug 14, 2025 at 11:01:05AM +0200, Alejandro Colomar wrote: > +void > +decay_obvious (int a[2]) > +{ > + _Countof (typeof (a)); /* { dg-error "invalid" } */ > + _Countof (a + 1); /* { dg-error "invalid" } */
It didn't occur to me the following test: alx@devuan:~/tmp$ cat c.c | nl -ba 1 int 2 main(int argc, char *argv[argc + 1]) 3 { 4 argv++; 5 6 return _Countof(argv); 7 } alx@devuan:~/tmp$ /opt/local/gnu/gcc/countof_ap/bin/gcc -Wall -Wextra c.c alx@devuan:~/tmp$ ./a.out alx@devuan:~/tmp$ echo $? 2 This is a weak point, which requires -farray-parameters-are-const as proposed in: <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121271> I'm willing to accept it as a known limitation of _Countof(), and tell that programmers to use const (or use -farray-parameters-are-const once we provide it) to ensure safety. So, I stand by this patch even with this known limitation. On the other, hand, it may be a GCC existing bug? I see that _Countof(a+0) remembers the array number of elements but _Countof(a+1) doesn't. Maybe once you do a++ you should also forget the number of elements (or update it)? Have a lovely day! Alex > + _Countof (42 ? NULL : a); /* { dg-error "invalid" } */ > + > + int *p = a; > + > + _Countof (p); /* { dg-error "invalid" } */ > + > + typeof(a) a2; > + > + _Countof (a2); /* { dg-error "invalid" } */ > +} > + > +/* These would decay if they were arrays, but being a parameter, it's works. > */ > +void > +no_decay_surprising (int a[2]) > +{ > + _Static_assert (2 == _Countof (a + 0)); > + _Static_assert (2 == _Countof (&*a)); > + _Static_assert (2 == _Countof (42, a)); > + _Static_assert (2 == _Countof (42 ? a : a)); > + _Static_assert (2 == _Countof (42 ? a : NULL)); > +} > + > +void > +no_decay_obvious (int a[2]) > +{ > + _Static_assert (2 == _Countof (a)); > + _Static_assert (2 == _Countof (*&a)); > + _Static_assert (2 == _Countof (*(&a + 0))); > +} > + > +/* It would not decay if it were an array, but being a parameter, it decays. > */ > +void > +decay_surprising (int a[2]) > +{ > + _Countof (*(&a + 1)); /* { dg-error "invalid" } */ > +} > diff --git a/gcc/testsuite/gcc.dg/countof-param-pedantic.c > b/gcc/testsuite/gcc.dg/countof-param-pedantic.c > new file mode 100644 > index 000000000000..7d52f27a72bb > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/countof-param-pedantic.c > @@ -0,0 +1,11 @@ > +/* { dg-do compile } */ > +/* { dg-options "-std=c2y -pedantic" } */ > + > +#include <stdcountof.h> > + > +int > +f (int a[1]) > +{ > + countof(a); /* { dg-warning "ISO C does not support array parameters" } */ > + _Countof(a); /* { dg-warning "ISO C does not support array parameters" } > */ > +} > diff --git a/gcc/testsuite/gcc.dg/countof-param.c > b/gcc/testsuite/gcc.dg/countof-param.c > new file mode 100644 > index 000000000000..e03f8b9389db > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/countof-param.c > @@ -0,0 +1,25 @@ > +/* { dg-do run } */ > +/* { dg-options "-Wvla-parameter -Warray-parameter=2" } */ > + > +#define assert(e) ((e) ? (void) 0 : __builtin_abort ()) > + > +int f1 (int , int a[3]) { return _Countof(a); } > +int f2 (int , int a[2]) { return _Countof(a); } > + > +int f1 (int , int a[2]); /* { dg-warning "with mismatched bound" } */ > +int f2 (int n, int a[n]); /* { dg-warning "declared as a variable length > array" } */ > + > +int g1 (int , int a[3]); > +int g2 (int , int a[2]); > + > +int g1 (int , int a[2]) { return _Countof(a); } // { dg-warning "with > mismatched bound" } */ > +int g2 (int n, int a[n]) { return _Countof(a); } // { dg-warning "declared > as a variable length array" } */ > + > +int > +main (void) > +{ > + assert (3 == f1 (42, (int [42]){})); > + assert (2 == f2 (42, (int [42]){})); > + assert (2 == g1 (42, (int [42]){})); > + assert (42 == g2 (42, (int [42]){})); > +} > -- > 2.50.1 > -- <https://www.alejandro-colomar.es/>
signature.asc
Description: PGP signature