use cBOOL for bool casts
David Mitchell [Thu, 15 Apr 2010 09:20:50 +0000 (10:20 +0100)]
bool b = (bool)some_int

doesn't necessarily do what you think. In some builds, bool is defined as
char, and that cast's behaviour is thus undefined. So this line in mg.c:

    const bool was_temp = (bool)SvTEMP(sv);

was actually setting was_temp to false even when the SVs_TEMP flag was set.
Fix this by replacing all the (bool) casts with a new cBOOL() cast macro
that (hopefully) does the right thing.

av.c
handy.h
mg.c
numeric.c
pp.c
regexec.c
scope.c
sv.c
toke.c

diff --git a/av.c b/av.c
index a4d6ea2..fb853a6 100644 (file)
--- a/av.c
+++ b/av.c
@@ -977,7 +977,7 @@ Perl_av_exists(pTHX_ AV *av, I32 key)
             mg = mg_find(sv, PERL_MAGIC_tiedelem);
             if (mg) {
                 magic_existspack(sv, mg);
-                return (bool)SvTRUE(sv);
+                return cBOOL(SvTRUE(sv));
             }
 
         }
diff --git a/handy.h b/handy.h
index 81bf1e2..ebe523f 100644 (file)
--- a/handy.h
+++ b/handy.h
@@ -110,6 +110,12 @@ Null SV pointer. (No longer available when C<PERL_CORE> is defined.)
 # define HAS_BOOL 1
 #endif
 
+/* a simple (bool) cast may not do the right thing: if bool is defined
+ * as char for example, then the cast from int is implementation-defined
+ */
+
+#define cBOOL(cbool) ((bool)!!(cbool))
+
 /* Try to figure out __func__ or __FUNCTION__ equivalent, if any.
  * XXX Should really be a Configure probe, with HAS__FUNCTION__
  *     and FUNCTION__ as results.
diff --git a/mg.c b/mg.c
index 3fb8ec4..4a8d767 100644 (file)
--- a/mg.c
+++ b/mg.c
@@ -193,7 +193,7 @@ Perl_mg_get(pTHX_ SV *sv)
 {
     dVAR;
     const I32 mgs_ix = SSNEW(sizeof(MGS));
-    const bool was_temp = (bool)SvTEMP(sv);
+    const bool was_temp = cBOOL(SvTEMP(sv));
     bool have_new = 0;
     MAGIC *newmg, *head, *cur, *mg;
     /* guard against sv having being freed midway by holding a private
@@ -2359,7 +2359,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
        sv_setsv(PL_bodytarget, sv);
        break;
     case '\003':       /* ^C */
-       PL_minus_c = (bool)SvIV(sv);
+       PL_minus_c = cBOOL(SvIV(sv));
        break;
 
     case '\004':       /* ^D */
index bfe6742..b116376 100644 (file)
--- a/numeric.c
+++ b/numeric.c
@@ -142,7 +142,7 @@ Perl_grok_bin(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result)
     NV value_nv = 0;
 
     const UV max_div_2 = UV_MAX / 2;
-    const bool allow_underscores = (bool)(*flags & PERL_SCAN_ALLOW_UNDERSCORES);
+    const bool allow_underscores = cBOOL(*flags & PERL_SCAN_ALLOW_UNDERSCORES);
     bool overflowed = FALSE;
     char bit;
 
@@ -259,7 +259,7 @@ Perl_grok_hex(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result)
     UV value = 0;
     NV value_nv = 0;
     const UV max_div_16 = UV_MAX / 16;
-    const bool allow_underscores = (bool)(*flags & PERL_SCAN_ALLOW_UNDERSCORES);
+    const bool allow_underscores = cBOOL(*flags & PERL_SCAN_ALLOW_UNDERSCORES);
     bool overflowed = FALSE;
 
     PERL_ARGS_ASSERT_GROK_HEX;
@@ -373,7 +373,7 @@ Perl_grok_oct(pTHX_ const char *start, STRLEN *len_p, I32 *flags, NV *result)
     UV value = 0;
     NV value_nv = 0;
     const UV max_div_8 = UV_MAX / 8;
-    const bool allow_underscores = (bool)(*flags & PERL_SCAN_ALLOW_UNDERSCORES);
+    const bool allow_underscores = cBOOL(*flags & PERL_SCAN_ALLOW_UNDERSCORES);
     bool overflowed = FALSE;
 
     PERL_ARGS_ASSERT_GROK_OCT;
