Gnulib has a few tests for N3322 behavior in functions. For example,
tests/test-memcpy.c has:

    ASSERT (memcpy (NULL, "x", 0) == NULL);

Earlier in the file, memcpy is #defined to call a wrapper function to
avoid the effects of the function prototype in the libc header and
compiler optimizations. Such a test is fine, but testing the behavior of
prototype-in-the-header + compiler is important too.

The attached patch adds such tests to 21 modules. They shouldn't
produce any warnings with -Wnonnull, which were a concern in the commit
15efa15b439e. With glibc 2.43 and GCC 16.1.1 with -O2, 15 tests fail:

    test-memccpy
    test-memchr
    test-memcmp
    test-memcpy
    test-memmove
    test-memset
    test-memset_explicit
    test-qsort
    test-strncat
    test-strncmp
    test-strncpy
    test-strndup
    test-wcsncat
    test-wcsncmp
    test-wcsncpy

With Clang 22.1.8, one test fails:

    test-bsearch

I have understood that glibc headers will be fixed. Old glibc versions
might remain in use for years though, so I looked for workaround ideas.
I wish I hadn't.

glibc >= 2.34 && (GCC >= 15 || Clang):

    One could add

        #define __nonnull(param)

    to the beginning of config.h. It prevents glibc's <sys/cdefs.h> from
    defining __nonnull to the nonnull attribute.

    I built coreutils 9.11 without and with this trick, and then
    disassembled all .o files. One file differed, and it was only a
    single instruction ("lea" with the source registers in swapped
    order).

glibc < 2.34 && (GCC >= 15 || Clang):

    __nonnull is defined unconditionally in <sys/cdefs.h>, so extra
    steps are needed to override __nonnull. Old glibc with new GCC
    isn't common, so this can be ignored.

GCC < 15:

    Overriding __nonnull in glibc headers is useless. Functions like
    memcpy are builtins and behave as if they had the nonnull attribute
    even when the prototypes in the headers don't have them.

    One doesn't want to use -fno-builtin, and it wouldn't even fully fix
    the issue: in glibc < 2.26, <bits/string2.h> may #define strncat to
    __builtin_strncat.

    Adding -fno-delete-null-pointer-checks to CFLAGS works with both
    GCC and Clang at least in sense that the tests in my patch don't
    fail. With coreutils, the generated code differs in many files, so
    this workaround will affect performance more than overriding
    __nonnull would.

Instead of workarounds, maybe the NULL-as-a-function-argument part of
N3322 could just be documented as "not fixed by Gnulib".
doc/gnulib-readme.texi refers to N3322 about NULL + 0, so an extra note
there would be good to ensure that readers won't accidentally think
that everything from N3322 is assumed.

-- 
Lasse Collin
>From 16068a119fa4ca1918fb1dac59963994f0ec455f Mon Sep 17 00:00:00 2001
From: Lasse Collin <[email protected]>
Date: Tue, 28 Jul 2026 20:56:29 +0300
Subject: [PATCH] tests: Verify N3322 compatibility of the function prototypes

