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
