Introduce PERL_BOOL_AS_CHAR define
authorFather Chrysostomos <sprout@cpan.org>
Wed, 30 Oct 2013 12:37:43 +0000 (05:37 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Thu, 31 Oct 2013 04:35:22 +0000 (21:35 -0700)
This allows compilers that do support real booleans (C++ or anything
with stdbool.h) to emulate those that don’t.

See ticket #120314.

This patch incorporates suggestions from Craig Berry.

handy.h
perl.c
perl.h
pod/perlhacktips.pod

diff --git a/handy.h b/handy.h
index 131ede2..d345abe 100644 (file)
--- a/handy.h
+++ b/handy.h
@@ -69,7 +69,7 @@ Null SV pointer. (No longer available when C<PERL_CORE> is defined.)
 #define MUTABLE_IO(p)  ((IO *)MUTABLE_PTR(p))
 #define MUTABLE_SV(p)  ((SV *)MUTABLE_PTR(p))
 
-#ifdef I_STDBOOL
+#if defined(I_STDBOOL) && !defined(PERL_BOOL_AS_CHAR)
 #  include <stdbool.h>
 #  ifndef HAS_BOOL
 #    define HAS_BOOL 1
@@ -85,9 +85,11 @@ Null SV pointer. (No longer available when C<PERL_CORE> is defined.)
    Andy Dougherty      February 2000
 */
 #ifdef __GNUG__                /* GNU g++ has bool built-in */
+# ifndef PERL_BOOL_AS_CHAR
 #  ifndef HAS_BOOL
 #    define HAS_BOOL 1
 #  endif
+# endif
 #endif
 
 /* The NeXT dynamic loader headers will not build with the bool macro
@@ -104,6 +106,9 @@ Null SV pointer. (No longer available when C<PERL_CORE> is defined.)
 #endif /* NeXT || __NeXT__ */
 
 #ifndef HAS_BOOL
+# ifdef bool
+#  undef bool
+# endif
 # define bool char
 # define HAS_BOOL 1
 #endif
diff --git a/perl.c b/perl.c
index 4c80edb..15adb8a 100644 (file)
--- a/perl.c
+++ b/perl.c
 #  include <sys/sysctl.h>
 #endif
 
-#ifdef USE_NSGETEXECUTABLEPATH
-#  include <mach-o/dyld.h>
-#endif
-
 #ifdef DEBUG_LEAKING_SCALARS_FORK_DUMP
 #  ifdef I_SYSUIO
 #    include <sys/uio.h>
diff --git a/perl.h b/perl.h
index dc140bd..0a8beda 100644 (file)
--- a/perl.h
+++ b/perl.h
@@ -2298,6 +2298,13 @@ typedef SV PADNAME;
 # define PERL_SAWAMPERSAND
 #endif
 
+/* Include mach-o/dyld.h here for perl.c’s sake, since it may #define bool,
+   and handy.h needs to be able to re#define it under
+  -Accflags=-DPERL_BOOL_AS_CHAR. */
+#if defined(USE_NSGETEXECUTABLEPATH) && defined(PERL_IN_PERL_C)
+# include <mach-o/dyld.h>
+#endif
+
 #include "handy.h"
 
 #if defined(USE_LARGE_FILES) && !defined(NO_64_BIT_RAWIO)
index 7851db9..32739ff 100644 (file)
@@ -1329,6 +1329,18 @@ op slabs belonging to C<BEGIN> blocks.
 However, as an 80% solution it is still effective, as it has caught
 bugs in the past.
 
+=head2 When is a bool not a bool?
+
+On pre-C99 compilers, C<bool> is defined as equivalent to C<char>.
+Consequently assignment of any larger type to a C<bool> is unsafe and may
+be truncated.  The C<cBOOL> macro exists to cast it correctly.
+
+On those platforms and compilers where C<bool> really is a boolean (C++,
+C99), it is easy to forget the cast.  You can force C<bool> to be a C<char>
+by compiling with C<-Accflags=-DPERL_BOOL_AS_CHAR>.  You may also wish to
+add C<-Accflags=-Werror=conversion> or your compiler's equivalent to make
+it impossible to ignore the unsafe truncations.
+
 =head2 The .i Targets
 
 You can expand the macros in a F<foo.c> file by saying