Test that the compiler doesn't optimize a NULL check away when it sees
the prototypes in the headers <string.h>, <wchar.h>, and <stdlib.h>.
(The existing tests explicitly avoided the effects of the attributes
in the function prototypes.)
* tests/test-bsearch.c: Add the test null_bsearch.
* tests/test-memccpy.c: Add the test null_memccpy.
* tests/test-memchr.c: Add the test null_memchr.
* tests/test-memcmp.c: Add the test null_memcmp.
* tests/test-memcpy.c: Add the test null_memcpy.
* tests/test-memmove.c: Add the test null_memmove.
* tests/test-memset.c: Add the test null_memset.
* tests/test-memset_explicit.c: Add the test null_memset_explicit.
* tests/test-qsort.c: Add the test null_qsort.
* tests/test-strncat.c: Add the test null_strncat.
* tests/test-strncmp.c: Add the test null_strncmp.
* tests/test-strncpy.c: Add the test null_strncpy.
* tests/test-strndup.c: Add the test null_strndup.
* tests/test-wcsncat.c: Add the test null_wcsncat.
* tests/test-wcsncmp.c: Add the test null_wcsncmp.
* tests/test-wcsncpy.c: Add the test null_wcsncpy.
* tests/test-wmemchr.c: Add the test null_wmemchr.
* tests/test-wmemcmp.c: Add the test null_wmemcmp.
* tests/test-wmemcpy.c: Add the test null_wmemcpy.
* tests/test-wmemmove.c: Add the test null_wmemmove.
* tests/test-wmemset.c: Add the test null_wmemset.
---
 ChangeLog                    | 29 +++++++++++++++++++++++++++++
 tests/test-bsearch.c         | 14 ++++++++++++++
 tests/test-memccpy.c         | 12 ++++++++++++
 tests/test-memchr.c          | 12 ++++++++++++
 tests/test-memcmp.c          | 12 ++++++++++++
 tests/test-memcpy.c          | 14 ++++++++++++++
 tests/test-memmove.c         | 12 ++++++++++++
 tests/test-memset.c          | 12 ++++++++++++
 tests/test-memset_explicit.c | 12 ++++++++++++
 tests/test-qsort.c           | 14 ++++++++++++++
 tests/test-strncat.c         | 12 ++++++++++++
 tests/test-strncmp.c         | 12 ++++++++++++
 tests/test-strncpy.c         | 12 ++++++++++++
 tests/test-strndup.c         | 12 ++++++++++++
 tests/test-wcsncat.c         | 12 ++++++++++++
 tests/test-wcsncmp.c         | 12 ++++++++++++
 tests/test-wcsncpy.c         | 12 ++++++++++++
 tests/test-wmemchr.c         | 12 ++++++++++++
 tests/test-wmemcmp.c         | 12 ++++++++++++
 tests/test-wmemcpy.c         | 12 ++++++++++++
 tests/test-wmemmove.c        | 12 ++++++++++++
 tests/test-wmemset.c         | 12 ++++++++++++
 22 files changed, 287 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index e392c9b8ac..d73674dd1c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2026-07-28  Lasse Collin  <[email protected]>
+
+	tests: Verify N3322 compatibility of the function prototypes.
+	Test that the compiler doesn't optimize a NULL check away when it sees
+	the prototypes in the headers <string.h>, <wchar.h>, and <stdlib.h>.
+	(The existing tests explicitly avoided the effects of the attributes
+	in the function prototypes.)
+	* tests/test-bsearch.c: Add the test null_bsearch.
+	* tests/test-memccpy.c: Add the test null_memccpy.
+	* tests/test-memchr.c: Add the test null_memchr.
+	* tests/test-memcmp.c: Add the test null_memcmp.
+	* tests/test-memcpy.c: Add the test null_memcpy.
+	* tests/test-memmove.c: Add the test null_memmove.
+	* tests/test-memset.c: Add the test null_memset.
+	* tests/test-memset_explicit.c: Add the test null_memset_explicit.
+	* tests/test-qsort.c: Add the test null_qsort.
+	* tests/test-strncat.c: Add the test null_strncat.
+	* tests/test-strncmp.c: Add the test null_strncmp.
+	* tests/test-strncpy.c: Add the test null_strncpy.
+	* tests/test-strndup.c: Add the test null_strndup.
+	* tests/test-wcsncat.c: Add the test null_wcsncat.
+	* tests/test-wcsncmp.c: Add the test null_wcsncmp.
+	* tests/test-wcsncpy.c: Add the test null_wcsncpy.
+	* tests/test-wmemchr.c: Add the test null_wmemchr.
+	* tests/test-wmemcmp.c: Add the test null_wmemcmp.
+	* tests/test-wmemcpy.c: Add the test null_wmemcpy.
+	* tests/test-wmemmove.c: Add the test null_wmemmove.
+	* tests/test-wmemset.c: Add the test null_wmemset.
+
 2026-07-28  Paul Eggert  <[email protected]>
             Bruno Haible  <[email protected]>
 
