Hi Bruno, Paul,

On Tue, Jun 03, 2025 at 11:52:04AM +0200, Bruno Haible wrote:
> As written yesterday, the use of __SIZE_TYPE__ is wrong.

Agree; IMO, <stddef.h> is so fundamental, that anyone attempting to
redefine anything from there is doomed.  size_t should be considered a
reserved keyword even without including any headers, even if the
standards theoretically allow using that identifier if you don't include
<stddef.h>.


Have a lovely day!
Alex

> 
> And the "simplification" of sizeof ((a)[0]) to sizeof *(a)
> is besides the point, because countof is about array elements and
> the common syntax for accessing elements is  array[index].
> 
> I'm therefore applying this patch:
> 
> 
> 2025-06-03  Bruno Haible  <br...@clisp.org>
> 
>       stdcountof-h: Always return size_t, in a better way.
>       * lib/stdcountof.in.h: Revert last change. Include <stddef.h>
>       unconditionally.
>       (countof): Cast value to size_t.
>       * tests/test-stdcountof-h.c (HAVE___TYPEOF__, HAVE__GENERIC): New
>       macros.
>       (test_func): Check the return type of countof.
> 
> diff --git a/lib/stdcountof.in.h b/lib/stdcountof.in.h
> index 6803b676bc..105cf209a5 100644
> --- a/lib/stdcountof.in.h
> +++ b/lib/stdcountof.in.h
> @@ -18,10 +18,8 @@
>  #ifndef _GL_STDCOUNTOF_H
>  #define _GL_STDCOUNTOF_H
>  
> -#ifndef __SIZE_TYPE__
> -# include <stddef.h>
> -# define __SIZE_TYPE__ size_t
> -#endif
> +/* Get size_t.  */
> +#include <stddef.h>
>  
>  /* Returns the number of elements of the array A, as a value of type size_t.
>     Example declarations of arrays:
> @@ -33,7 +31,7 @@
>       void func (int a[10]) { ... }
>   */
>  #define countof(a) \
> -  ((__SIZE_TYPE__) (sizeof (a) / sizeof *(a) + 0 * _gl_verify_is_array (a)))
> +  ((size_t) (sizeof (a) / sizeof ((a)[0]) + 0 * _gl_verify_is_array (a)))
>  
>  /* Attempts to verify that A is an array.  */
>  #if defined __cplusplus
> @@ -55,7 +53,7 @@ template <typename T>
>  template <typename T>
>    struct _gl_array_type_test<T[]> { static const int is_array = 1; };
>  /* Bounded arrays.  */
> -template <typename T, __SIZE_TYPE__ N>
> +template <typename T, size_t N>
>    struct _gl_array_type_test<T[N]> { static const int is_array = 1; };
>  #   define _gl_verify_is_array(a) \
>       sizeof (_gl_verify_type<_gl_array_type_test<decltype(a)>::is_array>)
> @@ -69,7 +67,7 @@ template <typename T>
>  template <typename T>
>    struct _gl_array_type_test<T[]> { char small; };
>  /* Bounded arrays.  */
> -template <typename T, __SIZE_TYPE__ N>
> +template <typename T, size_t N>
>    struct _gl_array_type_test<T[N]> { char small; };
>  /* The T& parameter is essential here: it prevents decay (array-to-pointer
>     conversion).  */
> diff --git a/tests/test-stdcountof-h.c b/tests/test-stdcountof-h.c
> index 619a666186..a382dc1b1e 100644
> --- a/tests/test-stdcountof-h.c
> +++ b/tests/test-stdcountof-h.c
> @@ -20,6 +20,25 @@
>  
>  #include "macros.h"
>  
> +/* Whether the compiler supports __typeof__.  */
> +#if ((defined __GNUC__ && 2 <= __GNUC__) \
> +     || (defined __clang_major__ && 4 <= __clang_major__) \
> +     || (defined __IBMC__ && 1210 <= __IBMC__ && defined __IBM__TYPEOF__) \
> +     || (defined __SUNPRO_C && 0x5110 <= __SUNPRO_C && !__STDC__) \
> +     || (defined _MSC_VER && 1939 <= _MSC_VER))
> +# define HAVE___TYPEOF__ 1
> +#endif
> +
> +/* Whether the compiler supports _Generic.
> +   Test program:
> +     int f (int x) { return _Generic (x, char *: 2, int: 3); }
> + */
> +#if (defined __GNUC__ && __GNUC__ + (__GNUC_MINOR__ >= 9) > 4) \
> +    || (defined __clang__ && __clang_major__ >= 3) \
> +    || (defined __SUNPRO_C && __SUNPRO_C >= 0x5150)
> +# define HAVE__GENERIC 1
> +#endif
> +
>  extern int integer;
>  extern int unbounded[];
>  extern int bounded[10];
> @@ -47,6 +66,13 @@ test_func (int parameter[3])
>    ASSERT (countof (integer) >= 0);
>    ASSERT (countof (unbounded) >= 0);
>  #endif
> +
> +  /* Check that countof(...) is an expression of type size_t.  */
> +#if !defined __cplusplus && HAVE___TYPEOF__ && HAVE__GENERIC
> +  ASSERT (_Generic (__typeof__ (countof (bounded)),          size_t: 1, 
> default: 0));
> +  ASSERT (_Generic (__typeof__ (countof (multidimensional)), size_t: 1, 
> default: 0));
> +  ASSERT (_Generic (__typeof__ (countof (local_bounded)),    size_t: 1, 
> default: 0));
> +#endif
>  }
>  
>  int
> 
> 
> 

-- 
<https://www.alejandro-colomar.es/>

Attachment: signature.asc
Description: PGP signature

Reply via email to