As written yesterday, the use of __SIZE_TYPE__ is wrong.

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




Reply via email to