diff --git a/tests/test-bsearch.c b/tests/test-bsearch.c
index 6f318256cb..117f4a0d51 100644
--- a/tests/test-bsearch.c
+++ b/tests/test-bsearch.c
@@ -21,6 +21,17 @@
 
 #include "macros.h"
 
+/* Test the prototype in <stdlib.h> + compiler.
+   In glibc >= 2.18, <bits/stdlib-bsearch.h> has an inline version.  */
+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);
+  ASSERT (base == NULL);
+  return (void *) p;
+}
+
 /* Test the library, not the compiler+library.  */
 static void *
 lib_bsearch (void const *key, void const *base, size_t nel, size_t width,
@@ -48,5 +59,8 @@ main (void)
      <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>.  */
   ASSERT (bsearch ("x", NULL, 0, 1, cmp) == NULL);
 
+  volatile_bsearch = null_bsearch;
+  ASSERT (bsearch ("x", NULL, 0, 1, cmp) == NULL);
+
   return test_exit_status;
 }
diff --git a/tests/test-memccpy.c b/tests/test-memccpy.c
index 4232e36fb1..a711ed06d2 100644
--- a/tests/test-memccpy.c
+++ b/tests/test-memccpy.c
@@ -23,6 +23,15 @@
 
 #include "macros.h"
 
+/* 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);
+  ASSERT (dest == NULL);
+  return p;
+}
+
 /* Test the library, not the compiler+library.  */
 static void *
 lib_memccpy (void *dest, void const *src, int c, size_t n)
@@ -47,5 +56,8 @@ main (void)
     ASSERT (memccpy (y, NULL, '?', 0) == NULL);
   }
 
+  volatile_memccpy = null_memccpy;
+  ASSERT (memccpy (NULL, "x", '?', 0) == NULL);
+
   return test_exit_status;
 }
diff --git a/tests/test-memchr.c b/tests/test-memchr.c
index 7d72dbac5b..8867026aeb 100644
--- a/tests/test-memchr.c
+++ b/tests/test-memchr.c
@@ -27,6 +27,15 @@ SIGNATURE_CHECK (memchr, void *, (void const *, int, size_t));
 #include "zerosize-ptr.h"
 #include "macros.h"
 
+/* 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);
+  ASSERT (s == NULL);
+  return (void *) p;
+}
+
 /* Test the library, not the compiler+library.  */
 static void *
 lib_memchr (void const *s, int c, size_t n)
@@ -138,5 +147,8 @@ main (void)
      <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>.  */
   ASSERT (memchr (NULL, '?', 0) == NULL);
 
+  volatile_memchr = null_memchr;
+  ASSERT (memchr (NULL, '?', 0) == NULL);
+
   return test_exit_status;
 }
diff --git a/tests/test-memcmp.c b/tests/test-memcmp.c
index d773652214..5b66bda9a9 100644
--- a/tests/test-memcmp.c
+++ b/tests/test-memcmp.c
@@ -25,6 +25,15 @@ SIGNATURE_CHECK (memcmp, int, (void const *, void const *, size_t));
 #include "zerosize-ptr.h"
 #include "macros.h"
 
+/* 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);
+  ASSERT (s1 == NULL);
+  return r;
+}
+
 /* Test the library, not the compiler+library.  */
 static int
 lib_memcmp (void const *s1, void const *s2, size_t n)
@@ -86,5 +95,8 @@ main (void)
   ASSERT (memcmp ("x", NULL, 0) == 0);
   ASSERT (memcmp (NULL, NULL, 0) == 0);
 
+  volatile_memcmp = null_memcmp;
+  ASSERT (memcmp (NULL, "x", 0) == 0);
+
   return test_exit_status;
 }
