From 7a0574b50ee9c2b96ce94c29e031c103285c0b1d Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 12 Nov 2019 13:00:04 -0500 Subject: [PATCH] Fix ecpglib.h to declare bool consistently with c.h. This completes the task begun in commit 1408d5d86, to synchronize ECPG's exported definitions with the definition of bool used by c.h (and, therefore, the one actually in use in the ECPG library). On practically all modern platforms, ecpglib.h will now just include , which should surprise nobody anymore. That removes a header-inclusion-order hazard for ECPG clients, who previously might get build failures or unexpected behavior depending on whether they'd included themselves, and if so, whether before or after ecpglib.h. On platforms where sizeof(_Bool) is not 1 (only old PPC-based Mac systems, as far as I know), things are still messy, as inclusion of could still break ECPG client code. There doesn't seem to be any clean fix for that, and given the probably-negligible population of users who would care anymore, it's not clear we should go far out of our way to cope with it. This change at least fixes some header-inclusion-order hazards for our own code, since c.h and ecpglib.h previously disagreed on whether bool should be char or unsigned char. To implement this with minimal invasion of ECPG client namespace, move the choice of whether to rely on into configure, and have it export a configuration symbol PG_USE_STDBOOL. ecpglib.h no longer exports definitions for TRUE and FALSE, only their lowercase brethren. We could undo that if we get push-back about it. Ideally we'd back-patch this as far as v11, which is where c.h started to rely on . But the odds of creating problems for formerly-working ECPG client code seem about as large as the odds of fixing any non-working cases, so we'll just do this in HEAD. Discussion: https://postgr.es/m/CAA4eK1LmaKO7Du9M9Lo=kxGU8sB6aL8fa3sF6z6d5yYYVe3BuQ@mail.gmail.com --- configure | 6 ++++ configure.in | 7 ++++ src/backend/utils/fmgr/dfmgr.c | 2 +- src/include/c.h | 9 ++--- src/include/pg_config.h.in | 3 ++ src/include/pg_config.h.win32 | 3 ++ src/interfaces/ecpg/include/ecpg_config.h.in | 3 ++ src/interfaces/ecpg/include/ecpglib.h | 38 ++++++++++++-------- src/pl/plperl/plperl.h | 4 +-- src/tools/msvc/Solution.pm | 1 + 10 files changed, 55 insertions(+), 21 deletions(-) diff --git a/configure b/configure index d6ce3945256..629fe8ecf03 100755 --- a/configure +++ b/configure @@ -14786,6 +14786,12 @@ _ACEOF +if test "$ac_cv_header_stdbool_h" = yes -a "$ac_cv_sizeof_bool" = 1; then + +$as_echo "#define PG_USE_STDBOOL 1" >>confdefs.h + +fi + ## ## Functions, global variables diff --git a/configure.in b/configure.in index 5bd31a876e8..1ea1c465504 100644 --- a/configure.in +++ b/configure.in @@ -1593,6 +1593,13 @@ AC_CHECK_SIZEOF([bool], [], #include #endif]) +dnl We use if we have it and it declares type bool as having +dnl size 1. Otherwise, c.h will fall back to declaring bool as unsigned char. +if test "$ac_cv_header_stdbool_h" = yes -a "$ac_cv_sizeof_bool" = 1; then + AC_DEFINE([PG_USE_STDBOOL], 1, + [Define to 1 to use to define type bool.]) +fi + ## ## Functions, global variables diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c index be684786d64..c8d2cef35ff 100644 --- a/src/backend/utils/fmgr/dfmgr.c +++ b/src/backend/utils/fmgr/dfmgr.c @@ -23,7 +23,7 @@ * On macOS, insists on including . If we're not * using stdbool, undef bool to undo the damage. */ -#ifndef USE_STDBOOL +#ifndef PG_USE_STDBOOL #ifdef bool #undef bool #endif diff --git a/src/include/c.h b/src/include/c.h index c95acd35f7f..802a731267f 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -288,20 +288,21 @@ * bool * Boolean value, either true or false. * - * Use stdbool.h if available and its bool has size 1. That's useful for + * We use stdbool.h if available and its bool has size 1. 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. */ #ifndef __cplusplus -#if defined(HAVE_STDBOOL_H) && SIZEOF_BOOL == 1 +#ifdef PG_USE_STDBOOL #include -#define USE_STDBOOL 1 #else #ifndef bool @@ -316,7 +317,7 @@ typedef unsigned char bool; #define false ((bool) 0) #endif -#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 25a48d3ba78..fc22526b7e3 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -829,6 +829,9 @@ /* Define to best printf format archetype, usually gnu_printf if available. */ #undef PG_PRINTF_ATTRIBUTE +/* Define to 1 to use to define type bool. */ +#undef PG_USE_STDBOOL + /* PostgreSQL version as a string */ #undef PG_VERSION diff --git a/src/include/pg_config.h.win32 b/src/include/pg_config.h.win32 index 6b67fb06308..6c98ef49162 100644 --- a/src/include/pg_config.h.win32 +++ b/src/include/pg_config.h.win32 @@ -624,6 +624,9 @@ (--with-krb-srvnam=NAME) */ #define PG_KRB_SRVNAM "postgres" +/* Define to 1 to use to define type bool. */ +#define PG_USE_STDBOOL 1 + /* A string containing the version number, platform, and C compiler */ #define PG_VERSION_STR "Uninitialized version string (win32)" diff --git a/src/interfaces/ecpg/include/ecpg_config.h.in b/src/interfaces/ecpg/include/ecpg_config.h.in index c18556130ef..17e93c40dbb 100644 --- a/src/interfaces/ecpg/include/ecpg_config.h.in +++ b/src/interfaces/ecpg/include/ecpg_config.h.in @@ -10,6 +10,9 @@ /* Define to 1 if `long long int' works and is 64 bits. */ #undef HAVE_LONG_LONG_INT_64 +/* Define to 1 to use to define type bool. */ +#undef PG_USE_STDBOOL + /* Define to 1 to build client libraries as thread-safe code. * (--enable-thread-safety) */ #undef ENABLE_THREAD_SAFETY diff --git a/src/interfaces/ecpg/include/ecpglib.h b/src/interfaces/ecpg/include/ecpglib.h index de9c76aefc3..c65073f15ac 100644 --- a/src/interfaces/ecpg/include/ecpglib.h +++ b/src/interfaces/ecpg/include/ecpglib.h @@ -1,6 +1,6 @@ /* - * this is a small part of c.h since we don't want to leak all postgres - * definitions into ecpg programs + * Client-visible declarations for ecpglib + * * src/interfaces/ecpg/include/ecpglib.h */ @@ -8,30 +8,40 @@ #define _ECPGLIB_H #include "libpq-fe.h" +#include "ecpg_config.h" #include "ecpgtype.h" #include "sqlca.h" #include +/* + * 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 -#ifndef bool -#define bool char -#endif /* ndef bool */ + +#ifdef PG_USE_STDBOOL +#include +#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 /* ndef true */ +#endif + #ifndef false #define false ((bool) 0) -#endif /* ndef false */ +#endif + +#endif /* not PG_USE_STDBOOL */ #endif /* not C++ */ -#ifndef TRUE -#define TRUE 1 -#endif /* TRUE */ - -#ifndef FALSE -#define FALSE 0 -#endif /* FALSE */ #ifdef __cplusplus extern "C" diff --git a/src/pl/plperl/plperl.h b/src/pl/plperl/plperl.h index 3748158a86d..7ae3c69c086 100644 --- a/src/pl/plperl/plperl.h +++ b/src/pl/plperl/plperl.h @@ -64,7 +64,7 @@ * warnings. If PostgreSQL does not but Perl does, we need to undefine bool * after we include the Perl headers; see below. */ -#ifdef USE_STDBOOL +#ifdef PG_USE_STDBOOL #define HAS_BOOL 1 #endif @@ -175,7 +175,7 @@ * makes bool a macro, but our own replacement is a typedef, so the undef * makes ours visible again). */ -#ifndef USE_STDBOOL +#ifndef PG_USE_STDBOOL #ifdef bool #undef bool #endif diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm index a6958273ac1..7f179f194be 100644 --- a/src/tools/msvc/Solution.pm +++ b/src/tools/msvc/Solution.pm @@ -513,6 +513,7 @@ sub GenerateFiles print $o <