diff --git a/pp.c b/pp.c
index 9565c6c..2c5f69a 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -1030,7 +1030,7 @@ PP(pp_pow)
                           on same algorithm as above */
                        register UV result = 1;
                        register UV base = baseuv;
-                       const bool odd_power = (bool)(power & 1);
+                       const bool odd_power = cBOOL(power & 1);
                        if (odd_power) {
                            result *= base;
                        }
index 17a0dc6..a9b3335 100644 (file)
--- a/regexec.c
+++ b/regexec.c
                     LEAVE;                                                              \
                 }                                                                       \
                 if (!(OP(scan) == NAME                                                  \
-                    ? (bool)swash_fetch(CAT2(PL_utf8_,CLASS), (U8*)locinput, do_utf8)   \
+                    ? cBOOL(swash_fetch(CAT2(PL_utf8_,CLASS), (U8*)locinput, do_utf8))  \
                     : LCFUNC_utf8((U8*)locinput)))                                      \
                 {                                                                       \
                     sayNO;                                                              \
                     LEAVE;                                                              \
                 }                                                                       \
                 if ((OP(scan) == NAME                                                  \
-                    ? (bool)swash_fetch(CAT2(PL_utf8_,CLASS), (U8*)locinput, do_utf8)    \
+                    ? cBOOL(swash_fetch(CAT2(PL_utf8_,CLASS), (U8*)locinput, do_utf8))  \
                     : LCFUNC_utf8((U8*)locinput)))                                      \
                 {                                                                       \
                     sayNO;                                                              \
@@ -1179,7 +1179,7 @@ uvc, charid, foldlen, foldbuf, uniflags) STMT_START {                       \
     if ( (CoNd)                                        \
         && (ln == len ||                              \
             !ibcmp_utf8(s, &my_strend, 0,  do_utf8,   \
-                       m, NULL, ln, (bool)UTF))       \
+                       m, NULL, ln, cBOOL(UTF)))      \
         && (!reginfo || regtry(reginfo, &s)) )        \
        goto got_it;                                   \
     else {                                             \
@@ -1190,7 +1190,7 @@ uvc, charid, foldlen, foldbuf, uniflags) STMT_START {                       \
              && (f == c1 || f == c2)                  \
              && (ln == len ||                         \
                !ibcmp_utf8(s, &my_strend, 0,  do_utf8,\
-                             m, NULL, ln, (bool)UTF)) \
+                             m, NULL, ln, cBOOL(UTF)))\
              && (!reginfo || regtry(reginfo, &s)) )   \
              goto got_it;                             \
     }                                                  \