diff --git a/tests/test-memcpy.c b/tests/test-memcpy.c
index 180525fca6..3800af7ed5 100644
--- a/tests/test-memcpy.c
+++ b/tests/test-memcpy.c
@@ -23,6 +23,15 @@
 
 #include "macros.h"
 
+/* 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);
+  ASSERT (dest == NULL);
+  return p;
+}
+
 /* Test the library, not the compiler+library.  */
 static void *
 lib_memcpy (void *s1, void const *s2, size_t n)
@@ -47,5 +56,10 @@ main (void)
     ASSERT (memcpy (y, NULL, 0) == y);
   }
 
+  /* Redirect via the volatile function pointer to ensure that that the ASSERT
+     in null_memcpy won't be optimized away by GCC 6.3.0.  */
+  volatile_memcpy = null_memcpy;
+  ASSERT (memcpy (NULL, "x", 0) == NULL);
+
   return test_exit_status;
 }
diff --git a/tests/test-memmove.c b/tests/test-memmove.c
index 438d5aaa83..e2091852a4 100644
--- a/tests/test-memmove.c
+++ b/tests/test-memmove.c
@@ -23,6 +23,15 @@
 
 #include "macros.h"
 
+/* 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);
+  ASSERT (dest == NULL);
+  return p;
+}
+
 /* Test the library, not the compiler+library.  */
 static void *
 lib_memmove (void *s1, void const *s2, size_t n)
@@ -47,5 +56,8 @@ main (void)
     ASSERT (memmove (y, NULL, 0) == y);
   }
 
+  volatile_memmove = null_memmove;
+  ASSERT (memmove (NULL, "x", 0) == NULL);
+
   return test_exit_status;
 }
diff --git a/tests/test-memset.c b/tests/test-memset.c
index be744d0dfd..0adb285d9f 100644
--- a/tests/test-memset.c
+++ b/tests/test-memset.c
@@ -23,6 +23,15 @@
 
 #include "macros.h"
 
+/* Test the prototype in <string.h> + compiler.  */
+static void *
+null_memset (void *s, int c, size_t n)
+{
+  void *p = memset (s, c, n);
+  ASSERT (s == NULL);
+  return p;
+}
+
 /* Test the library, not the compiler+library.  */
 static void *
 lib_memset (void *s, int c, size_t n)
@@ -41,5 +50,8 @@ main (void)
      <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>.  */
   ASSERT (memset (NULL, '?', 0) == NULL);
 
+  volatile_memset = null_memset;
+  ASSERT (memset (NULL, '?', 0) == NULL);
+
   return test_exit_status;
 }
diff --git a/tests/test-memset_explicit.c b/tests/test-memset_explicit.c
index 02cb7e01ef..7331e3c415 100644
--- a/tests/test-memset_explicit.c
+++ b/tests/test-memset_explicit.c
@@ -48,6 +48,15 @@ static char zero[SECRET_SIZE] = { 0 };
 # define memset_explicit memset
 #endif
 
+/* 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);
+  ASSERT (s == NULL);
+  return p;
+}
+
 /* Test the library, not the compiler+library.  */
 static void *
 lib_memset_explicit (void *s, int c, size_t n)
@@ -265,5 +274,8 @@ main ()
      <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>.  */
   ASSERT (memset_explicit (NULL, '?', 0) == NULL);
 
+  volatile_memset_explicit = null_memset_explicit;
+  ASSERT (memset_explicit (NULL, '?', 0) == NULL);
+
   return test_exit_status;
 }
diff --git a/tests/test-qsort.c b/tests/test-qsort.c
index 43c4909f03..772f6b138b 100644
--- a/tests/test-qsort.c
+++ b/tests/test-qsort.c
@@ -19,6 +19,17 @@
 /* Specification.  */
 #include <stdlib.h>
 
