tests: Avoid GCC over-optimization caused by _GL_ARG_NONNULL attributes.
authorBruno Haible <bruno@clisp.org>
Sun, 5 Jan 2020 08:13:25 +0000 (09:13 +0100)
committerBruno Haible <bruno@clisp.org>
Sun, 5 Jan 2020 18:20:45 +0000 (19:20 +0100)
Reported by Jim Meyering in
<https://lists.gnu.org/archive/html/bug-gnulib/2020-01/msg00040.html>.

* lib/stdlib.in.h (GNULIB_defined_canonicalize_file_name): New macro.
(GNULIB_defined_ptsname_r): New macro.
* tests/test-canonicalize.c (_GL_ARG_NONNULL): Define to empty.
(main): Disable the NULL argument test if canonicalize_file_name does
not come from gnulib.
* tests/test-canonicalize-lgpl.c (_GL_ARG_NONNULL): Define to empty.
(main): Disable the NULL argument test if canonicalize_file_name does
not come from gnulib.
* tests/test-ptsname_r.c (_GL_ARG_NONNULL): Define to empty.
(test_errors): Disable the NULL argument test if ptsname_r does not come
from gnulib.

ChangeLog
lib/stdlib.in.h
tests/test-canonicalize-lgpl.c
tests/test-canonicalize.c
tests/test-ptsname_r.c

index a69db8585d10c5b577196c118b440b2f85cb2117..c8a9dbfac87685df4e5024cc2a9e2d55ac37d295 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2020-01-05  Bruno Haible  <bruno@clisp.org>
+
+       tests: Avoid GCC over-optimization caused by _GL_ARG_NONNULL attributes.
+       Reported by Jim Meyering in
+       <https://lists.gnu.org/archive/html/bug-gnulib/2020-01/msg00040.html>.
+       * lib/stdlib.in.h (GNULIB_defined_canonicalize_file_name): New macro.
+       (GNULIB_defined_ptsname_r): New macro.
+       * tests/test-canonicalize.c (_GL_ARG_NONNULL): Define to empty.
+       (main): Disable the NULL argument test if canonicalize_file_name does
+       not come from gnulib.
+       * tests/test-canonicalize-lgpl.c (_GL_ARG_NONNULL): Define to empty.
+       (main): Disable the NULL argument test if canonicalize_file_name does
+       not come from gnulib.
+       * tests/test-ptsname_r.c (_GL_ARG_NONNULL): Define to empty.
+       (test_errors): Disable the NULL argument test if ptsname_r does not come
+       from gnulib.
+
 2020-01-04  Jim Meyering  <meyering@fb.com>
 
        update-copyright: reenable its always-skipped test
index e088959b285b724b74ff228835247e1b76865b64..e96e9d9e2535e4d5b3dccbbf480c27c82aef5d7d 100644 (file)
@@ -201,6 +201,10 @@ _GL_FUNCDECL_SYS (canonicalize_file_name, char *, (const char *name)
 #  endif
 _GL_CXXALIAS_SYS (canonicalize_file_name, char *, (const char *name));
 # endif
+# ifndef GNULIB_defined_canonicalize_file_name
+#  define GNULIB_defined_canonicalize_file_name \
+     !@HAVE_CANONICALIZE_FILE_NAME@ || @REPLACE_CANONICALIZE_FILE_NAME@
+# endif
 _GL_CXXALIASWARN (canonicalize_file_name);
 #elif defined GNULIB_POSIXCHECK
 # undef canonicalize_file_name
@@ -516,6 +520,9 @@ _GL_FUNCDECL_SYS (ptsname_r, int, (int fd, char *buf, size_t len));
 #  endif
 _GL_CXXALIAS_SYS (ptsname_r, int, (int fd, char *buf, size_t len));
 # endif
+# ifndef GNULIB_defined_ptsname_r
+#  define GNULIB_defined_ptsname_r !@HAVE_PTSNAME_R@ || @REPLACE_PTSNAME_R@
+# endif
 _GL_CXXALIASWARN (ptsname_r);
 #elif defined GNULIB_POSIXCHECK
 # undef ptsname_r
index b46ad872e1625e14371cf89e84fa37956792fd8e..fb49b2047e86ee0ea02c721c5496d825d920cea2 100644 (file)
@@ -1,4 +1,4 @@
-/* Test of execution of program termination handlers.
+/* Test of execution of file name canonicalization.
    Copyright (C) 2007-2020 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
 
 /* Written by Bruno Haible <bruno@clisp.org>, 2007.  */
 
+/* Don't use __attribute__ __nonnull__ in this compilation unit.  Otherwise gcc
+   may "optimize" the null_ptr function, when its result gets passed to a
+   function that has an argument declared as _GL_ARG_NONNULL.  */
+#define _GL_ARG_NONNULL(params)
+
 #include <config.h>
 
 #include <stdlib.h>
@@ -66,14 +71,22 @@ main (void)
     ASSERT (strstr (result, "/" BASE "/tra")
             == result + strlen (result) - strlen ("/" BASE "/tra"));
     free (result);
+
     errno = 0;
     result = canonicalize_file_name ("");
     ASSERT (result == NULL);
     ASSERT (errno == ENOENT);
+
+    /* This test works only if the canonicalize_file_name implementation
+       comes from gnulib.  If it comes from libc, we have no way to prevent
+       gcc from "optimizing" the null_ptr function in invalid ways.  See
+       <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93156>.  */
+#if GNULIB_defined_canonicalize_file_name
     errno = 0;
     result = canonicalize_file_name (null_ptr ());
     ASSERT (result == NULL);
     ASSERT (errno == EINVAL);
+#endif
   }
 
   /* Check that a non-directory with trailing slash yields NULL.  */
