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 <stdbool.h>, 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 <stdbool.h> 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 <stdbool.h> 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 <stdbool.h> 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 <stdbool.h>.  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
This commit is contained in:
Tom Lane 2019-11-12 13:00:04 -05:00
parent de7c2d30b6
commit 7a0574b50e
10 changed files with 55 additions and 21 deletions

6
configure vendored
View File

@ -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

View File

@ -1593,6 +1593,13 @@ AC_CHECK_SIZEOF([bool], [],
#include <stdbool.h>
#endif])
dnl We use <stdbool.h> 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 <stdbool.h> to define type bool.])
fi
##
## Functions, global variables

View File

@ -23,7 +23,7 @@
* On macOS, <dlfcn.h> insists on including <stdbool.h>. If we're not
* using stdbool, undef bool to undo the damage.
*/
#ifndef USE_STDBOOL
#ifndef PG_USE_STDBOOL
#ifdef bool
#undef bool
#endif

View File

@ -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 <stdbool.h>
#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++ */

View File

@ -829,6 +829,9 @@
/* 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

View File

@ -624,6 +624,9 @@
(--with-krb-srvnam=NAME) */
#define PG_KRB_SRVNAM "postgres"
/* Define to 1 to use <stdbool.h> 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)"

View File

@ -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 <stdbool.h> 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

View File

@ -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 <string.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
#ifndef bool
#define bool char
#endif /* ndef bool */
#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 /* 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"

View File

@ -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

View File

@ -513,6 +513,7 @@ sub GenerateFiles
print $o <<EOF;
#define HAVE_LONG_LONG_INT 1
#define HAVE_LONG_LONG_INT_64 1
#define PG_USE_STDBOOL 1
#define ENABLE_THREAD_SAFETY 1
EOF
close($o);