From 34dce524e487488ee0603d74d95ad31f81d3441b Mon Sep 17 00:00:00 2001
From: Thomas Munro <tmunro@postgresql.org>
Date: Wed, 27 Nov 2024 18:09:49 +1300
Subject: [PATCH] Require sizeof(bool) == 1.

The C standard says that sizeof(bool) is implementation-defined, but we
know of no current systems where it is not 1.  The last known systems
seem to have been Apple macOS/PowerPC 10.5 and Microsoft Visual C++ 4,
both long defunct.

PostgreSQL has always required sizeof(bool) == 1 for the definition of
bool that it used, but previously it would define its own type if the
system-provided bool had a different size.  That was always liable to
cause memory layout problems when interacting with system and
third-party libraries on (by now hypothetical) computers with wider
bool.  C23 has now introduced a new problem by making bool a built in
datatype (like C++), so the fallback code doesn't even compile.  We
could probably work around that, but then we'd be writing new untested
code for a computer that doesn't exist.

Instead, delete the unreachable and C23-uncompilable fallback code, and
let existing static assertions fail if the system-provided bool is too
wide.  If we ever get a problem report from a real system, then it will
be time to figure out what to do about it in a way that also works on
modern compilers.

Note on C++: previously we avoided including <stdbool.h> or trying to
define a new bool type in headers included by C++ code.  Now that the
latter is removed, we might as well just include <stdbool.h>
unconditionally: it should be visible to C++11 but do nothing, just as
in C23.  We already include <stdint.h> without C++ guards in c.h, and
that falls under the same C99-compatibility section of the C++11
standard as <stdbool.h>, so let's remove the guards here too.

Reviewed-by:
Discussion: https://postgr.es/m/3198438.1731895163%40sss.pgh.pa.us
---
 configure                                    | 41 --------------------
 configure.ac                                 |  9 -----
 meson.build                                  |  7 ----
 src/backend/jit/llvm/llvmjit_types.c         |  8 ++--
 src/backend/utils/fmgr/dfmgr.c               | 10 -----
 src/include/c.h                              | 30 +-------------
 src/include/pg_config.h.in                   |  6 ---
 src/interfaces/ecpg/include/ecpg_config.h.in |  3 --
 src/interfaces/ecpg/include/ecpglib.h        | 30 +-------------
 src/interfaces/ecpg/include/meson.build      |  1 -
 src/pl/plperl/plperl_system.h                | 23 +----------
 11 files changed, 8 insertions(+), 160 deletions(-)

diff --git a/configure b/configure
index 199d666aa73..5470b863824 100755
--- a/configure
+++ b/configure
@@ -14958,47 +14958,6 @@ if test "$ac_cv_sizeof_off_t" -lt 8; then
   fi
 fi
 