@@ -1479,7 +1479,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
                LOAD_UTF8_CHARCLASS_ALNUM();
                REXEC_FBC_UTF8_SCAN(
                    if (tmp == !(OP(c) == BOUND ?
-                                (bool)swash_fetch(PL_utf8_alnum, (U8*)s, do_utf8) :
+                                cBOOL(swash_fetch(PL_utf8_alnum, (U8*)s, do_utf8)) :
                                 isALNUM_LC_utf8((U8*)s)))
                    {
                        tmp = !tmp;
@@ -1517,7 +1517,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
                LOAD_UTF8_CHARCLASS_ALNUM();
                REXEC_FBC_UTF8_SCAN(
                    if (tmp == !(OP(c) == NBOUND ?
-                                (bool)swash_fetch(PL_utf8_alnum, (U8*)s, do_utf8) :
+                                cBOOL(swash_fetch(PL_utf8_alnum, (U8*)s, do_utf8)) :
                                 isALNUM_LC_utf8((U8*)s)))
                        tmp = !tmp;
                    else REXEC_FBC_TRYIT;
@@ -1872,7 +1872,7 @@ Perl_regexec_flags(pTHX_ REGEXP * const rx, char *stringarg, register char *stre
     I32 end_shift = 0;                 /* Same for the end. */         /* CC */
     I32 scream_pos = -1;               /* Internal iterator of scream. */
     char *scream_olds = NULL;
-    const bool do_utf8 = (bool)DO_UTF8(sv);
+    const bool do_utf8 = cBOOL(DO_UTF8(sv));
     I32 multiline;
     RXi_GET_DECL(prog,progi);
     regmatch_info reginfo;  /* create some info to pass to regtry etc */
@@ -3419,7 +3419,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog)
                const char * const l = locinput;
                char *e = PL_regeol;
 
-               if (ibcmp_utf8(s, 0,  ln, (bool)UTF,
+               if (ibcmp_utf8(s, 0,  ln, cBOOL(UTF),
                               l, &e, 0,  do_utf8)) {
                     /* One more case for the sharp s:
                      * pack("U0U*", 0xDF) =~ /ss/i,
@@ -4055,7 +4055,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog)
                /* NOTREACHED */
            }
            /* logical is 1,   /(?(?{...})X|Y)/ */
-           sw = (bool)SvTRUE(ret);
+           sw = cBOOL(SvTRUE(ret));
            logical = 0;
            break;
        }
@@ -4156,11 +4156,11 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog)
            /*NOTREACHED*/          
        case GROUPP:
            n = ARG(scan);  /* which paren pair */
-           sw = (bool)(*PL_reglastparen >= n && PL_regoffs[n].end != -1);
+           sw = cBOOL(*PL_reglastparen >= n && PL_regoffs[n].end != -1);
            break;
        case NGROUPP:
            /* reg_check_named_buff_matched returns 0 for no match */
-           sw = (bool)(0 < reg_check_named_buff_matched(rex,scan));
+           sw = cBOOL(0 < reg_check_named_buff_matched(rex,scan));
            break;
         case INSUBP:
             n = ARG(scan);
@@ -5167,7 +5167,7 @@ NULL
                    /* trivial fail */
                    if (logical) {
                        logical = 0;
-                       sw = 1 - (bool)ST.wanted;
+                       sw = 1 - cBOOL(ST.wanted);
                    }
                    else if (ST.wanted)
                        sayNO;
@@ -5196,7 +5196,7 @@ NULL
 
        case IFMATCH_A: /* body of (?...A) succeeded */
            if (ST.logical) {
-               sw = (bool)ST.wanted;
+               sw = cBOOL(ST.wanted);
            }
            else if (!ST.wanted)
                sayNO;
diff --git a/scope.c b/scope.c
index 994151e..2a9d2d0 100644 (file)
--- a/scope.c
+++ b/scope.c
@@ -780,7 +780,7 @@ Perl_leave_scope(pTHX_ I32 base)
            break;
        case SAVEt_BOOL:                        /* bool reference */
            ptr = SSPOPPTR;
-           *(bool*)ptr = (bool)SSPOPBOOL;
+           *(bool*)ptr = cBOOL(SSPOPBOOL);
            break;
        case SAVEt_I32:                         /* I32 reference */
            ptr = SSPOPPTR;
diff --git a/sv.c b/sv.c
index 5759b2b..21d0a8e 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -3124,7 +3124,7 @@ Perl_sv_2bool(pTHX_ register SV *const sv)
        if (SvAMAGIC(sv)) {
            SV * const tmpsv = AMG_CALLun(sv,bool_);
            if (tmpsv && (!SvROK(tmpsv) || (SvRV(tmpsv) != SvRV(sv))))
-               return (bool)SvTRUE(tmpsv);
+               return cBOOL(SvTRUE(tmpsv));
        }
        return SvRV(sv) != 0;
     }
@@ -11243,7 +11243,7 @@ Perl_sv_dup(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
                        daux->xhv_riter = saux->xhv_riter;
                        daux->xhv_eiter = saux->xhv_eiter
                            ? he_dup(saux->xhv_eiter,
-                                       (bool)!!HvSHAREKEYS(sstr), param) : 0;
+                                       cBOOL(HvSHAREKEYS(sstr)), param) : 0;
                        /* backref array needs refcnt=2; see sv_add_backref */
                        daux->xhv_backreferences =
                            saux->xhv_backreferences
@@ -11696,7 +11696,7 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl, CLONE_PARAMS* param)
            ptr = POPPTR(ss,ix);
            TOPPTR(nss,ix) = any_dup(ptr, proto_perl);
            longval = (long)POPBOOL(ss,ix);
-           TOPBOOL(nss,ix) = (bool)longval;
+           TOPBOOL(nss,ix) = cBOOL(longval);
            break;
        case SAVEt_SET_SVFLAGS:
            i = POPINT(ss,ix);
diff --git a/toke.c b/toke.c
index b6735cf..b5236da 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -13700,7 +13700,7 @@ S_utf16_textfilter(pTHX_ int idx, SV *sv, int maxlen)
     SV *const utf16_buffer = MUTABLE_SV(IoTOP_GV(filter));
     SV *const utf8_buffer = filter;
     IV status = IoPAGE(filter);
-    const bool reverse = (bool) IoLINES(filter);
+    const bool reverse = cBOOL(IoLINES(filter));
     I32 retval;
 
     /* As we're automatically added, at the lowest level, and hence only called