Improve the test for the bug in MSVC and Oracle Developer Studio
so that it does not rely on symbols like _MSC_VER and so is more
likely to be portable to other compilers that have the bug, e.g.,
IBM XL C for AIX 16.1.  Also, document bug since countof exposes it.
* doc/posix-headers/stdcountof.texi: New file.
* tests/test-stdcountof-h.c (a, b, c): Remove these extern decls.
(call_count): New static var.
(do_call): New static function.
(test_func): Use it to test whether the compiler bug exists with
sizeof, and if so, to skip the countof test.
---
 ChangeLog                         | 14 ++++++++++++++
 doc/gnulib.texi                   |  2 ++
 doc/posix-headers/stdcountof.texi | 29 +++++++++++++++++++++++++++++
 tests/test-stdcountof-h.c         | 29 ++++++++++++++++-------------
 4 files changed, 61 insertions(+), 13 deletions(-)
 create mode 100644 doc/posix-headers/stdcountof.texi

diff --git a/ChangeLog b/ChangeLog
index b0012b9b88..d52868356a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2026-02-14  Paul Eggert  <[email protected]>
+
+       stdcountof-h: port to IBM XL C for AIX 16.1
+       Improve the test for the bug in MSVC and Oracle Developer Studio
+       so that it does not rely on symbols like _MSC_VER and so is more
+       likely to be portable to other compilers that have the bug, e.g.,
+       IBM XL C for AIX 16.1.  Also, document bug since countof exposes it.
+       * doc/posix-headers/stdcountof.texi: New file.
+       * tests/test-stdcountof-h.c (a, b, c): Remove these extern decls.
+       (call_count): New static var.
+       (do_call): New static function.
+       (test_func): Use it to test whether the compiler bug exists with
+       sizeof, and if so, to skip the countof test.
+
 2026-02-14  Bruno Haible  <[email protected]>
 
        obstack-printf-{posix,gnu}: Fix broken configuration result.
diff --git a/doc/gnulib.texi b/doc/gnulib.texi
index ababc9b5d4..5073908078 100644
--- a/doc/gnulib.texi
+++ b/doc/gnulib.texi
@@ -1167,6 +1167,7 @@ which (known) portability problems are not worked around 
by Gnulib.
 * stdbit.h::
 * stdbool.h::
 * stdckdint.h::
+* stdcountof.h::
 * stddef.h::
 * stdint.h::
 * stdio.h::
@@ -1257,6 +1258,7 @@ which (known) portability problems are not worked around 
by Gnulib.
 @include posix-headers/stdbit.texi
 @include posix-headers/stdbool.texi
 @include posix-headers/stdckdint.texi
+@include posix-headers/stdcountof.texi
 @include posix-headers/stddef.texi
 @include posix-headers/stdint.texi
 @include posix-headers/stdio.texi
diff --git a/doc/posix-headers/stdcountof.texi 
b/doc/posix-headers/stdcountof.texi
new file mode 100644
index 0000000000..559d8a0940
--- /dev/null
+++ b/doc/posix-headers/stdcountof.texi
@@ -0,0 +1,29 @@
+@node stdcountof.h
+@section @file{stdcountof.h}
+
+POSIX specification:@* Not in POSIX yet, but we expect it will be.
+ISO draft C2y N3783
+(@url{https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3783.pdf})
+§ 7.21.
+
+Gnulib module: stdcountof-h
+@mindex stdcountof-h
+
+Portability problems fixed by Gnulib:
+@itemize
+@item
+This header file is missing on many platforms:
+GCC 15, Clang 20, MSVC 14.50, Oracle Developer Studio 12.6,
+IBM Open XL C for AIX 17.1, TCC 0.9.27.
+@end itemize
+
+Portability problems not fixed by Gnulib:
+@itemize
+@item
+On some platforms, arguments of @code{countof} are evaluated
+if they contain designated initializers, e.g.,
+@code{countof ((int[]) @{getchar ()@})} incorrectly calls @code{getchar}.
+This is because these platforms have a similar bug with
+@code{sizeof ((int[]) @{getchar ()@})}:
+MSVC 14.50, Oracle Developer Studio 12.6, IBM XL C for AIX 16.1.
+@end itemize
diff --git a/tests/test-stdcountof-h.c b/tests/test-stdcountof-h.c
index 07a86fef98..8be40adc40 100644
--- a/tests/test-stdcountof-h.c
+++ b/tests/test-stdcountof-h.c
@@ -34,7 +34,13 @@ extern int integer;
 extern int unbounded[];
 extern int bounded[10];
 extern int multidimensional[10][20];
-extern int a, b, c;
+
+static int call_count;
+static int
+do_call ()
+{
+  return call_count++;
+}
 
 static void
 test_func (int parameter[3])
@@ -82,8 +88,15 @@ test_func (int parameter[3])
   /* Avoid MSVC C++ error C4576 "a parenthesized type followed by an
      initializer list is a non-standard explicit type conversion syntax".  */
 #if !defined __cplusplus
-  ASSERT (countof ((int[]) { a, b, c }) == 3);
-  ASSERT (countof (((int[]) { a, b, c })) == 3);
+  /* Work around a bug in MSVC 14.50, Oracle Developer Studio 12.6,
+     and IBM XL C for AIX 16.1, where sizeof of a designated
+     initializer evaluates the initializer.  */
+  if (sizeof (int[]) { do_call () } == sizeof (int[]) {0} && call_count == 0)
+    {
+      ASSERT (countof ((int[]) { do_call (), 0, 0 }) == 3);
+      ASSERT (countof (((int[]) { do_call (), 0, 0 })) == 3);
+      ASSERT (call_count == 0);
+    }
 #endif
 
   /* Check that countof(...) is an expression of type size_t.  */
@@ -110,13 +123,3 @@ main ()
 
   return test_exit_status;
 }
-
-/* A definition of the variables a, b, c is not required by ISO C, because
-   these identifiers are only used as part of 'sizeof' expressions whose
-   results are integer expressions.  See ISO C 23 § 6.9.1.(5).  However,
-   MSVC 14 and Oracle Developer Studio 12.6 generate actual references
-   to these variables.  We thus need to define these variables;
-   otherwise we get link errors.  */
-#if (defined _MSC_VER && !defined __clang__) || defined __SUNPRO_C
-int a, b, c;
-#endif
-- 
2.51.0


Reply via email to