Re: N3322 functionality tests

Lasse Collin <[email protected]>
Newsgroups gmane.comp.lib.gnulib.bugs
Message-ID <[email protected]>
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
0001-tests-Remove-redundant-ifs-from-N3322-tests.patch (text/x-patch, 23.8 KB)
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
0002-tests-Avoid-undefined-behavior-on-mingw-w64.patch (text/x-patch, 4 KB)
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.