]> git.ipfire.org Git - thirdparty/autoconf.git/commitdiff
AC_INCLUDES_DEFAULT: Check for presence of C90 hosted headers (#110393)
authorZack Weinberg <zackw@panix.com>
Sun, 6 Dec 2020 16:40:39 +0000 (11:40 -0500)
committerZack Weinberg <zackw@panix.com>
Sun, 6 Dec 2020 16:40:39 +0000 (11:40 -0500)
Since 1993, Autoconf has been assuming that it is safe to include any
of the headers defined by ISO C90 without checking for them; this is
inaccurate, since only a subset are necessarily available in a
C90 *freestanding* environment.

It is OK to assume the presence of a header in a macro that checks
specifically for something declared by that header (if the header is
not present, we will think the specific declaration is unavailable,
which is probably accurate for modern embedded environments).  It is
also OK to continue recommending that user code use these headers
unconditionally—anyone working with a freestanding environment knows
it.  But it is not OK for very generic code within Autoconf itself,
such as AC_INCLUDES_DEFAULT, to make this assumption.

Note that the set of headers that are not always available includes
stdio.h, which we have been assuming can be included unconditionally
for even longer.

In AC_INCLUDES_DEFAULT, revert to checking for string.h and stdlib.h
before including them.  Also revert to defining STDC_HEADERS only when
string.h and stdlib.h are available (but do not check for float.h and
stdarg.h, as these are part of the freestanding set).  Add a new check
for stdio.h.  Sort the inclusion list by standard (C90 freestanding;
C90 hosted; C99; POSIX) and alphabetically within each group.  Revise
all the documentation and update the testsuite.

This partially reverts commit 86c213d0e355296f026a36e3203c0813041aae89
and is a partial fix for bug #110393.

* lib/autoconf/headers.m4 (AC_CHECK_INCLUDES_DEFAULT): Check for
  stdio.h, stdlib.h, and string.h before including them.  Define
  STDC_HEADERS only when string.h and stdlib.h are both available.
  Organize includes list by standard, then alphabetically.

* doc/autoconf.texi, NEWS: Update to match.

* tests/local.at (AT_CHECK_DEFINES): Make regexes more specific.
  Also expect a definition of HAVE_STDIO_H.
* tests/c.at, tests/semantics.at, tests/tools.at: Use <float.h>,
  not <stdio.h>, as a header that we expect always to exist.
  Add HAVE_STDIO_H to various lists of macros that are expected to
  appear in config.h.

NEWS
doc/autoconf.texi
lib/autoconf/headers.m4
tests/c.at
tests/local.at
tests/semantics.at
tests/tools.at

diff --git a/NEWS b/NEWS
index dbbea22271d5e40ce926b90a28a2acb725ff571c..a255536cc6faeea14335d0f47785a4a37845dff4 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -136,19 +136,25 @@ GNU Autoconf NEWS - User visible changes.
 
 *** AC_INCLUDES_DEFAULT assumes an ISO C90 compliant C implementation.
 
-  Specifically, it assumes that the ISO C90 headers <stdlib.h> and
-  <string.h> are available, without checking for them, and does not
-  include the pre-standard header <memory.h> at all.  If the POSIX
-  header <strings.h> exists, it will be included, without testing
-  whether it is safe to include both <string.h> and <strings.h> in the
+  Specifically, it assumes that the ISO C90 header <stddef.h>
+  is available, without checking for it, and it does not include
+  the pre-standard header <memory.h> at all.  If the POSIX header
+  <strings.h> exists, it will be included, without first testing
+  whether both <string.h> and <strings.h> can be included in the
   same source file.
 
-  For compatibility’s sake, the C preprocessor macros STDC_HEADERS,
-  HAVE_STDLIB_H, and HAVE_STRING_H are defined unconditionally.
-  These preprocessor macros should be considered obsolescent.
-  However, cache variables like ac_cv_header_stdlib_h are not set;
-  this is intentional, so that AC_CHECK_HEADER([stdlib.h]) will still
-  do a test for the presence of stdlib.h, in case you genuinely need that.
+  AC_INCLUDES_DEFAULT still checks for the existence of <stdlib.h>,
+  <string.h>, and <stdio.h>, because these headers may not exist
+  in a “freestanding environment” (a compilation mode intended for OS
+  kernels and similar, where most of the features of the C library are
+  optional).  Most programs need not use ‘#ifdef HAVE_STDLIB_H’ etc in
+  their own code.
+
+  For compatibility’s sake, the C preprocessor macro STDC_HEADERS
+  will be defined when both <stdlib.h> and <string.h> are available;
+  however, <stdarg.h> and <float.h> are no longer checked for
+  (these, like <stddef.h>, are required to exist in a freestanding
+  environment).  New code should not refer to this macro.
 
   Future releases of Autoconf may reduce the set of headers checked
   for by AC_INCLUDES_DEFAULT.
index 01af2b296d1b1e0f0566766c7e398dfb7ee4e1fd..cdd056c5b70cb966e25fdf67a581e5815570e096 100644 (file)
@@ -4070,17 +4070,14 @@ Expand to @var{include-directives} if present and nonempty, otherwise to:
 @example
 @group
 #include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
+#ifdef HAVE_STDIO_H
+# include <stdio.h>
 #endif
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
 #endif
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
+#ifdef HAVE_STRING_H
+# include <string.h>
 #endif
 #ifdef HAVE_INTTYPES_H
 # include <inttypes.h>
@@ -4088,6 +4085,15 @@ Expand to @var{include-directives} if present and nonempty, otherwise to:
 #ifdef HAVE_STDINT_H
 # include <stdint.h>
 #endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif
@@ -4095,12 +4101,26 @@ Expand to @var{include-directives} if present and nonempty, otherwise to:
 @end example
 
 Using this macro without @var{include-directives} has the side effect of
-checking for @file{sys/types.h}, @file{sys/stat.h}, @file{strings.h},
-@file{inttypes.h}, @file{stdint.h}, and @file{unistd.h}, as if by
-@code{AC_CHECK_HEADERS}.  For backward compatibility's sake, it also
-unconditionally defines @code{HAVE_STRING_H}, @code{HAVE_STDLIB_H}, and
-@code{STDC_HEADERS}.  New code should not make use of these preprocessor
-macros.
+checking for @file{stdio.h}, @file{stdlib.h}, @file{string.h},
+@file{inttypes.h}, @file{stdint.h}, @file{strings.h},
+@file{sys/types.h}, @file{sys/stat.h}, and @file{unistd.h}, as if by
+@code{AC_CHECK_HEADERS_ONCE}.  For backward compatibility, the macro
+@code{STDC_HEADERS} will be defined when both @file{stdlib.h} and
+@file{string.h} are available.
+
+@strong{Portability Note:} It is safe for most programs to assume the
+presence of all of the headers required by the original 1990 C standard.
+@code{AC_INCLUDES_DEFAULT} checks for @file{stdio.h}, @file{stdlib.h},
+and @file{string.h}, even though they are in that list, because they
+might not be available when compiling for a ``freestanding environment''
+(in which most of the features of the C library are optional).  You
+probably do not need to write @samp{#ifdef HAVE_STDIO_H} in your own
+code.
+
+@file{inttypes.h} and @file{stdint.h} were added to C in the 1999
+revision of the standard, and @file{strings.h}, @file{sys/types.h},
+@file{sys/stat.h}, and @file{unistd.h} are POSIX extensions.  You
+@emph{should} guard uses of these headers with appropriate conditionals.
 @end defmac
 
 @defmac AC_CHECK_INCLUDES_DEFAULT
index 17a5abac15cb7d918a87f76f46d8541ac76b1d38..bc70e0b6fa8c4e8cbc8bc40587e5abb76e287917 100644 (file)
@@ -293,17 +293,14 @@ dnl If ever you change this variable, please keep autoconf.texi in sync.
 [# Factoring default headers for most tests.
 ac_includes_default="\
 #include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
+#ifdef HAVE_STDIO_H
+# include <stdio.h>
 #endif
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
 #endif
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
+#ifdef HAVE_STRING_H
+# include <string.h>
 #endif
 #ifdef HAVE_INTTYPES_H
 # include <inttypes.h>
@@ -311,24 +308,30 @@ ac_includes_default="\
 #ifdef HAVE_STDINT_H
 # include <stdint.h>
 #endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif"
 ])]dnl
