summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Mai <l.mai@web.de>2014-11-29 12:17:05 +0100
committerFather Chrysostomos <sprout@cpan.org>2014-11-29 06:11:08 -0800
commit6d59e610a3f269be73ffea56a90d1cd7dc8bf2fd (patch)
tree3323ee9f84c4e0909c8066796c8ea4bfa4e36bbd
parente59642234eb8b658c16fed728636bfbbc49c4514 (diff)
downloadperl-6d59e610a3f269be73ffea56a90d1cd7dc8bf2fd.tar.gz
define and use STATIC_ASSERT_STMT for compile-time invariants
-rw-r--r--op.c2
-rw-r--r--perl.h26
-rw-r--r--pp.c2
-rw-r--r--pp_hot.c2
-rw-r--r--pp_sys.c6
-rw-r--r--sv.c8
-rw-r--r--toke.c2
7 files changed, 36 insertions, 12 deletions
diff --git a/op.c b/op.c
index 30410b6919..523fd5ca96 100644
--- a/op.c
+++ b/op.c
@@ -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)));
diff --git a/perl.h b/perl.h
index f36157c360..8a930deb4a 100644
--- a/perl.h
+++ b/perl.h
@@ -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 */
diff --git a/pp.c b/pp.c
index fdd23350bf..6d575f75ca 100644
--- a/pp.c
+++ b/pp.c
@@ -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))
diff --git a/pp_hot.c b/pp_hot.c
index 846c1af882..48cc1cbea7 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -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;
diff --git a/pp_sys.c b/pp_sys.c
index 0bc1aa179f..8f6c75326c 100644
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -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);
diff --git a/sv.c b/sv.c
index 40b614e81e..3cbcbf8664 100644
--- a/sv.c
+++ b/sv.c
@@ -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;
diff --git a/toke.c b/toke.c
index 236acd5adc..2433f1f796 100644
--- a/toke.c
+++ b/toke.c
@@ -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));