+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
# 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
# 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
-/* 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>
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. */
/* 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"
== 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);
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>
}
}
+ /* 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