-[m4_map_args([_AC_CHECK_HEADER_ONCE],
-  [sys/types.h], [sys/stat.h], [strings.h],
-  [inttypes.h], [stdint.h], [unistd.h])]dnl
-dnl For backward compatibility, provide unconditional AC_DEFINEs of
-dnl HAVE_STDLIB_H, HAVE_STRING_H, and STDC_HEADERS.
-[AC_DEFINE([HAVE_STDLIB_H], [1],
-  [Always define to 1, for backward compatibility.
-   You can assume <stdlib.h> exists.])]dnl
-[AC_DEFINE([HAVE_STRING_H], [1],
-  [Always define to 1, for backward compatibility.
-   You can assume <string.h> exists.])]dnl
+[dnl We have to check for all the headers that aren't part of the
+dnl C-1990 *freestanding* environment, which is all of them except stddef.h.
+m4_map_args([_AC_CHECK_HEADER_ONCE],
+  [stdio.h], [stdlib.h], [string.h], [inttypes.h], [stdint.h],
+  [strings.h], [sys/stat.h], [sys/types.h], [unistd.h])]dnl
+[AS_IF([test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes],
 [AC_DEFINE([STDC_HEADERS], [1],
-  [Always define to 1, for backward compatibility.
-   You can assume the C90 standard headers exist.])])
+  [Define to 1 if all of the C90 standard headers exist
+   (not just the ones required in a freestanding environment).
+   This macro is provided for backward compatibility;
+   new code need not use it.])])])
 # AC_CHECK_INCLUDES_DEFAULT
 
 