-# The cast to long int works around a bug in the HP C Compiler
-# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
-# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
-# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of bool" >&5
-$as_echo_n "checking size of bool... " >&6; }
-if ${ac_cv_sizeof_bool+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (bool))" "ac_cv_sizeof_bool"        "#include <stdbool.h>
-"; then :
-
-else
-  if test "$ac_cv_type_bool" = yes; then
-     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 77 "cannot compute sizeof (bool)
-See \`config.log' for more details" "$LINENO" 5; }
-   else
-     ac_cv_sizeof_bool=0
-   fi
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_bool" >&5
-$as_echo "$ac_cv_sizeof_bool" >&6; }
-
-
-
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_BOOL $ac_cv_sizeof_bool
-_ACEOF
-
-
-
-if test "$ac_cv_sizeof_bool" = 1; then
-
-$as_echo "#define PG_USE_STDBOOL 1" >>confdefs.h
-
-fi
-
 
 ##
 ## Functions, global variables
diff --git a/configure.ac b/configure.ac
index 4f56bb5062e..b792ab110a9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1691,15 +1691,6 @@ if test "$ac_cv_sizeof_off_t" -lt 8; then
   fi
 fi
 
-AC_CHECK_SIZEOF([bool], [], [#include <stdbool.h>])
-
-dnl We use <stdbool.h> if bool has size 1 after including it.  Otherwise, c.h
-dnl will fall back to declaring bool as unsigned char.
-if test "$ac_cv_sizeof_bool" = 1; then
-  AC_DEFINE([PG_USE_STDBOOL], 1,
-            [Define to 1 to use <stdbool.h> to define type bool.])
-fi
-
 
 ##
 ## Functions, global variables
diff --git a/meson.build b/meson.build
index 83e61d0f4a8..1644600f5ef 100644
--- a/meson.build
+++ b/meson.build
@@ -1755,13 +1755,6 @@ if cc.compiles('''
 endif
 
 
-# We use <stdbool.h> if bool has size 1 after including it.  Otherwise, c.h
-# will fall back to declaring bool as unsigned char.
-if cc.sizeof('bool', prefix: '#include <stdbool.h>', args: test_c_args) == 1
-  cdata.set('PG_USE_STDBOOL', 1)
-endif
-
-
 # Need to check a call with %m because netbsd supports gnu_printf but emits a
 # warning for each use of %m.
 printf_attributes = ['gnu_printf', '__syslog__', 'printf']
diff --git a/src/backend/jit/llvm/llvmjit_types.c b/src/backend/jit/llvm/llvmjit_types.c
index 4a9e0770145..13efe18e6b0 100644
--- a/src/backend/jit/llvm/llvmjit_types.c
+++ b/src/backend/jit/llvm/llvmjit_types.c
@@ -117,11 +117,9 @@ ExecEvalBoolSubroutineTemplate(ExprState *state,
 }
 
 /*
- * Clang represents stdbool.h style booleans that are returned by functions
- * differently (as i1) than stored ones (as i8). Therefore we do not just need
- * TypeBool (above), but also a way to determine the width of a returned
- * integer. This allows us to keep compatible with non-stdbool using
- * architectures.
+ * Clang represents bool returned by functions differently (as i1) than stored
+ * ones (as i8).  Therefore we do not just need TypeStorageBool (above), but
+ * also a way to determine the width of a returned integer.
  */
 extern bool FunctionReturningBool(void);
 bool
diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c
index c7aa789b51b..8e81ecc7491 100644
--- a/src/backend/utils/fmgr/dfmgr.c
+++ b/src/backend/utils/fmgr/dfmgr.c
@@ -18,16 +18,6 @@
 
 #ifndef WIN32
 #include <dlfcn.h>
-
-/*
- * On macOS, <dlfcn.h> insists on including <stdbool.h>.  If we're not
- * using stdbool, undef bool to undo the damage.
- */
-#ifndef PG_USE_STDBOOL
-#ifdef bool
-#undef bool
-#endif
-#endif
 #endif							/* !WIN32 */
 
 #include "fmgr.h"
diff --git a/src/include/c.h b/src/include/c.h
index fe1ce87882b..304dff27e34 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -450,37 +450,11 @@ typedef void (*pg_funcptr_t) (void);
  * bool
  *		Boolean value, either true or false.
  *
- * We use stdbool.h if bool has size 1 after including it.  That's useful for
- * better compiler and debugger output and for compatibility with third-party
- * libraries.  But PostgreSQL currently cannot deal with bool of other sizes;
- * there are static assertions around the code to prevent that.
- *
- * For C++ compilers, we assume the compiler has a compatible built-in
- * definition of bool.
- *
- * See also the version of this code in src/interfaces/ecpg/include/ecpglib.h.
+ * PostgreSQL currently cannot deal with bool of size other than 1; there are
+ * static assertions around the code to prevent that.
  */
 
-#ifndef __cplusplus
-
-#ifdef PG_USE_STDBOOL
 #include <stdbool.h>
-#else
-
-#ifndef bool
-typedef unsigned char bool;
-#endif
-
-#ifndef true
-#define true	((bool) 1)
-#endif
-
-#ifndef false
-#define false	((bool) 0)
-#endif
-
-#endif							/* not PG_USE_STDBOOL */
-#endif							/* not C++ */
 
 
 /* ----------------------------------------------------------------
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 40e4b2e3816..7e578cc712c 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -600,9 +600,6 @@
 /* Define to best printf format archetype, usually gnu_printf if available. */
 #undef PG_PRINTF_ATTRIBUTE
 
-/* Define to 1 to use <stdbool.h> to define type bool. */
-#undef PG_USE_STDBOOL
-
 /* PostgreSQL version as a string */
 #undef PG_VERSION
 
@@ -633,9 +630,6 @@
    RELSEG_SIZE requires an initdb. */
 #undef RELSEG_SIZE
 
-/* The size of `bool', as computed by sizeof. */
-#undef SIZEOF_BOOL
-
 /* The size of `long', as computed by sizeof. */
 #undef SIZEOF_LONG
 
