]> git.ipfire.org Git - thirdparty/gnulib.git/commitdiff
stdcountof-h: allow compound literal args
authorPaul Eggert <eggert@cs.ucla.edu>
Fri, 7 Nov 2025 06:38:55 +0000 (22:38 -0800)
committerPaul Eggert <eggert@cs.ucla.edu>
Fri, 7 Nov 2025 06:42:08 +0000 (22:42 -0800)
* lib/stdcountof.in.h (countof, _gl_verify_is_array):
Allow arguments that are compound literals, and thus
appear as multiple arguments to a C macro.
* tests/test-stdcountof-h.c: Test for this.

ChangeLog
lib/stdcountof.in.h
tests/test-stdcountof-h.c

index f3a5d317fdc467fd8603f8fd7b710560aba6c22f..1dd55d1ade7d658f7b0b600a41a4139f71551f6c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2025-11-06  Paul Eggert  <eggert@cs.ucla.edu>
 
+       stdcountof-h: allow compound literal args
+       * lib/stdcountof.in.h (countof, _gl_verify_is_array):
+       Allow arguments that are compound literals, and thus
+       appear as multiple arguments to a C macro.
+       * tests/test-stdcountof-h.c: Test for this.
+
        stdio-windows: fix <stdarg.h> include position
        Problem reported by Andy Moreton in:
        https://lists.gnu.org/r/bug-gnulib/2025-11/msg00059.html
index 6e602b4a9ffccbd29267421a2ed0b7c3326cb17b..1fc06401beb6907ca38a4ea53d984e6369c78c6b 100644 (file)
@@ -47,8 +47,9 @@
    Attempts to produce an error if A is a pointer, e.g. in
      void func (int a[10]) { ... }
  */
-#define countof(a) \
-  ((size_t) (sizeof (a) / sizeof ((a)[0]) + 0 * _gl_verify_is_array (a)))
+#define countof(...) \
+  ((size_t) (sizeof (__VA_ARGS__) / sizeof (__VA_ARGS__)[0] \
+             + 0 * _gl_verify_is_array (__VA_ARGS__)))
 
 /* Attempts to verify that A is an array.  */
 #if defined __cplusplus
@@ -75,8 +76,8 @@ template <typename T, size_t N>
 /* String literals.  */
 template <typename T, size_t N>
   struct _gl_array_type_test<T const (&)[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>)
+#   define _gl_verify_is_array(...) \
+     sizeof (_gl_verify_type<_gl_array_type_test<decltype(__VA_ARGS__)>::is_array>)
 #  else
   /* Use template argument deduction.
      Use sizeof to get a constant expression from an unknown type.
@@ -93,22 +94,22 @@ template <typename T, size_t N>
 /* The T& parameter is essential here: it prevents decay (array-to-pointer
    conversion).  */
 template <typename T> _gl_array_type_test<T> _gl_array_type_test_helper(T&);
-#   define _gl_verify_is_array(a) \
-     sizeof (_gl_verify_type<(sizeof (_gl_array_type_test_helper(a)) < sizeof (double) ? 1 : -1)>)
+#   define _gl_verify_is_array(...) \
+     sizeof (_gl_verify_type<(sizeof (_gl_array_type_test_helper(__VA_ARGS__)) < sizeof (double) ? 1 : -1)>)
 #  endif
 # else
 /* The compiler does not have the necessary functionality.  */
-#  define _gl_verify_is_array(a) 0
+#  define _gl_verify_is_array(...) 0
 # endif
 #else
 /* In C, we can use typeof and __builtin_types_compatible_p.  */
 /* Work around clang bug <https://github.com/llvm/llvm-project/issues/143284>.  */
 # if _GL_GNUC_PREREQ (3, 1) && ! defined __clang__ /* || defined __clang__ */
-#  define _gl_verify_is_array(a) \
-    sizeof (struct { unsigned int _gl_verify_error_if_negative : __builtin_types_compatible_p (typeof (a), typeof (&*(a))) ? -1 : 1; })
+#  define _gl_verify_is_array(...) \
+    sizeof (struct { unsigned int _gl_verify_error_if_negative : __builtin_types_compatible_p (typeof (__VA_ARGS__), typeof (&*(__VA_ARGS__))) ? -1 : 1; })
 # else
 /* The compiler does not have the necessary built-ins.  */
-#  define _gl_verify_is_array(a) 0
+#  define _gl_verify_is_array(...) 0
 # endif
 #endif
 
index 42f2f825377243cf655514090f0f9115253b72d7..4e88d5bf6647c2af4c9d69246a7eb83ff609cd3d 100644 (file)
@@ -80,6 +80,7 @@ test_func (int parameter[3])
 
   {
     extern int a, b, c;
+    ASSERT (countof ((int[]) { a, b, c }) == 3);
     ASSERT (countof (((int[]) { a, b, c })) == 3);
   }