index 40720fe42f6e215a3c5359135a746627ecb9f36b..c617c76f9de8b94f2ecd793559cde1cd7e16191a 100644 (file)
@@ -130,14 +130,14 @@ CPP="./mycpp $CPP"
 
 # Exercise CPP.
 
-AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include <stdio.h>]])],
-  [AC_DEFINE([HAVE_STDIO_H], [1], [Define if you have stdio.h])])
+AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include <float.h>]])],
+  [AC_DEFINE([HAVE_FLOAT_H], [1], [Define if you have float.h])])
 AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include <autoconf_io.h>]])],
   [AC_DEFINE([HAVE_AUTOCONF_IO_H], [1], [Define if you have autoconf_io.h])])
 ]])
 AT_CHECK_DEFINES(
 [/* #undef HAVE_AUTOCONF_IO_H */
-#define HAVE_STDIO_H 1
+#define HAVE_FLOAT_H 1
 ])
 
 AT_CLEANUP
@@ -169,15 +169,15 @@ test "x$ac_c_preproc_warn_flag" != xyes &&
   AC_MSG_ERROR([failed to detect preprocessor warning option])
 
 # Exercise CPP.
-AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include <stdio.h>]])],
-  [AC_DEFINE([HAVE_STDIO_H], [1], [Define if you have stdio.h])])
+AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include <float.h>]])],
+  [AC_DEFINE([HAVE_FLOAT_H], [1], [Define if you have float.h])])
 AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include <autoconf_io.h>]])],
   [AC_DEFINE([HAVE_AUTOCONF_IO_H], [1], [Define if you have autoconf_io.h])])
 ]])
 
 AT_CHECK_DEFINES(
 [/* #undef HAVE_AUTOCONF_IO_H */
-#define HAVE_STDIO_H 1
+#define HAVE_FLOAT_H 1
 ])
 
 AT_CLEANUP
@@ -218,15 +218,15 @@ test "$CPP" != "$CC -E" &&
   AC_MSG_ERROR([error messages on stderr cause the preprocessor selection to fail])
 
 # Exercise CPP.
-AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include <stdio.h>]])],
-  [AC_DEFINE([HAVE_STDIO_H], [1], [Define if you have stdio.h])])
+AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include <float.h>]])],
+  [AC_DEFINE([HAVE_FLOAT_H], [1], [Define if you have float.h])])
 AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include <autoconf_io.h>]])],
   [AC_DEFINE([HAVE_AUTOCONF_IO_H], [1], [Define if you have autoconf_io.h])])
 ]])
 
 AT_CHECK_DEFINES(
 [/* #undef HAVE_AUTOCONF_IO_H */
-#define HAVE_STDIO_H 1
+#define HAVE_FLOAT_H 1
 ])
 
 AT_CLEANUP