diff --git a/src/interfaces/ecpg/include/ecpg_config.h.in b/src/interfaces/ecpg/include/ecpg_config.h.in
index 2b439c1e58d..75f542f263b 100644
--- a/src/interfaces/ecpg/include/ecpg_config.h.in
+++ b/src/interfaces/ecpg/include/ecpg_config.h.in
@@ -6,6 +6,3 @@
 
 /* Define to 1 if `long long int' works and is 64 bits. */
 #undef HAVE_LONG_LONG_INT_64
-
-/* Define to 1 to use <stdbool.h> to define type bool. */
-#undef PG_USE_STDBOOL
diff --git a/src/interfaces/ecpg/include/ecpglib.h b/src/interfaces/ecpg/include/ecpglib.h
index 771761ffe49..dbf3cc3a0c2 100644
--- a/src/interfaces/ecpg/include/ecpglib.h
+++ b/src/interfaces/ecpg/include/ecpglib.h
@@ -7,6 +7,7 @@
 #ifndef _ECPGLIB_H
 #define _ECPGLIB_H
 
+#include <stdbool.h>
 #include <string.h>
 
 #include "ecpg_config.h"
@@ -14,35 +15,6 @@
 #include "libpq-fe.h"
 #include "sqlca.h"
 
-/*
- * This is a small extract from c.h since we don't want to leak all postgres
- * definitions into ecpg programs; but we need to know what bool is.
- */
-#ifndef __cplusplus
-
-#ifdef PG_USE_STDBOOL
-#include <stdbool.h>
-#else
-
-/*
- * We assume bool has been defined if true and false are.  This avoids
- * duplicate-typedef errors if this file is included after c.h.
- */
-#if !(defined(true) && defined(false))
-typedef unsigned char bool;
-#endif
-
-#ifndef true
-#define true	((bool) 1)
-#endif
-
-#ifndef false
-#define false	((bool) 0)
-#endif
-
-#endif							/* not PG_USE_STDBOOL */
-#endif							/* not C++ */
-
 
 #ifdef __cplusplus
 extern "C"
diff --git a/src/interfaces/ecpg/include/meson.build b/src/interfaces/ecpg/include/meson.build
index b4a5aedd51f..a3beb3cc7be 100644
--- a/src/interfaces/ecpg/include/meson.build
+++ b/src/interfaces/ecpg/include/meson.build
@@ -5,7 +5,6 @@ ecpg_inc = include_directories('.')
 ecpg_conf_keys = [
   'HAVE_LONG_INT_64',
   'HAVE_LONG_LONG_INT_64',
-  'PG_USE_STDBOOL',
 ]
 
 ecpg_conf_data = configuration_data()
diff --git a/src/pl/plperl/plperl_system.h b/src/pl/plperl/plperl_system.h
index 48f6575e513..d1b9ea17fca 100644
--- a/src/pl/plperl/plperl_system.h
+++ b/src/pl/plperl/plperl_system.h
@@ -72,16 +72,10 @@
 #endif
 
 /*
- * Regarding bool, both PostgreSQL and Perl might use stdbool.h or not,
- * depending on configuration.  If both agree, things are relatively harmless.
- * If not, things get tricky.  If PostgreSQL does but Perl does not, define
- * HAS_BOOL here so that Perl does not redefine bool; this avoids compiler
- * warnings.  If PostgreSQL does not but Perl does, we need to undefine bool
- * after we include the Perl headers; see below.
+ * Define HAS_BOOL here so that Perl does not redefine bool.  We included
+ * <stdbool.h> in c.h.
  */
-#ifdef PG_USE_STDBOOL
 #define HAS_BOOL 1
-#endif
 
 /*
  * Get the basic Perl API.  We use PERL_NO_GET_CONTEXT mode so that our code
@@ -180,19 +174,6 @@
 /* perl version and platform portability */
 #include "ppport.h"
 
-/*
- * perl might have included stdbool.h.  If we also did that earlier (see c.h),
- * then that's fine.  If not, we probably rejected it for some reason.  In
- * that case, undef bool and proceed with our own bool.  (Note that stdbool.h
- * makes bool a macro, but our own replacement is a typedef, so the undef
- * makes ours visible again).
- */
-#ifndef PG_USE_STDBOOL
-#ifdef bool
-#undef bool
-#endif
-#endif
-
 /* supply HeUTF8 if it's missing - ppport.h doesn't supply it, unfortunately */
 #ifndef HeUTF8
 #define HeUTF8(he)			   ((HeKLEN(he) == HEf_SVKEY) ?			   \
-- 
2.47.0

