autoconf-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/2 COMMITTED] Fix regressions when using the C++ compiler to per


From: Zack Weinberg
Subject: [PATCH 1/2 COMMITTED] Fix regressions when using the C++ compiler to perform tests.
Date: Sat, 10 Oct 2020 14:00:07 -0400

The Debian project has done an archive rebuild using autoconf 2.69c,
which found several serious regressions from 2.69 where test programs
used to be accepted by a C++ compiler, but are now rejected.  Part of
the problem is that newer C++ compilers are more likely to reject
“traditional” sloppy C, but part of it is that bug fixes since 2.69
did not consider the possibility of test macros being used with
AC_LANG([C++]) in effect.

I’m still working on test suite improvements that will catch these
regressions in the future, but I don’t see any reason to delay the
actual bugfixes.  (I’ve gotten far enough on the test suite changes
that I know they _will_ catch the bugs.)

* NEWS: Document that AC_FUNC_STRERROR_R no longer tries to detect a
  strerror_r that exists in the C library but isn’t declared by string.h.

* lib/autoconf/c.m4
  (AC_LANG_CALL(C++)): New macro.  Use a more robust technique for
  avoiding a type conflict with any intrinsic prototype.
  (AC_LANG_CALL(C)): Remove #ifdef __cplusplus, this macro is no longer
  used to generate C++ code.

* lib/autoconf/functions.m4
  (AC_FUNC_CLOSEDIR_VOID): Rely on <dirent.h> to declare closedir.
  Simplify test program.  Use AC_COMPILE_IFELSE, not AC_RUN_IFELSE.
  (_AC_FUNC_MALLOC_IF, _AC_FUNC_REALLOC_IF): Use void *, not char *,
  for variable holding a value returned by malloc/realloc respectively.
  (AC_FUNC_STRERROR_R): Don’t AC_CHECK_FUNCS_ONCE strerror_r.
  AC_DEFINE HAVE_STRERROR_R if and only if we are also going to define
  HAVE_DECL_STRERROR_R.  Remove AC_RUN_IFELSE fallback when strerror_r
  is not declared.

* lib/autoconf/headers.m4 (AC_USG): Use "", not 0, for the first
  argument to rindex.
---
 NEWS                      | 10 ++++++
 lib/autoconf/c.m4         | 18 ++++++++--
 lib/autoconf/functions.m4 | 71 +++++++++++++++++----------------------
 lib/autoconf/headers.m4   |  2 +-
 4 files changed, 56 insertions(+), 45 deletions(-)

diff --git a/NEWS b/NEWS
index 55e938b3..be82eab9 100644
--- a/NEWS
+++ b/NEWS
@@ -124,6 +124,16 @@ GNU Autoconf NEWS - User visible changes.
   support for Solaris 2.4.  Most programs will want to avoid ‘vfork’
   on this OS because of this bug.
 
+*** AC_FUNC_STRERROR_R assumes strerror_r is unavailable if it’s not declared.
+
+  The fallback technique it used to probe strerror_r’s return type
+  when the function was present in the C library, but not declared by
+  <string.h>, was fragile and did not work at all when cross-compiling.
+  The systems where this fallback was necessary were all obsolete.
+
+  Programs that use AC_FUNC_STRERROR_R should make sure to test the
+  preprocessor macro HAVE_DECL_STRERROR_R before using strerror_r at all.
+
 ** New features
 
 *** Configure scripts now support a ‘--runstatedir’ option.