+#include "macros.h"
+
+/* 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);
+  ASSERT (base == NULL);
+}
+
 /* Test the library, not the compiler+library.  */
 static void
 lib_qsort (void *base, size_t nel, size_t width,
@@ -46,5 +57,8 @@ main (void)
 
   qsort (NULL, 0, 1, cmp);
 
+  volatile_qsort = null_qsort;
+  qsort (NULL, 0, 1, cmp);
+
   return 0;
 }
diff --git a/tests/test-strncat.c b/tests/test-strncat.c
index 1817bb9d10..935523a7ec 100644
--- a/tests/test-strncat.c
+++ b/tests/test-strncat.c
@@ -29,6 +29,15 @@ SIGNATURE_CHECK (strncat, char *, (char *, const char *, size_t));
 #include "zerosize-ptr.h"
 #include "macros.h"
 
+/* 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);
+  ASSERT (s2 == NULL);
+  return p;
+}
+
 /* Test the library, not the compiler+library.  */
 static char *
 lib_strncat (char *s1, char const *s2, size_t n)
@@ -80,6 +89,9 @@ main ()
   {
     char y[2] = { 'x', '\0' };
     ASSERT (strncat (y, NULL, 0) == y);
+
+    volatile_strncat = null_strncat;
+    ASSERT (strncat (y, NULL, 0) == y);
   }
 
   return test_exit_status;
diff --git a/tests/test-strncmp.c b/tests/test-strncmp.c
index 6d49af9056..031b3071fb 100644
--- a/tests/test-strncmp.c
+++ b/tests/test-strncmp.c
@@ -23,6 +23,15 @@
 
 #include "macros.h"
 
+/* 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);
+  ASSERT (s1 == NULL);
+  return r;
+}
+
 /* Test the library, not the compiler+library.  */
 static int
 lib_strncmp (char const *s1, char const *s2, size_t n)
@@ -43,5 +52,8 @@ main (void)
   ASSERT (strncmp ("x", NULL, 0) == 0);
   ASSERT (strncmp (NULL, NULL, 0) == 0);
 
+  volatile_strncmp = null_strncmp;
+  ASSERT (strncmp (NULL, "x", 0) == 0);
+
   return test_exit_status;
 }
diff --git a/tests/test-strncpy.c b/tests/test-strncpy.c
index 83535a4bee..a191656f22 100644
--- a/tests/test-strncpy.c
+++ b/tests/test-strncpy.c
@@ -25,6 +25,15 @@
 #include "zerosize-ptr.h"
 #include "macros.h"
 
+/* 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);
+  ASSERT (s2 == NULL);
+  return p;
+}
+
 /* Test the library, not the compiler+library.  */
 static char *
 lib_strncpy (char *s1, char const *s2, size_t n)
@@ -116,6 +125,9 @@ main (void)
   {
     char y[1];
     ASSERT (strncpy (y, NULL, 0) == y);
+
+    volatile_strncpy = null_strncpy;
+    ASSERT (strncpy (y, NULL, 0) == y);
   }
 
   return test_exit_status;
diff --git a/tests/test-strndup.c b/tests/test-strndup.c
index 10ad604f24..8d9db08cf4 100644
--- a/tests/test-strndup.c
+++ b/tests/test-strndup.c
@@ -23,6 +23,15 @@
 
 #include "macros.h"
 
+/* Test the prototype in <string.h> + compiler.  */
+static char *
+null_strndup (char const *s, size_t size)
+{
+  char *p = strndup (s, size);
+  ASSERT (s == NULL);
+  return p;
+}
+
 /* Test the library, not the compiler+library.  */
 static char *
 lib_strndup (char const *s, size_t size)
@@ -41,5 +50,8 @@ main (void)
      <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>.  */
   ASSERT (strndup (NULL, 0) != NULL);
 
+  volatile_strndup = null_strndup;
+  ASSERT (strndup (NULL, 0) != NULL);
+
   return test_exit_status;
 }
diff --git a/tests/test-wcsncat.c b/tests/test-wcsncat.c
index 3aaa68a24f..af9c2cb757 100644
--- a/tests/test-wcsncat.c
+++ b/tests/test-wcsncat.c
@@ -25,6 +25,15 @@
 
 #include "macros.h"
 
