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/>

Attachment: signature.asc
Description: PGP signature

Reply via email to