index a62ad240ebac2e1bfa1cd55a5312abe3ca082797..cda8db805935ebc52a84f583ba2c712e3e46ca5a 100644 (file)
@@ -609,16 +609,18 @@ cp -f config.status config-status.$1
 # AT_CHECK_HEADER is a better name, but too close from AC_CHECK_HEADER.
 m4_define([AT_CHECK_DEFINES],
 [AT_CHECK([[sed '/#/!d
-/INTTYPES/d
-/MEMORY/d
+/INTTYPES_H/d
+/MEMORY_H/d
 /PACKAGE_/d
 /STDC_HEADERS/d
-/STDINT/d
-/STDLIB/d
-/STRING/d
-/SYS_STAT/d
-/SYS_TYPES/d
-/UNISTD/d' config.h]],,
+/STDINT_H/d
+/STDIO_H/d
+/STDLIB_H/d
+/STRING_H/d
+/STRINGS_H/d
+/SYS_STAT_H/d
+/SYS_TYPES_H/d
+/UNISTD_H/d' config.h]],,
          [$1])])
 
 
index 8e218355d425e06951966ed41fb6c3ca3fd27a1f..e6c7cf20da960e5e226620797e8c3e77c16f07eb 100644 (file)
@@ -335,17 +335,18 @@ AT_CLEANUP
 # AC_CHECK_HEADERS
 # ----------------
 # Check that it performs the correct actions:
-# Must define HAVE_STDIO_H, but not HAVE_AUTOCONF_IO_H.
+# Must define HAVE_FLOAT_H, but not HAVE_AUTOCONF_IO_H.
 AT_SETUP([AC_CHECK_HEADERS])
 
 AT_DATA([autoconf_io.h],
 [blah blah
 ])
 
-AT_CONFIGURE_AC([AC_CHECK_HEADERS(stdio.h autoconf_io.h)])
+AT_CONFIGURE_AC([AC_CHECK_HEADERS([float.h autoconf_io.h])])
 AT_CHECK_AUTOCONF
 AT_CHECK_AUTOHEADER([], [
   HAVE_AUTOCONF_IO_H
+  HAVE_FLOAT_H
   HAVE_INTTYPES_H
   HAVE_STDINT_H
   HAVE_STDIO_H
@@ -361,7 +362,7 @@ AT_CHECK_CONFIGURE([CPPFLAGS=-I.])
 AT_CHECK_ENV
 AT_CHECK_DEFINES(
 [/* #undef HAVE_AUTOCONF_IO_H */
-#define HAVE_STDIO_H 1
+#define HAVE_FLOAT_H 1
 ])
 
 AT_CLEANUP
@@ -745,6 +746,7 @@ AT_CHECK_AUTOHEADER([--force], [
   AC_APPLE_UNIVERSAL_BUILD
   HAVE_INTTYPES_H
   HAVE_STDINT_H
+  HAVE_STDIO_H
   HAVE_STDLIB_H
   HAVE_STRINGS_H
   HAVE_STRING_H
@@ -1091,6 +1093,7 @@ AT_CHECK_AUTOHEADER([-W no-obsolete], [
   HAVE_NOCOMMENT_H
   HAVE_QUUX_H
   HAVE_STDINT_H
+  HAVE_STDIO_H
   HAVE_STDLIB_H
   HAVE_STRINGS_H
   HAVE_STRING_H
@@ -1132,6 +1135,7 @@ AT_CHECK_AUTOHEADER([-W no-obsolete], [
   HAVE_NOCOMMENT_H
   HAVE_QUUX_H
   HAVE_STDINT_H
+  HAVE_STDIO_H
   HAVE_STDLIB_H
   HAVE_STRINGS_H
   HAVE_STRING_H
index 967d9be1e923d8d4cd7210737880cbd8e51cd1a0..d32ad362a1e84534b7d901f077896469ed64ce52 100644 (file)
@@ -1035,6 +1035,7 @@ AT_CHECK_AUTOHEADER([-Wno-obsolete], [
   AC_APPLE_UNIVERSAL_BUILD
   HAVE_INTTYPES_H
   HAVE_STDINT_H
+  HAVE_STDIO_H
   HAVE_STDLIB_H
   HAVE_STRINGS_H
   HAVE_STRING_H