+/* 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);
+  ASSERT (ws2 == NULL);
+  return p;
+}
+
 /* Test the library, not the compiler+library.  */
 static wchar_t *
 lib_wcsncat (wchar_t *ws1, wchar_t const *ws2, size_t n)
@@ -50,6 +59,9 @@ main ()
   {
     wchar_t y[2] = { L'x', 0 };
     ASSERT (wcsncat (y, NULL, 0) == y);
+
+    volatile_wcsncat = null_wcsncat;
+    ASSERT (wcsncat (y, NULL, 0) == y);
   }
 
   return test_exit_status;
diff --git a/tests/test-wcsncmp.c b/tests/test-wcsncmp.c
index c43ce8273c..32e354f3ef 100644
--- a/tests/test-wcsncmp.c
+++ b/tests/test-wcsncmp.c
@@ -25,6 +25,15 @@ SIGNATURE_CHECK (wcsncmp, int, (const wchar_t *, const wchar_t *, size_t));
 
 #include "macros.h"
 
+/* 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);
+  ASSERT (ws1 == NULL);
+  return r;
+}
+
 /* Test the library, not the compiler+library.  */
 static int
 lib_wcsncmp (wchar_t const *ws1, wchar_t const *ws2, size_t n)
@@ -196,5 +205,8 @@ main (int argc, char *argv[])
   ASSERT (wcsncmp (L"x", NULL, 0) == 0);
   ASSERT (wcsncmp (NULL, NULL, 0) == 0);
 
+  volatile_wcsncmp = null_wcsncmp;
+  ASSERT (wcsncmp (NULL, L"x", 0) == 0);
+
   return test_exit_status;
 }
diff --git a/tests/test-wcsncpy.c b/tests/test-wcsncpy.c
index 321fabd6ef..7d548fbb68 100644
--- a/tests/test-wcsncpy.c
+++ b/tests/test-wcsncpy.c
@@ -23,6 +23,15 @@
 
 #include "macros.h"
 
+/* 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);
+  ASSERT (ws2 == NULL);
+  return p;
+}
+
 /* Test the library, not the compiler+library.  */
 static wchar_t *
 lib_wcsncpy (wchar_t *ws1, wchar_t const *ws2, size_t n)
@@ -46,6 +55,9 @@ main (void)
   {
     wchar_t y[1];
     ASSERT (wcsncpy (y, NULL, 0) == y);
+
+    volatile_wcsncpy = null_wcsncpy;
+    ASSERT (wcsncpy (y, NULL, 0) == y);
   }
 
   return test_exit_status;
diff --git a/tests/test-wmemchr.c b/tests/test-wmemchr.c
index 877f519aa8..04858ba93e 100644
--- a/tests/test-wmemchr.c
+++ b/tests/test-wmemchr.c
@@ -23,6 +23,15 @@
 
 #include "macros.h"
 
+/* Test the prototype in <wchar.h> + compiler.  */
+static wchar_t *
+null_wmemchr (wchar_t const *s, wchar_t wc, size_t n)
+{
+  wchar_t const *p = wmemchr (s, wc, n);
+  ASSERT (s == NULL);
+  return (wchar_t *) p;
+}
+
 /* Test the library, not the compiler+library.  */
 static wchar_t *
 lib_wmemchr (wchar_t const *s, wchar_t wc, size_t n)
@@ -41,5 +50,8 @@ main (void)
      <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>.  */
   ASSERT (wmemchr (NULL, L'?', 0) == NULL);
 
+  volatile_wmemchr = null_wmemchr;
+  ASSERT (wmemchr (NULL, L'?', 0) == NULL);
+
   return test_exit_status;
 }
