From 9b93d70131a690c9b161e2fb0700a9966e85ad72 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Wed, 16 Aug 2017 00:22:32 -0400 Subject: [PATCH v2 9/9] Use stdbool.h if available While we could do without this, extension code and third-party headers are increasingly pulling this in, creating possible complications. One, bool defined in stdbool.h is not necessarily one byte in size. Two, it can only contain values 0 or 1 on output. So having multiple definitions of bool in play depending on include file order could create a mess. So we just get on board with this and use stdbool.h always if available. As a benefit, some recent compilers can give some better warnings if the official bool type is used. --- configure | 210 ++++++++++++++++++++++++++++++++++++--------- configure.in | 4 + src/include/c.h | 23 ++--- src/include/pg_config.h.in | 9 ++ src/pl/plperl/plperl.h | 10 +-- 5 files changed, 200 insertions(+), 56 deletions(-) diff --git a/configure b/configure index 0d76e5ea42..26ffe02443 100755 --- a/configure +++ b/configure @@ -2001,116 +2001,116 @@ $as_echo "$ac_res" >&6; } } # ac_fn_c_check_func -# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES -# ---------------------------------------------------- -# Tries to find if the field MEMBER exists in type AGGR, after including -# INCLUDES, setting cache variable VAR accordingly. -ac_fn_c_check_member () +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 -$as_echo_n "checking for $2.$3... " >&6; } -if eval \${$4+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else + eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -$5 +$4 int main () { -static $2 ac_aggr; -if (ac_aggr.$3) -return 0; +if (sizeof ($2)) + return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - eval "$4=yes" -else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -$5 +$4 int main () { -static $2 ac_aggr; -if (sizeof ac_aggr.$3) -return 0; +if (sizeof (($2))) + return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - eval "$4=yes" + else - eval "$4=no" + eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -eval ac_res=\$$4 +eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno -} # ac_fn_c_check_member +} # ac_fn_c_check_type -# ac_fn_c_check_type LINENO TYPE VAR INCLUDES -# ------------------------------------------- -# Tests whether TYPE exists after having included INCLUDES, setting cache -# variable VAR accordingly. -ac_fn_c_check_type () +# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES +# ---------------------------------------------------- +# Tries to find if the field MEMBER exists in type AGGR, after including +# INCLUDES, setting cache variable VAR accordingly. +ac_fn_c_check_member () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 +$as_echo_n "checking for $2.$3... " >&6; } +if eval \${$4+:} false; then : $as_echo_n "(cached) " >&6 else - eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -$4 +$5 int main () { -if (sizeof ($2)) - return 0; +static $2 ac_aggr; +if (ac_aggr.$3) +return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -$4 +$5 int main () { -if (sizeof (($2))) - return 0; +static $2 ac_aggr; +if (sizeof ac_aggr.$3) +return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - + eval "$4=yes" else - eval "$3=yes" + eval "$4=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -eval ac_res=\$$3 +eval ac_res=\$$4 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno -} # ac_fn_c_check_type +} # ac_fn_c_check_member # ac_fn_c_compute_int LINENO EXPR VAR INCLUDES # -------------------------------------------- @@ -10732,6 +10732,100 @@ fi ## Header files ## +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5 +$as_echo_n "checking for stdbool.h that conforms to C99... " >&6; } +if ${ac_cv_header_stdbool_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #ifndef bool + "error: bool is not defined" + #endif + #ifndef false + "error: false is not defined" + #endif + #if false + "error: false is not 0" + #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" + #endif + + 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]; + /* 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 + */ + _Bool q = true; + _Bool *pq = &q; + +int +main () +{ + + 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); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdbool_h=yes +else + ac_cv_header_stdbool_h=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5 +$as_echo "$ac_cv_header_stdbool_h" >&6; } + ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default" +if test "x$ac_cv_type__Bool" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE__BOOL 1 +_ACEOF + + +fi + + +if test $ac_cv_header_stdbool_h = yes; then + +$as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h + +fi + + for ac_header in atomic.h crypt.h dld.h fp_class.h getopt.h ieeefp.h ifaddrs.h langinfo.h mbarrier.h poll.h sys/epoll.h sys/ipc.h sys/pstat.h sys/resource.h sys/select.h sys/sem.h sys/shm.h sys/sockio.h sys/tas.h sys/un.h termios.h ucred.h utime.h wchar.h wctype.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` @@ -12818,6 +12912,40 @@ if test "$ac_cv_sizeof_off_t" -lt 8 -a "$segsize" != "1"; then as_fn_error $? "Large file support is not enabled. Segment size cannot be larger than 1GB." "$LINENO" 5 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" "$ac_includes_default"; 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 + + + ## ## Functions, global variables diff --git a/configure.in b/configure.in index bdc41b071f..2d546940b0 100644 --- a/configure.in +++ b/configure.in @@ -1180,6 +1180,8 @@ AC_SUBST(UUID_LIBS) ## Header files ## +AC_HEADER_STDBOOL + AC_CHECK_HEADERS([atomic.h crypt.h dld.h fp_class.h getopt.h ieeefp.h ifaddrs.h langinfo.h mbarrier.h poll.h sys/epoll.h sys/ipc.h sys/pstat.h sys/resource.h sys/select.h sys/sem.h sys/shm.h sys/sockio.h sys/tas.h sys/un.h termios.h ucred.h utime.h wchar.h wctype.h]) # On BSD, test for net/if.h will fail unless sys/socket.h @@ -1413,6 +1415,8 @@ if test "$ac_cv_sizeof_off_t" -lt 8 -a "$segsize" != "1"; then AC_MSG_ERROR([Large file support is not enabled. Segment size cannot be larger than 1GB.]) fi +AC_CHECK_SIZEOF(_Bool) + ## ## Functions, global variables diff --git a/src/include/c.h b/src/include/c.h index 6574d5aad7..1035c286d5 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -192,24 +192,27 @@ * bool * Boolean value, either true or false. * - * XXX for C++ compilers, we assume the compiler has a compatible + * Use stdbool.h if available, to ensure best compatibility with third-party + * libraries. For C++ compilers, we assume the compiler has a compatible * built-in definition of bool. */ #ifndef __cplusplus -#ifndef bool -typedef char bool; -#define SIZEOF_BOOL 1 +#ifdef HAVE_STDBOOL_H +#include +#else +#ifndef HAVE__BOOL +#define _Bool signed char +#define SIZEOF__BOOL 1 #endif - -#ifndef true -#define true ((bool) 1) +#define bool _Bool +#define false 0 +#define true 1 #endif -#ifndef false -#define false ((bool) 0) -#endif +#define SIZEOF_BOOL SIZEOF__BOOL + #endif /* not C++ */ /* diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index 579d195663..f964fea12c 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -469,6 +469,9 @@ /* Define to 1 if you have the `SSL_get_current_compression' function. */ #undef HAVE_SSL_GET_CURRENT_COMPRESSION +/* Define to 1 if stdbool.h conforms to C99. */ +#undef HAVE_STDBOOL_H + /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H @@ -671,6 +674,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_WINLDAP_H +/* Define to 1 if the system has the type `_Bool'. */ +#undef HAVE__BOOL + /* Define to 1 if your compiler understands __builtin_bswap32. */ #undef HAVE__BUILTIN_BSWAP32 @@ -786,6 +792,9 @@ /* The size of `void *', as computed by sizeof. */ #undef SIZEOF_VOID_P +/* The size of `_Bool', as computed by sizeof. */ +#undef SIZEOF__BOOL + /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS diff --git a/src/pl/plperl/plperl.h b/src/pl/plperl/plperl.h index c4e06d089f..f144813e94 100644 --- a/src/pl/plperl/plperl.h +++ b/src/pl/plperl/plperl.h @@ -42,6 +42,11 @@ #undef vsnprintf #endif +/* + * Prevent perl from redefining "bool". + */ +#define HAS_BOOL 1 + /* * Get the basic Perl API. We use PERL_NO_GET_CONTEXT mode so that our code @@ -83,11 +88,6 @@ #define NEED_sv_2pv_flags #include "ppport.h" -/* perl may have a different width of "bool", don't buy it */ -#ifdef bool -#undef bool -#endif - /* supply HeUTF8 if it's missing - ppport.h doesn't supply it, unfortunately */ #ifndef HeUTF8 #define HeUTF8(he) ((HeKLEN(he) == HEf_SVKEY) ? \ -- 2.11.0 (Apple Git-81)