index e7138a655d4a1b1cb81e6fd19b68829b89e3fc2f..81580c53d5e74229e1750c1584aade8645dda015 100644 (file)
 
 /* Written by Bruno Haible <bruno@clisp.org>, 2007.  */
 
+/* Don't use __attribute__ __nonnull__ in this compilation unit.  Otherwise gcc
+   may "optimize" the null_ptr function, when its result gets passed to a
+   function that has an argument declared as _GL_ARG_NONNULL.  */
+#define _GL_ARG_NONNULL(params)
+
 #include <config.h>
 
 #include "canonicalize.h"
@@ -62,22 +67,34 @@ main (void)
             == result1 + strlen (result1) - strlen ("/" BASE "/tra"));
     free (result1);
     free (result2);
+
     errno = 0;
     result1 = canonicalize_file_name ("");
     ASSERT (result1 == NULL);
     ASSERT (errno == ENOENT);
+
     errno = 0;
     result2 = canonicalize_filename_mode ("", CAN_EXISTING);
     ASSERT (result2 == NULL);
     ASSERT (errno == ENOENT);
+
+    /* This test works only if the canonicalize_file_name implementation
+       comes from gnulib.  If it comes from libc, we have no way to prevent
+       gcc from "optimizing" the null_ptr function in invalid ways.  See
+       <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93156>.  */
+#if GNULIB_defined_canonicalize_file_name
     errno = 0;
     result1 = canonicalize_file_name (null_ptr ());
     ASSERT (result1 == NULL);
     ASSERT (errno == EINVAL);
+#endif
+
     errno = 0;
     result2 = canonicalize_filename_mode (NULL, CAN_EXISTING);
     ASSERT (result2 == NULL);
     ASSERT (errno == EINVAL);
+
+    errno = 0;
     result2 = canonicalize_filename_mode (".", CAN_MISSING | CAN_ALL_BUT_LAST);
     ASSERT (result2 == NULL);
     ASSERT (errno == EINVAL);
index 19e33ea858e2503e61f405782b5dd91bfd57a570..24be52f31a3cd43e18ef81cdde15b90cd6599993 100644 (file)
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
 
+/* Don't use __attribute__ __nonnull__ in this compilation unit.  Otherwise gcc
+   may "optimize" the null_ptr function, when its result gets passed to a
+   function that has an argument declared as _GL_ARG_NONNULL.  */
+#define _GL_ARG_NONNULL(params)
+
 #include <config.h>
 
 #include <stdlib.h>
@@ -84,9 +89,15 @@ test_errors (int fd, const char *slave)
         }
     }
 
+  /* This test works only if the ptsname_r implementation comes from gnulib.
+     If it comes from libc, we have no way to prevent gcc from "optimizing"
+     the null_ptr function in invalid ways.  See
+     <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93156>.  */
+#if GNULIB_defined_ptsname_r
   result = ptsname_r (fd, null_ptr (), 0);
   ASSERT (result != 0);
   ASSERT (result == EINVAL);
+#endif
 }
 
 int