diff options
author | Lukas Mai <l.mai@web.de> | 2014-11-29 12:17:05 +0100 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2014-11-29 06:11:08 -0800 |
commit | 6d59e610a3f269be73ffea56a90d1cd7dc8bf2fd (patch) | |
tree | 3323ee9f84c4e0909c8066796c8ea4bfa4e36bbd | |
parent | e59642234eb8b658c16fed728636bfbbc49c4514 (diff) | |
download | perl-6d59e610a3f269be73ffea56a90d1cd7dc8bf2fd.tar.gz |
define and use STATIC_ASSERT_STMT for compile-time invariants
-rw-r--r-- | op.c | 2 | ||||
-rw-r--r-- | perl.h | 26 | ||||
-rw-r--r-- | pp.c | 2 | ||||
-rw-r--r-- | pp_hot.c | 2 | ||||
-rw-r--r-- | pp_sys.c | 6 | ||||
-rw-r--r-- | sv.c | 8 | ||||
-rw-r--r-- | toke.c | 2 |
7 files changed, 36 insertions, 12 deletions
@@ -9627,7 +9627,7 @@ Perl_ck_rvconst(pTHX_ OP *o) SvREFCNT_dec(kid->op_sv); #ifdef USE_ITHREADS /* XXX hack: dependence on sizeof(PADOP) <= sizeof(SVOP) */ - assert (sizeof(PADOP) <= sizeof(SVOP)); + STATIC_ASSERT_STMT(sizeof(PADOP) <= sizeof(SVOP)); kPADOP->op_padix = pad_alloc(OP_GV, SVf_READONLY); SvREFCNT_dec(PAD_SVl(kPADOP->op_padix)); PAD_SETSV(kPADOP->op_padix, MUTABLE_SV(SvREFCNT_inc_simple_NN(gv))); @@ -3467,7 +3467,10 @@ typedef pthread_key_t perl_key; # define __attribute__warn_unused_result__ #endif -#if defined(DEBUGGING) && defined(I_ASSERT) +#ifdef I_ASSERT +# if !defined(DEBUGGING) && !defined(NDEBUG) +# define NDEBUG 1 +# endif # include <assert.h> #endif @@ -3498,6 +3501,27 @@ typedef pthread_key_t perl_key; /* placeholder */ #endif +#if defined(static_assert) || (defined(__cplusplus) && __cplusplus >= 201103L) +/* static_assert is a macro defined in <assert.h> in C11 or a compiler + builtin in C++11. +*/ +# define STATIC_ASSERT_GLOBAL(COND) static_assert(COND, #COND) +#else +/* We use a bit-field instead of an array because gcc accepts + 'typedef char x[n]' where n is not a compile-time constant. + We want to enforce constantness. +*/ +# define STATIC_ASSERT_2(COND, SUFFIX) \ + typedef struct { \ + unsigned int _static_assertion_failed_##SUFFIX : (COND) ? 1 : -1; \ + } _static_assertion_failed_##SUFFIX PERL_UNUSED_DECL +# define STATIC_ASSERT_1(COND, SUFFIX) STATIC_ASSERT_2(COND, SUFFIX) +# define STATIC_ASSERT_GLOBAL(COND) STATIC_ASSERT_1(COND, __LINE__) +#endif +/* We need this wrapper even in C11 because 'case X: static_assert(...);' is an + error (static_assert is a declaration, and only statements can have labels). +*/ +#define STATIC_ASSERT_STMT(COND) do { STATIC_ASSERT_GLOBAL(COND); } while (0) #ifndef __has_builtin # define __has_builtin(x) 0 /* not a clang style compiler */ @@ -2956,7 +2956,7 @@ PP(pp_length) /* simplest case shortcut */ /* turn off SVf_UTF8 in tmp flags if HINT_BYTES on*/ U32 svflags = (SvFLAGS(sv) ^ (in_bytes << 26)) & (SVf_POK|SVs_GMG|SVf_UTF8); - assert(HINT_BYTES == 0x00000008 && SVf_UTF8 == 0x20000000 && (SVf_UTF8 == HINT_BYTES << 26)); + STATIC_ASSERT_STMT(HINT_BYTES == 0x00000008 && SVf_UTF8 == 0x20000000 && (SVf_UTF8 == HINT_BYTES << 26)); SETs(TARG); if(LIKELY(svflags == SVf_POK)) @@ -386,7 +386,7 @@ PP(pp_padrange) (base << (OPpPADRANGE_COUNTSHIFT + SAVE_TIGHT_SHIFT)) | (count << SAVE_TIGHT_SHIFT) | SAVEt_CLEARPADRANGE); - assert(OPpPADRANGE_COUNTMASK + 1 == (1 <<OPpPADRANGE_COUNTSHIFT)); + STATIC_ASSERT_STMT(OPpPADRANGE_COUNTMASK + 1 == (1 << OPpPADRANGE_COUNTSHIFT)); assert((payload >> (OPpPADRANGE_COUNTSHIFT+SAVE_TIGHT_SHIFT)) == base); { dSS_ADD; @@ -534,9 +534,9 @@ Perl_tied_method(pTHX_ SV *methname, SV **sp, SV *const sv, PERL_ARGS_ASSERT_TIED_METHOD; /* Ensure that our flag bits do not overlap. */ - assert((TIED_METHOD_MORTALIZE_NOT_NEEDED & G_WANT) == 0); - assert((TIED_METHOD_ARGUMENTS_ON_STACK & G_WANT) == 0); - assert((TIED_METHOD_SAY & G_WANT) == 0); + STATIC_ASSERT_STMT((TIED_METHOD_MORTALIZE_NOT_NEEDED & G_WANT) == 0); + STATIC_ASSERT_STMT((TIED_METHOD_ARGUMENTS_ON_STACK & G_WANT) == 0); + STATIC_ASSERT_STMT((TIED_METHOD_SAY & G_WANT) == 0); PUTBACK; /* sp is at *foot* of args, so this pops args from old stack */ PUSHSTACKi(PERLSI_MAGIC); @@ -1320,8 +1320,8 @@ Perl_sv_upgrade(pTHX_ SV *const sv, svtype new_type) break; case SVt_PV: assert(new_type > SVt_PV); - assert(SVt_IV < SVt_PV); - assert(SVt_NV < SVt_PV); + STATIC_ASSERT_STMT(SVt_IV < SVt_PV); + STATIC_ASSERT_STMT(SVt_NV < SVt_PV); break; case SVt_PVIV: break; @@ -4311,7 +4311,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, SV* sstr, const I32 flags) /* We're starting from SVt_NULL, so provided that's * actual 0, we don't have to unset any SV type flags * to promote to SVt_IV. */ - assert(SVt_NULL == 0); + STATIC_ASSERT_STMT(SVt_NULL == 0); SET_SVANY_FOR_BODYLESS_IV(dstr); SvFLAGS(dstr) |= SVt_IV; break; @@ -9366,7 +9366,7 @@ Perl_newSViv(pTHX_ const IV i) /* We're starting from SVt_FIRST, so provided that's * actual 0, we don't have to unset any SV type flags * to promote to SVt_IV. */ - assert(SVt_FIRST == 0); + STATIC_ASSERT_STMT(SVt_FIRST == 0); SET_SVANY_FOR_BODYLESS_IV(sv); SvFLAGS(sv) |= SVt_IV; @@ -730,7 +730,7 @@ Perl_lex_start(pTHX_ SV *line, PerlIO *rsfp, U32 flags) parser->bufend = parser->bufptr + SvCUR(parser->linestr); parser->last_lop = parser->last_uni = NULL; - assert(FITS_IN_8_BITS(LEX_IGNORE_UTF8_HINTS|LEX_EVALBYTES + STATIC_ASSERT_STMT(FITS_IN_8_BITS(LEX_IGNORE_UTF8_HINTS|LEX_EVALBYTES |LEX_DONT_CLOSE_RSFP)); parser->lex_flags = (U8) (flags & (LEX_IGNORE_UTF8_HINTS|LEX_EVALBYTES |LEX_DONT_CLOSE_RSFP)); |