diff --git a/tests/test-wmemcmp.c b/tests/test-wmemcmp.c
index 6b7564659d..8d68196074 100644
--- a/tests/test-wmemcmp.c
+++ b/tests/test-wmemcmp.c
@@ -25,6 +25,15 @@ SIGNATURE_CHECK (wmemcmp, int, (const wchar_t *, const wchar_t *, size_t));
 
 #include "macros.h"
 
+/* Test the prototype in <wchar.h> + compiler.  */
+static int
+null_wmemcmp (wchar_t const *ws1, wchar_t const *ws2, size_t n)
+{
+  int r = wmemcmp (ws1, ws2, n);
+  ASSERT (ws1 == NULL);
+  return r;
+}
+
 /* Test the library, not the compiler+library.  */
 static int
 lib_wmemcmp (wchar_t const *ws1, wchar_t const *ws2, size_t n)
@@ -108,5 +117,8 @@ main (int argc, char *argv[])
   ASSERT (wmemcmp (L"x", NULL, 0) == 0);
   ASSERT (wmemcmp (NULL, NULL, 0) == 0);
 
+  volatile_wmemcmp = null_wmemcmp;
+  ASSERT (wmemcmp (NULL, L"x", 0) == 0);
+
   return test_exit_status;
 }
diff --git a/tests/test-wmemcpy.c b/tests/test-wmemcpy.c
index f5bb779ce8..296a0cae1e 100644
--- a/tests/test-wmemcpy.c
+++ b/tests/test-wmemcpy.c
@@ -23,6 +23,15 @@
 
 #include "macros.h"
 
+/* 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);
+  ASSERT (s1 == NULL);
+  return p;
+}
+
 /* Test the library, not the compiler+library.  */
 static wchar_t *
 lib_wmemcpy (wchar_t *s1, wchar_t const *s2, size_t n)
@@ -48,5 +57,8 @@ main (void)
     ASSERT (wmemcpy (y, NULL, 0) == y);
   }
 
+  volatile_wmemcpy = null_wmemcpy;
+  ASSERT (wmemcpy (NULL, L"x", 0) == NULL);
+
   return test_exit_status;
 }
diff --git a/tests/test-wmemmove.c b/tests/test-wmemmove.c
index 4e0401c37f..3737d62d98 100644
--- a/tests/test-wmemmove.c
+++ b/tests/test-wmemmove.c
@@ -23,6 +23,15 @@
 
 #include "macros.h"
 
+/* 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);
+  ASSERT (s1 == NULL);
+  return p;
+}
+
 /* Test the library, not the compiler+library.  */
 static wchar_t *
 lib_wmemmove (wchar_t *s1, wchar_t const *s2, size_t n)
@@ -48,5 +57,8 @@ main (void)
     ASSERT (wmemmove (y, NULL, 0) == y);
   }
 
+  volatile_wmemmove = null_wmemmove;
+  ASSERT (wmemmove (NULL, L"x", 0) == NULL);
+
   return test_exit_status;
 }
diff --git a/tests/test-wmemset.c b/tests/test-wmemset.c
index a7fb360932..9d45f4c5a6 100644
--- a/tests/test-wmemset.c
+++ b/tests/test-wmemset.c
@@ -23,6 +23,15 @@
 
 #include "macros.h"
 
+/* Test the prototype in <wchar.h> + compiler.  */
+static wchar_t *
+null_wmemset (wchar_t *ws, wchar_t wc, size_t n)
+{
+  wchar_t *p = wmemset (ws, wc, n);
+  ASSERT (ws == NULL);
+  return p;
+}
+
 /* Test the library, not the compiler+library.  */
 static wchar_t *
 lib_wmemset (wchar_t *ws, wchar_t wc, size_t n)
@@ -41,5 +50,8 @@ main (void)
      <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>.  */
   ASSERT (wmemset (NULL, L'?', 0) == NULL);
 
+  volatile_wmemset = null_wmemset;
+  ASSERT (wmemset (NULL, L'?', 0) == NULL);
+
   return test_exit_status;
 }
-- 
2.55.0

Reply via email to