[PATCH 1/3] ISO C23: Backport stdbool.m4 from gnulib-devel-0-52.20230709git.fc42.noarch

<[email protected]> Wed, 5 Mar 2025 10:56:25 +0100
Newsgroups gmane.comp.gnu.utils.bugs
Message-ID <[email protected]>
From: Petr Písař <[email protected]>

The bundled gnulib check for stdbool.h did not account for ISO C23
which provides its own false and true keywords. As a result stdbool.h
presence was not correctly detected and libopts/compat/compat.h,
bundled from AutoGen, failed to compile with GCC 15 which defaults to
ISO C23:

    In file included from autoopts/project.h:30,
		     from libopts.c:2:
    ./compat/compat.h:188:19: error: cannot use keyword ‘false’ as enumeration constant
      188 |    typedef enum { false = 0, true = 1 } _Bool;
	  |                   ^~~~~
    ./compat/compat.h:188:19: note: ‘false’ is a keyword with ‘-std=c23’ onwards
    ./compat/compat.h:188:41: error: expected ‘;’, identifier or ‘(’ before ‘_Bool’
      188 |    typedef enum { false = 0, true = 1 } _Bool;
	  |                                         ^~~~~

Signed-off-by: Petr Písař <[email protected]>
---
 m4/stdbool.m4 | 129 +++++++++++++++++++++++++++++---------------------
 1 file changed, 74 insertions(+), 55 deletions(-)

diff --git a/m4/stdbool.m4 b/m4/stdbool.m4
index 7273b82..8e00e4a 100644
--- a/m4/stdbool.m4
+++ b/m4/stdbool.m4
@@ -1,27 +1,40 @@
 # Check for stdbool.h that conforms to C99.
 
-dnl Copyright (C) 2002-2006, 2009-2015 Free Software Foundation, Inc.
+dnl Copyright (C) 2002-2006, 2009-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
 
-#serial 5
+#serial 10
 
 # Prepare for substituting <stdbool.h> if it is not supported.
 
 AC_DEFUN([AM_STDBOOL_H],
 [
   AC_REQUIRE([AC_CHECK_HEADER_STDBOOL])
+  AC_REQUIRE([AC_CANONICAL_HOST])
 
-  # Define two additional variables used in the Makefile substitution.
-
+  dnl On some platforms, <stdbool.h> does not exist or does not conform to C99.
+  dnl On Solaris 10 with CC=cc CXX=CC, <stdbool.h> exists but is not usable
+  dnl in C++ mode (and no <cstdbool> exists). In this case, we use our
+  dnl replacement, also in C mode (for binary compatibility between C and C++).
   if test "$ac_cv_header_stdbool_h" = yes; then
-    STDBOOL_H=''
+    case "$host_os" in
+      solaris*)
+        if test -z "$GCC"; then
+          GL_GENERATE_STDBOOL_H=true
+        else
+          GL_GENERATE_STDBOOL_H=false
+        fi
+        ;;
+      *)
+        GL_GENERATE_STDBOOL_H=false
+        ;;
+    esac
   else
-    STDBOOL_H='stdbool.h'
+    GL_GENERATE_STDBOOL_H=true
   fi
-  AC_SUBST([STDBOOL_H])
-  AM_CONDITIONAL([GL_GENERATE_STDBOOL_H], [test -n "$STDBOOL_H"])
+  AM_CONDITIONAL([GL_GENERATE_STDBOOL_H], [test "$GL_GENERATE_STDBOOL_H" = "true"])
 
   if test "$ac_cv_type__Bool" = yes; then
     HAVE__BOOL=1
@@ -31,70 +44,76 @@ AC_DEFUN([AM_STDBOOL_H],
   AC_SUBST([HAVE__BOOL])
 ])
 
