On 2026-08-17 Bruno Haible wrote: > Since I now have a clang 22 + UBSAN + ASAN pass in my CI, there is > need to silence these failures. Previously I had used gnulib-tool > options --avoid=memchr-tests --avoid=memcmp-tests ... > but this is no longer practical.
Sorry, I should have placed the #ifs like that since the beginning. I attached patches. The first one the removes the now-redundant #ifs and moves the comments to the main function. The second patch updates the mingw-w64 workaround in test-wmemcpy.c and test-wmemmove.c to avoid undefined behavior completely. -- Lasse Collin
From 3bb855134d23a6950ac543c2dbe7fd774665d31a Mon Sep 17 00:00:00 2001 From: Lasse Collin <[email protected]> Date: Tue, 18 Aug 2026 18:10:25 +0300 Subject: [PATCH 1/2] tests: Remove redundant #ifs from N3322 tests * tests/test-bsearch.c (null_bsearch, main): Remove the #if from null_bsearch because having the same condition in main is enough. Move the comment explaining the #if from null_bsearch to main. * tests/test-memccpy.c (null_memccpy, main): Likewise. * tests/test-memchr.c (null_memchr, main): Likewise. * tests/test-memcmp.c (null_memcmp, main): Likewise. * tests/test-memcpy.c (null_memcpy, main): Likewise. * tests/test-memmove.c (null_memmove, main): Likewise. * tests/test-memset.c (null_memset, main): Likewise. * tests/test-memset_explicit.c (null_memset_explicit, main): Likewise. * tests/test-qsort.c (null_qsort, main): Likewise. * tests/test-strncat.c (null_strncat, main): Likewise. * tests/test-strncmp.c (null_strncmp, main): Likewise. * tests/test-strncpy.c (null_strncpy, main): Likewise. * tests/test-strndup.c (null_strndup, main): Likewise. * tests/test-wcsncat.c (null_wcsncat, main): Likewise. * tests/test-wcsncmp.c (null_wcsncmp, main): Likewise. * tests/test-wcsncpy.c (null_wcsncpy, main): Likewise. --- ChangeLog | 22 ++++++++++++++++++++++ tests/test-bsearch.c | 10 ++++------ tests/test-memccpy.c | 8 +++----- tests/test-memchr.c | 11 ++++------- tests/test-memcmp.c | 11 ++++------- tests/test-memcpy.c | 11 ++++------- tests/test-memmove.c | 11 ++++------- tests/test-memset.c | 11 ++++------- tests/test-memset_explicit.c | 8 +++----- tests/test-qsort.c | 8 +++----- tests/test-strncat.c | 11 ++++------- tests/test-strncmp.c | 11 ++++------- tests/test-strncpy.c | 11 ++++------- tests/test-strndup.c | 11 ++++------- tests/test-wcsncat.c | 8 +++----- tests/test-wcsncmp.c | 8 +++----- tests/test-wcsncpy.c | 8 +++----- 17 files changed, 80 insertions(+), 99 deletions(-) diff --git a/ChangeLog b/ChangeLog index 30ad4d78e8..83e0fedaa4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2026-08-18 Lasse Collin <[email protected]> + + tests: Remove redundant #ifs from N3322 tests. + * tests/test-bsearch.c (null_bsearch, main): Remove the #if from + null_bsearch because having the same condition in main is enough. + Move the comment explaining the #if from null_bsearch to main. + * tests/test-memccpy.c (null_memccpy, main): Likewise. + * tests/test-memchr.c (null_memchr, main): Likewise. + * tests/test-memcmp.c (null_memcmp, main): Likewise. + * tests/test-memcpy.c (null_memcpy, main): Likewise. + * tests/test-memmove.c (null_memmove, main): Likewise. + * tests/test-memset.c (null_memset, main): Likewise. + * tests/test-memset_explicit.c (null_memset_explicit, main): Likewise. + * tests/test-qsort.c (null_qsort, main): Likewise. + * tests/test-strncat.c (null_strncat, main): Likewise. + * tests/test-strncmp.c (null_strncmp, main): Likewise. + * tests/test-strncpy.c (null_strncpy, main): Likewise. + * tests/test-strndup.c (null_strndup, main): Likewise. + * tests/test-wcsncat.c (null_wcsncat, main): Likewise. + * tests/test-wcsncmp.c (null_wcsncmp, main): Likewise. + * tests/test-wcsncpy.c (null_wcsncpy, main): Likewise. + 2026-08-18 Paul Eggert <[email protected]> exclude: new function excluded_file_name_status diff --git a/tests/test-bsearch.c b/tests/test-bsearch.c index 60cd0ff08c..3aeee9a558 100644 --- a/tests/test-bsearch.c +++ b/tests/test-bsearch.c @@ -21,17 +21,13 @@ #include "macros.h" -/* Test the prototype in <stdlib.h> + compiler. - In glibc >= 2.18, <bits/stdlib-bsearch.h> has an inline version. - Some glibc versions use the nonnull attribute, which breaks this test. */ +/* Test the prototype in <stdlib.h> + compiler. */ static void * null_bsearch (void const *key, void const *base, size_t nel, size_t width, int (*compar) (void const *, void const *)) { void const *p = bsearch (key, base, nel, width, compar); -#if ! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__) ASSERT (base == NULL); -#endif return (void *) p; } static void *(*volatile volatile_null_bsearch) (void const *, void const *, @@ -63,7 +59,9 @@ int main (void) { /* Test zero-length operations on NULL pointers, allowed by - <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ + <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. + In glibc >= 2.18, <bits/stdlib-bsearch.h> has an inline version. + Some glibc versions use the nonnull attribute, which breaks this test. */ #if ! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__) ASSERT (bsearch ("x", NULL, 0, 1, cmp) == NULL); diff --git a/tests/test-memccpy.c b/tests/test-memccpy.c index c942e18675..35a7c0488d 100644 --- a/tests/test-memccpy.c +++ b/tests/test-memccpy.c @@ -23,15 +23,12 @@ #include "macros.h" -/* Test the prototype in <string.h> + compiler. - Some glibc versions use the nonnull attribute, which breaks this test. */ +/* Test the prototype in <string.h> + compiler. */ static void * null_memccpy (void *dest, const void *src, int c, size_t n) { void *p = memccpy (dest, src, c, n); -#if ! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__) ASSERT (dest == NULL); -#endif return p; } static void *(*volatile volatile_null_memccpy) (void *, void const *, int, @@ -54,7 +51,8 @@ int main (void) { /* Test zero-length operations on NULL pointers, allowed by - <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ + <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. + Some glibc versions use the nonnull attribute, which breaks this test. */ #if ! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__) ASSERT (memccpy (NULL, "x", '?', 0) == NULL); diff --git a/tests/test-memchr.c b/tests/test-memchr.c index ea662ca2f2..4ed0e10383 100644 --- a/tests/test-memchr.c +++ b/tests/test-memchr.c @@ -27,17 +27,12 @@ SIGNATURE_CHECK (memchr, void *, (void const *, int, size_t)); #include "zerosize-ptr.h" #include "macros.h" -/* Test the prototype in <string.h> + compiler. - In GCC < 15 this is a builtin that has the nonnull attribute. - Some glibc versions use the nonnull attribute, which breaks this test. */ +/* Test the prototype in <string.h> + compiler. */ static void * null_memchr (void const *s, int c, size_t n) { const void *p = memchr (s, c, n); -#if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ - && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) ASSERT (s == NULL); -#endif return (void *) p; } static void *(*volatile volatile_null_memchr) (void const *, int, size_t) @@ -151,7 +146,9 @@ main (void) } /* Test zero-length operations on NULL pointers, allowed by - <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ + <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. + In GCC < 15 this is a builtin that has the nonnull attribute. + Some glibc versions use the nonnull attribute, which breaks this test. */ #if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) ASSERT (memchr (NULL, '?', 0) == NULL); diff --git a/tests/test-memcmp.c b/tests/test-memcmp.c index 601f46859f..30822b8e62 100644 --- a/tests/test-memcmp.c +++ b/tests/test-memcmp.c @@ -25,17 +25,12 @@ SIGNATURE_CHECK (memcmp, int, (void const *, void const *, size_t)); #include "zerosize-ptr.h" #include "macros.h" -/* Test the prototype in <string.h> + compiler. - In GCC < 15 this is a builtin that has the nonnull attribute. - Some glibc versions use the nonnull attribute, which breaks this test. */ +/* Test the prototype in <string.h> + compiler. */ static int null_memcmp (void const *s1, void const *s2, size_t n) { int r = memcmp (s1, s2, n); -#if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ - && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) ASSERT (s1 == NULL); -#endif return r; } int (*volatile volatile_null_memcmp) (void const *, void const *, size_t) @@ -97,7 +92,9 @@ main (void) } /* Test zero-length operations on NULL pointers, allowed by - <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ + <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. + In GCC < 15 this is a builtin that has the nonnull attribute. + Some glibc versions use the nonnull attribute, which breaks this test. */ #if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) ASSERT (memcmp (NULL, "x", 0) == 0); diff --git a/tests/test-memcpy.c b/tests/test-memcpy.c index 8836e9680a..b6bd045625 100644 --- a/tests/test-memcpy.c +++ b/tests/test-memcpy.c @@ -23,17 +23,12 @@ #include "macros.h" -/* Test the prototype in <string.h> + compiler. - In GCC < 15 this is a builtin that has the nonnull attribute. - Some glibc versions use the nonnull attribute, which breaks this test. */ +/* Test the prototype in <string.h> + compiler. */ static void * null_memcpy (void *dest, const void *src, size_t n) { void *p = memcpy (dest, src, n); -#if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ - && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) ASSERT (dest == NULL); -#endif return p; } void *(*volatile volatile_null_memcpy) (void *, void const *, size_t) @@ -54,7 +49,9 @@ int main (void) { /* Test zero-length operations on NULL pointers, allowed by - <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ + <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. + In GCC < 15 this is a builtin that has the nonnull attribute. + Some glibc versions use the nonnull attribute, which breaks this test. */ #if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) diff --git a/tests/test-memmove.c b/tests/test-memmove.c index 6b433ce7f0..6282d73158 100644 --- a/tests/test-memmove.c +++ b/tests/test-memmove.c @@ -23,17 +23,12 @@ #include "macros.h" -/* Test the prototype in <string.h> + compiler. - In GCC < 15 this is a builtin that has the nonnull attribute. - Some glibc versions use the nonnull attribute, which breaks this test. */ +/* Test the prototype in <string.h> + compiler. */ static void * null_memmove (void *dest, const void *src, size_t n) { void * p = memmove (dest, src, n); -#if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ - && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) ASSERT (dest == NULL); -#endif return p; } static void *(*volatile volatile_null_memmove) (void *, void const *, size_t) @@ -54,7 +49,9 @@ int main (void) { /* Test zero-length operations on NULL pointers, allowed by - <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ + <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. + In GCC < 15 this is a builtin that has the nonnull attribute. + Some glibc versions use the nonnull attribute, which breaks this test. */ #if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) diff --git a/tests/test-memset.c b/tests/test-memset.c index 39dd047b65..cb35c3a1fd 100644 --- a/tests/test-memset.c +++ b/tests/test-memset.c @@ -23,17 +23,12 @@ #include "macros.h" -/* Test the prototype in <string.h> + compiler. - In GCC < 15 this is a builtin that has the nonnull attribute. - Some glibc versions use the nonnull attribute, which breaks this test. */ +/* Test the prototype in <string.h> + compiler. */ static void * null_memset (void *s, int c, size_t n) { void *p = memset (s, c, n); -#if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ - && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) ASSERT (s == NULL); -#endif return p; } static void *(*volatile volatile_null_memset) (void *, int, size_t) @@ -54,7 +49,9 @@ int main (void) { /* Test zero-length operations on NULL pointers, allowed by - <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ + <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. + In GCC < 15 this is a builtin that has the nonnull attribute. + Some glibc versions use the nonnull attribute, which breaks this test. */ #if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) ASSERT (memset (NULL, '?', 0) == NULL); diff --git a/tests/test-memset_explicit.c b/tests/test-memset_explicit.c index e2ab32097f..488f07beea 100644 --- a/tests/test-memset_explicit.c +++ b/tests/test-memset_explicit.c @@ -48,15 +48,12 @@ static char zero[SECRET_SIZE] = { 0 }; # define memset_explicit memset #endif -/* Test the prototype in <string.h> + compiler. - Some glibc versions use the nonnull attribute, which breaks this test. */ +/* Test the prototype in <string.h> + compiler. */ static void * null_memset_explicit (void *s, int c, size_t n) { void *p = memset_explicit (s, c, n); -#if ! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__) ASSERT (s == NULL); -#endif return p; } static void *(*volatile volatile_null_memset_explicit) (void *, int, size_t) @@ -279,7 +276,8 @@ main () test_stack (); /* Test zero-length operations on NULL pointers, allowed by - <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ + <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. + Some glibc versions use the nonnull attribute, which breaks this test. */ #if ! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__) ASSERT (memset_explicit (NULL, '?', 0) == NULL); diff --git a/tests/test-qsort.c b/tests/test-qsort.c index 8904882ac1..382dfe99f7 100644 --- a/tests/test-qsort.c +++ b/tests/test-qsort.c @@ -21,16 +21,13 @@ #include "macros.h" -/* Test the prototype in <stdlib.h> + compiler. - Some glibc versions use the nonnull attribute, which breaks this test. */ +/* Test the prototype in <stdlib.h> + compiler. */ static void null_qsort (void *base, size_t nel, size_t width, int (*compar) (void const *, void const *)) { qsort (base, nel, width, compar); -#if ! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__) ASSERT (base == NULL); -#endif } static void (*volatile volatile_null_qsort) (void *, size_t, size_t, int (*) (void const *, void const *)) @@ -59,7 +56,8 @@ int main (void) { /* Test zero-length operations on NULL pointers, allowed by - <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ + <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. + Some glibc versions use the nonnull attribute, which breaks this test. */ #if ! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__) qsort (NULL, 0, 1, cmp); diff --git a/tests/test-strncat.c b/tests/test-strncat.c index 162b3d4e42..a74e882a4e 100644 --- a/tests/test-strncat.c +++ b/tests/test-strncat.c @@ -29,17 +29,12 @@ SIGNATURE_CHECK (strncat, char *, (char *, const char *, size_t)); #include "zerosize-ptr.h" #include "macros.h" -/* Test the prototype in <string.h> + compiler. - In GCC < 15 this is a builtin that has the nonnull attribute. - Some glibc versions use the nonnull attribute, which breaks this test. */ +/* Test the prototype in <string.h> + compiler. */ static char * null_strncat (char *s1, char const *s2, size_t n) { char *p = strncat (s1, s2, n); -#if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ - && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) ASSERT (s2 == NULL); -#endif return p; } static char *(*volatile volatile_null_strncat) (char *, char const *, size_t) @@ -87,7 +82,9 @@ main () } /* Test zero-length operations on NULL pointers, allowed by - <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ + <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. + In GCC < 15 this is a builtin that has the nonnull attribute. + Some glibc versions use the nonnull attribute, which breaks this test. */ #if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) diff --git a/tests/test-strncmp.c b/tests/test-strncmp.c index cbc2327861..83526a4a3a 100644 --- a/tests/test-strncmp.c +++ b/tests/test-strncmp.c @@ -23,17 +23,12 @@ #include "macros.h" -/* Test the prototype in <string.h> + compiler. - In GCC < 15 this is a builtin that has the nonnull attribute. - Some glibc versions use the nonnull attribute, which breaks this test. */ +/* Test the prototype in <string.h> + compiler. */ static int null_strncmp (char const *s1, char const *s2, size_t n) { int r = strncmp (s1, s2, n); -#if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ - && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) ASSERT (s1 == NULL); -#endif return r; } static int (*volatile volatile_null_strncmp) (char const *, char const *, @@ -56,7 +51,9 @@ int main (void) { /* Test zero-length operations on NULL pointers, allowed by - <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ + <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. + In GCC < 15 this is a builtin that has the nonnull attribute. + Some glibc versions use the nonnull attribute, which breaks this test. */ #if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) ASSERT (strncmp (NULL, "x", 0) == 0); diff --git a/tests/test-strncpy.c b/tests/test-strncpy.c index 2bbbecd991..03f5e245ab 100644 --- a/tests/test-strncpy.c +++ b/tests/test-strncpy.c @@ -25,17 +25,12 @@ #include "zerosize-ptr.h" #include "macros.h" -/* Test the prototype in <string.h> + compiler. - In GCC < 15 this is a builtin that has the nonnull attribute. - Some glibc versions use the nonnull attribute, which breaks this test. */ +/* Test the prototype in <string.h> + compiler. */ static char * null_strncpy (char *s1, char const *s2, size_t n) { char *p = strncpy (s1, s2, n); -#if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ - && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) ASSERT (s2 == NULL); -#endif return p; } static char *(*volatile volatile_null_strncpy) (char *, char const *, size_t) @@ -125,7 +120,9 @@ main (void) } /* Test zero-length operations on NULL pointers, allowed by - <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ + <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. + In GCC < 15 this is a builtin that has the nonnull attribute. + Some glibc versions use the nonnull attribute, which breaks this test. */ #if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) diff --git a/tests/test-strndup.c b/tests/test-strndup.c index b7f9db05c5..36f93e85e8 100644 --- a/tests/test-strndup.c +++ b/tests/test-strndup.c @@ -23,17 +23,12 @@ #include "macros.h" -/* Test the prototype in <string.h> + compiler. - In GCC < 15 this is a builtin that has the nonnull attribute. - Some glibc versions use the nonnull attribute, which breaks this test. */ +/* Test the prototype in <string.h> + compiler. */ static char * null_strndup (char const *s, size_t size) { char *p = strndup (s, size); -#if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ - && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) ASSERT (s == NULL); -#endif return p; } static char *(*volatile volatile_null_strndup) (char const *, size_t) @@ -54,7 +49,9 @@ int main (void) { /* Test zero-length operations on NULL pointers, allowed by - <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ + <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. + In GCC < 15 this is a builtin that has the nonnull attribute. + Some glibc versions use the nonnull attribute, which breaks this test. */ #if (! defined __GNUC__ || __GNUC__ >= 15 || defined __clang__) \ && (! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__)) ASSERT (strndup (NULL, 0) != NULL); diff --git a/tests/test-wcsncat.c b/tests/test-wcsncat.c index bf5cc48ae8..40a502d347 100644 --- a/tests/test-wcsncat.c +++ b/tests/test-wcsncat.c @@ -25,15 +25,12 @@ #include "macros.h" -/* Test the prototype in <wchar.h> + compiler. - Some glibc versions use the nonnull attribute, which breaks this test. */ +/* Test the prototype in <wchar.h> + compiler. */ static wchar_t * null_wcsncat (wchar_t *ws1, wchar_t const *ws2, size_t n) { wchar_t *p = wcsncat (ws1, ws2, n); -#if ! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__) ASSERT (ws2 == NULL); -#endif return p; } static wchar_t *(*volatile volatile_null_wcsncat) (wchar_t *, wchar_t const *, @@ -56,7 +53,8 @@ int main () { /* Test zero-length operations on NULL pointers, allowed by - <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ + <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. + Some glibc versions use the nonnull attribute, which breaks this test. */ #if ! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__) # if 0 /* I think this is invalid, per ISO C 23 § 7.31.4.3.2. */ diff --git a/tests/test-wcsncmp.c b/tests/test-wcsncmp.c index 16990772ad..bb9dcd1a99 100644 --- a/tests/test-wcsncmp.c +++ b/tests/test-wcsncmp.c @@ -25,15 +25,12 @@ SIGNATURE_CHECK (wcsncmp, int, (const wchar_t *, const wchar_t *, size_t)); #include "macros.h" -/* Test the prototype in <wchar.h> + compiler. - Some glibc versions use the nonnull attribute, which breaks this test. */ +/* Test the prototype in <wchar.h> + compiler. */ static int null_wcsncmp (wchar_t const *ws1, wchar_t const *ws2, size_t n) { int r = wcsncmp (ws1, ws2, n); -#if ! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__) ASSERT (ws1 == NULL); -#endif return r; } static int (*volatile volatile_null_wcsncmp) (wchar_t const *, @@ -206,7 +203,8 @@ main (int argc, char *argv[]) } /* Test zero-length operations on NULL pointers, allowed by - <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ + <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. + Some glibc versions use the nonnull attribute, which breaks this test. */ #if ! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__) ASSERT (wcsncmp (NULL, L"x", 0) == 0); ASSERT (wcsncmp (L"x", NULL, 0) == 0); diff --git a/tests/test-wcsncpy.c b/tests/test-wcsncpy.c index a2e8622ca8..169ce787cf 100644 --- a/tests/test-wcsncpy.c +++ b/tests/test-wcsncpy.c @@ -23,15 +23,12 @@ #include "macros.h" -/* Test the prototype in <wchar.h> + compiler. - Some glibc versions use the nonnull attribute, which breaks this test. */ +/* Test the prototype in <wchar.h> + compiler. */ static wchar_t * null_wcsncpy (wchar_t *ws1, wchar_t const *ws2, size_t n) { wchar_t *p = wcsncpy (ws1, ws2, n); -#if ! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__) ASSERT (ws2 == NULL); -#endif return p; } static wchar_t *(*volatile volatile_null_wcsncpy) (wchar_t *, wchar_t const *, @@ -54,7 +51,8 @@ int main (void) { /* Test zero-length operations on NULL pointers, allowed by - <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ + <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. + Some glibc versions use the nonnull attribute, which breaks this test. */ #if ! defined __GLIBC__ || 2 < __GLIBC__ + (99 <= __GLIBC_MINOR__) ASSERT (wcsncpy (NULL, L"x", 0) == NULL); -- 2.55.0
>From 3d955c41ef0a0787a77ee0eb2ae83845c5f4d322 Mon Sep 17 00:00:00 2001 From: Lasse Collin <[email protected]> Date: Tue, 18 Aug 2026 18:10:25 +0300 Subject: [PATCH 2/2] tests: Avoid undefined behavior on mingw-w64 * tests/test-wmemcpy.c (null_wmemcpy, main): Move the #if and comment from null_wmemcpy to main to avoid invoking undefined behavior. * tests/test-wmemmove.c (null_wmemmove, main): Likewise. --- ChangeLog | 7 +++++++ tests/test-wmemcpy.c | 14 +++++++------- tests/test-wmemmove.c | 14 +++++++------- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 83e0fedaa4..920834ca9b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2026-08-18 Lasse Collin <[email protected]> + + tests: Avoid undefined behavior on mingw-w64. + * tests/test-wmemcpy.c (null_wmemcpy, main): Move the #if and comment + from null_wmemcpy to main to avoid invoking undefined behavior. + * tests/test-wmemmove.c (null_wmemmove, main): Likewise. + 2026-08-18 Lasse Collin <[email protected]> tests: Remove redundant #ifs from N3322 tests. diff --git a/tests/test-wmemcpy.c b/tests/test-wmemcpy.c index 8a0b31db68..e1a8a751d8 100644 --- a/tests/test-wmemcpy.c +++ b/tests/test-wmemcpy.c @@ -23,17 +23,12 @@ #include "macros.h" -/* Test the prototype in <wchar.h> + compiler. - In mingw-w64 14.0.0, wmemcpy is an inline function that calls memcpy. - In GCC < 15, memcpy is a builtin that has the nonnull attribute. */ +/* Test the prototype in <wchar.h> + compiler. */ static wchar_t * null_wmemcpy (wchar_t *s1, wchar_t const *s2, size_t n) { wchar_t *p = wmemcpy (s1, s2, n); -#if ! (defined __MINGW32__ \ - && defined __GNUC__ && !defined __clang__ && __GNUC__ < 15) ASSERT (s1 == NULL); -#endif return p; } static wchar_t *(*volatile volatile_null_wmemcpy) (wchar_t *, wchar_t const *, @@ -56,8 +51,12 @@ int main (void) { /* Test zero-length operations on NULL pointers, allowed by - <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ + <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. + In mingw-w64 14.0.0, wmemcpy is an inline function that calls memcpy. + In GCC < 15, memcpy is a builtin that has the nonnull attribute. */ +#if ! (defined __MINGW32__ \ + && defined __GNUC__ && !defined __clang__ && __GNUC__ < 15) ASSERT (wmemcpy (NULL, L"x", 0) == NULL); { @@ -66,6 +65,7 @@ main (void) } ASSERT (volatile_null_wmemcpy (NULL, L"x", 0) == NULL); +#endif return test_exit_status; } diff --git a/tests/test-wmemmove.c b/tests/test-wmemmove.c index ed924e1a68..82315281ab 100644 --- a/tests/test-wmemmove.c +++ b/tests/test-wmemmove.c @@ -23,17 +23,12 @@ #include "macros.h" -/* Test the prototype in <wchar.h> + compiler. - In mingw-w64 14.0.0, wmemmove is an inline function that calls memmove. - In GCC < 15, memmove is a builtin that has the nonnull attribute. */ +/* Test the prototype in <wchar.h> + compiler. */ static wchar_t * null_wmemmove (wchar_t *s1, wchar_t const *s2, size_t n) { wchar_t *p = wmemmove (s1, s2, n); -#if ! (defined __MINGW32__ \ - && defined __GNUC__ && !defined __clang__ && __GNUC__ < 15) ASSERT (s1 == NULL); -#endif return p; } static wchar_t *(*volatile volatile_null_wmemmove) (wchar_t *, wchar_t const *, @@ -56,8 +51,12 @@ int main (void) { /* Test zero-length operations on NULL pointers, allowed by - <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. */ + <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>. + In mingw-w64 14.0.0, wmemmove is an inline function that calls memmove. + In GCC < 15, memmove is a builtin that has the nonnull attribute. */ +#if ! (defined __MINGW32__ \ + && defined __GNUC__ && !defined __clang__ && __GNUC__ < 15) ASSERT (wmemmove (NULL, L"x", 0) == NULL); { @@ -66,6 +65,7 @@ main (void) } ASSERT (volatile_null_wmemmove (NULL, L"x", 0) == NULL); +#endif return test_exit_status; } -- 2.55.0