diff --git a/lib/autoconf/c.m4 b/lib/autoconf/c.m4
index be5e4148..de40b8ca 100644
--- a/lib/autoconf/c.m4
+++ b/lib/autoconf/c.m4
@@ -127,9 +127,6 @@ m4_if([$2], [main], ,
 [/* Override any GCC internal prototype to avoid an error.
    Use char because int might match the return type of a GCC
    builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
 char $2 ();])], [return $2 ();])])
 
 
@@ -240,6 +237,21 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
 ])
 
 
+# AC_LANG_CALL(C++)(PROLOGUE, FUNCTION)
+# -------------------------------------
+m4_define([AC_LANG_CALL(C++)],
+[AC_LANG_PROGRAM([[$1
+// We do not know the function signature of the real $2.
+// Declare it in a namespace so the compiler doesn't recognize it
+// (with, most likely, a clashing prototype); the 'extern "C"' will
+// hide the namespace from the linker, so it will still look for the
+// real (global) $2.
+namespace conftest {
+  extern "C" void $2 ();
+}]],
+[[conftest::$2 (); return 0;]])])
+
+
 # AC_LANG_CPLUSPLUS
 # -----------------
 AU_DEFUN([AC_LANG_CPLUSPLUS], [AC_LANG(C++)])
diff --git a/lib/autoconf/functions.m4 b/lib/autoconf/functions.m4
index aa560a63..4598b408 100644
--- a/lib/autoconf/functions.m4
+++ b/lib/autoconf/functions.m4
@@ -509,25 +509,23 @@ fi
 # AC_FUNC_CLOSEDIR_VOID
 # ---------------------
 # Check whether closedir returns void, and #define CLOSEDIR_VOID in
-# that case.
+# that case.  Note: the test program *fails* to compile when closedir
+# returns void.
 AC_DEFUN([AC_FUNC_CLOSEDIR_VOID],
 [AC_REQUIRE([AC_HEADER_DIRENT])dnl
 AC_CACHE_CHECK([whether closedir returns void],
               [ac_cv_func_closedir_void],
-[AC_RUN_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
 #include <$ac_header_dirent>
-#ifndef __cplusplus
-int closedir ();
-#endif
-],
-                               [[return closedir (opendir (".")) != 0;]])],
+]], [[
+  return closedir(0);
+]])],
               [ac_cv_func_closedir_void=no],
-              [ac_cv_func_closedir_void=yes],
               [ac_cv_func_closedir_void=yes])])
 if test $ac_cv_func_closedir_void = yes; then
   AC_DEFINE(CLOSEDIR_VOID, 1,
            [Define to 1 if the `closedir' function returns void instead
-            of `int'.])
+            of int.])
 fi
 ])
 
@@ -952,13 +950,12 @@ AC_DEFUN([_AC_FUNC_MALLOC_IF],
 [AC_REQUIRE([AC_CANONICAL_HOST])dnl for cross-compiles
 AC_CACHE_CHECK([for GNU libc compatible malloc], ac_cv_func_malloc_0_nonnull,
 [AC_RUN_IFELSE(
-[AC_LANG_PROGRAM(
-[[#include <stdlib.h>
-]],
-                [char *p = malloc (0);
-                 int result = !p;
-                 free (p);
-                 return result;])],
+[AC_LANG_PROGRAM([[#include <stdlib.h>
+                 ]],
+                [[void *p = malloc (0);
+                  int result = !p;
+                  free (p);
+                  return result;]])],
               [ac_cv_func_malloc_0_nonnull=yes],
               [ac_cv_func_malloc_0_nonnull=no],
               [case "$host_os" in # ((
@@ -1459,13 +1456,12 @@ AC_DEFUN([_AC_FUNC_REALLOC_IF],
 [AC_REQUIRE([AC_CANONICAL_HOST])dnl for cross-compiles
 AC_CACHE_CHECK([for GNU libc compatible realloc], ac_cv_func_realloc_0_nonnull,
 [AC_RUN_IFELSE(
-[AC_LANG_PROGRAM(
-[[#include <stdlib.h>
-]],
-                [char *p = realloc (0, 0);
-                 int result = !p;
-                 free (p);
-                 return result;])],
+[AC_LANG_PROGRAM([[#include <stdlib.h>
+                 ]],
+                [[void *p = realloc (0, 0);
+                  int result = !p;
+                  free (p);
+                  return result;]])],
               [ac_cv_func_realloc_0_nonnull=yes],
               [ac_cv_func_realloc_0_nonnull=no],
               [case "$host_os" in # ((
@@ -1692,33 +1688,26 @@ AU_ALIAS([AM_FUNC_STRTOD], [AC_FUNC_STRTOD])
 AN_FUNCTION([strerror_r], [AC_FUNC_STRERROR_R])
 AC_DEFUN([AC_FUNC_STRERROR_R],
 [AC_CHECK_DECLS_ONCE([strerror_r])
-AC_CHECK_FUNCS_ONCE([strerror_r])
+if test $ac_cv_have_decl_strerror_r = yes; then
+  # For backward compatibility's sake, define HAVE_STRERROR_R.
+  # (We used to run AC_CHECK_FUNCS_ONCE for strerror_r, as well
+  # as AC_CHECK_DECLS_ONCE.)
+  AC_DEFINE([HAVE_STRERROR_R], [1], [Define if you have `strerror_r'.])
+fi
+
 AC_CACHE_CHECK([whether strerror_r returns char *],
-              ac_cv_func_strerror_r_char_p,
-   [
+              [ac_cv_func_strerror_r_char_p], [
     ac_cv_func_strerror_r_char_p=no
     if test $ac_cv_have_decl_strerror_r = yes; then
-      AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],
+      AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
        [[
          char buf[100];
          char x = *strerror_r (0, buf, sizeof buf);
          char *p = strerror_r (0, buf, sizeof buf);
          return !p || x;
        ]])],
-                       ac_cv_func_strerror_r_char_p=yes)
-    else
-      # strerror_r is not declared.  Choose between
-      # systems that have relatively inaccessible declarations for the
-      # function.  BeOS and DEC UNIX 4.0 fall in this category, but the
-      # former has a strerror_r that returns char*, while the latter
-      # has a strerror_r that returns `int'.
-      # This test should segfault on the DEC system.
-      AC_RUN_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT
-       extern char *strerror_r ();],
-       [[char buf[100];
-         char x = *strerror_r (0, buf, sizeof buf);
-         return ! isalpha (x);]])],
-                   ac_cv_func_strerror_r_char_p=yes, , :)
+                       [ac_cv_func_strerror_r_char_p=yes])
+
     fi
   ])
 if test $ac_cv_func_strerror_r_char_p = yes; then
diff --git a/lib/autoconf/headers.m4 b/lib/autoconf/headers.m4
index 21b37197..3b97a185 100644
--- a/lib/autoconf/headers.m4
+++ b/lib/autoconf/headers.m4
@@ -776,7 +776,7 @@ AU_DEFUN([AC_USG],
 [# Obsolete code to be removed.
 AC_MSG_CHECKING([for BSD string and memory functions])
 AC_LINK_IFELSE([AC_LANG_PROGRAM([[@%:@include <strings.h>]],
-                               [[rindex(0, 0); bzero(0, 0);]])],
+                               [[rindex("", 0); bzero(0, 0);]])],
               [AC_MSG_RESULT(yes)],
               [AC_MSG_RESULT(no)
                AC_DEFINE(USG, 1,
-- 
2.28.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]