-# AM_STDBOOL_H will be renamed to gl_STDBOOL_H in the future.
-AC_DEFUN([gl_STDBOOL_H], [AM_STDBOOL_H])
-
-# This version of the macro is needed in autoconf <= 2.68.
+m4_version_prereq([2.72], [], [
 
 AC_DEFUN([AC_CHECK_HEADER_STDBOOL],
-  [AC_CACHE_CHECK([for stdbool.h that conforms to C99],
+  [AC_CHECK_TYPES([_Bool])
+   AC_CACHE_CHECK([for stdbool.h that conforms to C99 or later],
      [ac_cv_header_stdbool_h],
      [AC_COMPILE_IFELSE(
         [AC_LANG_PROGRAM(
-           [[
-             #include <stdbool.h>
-             #ifndef bool
-              "error: bool is not defined"
+           [[#include <stdbool.h>
+
+             /* "true" and "false" should be usable in #if expressions and
+                integer constant expressions, and "bool" should be a valid
+                type name.
+
+                Although C99 requires bool, true, and false to be macros,
+                C23 and C++11 overrule that, so do not test for that.
+                Although C99 requires __bool_true_false_are_defined and
+                _Bool, C23 says they are obsolescent, so do not require
+                them.  */
+
+             #if !true
+               #error "'true' is not true"
              #endif
-             #ifndef false
-              "error: false is not defined"
+             #if true != 1
+               #error "'true' is not equal to 1"
              #endif
+             char b[true == 1 ? 1 : -1];
+             char c[true];
+
              #if false
-              "error: false is not 0"
+               #error "'false' is not false"
              #endif
-             #ifndef true
-              "error: true is not defined"
-             #endif
-             #if true != 1
-              "error: true is not 1"
-             #endif
-             #ifndef __bool_true_false_are_defined
-              "error: __bool_true_false_are_defined is not defined"
+             #if false != 0
+               #error "'false' is not equal to 0"
              #endif
+             char d[false == 0 ? 1 : -1];
+
+             enum { e = false, f = true, g = false * true, h = true * 256 };
+
+             char i[(bool) 0.5 == true ? 1 : -1];
+             char j[(bool) 0.0 == false ? 1 : -1];
+             char k[sizeof (bool) > 0 ? 1 : -1];
+
+             struct sb { bool s: 1; bool t; } s;
+             char l[sizeof s.t > 0 ? 1 : -1];
 
-             struct s { _Bool s: 1; _Bool t; } s;
-
-             char a[true == 1 ? 1 : -1];
-             char b[false == 0 ? 1 : -1];
-             char c[__bool_true_false_are_defined == 1 ? 1 : -1];
-             char d[(bool) 0.5 == true ? 1 : -1];
-             /* See body of main program for 'e'.  */
-             char f[(_Bool) 0.0 == false ? 1 : -1];
-             char g[true];
-             char h[sizeof (_Bool)];
-             char i[sizeof s.t];
-             enum { j = false, k = true, l = false * true, m = true * 256 };
              /* The following fails for
                 HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */
-             _Bool n[m];
-             char o[sizeof n == m * sizeof n[0] ? 1 : -1];
-             char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1];
+             bool m[h];
+             char n[sizeof m == h * sizeof m[0] ? 1 : -1];
+             char o[-1 - (bool) 0 < 0 ? 1 : -1];
              /* Catch a bug in an HP-UX C compiler.  See
-                http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
-                http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html
+                https://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
+                https://lists.gnu.org/r/bug-coreutils/2005-11/msg00161.html
               */
-             _Bool q = true;
-             _Bool *pq = &q;
+             bool p = true;
+             bool *pp = &p;
            ]],
            [[
-             bool e = &s;
-             *pq |= q;
-             *pq |= ! q;
-             /* Refer to every declared value, to avoid compiler optimizations.  */
-             return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l
-                     + !m + !n + !o + !p + !q + !pq);
+             bool ps = &s;
+             *pp |= p;
+             *pp |= ! p;
+
+             /* Refer to every declared value, so they cannot be
+                discarded as unused.  */
+             return (!b + !c + !d + !e + !f + !g + !h + !i + !j + !k
+                     + !l + !m + !n + !o + !p + !pp + !ps);
            ]])],
         [ac_cv_header_stdbool_h=yes],
         [ac_cv_header_stdbool_h=no])])
-   AC_CHECK_TYPES([_Bool])
-])
+])# AC_CHECK_HEADER_STDBOOL
+
+]) # m4_version_prereq 2.72
-- 
2.48.1