From: Nicholas Clark <nick@ccl4.org>
Date: Mon, 27 Oct 2008 20:25:46 +0000 (+0000)
Subject: Add a macro MUTABLE_PTR(p), which on (non-pedantic) gcc will not cast
X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=b1bc3f345d4dfe19cd94c120c46649336b5cb92b;p=p5sagit%2Fp5-mst-13.2.git

Add a macro MUTABLE_PTR(p), which on (non-pedantic) gcc will not cast
away const, returning a void *. Add MUTABLE_SV(sv) which uses this, and
replace all (SV *) casts either with MUTABLE_SV(sv), or (const SV *).

This probably still needs some work - assigning to SvPVX() and SvRV()
is now likely to generate a casting error. The core doesn't do this.
But as-is it's finding bugs that can be fixed.

p4raw-id: //depot/perl@34605
---

diff --git a/av.h b/av.h
index a11a05b..c48df39 100644
--- a/av.h
+++ b/av.h
@@ -88,8 +88,8 @@ Same as C<av_len()>.  Deprecated, use C<av_len()> instead.
 
 #define AvREALISH(av)	(SvFLAGS(av) & (SVpav_REAL|SVpav_REIFY))
                                           
-#define AvFILL(av)	((SvRMAGICAL((SV *) (av))) \
-			  ? mg_size((SV *) av) : AvFILLp(av))
+#define AvFILL(av)	((SvRMAGICAL((const SV *) (av))) \
+			 ? mg_size(MUTABLE_SV(av)) : AvFILLp(av))
 
 #define NEGATIVE_INDICES_VAR "NEGATIVE_INDICES"
 
diff --git a/cop.h b/cop.h
index 6824f4a..3cd3d69 100644
--- a/cop.h
+++ b/cop.h
@@ -360,13 +360,13 @@ struct block_format {
 		cx->blk_sub.argarray = newAV();				\
 		av_extend(cx->blk_sub.argarray, fill);			\
 		AvREIFY_only(cx->blk_sub.argarray);			\
-		CX_CURPAD_SV(cx->blk_sub, 0) = (SV*)cx->blk_sub.argarray;	\
+		CX_CURPAD_SV(cx->blk_sub, 0) = MUTABLE_SV(cx->blk_sub.argarray); \
 	    }								\
 	    else {							\
 		CLEAR_ARGARRAY(cx->blk_sub.argarray);			\
 	    }								\
 	}								\
-	sv = (SV*)cx->blk_sub.cv;					\
+	sv = MUTABLE_SV(cx->blk_sub.cv);				\
 	if (sv && (CvDEPTH((CV*)sv) = cx->blk_sub.olddepth))		\
 	    sv = NULL;						\
     } STMT_END
diff --git a/gv.h b/gv.h
index f55d41f..85b0380 100644
--- a/gv.h
+++ b/gv.h
@@ -88,7 +88,7 @@ Return the SV from the GV.
 #endif
 
 #define GvREFCNT(gv)	(GvGP(gv)->gp_refcnt)
-#define GvIO(gv)	((gv) && SvTYPE((SV*)gv) == SVt_PVGV && GvGP(gv) ? GvIOp(gv) : NULL)
+#define GvIO(gv)	((gv) && SvTYPE((const SV*)gv) == SVt_PVGV && GvGP(gv) ? GvIOp(gv) : NULL)
 #define GvIOp(gv)	(GvGP(gv)->gp_io)
 #define GvIOn(gv)	(GvIO(gv) ? GvIOp(gv) : GvIOp(gv_IOadd(gv)))
 
diff --git a/handy.h b/handy.h
index d51b75d..d6a9026 100644
--- a/handy.h
+++ b/handy.h
@@ -48,6 +48,13 @@ Null SV pointer. (No longer available when C<PERL_CORE> is defined.)
 #define TRUE (1)
 #define FALSE (0)
 
+#if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
+#  define MUTABLE_PTR(p) ({ void *_p = (p); (void *) _p; })
+#else
+#  define MUTABLE_PTR(p) ((void *) (p))
+#endif
+
+#define MUTABLE_SV(p)	((SV *)MUTABLE_PTR(p))
 
 /* XXX Configure ought to have a test for a boolean type, if I can
    just figure out all the headers such a test needs.
diff --git a/hv.h b/hv.h
index 7f96a13..b5d0bda 100644
--- a/hv.h
+++ b/hv.h
@@ -394,7 +394,7 @@ C<SV*>.
 #define HV_ITERNEXT_WANTPLACEHOLDERS	0x01	/* Don't skip placeholders.  */
 
 #define hv_iternext(hv)	hv_iternext_flags(hv, 0)
-#define hv_magic(hv, gv, how) sv_magic((SV*)(hv), (SV*)(gv), how, NULL, 0)
+#define hv_magic(hv, gv, how) sv_magic(MUTABLE_SV(hv), MUTABLE_SV(gv), how, NULL, 0)
 
 /* available as a function in hv.c */
 #define Perl_sharepvn(sv, len, hash) HEK_KEY(share_hek(sv, len, hash))
@@ -418,8 +418,8 @@ C<SV*>.
     ((HE *) hv_common((hv), (keysv), NULL, 0, 0,			\
 		      ((lval) ? HV_FETCH_LVALUE : 0), NULL, (hash)))
 #define hv_delete_ent(hv, key, flags, hash)				\
-    ((SV *) hv_common((hv), (key), NULL, 0, 0, (flags) | HV_DELETE,	\
-		      NULL, (hash)))
+    (MUTABLE_SV(hv_common((hv), (key), NULL, 0, 0, (flags) | HV_DELETE,	\
+			  NULL, (hash))))
 
 #define hv_store_flags(hv, key, klen, val, hash, flags)			\
     ((SV**) hv_common((hv), NULL, (key), (klen), (flags),		\
@@ -441,8 +441,8 @@ C<SV*>.
 			      : HV_FETCH_JUST_SV, NULL, 0))
 
 #define hv_delete(hv, key, klen, flags)					\
-    ((SV*) hv_common_key_len((hv), (key), (klen),			\
-			     (flags) | HV_DELETE, NULL, 0))
+    (MUTABLE_SV(hv_common_key_len((hv), (key), (klen),			\
+				  (flags) | HV_DELETE, NULL, 0)))
 
 /* This refcounted he structure is used for storing the hints used for lexical
    pragmas. Without threads, it's basically struct he + refcount.
diff --git a/mg.h b/mg.h
index 1274efd..fcac411 100644
--- a/mg.h
+++ b/mg.h
@@ -48,13 +48,13 @@ struct magic {
 #define MgTAINTEDDIR_off(mg)	(mg->mg_flags &= ~MGf_TAINTEDDIR)
 
 #define MgPV(mg,lp)		((((int)(lp = (mg)->mg_len)) == HEf_SVKEY) ?   \
-				 SvPV((SV*)((mg)->mg_ptr),lp) :		\
+				 SvPV(MUTABLE_SV((mg)->mg_ptr),lp) :	\
 				 (mg)->mg_ptr)
 #define MgPV_const(mg,lp)	((((int)(lp = (mg)->mg_len)) == HEf_SVKEY) ? \
-				 SvPV_const((SV*)((mg)->mg_ptr),lp) :        \
+				 SvPV_const(MUTABLE_SV((mg)->mg_ptr),lp) :   \
 				 (const char*)(mg)->mg_ptr)
-#define MgPV_nolen_const(mg)	(((((int)(mg)->mg_len)) == HEf_SVKEY) ?   \
-				 SvPV_nolen_const((SV*)((mg)->mg_ptr)) :  \
+#define MgPV_nolen_const(mg)	(((((int)(mg)->mg_len)) == HEf_SVKEY) ?	\
+				 SvPV_nolen_const(MUTABLE_SV((mg)->mg_ptr)) : \
 				 (const char*)(mg)->mg_ptr)
 
 #define SvTIED_mg(sv,how) (SvRMAGICAL(sv) ? mg_find((sv),(how)) : NULL)
diff --git a/op.h b/op.h
index 438c936..c1120f7 100644
--- a/op.h
+++ b/op.h
@@ -340,9 +340,9 @@ struct pmop {
 /* BEWARE - something that calls this macro passes (r) which has a side
    effect.  */
 #define PM_SETRE(o,r)	STMT_START {					\
-                            const REGEXP *const _pm_setre = (r);	\
+                            REGEXP *const _pm_setre = (r);		\
                             assert(_pm_setre);				\
-			    PL_regex_pad[(o)->op_pmoffset] = (SV*)_pm_setre; \
+			    PL_regex_pad[(o)->op_pmoffset] = MUTABLE_SV(_pm_setre); \
                         } STMT_END
 #else
 #define PM_GETRE(o)     ((o)->op_pmregexp)
diff --git a/pad.h b/pad.h
index 647db33..2f0fb7c 100644
--- a/pad.h
+++ b/pad.h
@@ -37,7 +37,7 @@ typedef U64TYPE PADOFFSET;
 
 #if defined (DEBUGGING) && defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
 #  define COP_SEQ_RANGE_LOW(sv)						\
-	(({ SV *const _sv_cop_seq_range_low = (SV *) (sv);		\
+	(({ const SV *const _sv_cop_seq_range_low = (const SV *) (sv);	\
 	  assert(SvTYPE(_sv_cop_seq_range_low) == SVt_NV		\
 		 || SvTYPE(_sv_cop_seq_range_low) >= SVt_PVNV);		\
 	  assert(SvTYPE(_sv_cop_seq_range_low) != SVt_PVAV);		\
@@ -45,10 +45,10 @@ typedef U64TYPE PADOFFSET;
 	  assert(SvTYPE(_sv_cop_seq_range_low) != SVt_PVCV);		\
 	  assert(SvTYPE(_sv_cop_seq_range_low) != SVt_PVFM);		\
 	  assert(!isGV_with_GP(_sv_cop_seq_range_low));			\
-	  ((XPVNV*) SvANY(_sv_cop_seq_range_low))->xnv_u.xpad_cop_seq.xlow; \
+	  ((XPVNV*) MUTABLE_PTR(SvANY(_sv_cop_seq_range_low)))->xnv_u.xpad_cop_seq.xlow; \
 	 }))
 #  define COP_SEQ_RANGE_HIGH(sv)					\
-	(({ SV *const _sv_cop_seq_range_high = (SV *) (sv);		\
+	(({ const SV *const _sv_cop_seq_range_high = (const SV *) (sv);	\
 	  assert(SvTYPE(_sv_cop_seq_range_high) == SVt_NV 		\
                  || SvTYPE(_sv_cop_seq_range_high) >= SVt_PVNV);	\
 	  assert(SvTYPE(_sv_cop_seq_range_high) != SVt_PVAV);		\
@@ -56,10 +56,10 @@ typedef U64TYPE PADOFFSET;
 	  assert(SvTYPE(_sv_cop_seq_range_high) != SVt_PVCV);		\
 	  assert(SvTYPE(_sv_cop_seq_range_high) != SVt_PVFM);		\
 	  assert(!isGV_with_GP(_sv_cop_seq_range_high));		\
-	  ((XPVNV*) SvANY(_sv_cop_seq_range_high))->xnv_u.xpad_cop_seq.xhigh; \
+	  ((XPVNV*) MUTABLE_PTR(SvANY(_sv_cop_seq_range_high)))->xnv_u.xpad_cop_seq.xhigh; \
 	 }))
 #  define PARENT_PAD_INDEX(sv)						\
-	(({ SV *const _sv_parent_pad_index = (SV *) (sv);		\
+	(({ const SV *const _sv_parent_pad_index = (const SV *) (sv);	\
 	  assert(SvTYPE(_sv_parent_pad_index) == SVt_NV			\
 		 || SvTYPE(_sv_parent_pad_index) >= SVt_PVNV);		\
 	  assert(SvTYPE(_sv_parent_pad_index) != SVt_PVAV);		\
@@ -67,10 +67,10 @@ typedef U64TYPE PADOFFSET;
 	  assert(SvTYPE(_sv_parent_pad_index) != SVt_PVCV);		\
 	  assert(SvTYPE(_sv_parent_pad_index) != SVt_PVFM);		\
 	  assert(!isGV_with_GP(_sv_parent_pad_index));			\
-	  ((XPVNV*) SvANY(_sv_parent_pad_index))->xnv_u.xpad_cop_seq.xlow; \
+	  ((XPVNV*) MUTABLE_PTR(SvANY(_sv_parent_pad_index)))->xnv_u.xpad_cop_seq.xlow; \
 	 }))
 #  define PARENT_FAKELEX_FLAGS(sv)					\
-	(({ SV *const _sv_parent_fakelex_flags = (SV *) (sv);		\
+	(({ const SV *const _sv_parent_fakelex_flags = (const SV *) (sv); \
 	  assert(SvTYPE(_sv_parent_fakelex_flags) == SVt_NV  		\
 		 || SvTYPE(_sv_parent_fakelex_flags) >= SVt_PVNV);	\
 	  assert(SvTYPE(_sv_parent_fakelex_flags) != SVt_PVAV);		\
@@ -78,7 +78,7 @@ typedef U64TYPE PADOFFSET;
 	  assert(SvTYPE(_sv_parent_fakelex_flags) != SVt_PVCV);		\
 	  assert(SvTYPE(_sv_parent_fakelex_flags) != SVt_PVFM);		\
 	  assert(!isGV_with_GP(_sv_parent_fakelex_flags));		\
-	  ((XPVNV*) SvANY(_sv_parent_fakelex_flags))->xnv_u.xpad_cop_seq.xhigh;	\
+	  ((XPVNV*) MUTABLE_PTR(SvANY(_sv_parent_fakelex_flags)))->xnv_u.xpad_cop_seq.xhigh; \
 	 }))
 #else
 #  define COP_SEQ_RANGE_LOW(sv)		\
diff --git a/scope.h b/scope.h
index 067c56d..de658f3 100644
--- a/scope.h
+++ b/scope.h
@@ -127,8 +127,8 @@ Closing bracket on a callback.  See C<ENTER> and L<perlcall>.
 #define SAVEPPTR(s)	save_pptr((char**)&(s))
 #define SAVEVPTR(s)	save_vptr((void*)&(s))
 #define SAVEPADSVANDMORTALIZE(s)	save_padsv_and_mortalize(s)
-#define SAVEFREESV(s)	save_freesv((SV*)(s))
-#define SAVEMORTALIZESV(s)	save_mortalizesv((SV*)(s))
+#define SAVEFREESV(s)	save_freesv(MUTABLE_SV(s))
+#define SAVEMORTALIZESV(s)	save_mortalizesv(MUTABLE_SV(s))
 #define SAVEFREEOP(o)	save_freeop((OP*)(o))
 #define SAVEFREEPV(p)	save_freepv((char*)(p))
 #define SAVECLEARSV(sv)	save_clearsv((SV**)&(sv))
@@ -173,15 +173,15 @@ Closing bracket on a callback.  See C<ENTER> and L<perlcall>.
 #define SAVECOMPPAD() \
     STMT_START {						\
 	SSCHECK(2);						\
-	SSPUSHPTR((SV*)PL_comppad);				\
+	SSPUSHPTR(MUTABLE_SV(PL_comppad));			\
 	SSPUSHINT(SAVEt_COMPPAD);				\
     } STMT_END
 
 #define SAVESWITCHSTACK(f,t) \
     STMT_START {					\
 	SSCHECK(3);					\
-	SSPUSHPTR((SV*)(f));				\
-	SSPUSHPTR((SV*)(t));				\
+	SSPUSHPTR(MUTABLE_SV(f));			\
+	SSPUSHPTR(MUTABLE_SV(t));			\
 	SSPUSHINT(SAVEt_SAVESWITCHSTACK);		\
 	SWITCHSTACK((f),(t));				\
 	PL_curstackinfo->si_stack = (t);		\
diff --git a/sv.h b/sv.h
index c92e31e..964dae0 100644
--- a/sv.h
+++ b/sv.h
@@ -225,7 +225,7 @@ perform the upgrade if necessary.  See C<svtype>.
 #if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
 #  define SvREFCNT_inc(sv)		\
     ({					\
-	SV * const _sv = (SV*)(sv);	\
+	SV * const _sv = MUTABLE_SV(sv);	\
 	if (_sv)			\
 	     (SvREFCNT(_sv))++;		\
 	_sv;				\
@@ -234,41 +234,41 @@ perform the upgrade if necessary.  See C<svtype>.
     ({					\
 	if (sv)				\
 	     (SvREFCNT(sv))++;		\
-	(SV *)(sv);				\
+	MUTABLE_SV(sv);				\
     })
 #  define SvREFCNT_inc_NN(sv)		\
     ({					\
-	SV * const _sv = (SV*)(sv);	\
+	SV * const _sv = MUTABLE_SV(sv);	\
 	SvREFCNT(_sv)++;		\
 	_sv;				\
     })
 #  define SvREFCNT_inc_void(sv)		\
     ({					\
-	SV * const _sv = (SV*)(sv);	\
+	SV * const _sv = MUTABLE_SV(sv);	\
 	if (_sv)			\
 	    (void)(SvREFCNT(_sv)++);	\
     })
 #else
 #  define SvREFCNT_inc(sv)	\
-	((PL_Sv=(SV*)(sv)) ? (++(SvREFCNT(PL_Sv)),PL_Sv) : NULL)
+	((PL_Sv=MUTABLE_SV(sv)) ? (++(SvREFCNT(PL_Sv)),PL_Sv) : NULL)
 #  define SvREFCNT_inc_simple(sv) \
-	((sv) ? (SvREFCNT(sv)++,(SV*)(sv)) : NULL)
+	((sv) ? (SvREFCNT(sv)++,MUTABLE_SV(sv)) : NULL)
 #  define SvREFCNT_inc_NN(sv) \
-	(PL_Sv=(SV*)(sv),++(SvREFCNT(PL_Sv)),PL_Sv)
+	(PL_Sv=MUTABLE_SV(sv),++(SvREFCNT(PL_Sv)),PL_Sv)
 #  define SvREFCNT_inc_void(sv) \
-	(void)((PL_Sv=(SV*)(sv)) ? ++(SvREFCNT(PL_Sv)) : 0)
+	(void)((PL_Sv=MUTABLE_SV(sv)) ? ++(SvREFCNT(PL_Sv)) : 0)
 #endif
 
 /* These guys don't need the curly blocks */
 #define SvREFCNT_inc_simple_void(sv)	STMT_START { if (sv) SvREFCNT(sv)++; } STMT_END
-#define SvREFCNT_inc_simple_NN(sv)	(++(SvREFCNT(sv)),(SV*)(sv))
-#define SvREFCNT_inc_void_NN(sv)	(void)(++SvREFCNT((SV*)(sv)))
-#define SvREFCNT_inc_simple_void_NN(sv)	(void)(++SvREFCNT((SV*)(sv)))
+#define SvREFCNT_inc_simple_NN(sv)	(++(SvREFCNT(sv)),MUTABLE_SV(sv))
+#define SvREFCNT_inc_void_NN(sv)	(void)(++SvREFCNT(MUTABLE_SV(sv)))
+#define SvREFCNT_inc_simple_void_NN(sv)	(void)(++SvREFCNT(MUTABLE_SV(sv)))
 
 #if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
 #  define SvREFCNT_dec(sv)		\
     ({					\
-	SV * const _sv = (SV*)(sv);	\
+	SV * const _sv = MUTABLE_SV(sv);	\
 	if (_sv) {			\
 	    if (SvREFCNT(_sv)) {	\
 		if (--(SvREFCNT(_sv)) == 0) \
@@ -279,7 +279,7 @@ perform the upgrade if necessary.  See C<svtype>.
 	}				\
     })
 #else
-#define SvREFCNT_dec(sv)	sv_free((SV*)(sv))
+#define SvREFCNT_dec(sv)	sv_free(MUTABLE_SV(sv))
 #endif
 
 #define SVTYPEMASK	0xff
@@ -965,21 +965,21 @@ the scalar's value cannot change unless written to.
 #define SvEVALED_off(sv)	(SvFLAGS(sv) &= ~SVrepl_EVAL)
 
 #if defined (DEBUGGING) && defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
-#  define SvVALID(sv)		({ SV *const _svvalid = (SV *) (sv);	\
+#  define SvVALID(sv)		({ SV *const _svvalid = MUTABLE_SV(sv);	\
 				   if (SvFLAGS(_svvalid) & SVpbm_VALID)	\
 				       assert(!isGV_with_GP(_svvalid));	\
 				   (SvFLAGS(_svvalid) & SVpbm_VALID);	\
 				})
-#  define SvVALID_on(sv)	({ SV *const _svvalid = (SV *) (sv);	\
+#  define SvVALID_on(sv)	({ SV *const _svvalid = MUTABLE_SV(sv);	\
 				   assert(!isGV_with_GP(_svvalid));	\
 				   (SvFLAGS(_svvalid) |= SVpbm_VALID);	\
 				})
-#  define SvVALID_off(sv)	({ SV *const _svvalid = (SV *) (sv);	\
+#  define SvVALID_off(sv)	({ SV *const _svvalid = MUTABLE_SV(sv);	\
 				   assert(!isGV_with_GP(_svvalid));	\
 				   (SvFLAGS(_svvalid) &= ~SVpbm_VALID);	\
 				})
 
-#  define SvTAIL(sv)	({ SV *const _svtail = (SV *) (sv);		\
+#  define SvTAIL(sv)	({ SV *const _svtail = MUTABLE_SV(sv);		\
 			    assert(SvTYPE(_svtail) != SVt_PVAV);		\
 			    assert(SvTYPE(_svtail) != SVt_PVHV);		\
 			    (SvFLAGS(sv) & (SVpbm_TAIL|SVpbm_VALID))	\
@@ -1008,17 +1008,17 @@ the scalar's value cannot change unless written to.
 
 #if defined (DEBUGGING) && defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
 #  define SvPAD_TYPED_on(sv)	({					\
-	    SV *const _svpad = (SV *) (sv);				\
+	    SV *const _svpad = MUTABLE_SV(sv);				\
 	    assert(SvTYPE(_svpad) == SVt_PVMG);				\
 	    (SvFLAGS(_svpad) |= SVpad_NAME|SVpad_TYPED);		\
 	})
 #define SvPAD_OUR_on(sv)	({					\
-	    SV *const _svpad = (SV *) (sv);				\
+	    SV *const _svpad = MUTABLE_SV(sv);				\
 	    assert(SvTYPE(_svpad) == SVt_PVMG);				\
 	    (SvFLAGS(_svpad) |= SVpad_NAME|SVpad_OUR);			\
 	})
 #define SvPAD_STATE_on(sv)	({					\
-	    SV *const _svpad = (SV *) (sv);				\
+	    SV *const _svpad = MUTABLE_SV(sv);				\
 	    assert(SvTYPE(_svpad) == SVt_PVNV || SvTYPE(_svpad) == SVt_PVMG); \
 	    (SvFLAGS(_svpad) |= SVpad_NAME|SVpad_STATE);		\
 	})
@@ -1072,7 +1072,7 @@ the scalar's value cannot change unless written to.
 #  if defined (DEBUGGING) && defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
 /* These get expanded inside other macros that already use a variable _sv  */
 #    define SvPVX(sv)							\
-	(*({ SV *const _svpvx = (SV *) (sv);				\
+	(*({ const SV *const _svpvx = (const SV *)(sv);			\
 	    assert(SvTYPE(_svpvx) >= SVt_PV);				\
 	    assert(SvTYPE(_svpvx) != SVt_PVAV);				\
 	    assert(SvTYPE(_svpvx) != SVt_PVHV);				\
@@ -1080,35 +1080,35 @@ the scalar's value cannot change unless written to.
 	    &((_svpvx)->sv_u.svu_pv);					\
 	 }))
 #    define SvCUR(sv)							\
-	(*({ SV *const _svcur = (SV *) (sv);				\
+	(*({ const SV *const _svcur = (const SV *)(sv);			\
 	    assert(SvTYPE(_svcur) >= SVt_PV);				\
 	    assert(SvTYPE(_svcur) != SVt_PVAV);				\
 	    assert(SvTYPE(_svcur) != SVt_PVHV);				\
 	    assert(!isGV_with_GP(_svcur));				\
-	    &(((XPV*) SvANY(_svcur))->xpv_cur);				\
+	    &(((XPV*) MUTABLE_PTR(SvANY(_svcur)))->xpv_cur);		\
 	 }))
 #    define SvIVX(sv)							\
-	(*({ SV *const _svivx = (SV *) (sv);				\
+	(*({ const SV *const _svivx = (const SV *)(sv);			\
 	    assert(SvTYPE(_svivx) == SVt_IV || SvTYPE(_svivx) >= SVt_PVIV); \
 	    assert(SvTYPE(_svivx) != SVt_PVAV);				\
 	    assert(SvTYPE(_svivx) != SVt_PVHV);				\
 	    assert(SvTYPE(_svivx) != SVt_PVCV);				\
 	    assert(SvTYPE(_svivx) != SVt_PVFM);				\
 	    assert(!isGV_with_GP(_svivx));				\
-	    &(((XPVIV*) SvANY(_svivx))->xiv_iv);			\
+	    &(((XPVIV*) MUTABLE_PTR(SvANY(_svivx)))->xiv_iv);		\
 	 }))
 #    define SvUVX(sv)							\
-	(*({ SV *const _svuvx = (SV *) (sv);				\
+	(*({ const SV *const _svuvx = (const SV *)(sv);			\
 	    assert(SvTYPE(_svuvx) == SVt_IV || SvTYPE(_svuvx) >= SVt_PVIV); \
 	    assert(SvTYPE(_svuvx) != SVt_PVAV);				\
 	    assert(SvTYPE(_svuvx) != SVt_PVHV);				\
 	    assert(SvTYPE(_svuvx) != SVt_PVCV);				\
 	    assert(SvTYPE(_svuvx) != SVt_PVFM);				\
 	    assert(!isGV_with_GP(_svuvx));				\
-	    &(((XPVUV*) SvANY(_svuvx))->xuv_uv);			\
+	    &(((XPVUV*) MUTABLE_PTR(SvANY(_svuvx)))->xuv_uv);		\
 	 }))
 #    define SvNVX(sv)							\
-	(*({ SV *const _svnvx = (SV *) (sv);				\
+	(*({ const SV *const _svnvx = (const SV *)(sv);			\
 	    assert(SvTYPE(_svnvx) == SVt_NV || SvTYPE(_svnvx) >= SVt_PVNV); \
 	    assert(SvTYPE(_svnvx) != SVt_PVAV);				\
 	    assert(SvTYPE(_svnvx) != SVt_PVHV);				\
@@ -1116,10 +1116,10 @@ the scalar's value cannot change unless written to.
 	    assert(SvTYPE(_svnvx) != SVt_PVFM);				\
 	    assert(SvTYPE(_svnvx) != SVt_PVIO);				\
 	    assert(!isGV_with_GP(_svnvx));				\
-	   &(((XPVNV*) SvANY(_svnvx))->xnv_u.xnv_nv);			\
+	    &(((XPVNV*) MUTABLE_PTR(SvANY(_svnvx)))->xnv_u.xnv_nv);	\
 	 }))
 #    define SvRV(sv)							\
-	(*({ SV *const _svrv = (SV *) (sv);				\
+	(*({ const SV *const _svrv = (const SV *)(sv);			\
 	    assert(SvTYPE(_svrv) >= SVt_PV || SvTYPE(_svrv) == SVt_IV);	\
 	    assert(SvTYPE(_svrv) != SVt_PVAV);				\
 	    assert(SvTYPE(_svrv) != SVt_PVHV);				\
@@ -1129,16 +1129,16 @@ the scalar's value cannot change unless written to.
 	    &((_svrv)->sv_u.svu_rv);					\
 	 }))
 #    define SvMAGIC(sv)							\
-	(*({ SV *const _svmagic = (SV *) (sv);				\
+	(*({ const SV *const _svmagic = (const SV *)(sv);		\
 	    assert(SvTYPE(_svmagic) >= SVt_PVMG);			\
 	    if(SvTYPE(_svmagic) == SVt_PVMG)				\
 		assert(!SvPAD_OUR(_svmagic));				\
-	    &(((XPVMG*) SvANY(_svmagic))->xmg_u.xmg_magic);		\
+	    &(((XPVMG*) MUTABLE_PTR(SvANY(_svmagic)))->xmg_u.xmg_magic); \
 	  }))
 #    define SvSTASH(sv)							\
-	(*({ SV *const _svstash = (SV *) (sv);				\
+	(*({ const SV *const _svstash = (const SV *)(sv);		\
 	    assert(SvTYPE(_svstash) >= SVt_PVMG);			\
-	    &(((XPVMG*) SvANY(_svstash))->xmg_stash);			\
+	    &(((XPVMG*) MUTABLE_PTR(SvANY(_svstash)))->xmg_stash);	\
 	  }))
 #  else
 #    define SvPVX(sv) ((sv)->sv_u.svu_pv)
@@ -1284,26 +1284,26 @@ the scalar's value cannot change unless written to.
 */
 #if defined (DEBUGGING) && defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
 #  define BmFLAGS(sv)							\
-	(*({ SV *const _bmflags = (SV *) (sv);				\
+	(*({ SV *const _bmflags = MUTABLE_SV(sv);			\
 		assert(SvTYPE(_bmflags) == SVt_PVGV);			\
 		assert(SvVALID(_bmflags));				\
 	    &(((XPVGV*) SvANY(_bmflags))->xnv_u.xbm_s.xbm_flags);	\
 	 }))
 #  define BmRARE(sv)							\
-	(*({ SV *const _bmrare = (SV *) (sv);				\
+	(*({ SV *const _bmrare = MUTABLE_SV(sv);			\
 		assert(SvTYPE(_bmrare) == SVt_PVGV);			\
 		assert(SvVALID(_bmrare));				\
 	    &(((XPVGV*) SvANY(_bmrare))->xnv_u.xbm_s.xbm_rare);		\
 	 }))
 #  define BmUSEFUL(sv)							\
-	(*({ SV *const _bmuseful = (SV *) (sv);				\
+	(*({ SV *const _bmuseful = MUTABLE_SV(sv);			\
 	    assert(SvTYPE(_bmuseful) == SVt_PVGV);			\
 	    assert(SvVALID(_bmuseful));					\
 	    assert(!SvIOK(_bmuseful));					\
 	    &(((XPVGV*) SvANY(_bmuseful))->xiv_u.xivu_i32);		\
 	 }))
 #  define BmPREVIOUS(sv)						\
-    (*({ SV *const _bmprevious = (SV *) (sv);				\
+    (*({ SV *const _bmprevious = MUTABLE_SV(sv);			\
 		assert(SvTYPE(_bmprevious) == SVt_PVGV);		\
 		assert(SvVALID(_bmprevious));				\
 	    &(((XPVGV*) SvANY(_bmprevious))->xnv_u.xbm_s.xbm_previous);	\
@@ -1616,9 +1616,9 @@ Like C<sv_catsv> but doesn't process magic.
 
 #if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
 
-#  define SvIVx(sv) ({SV *_sv = (SV*)(sv); SvIV(_sv); })
-#  define SvUVx(sv) ({SV *_sv = (SV*)(sv); SvUV(_sv); })
-#  define SvNVx(sv) ({SV *_sv = (SV*)(sv); SvNV(_sv); })
+#  define SvIVx(sv) ({SV *_sv = MUTABLE_SV(sv); SvIV(_sv); })
+#  define SvUVx(sv) ({SV *_sv = MUTABLE_SV(sv); SvUV(_sv); })
+#  define SvNVx(sv) ({SV *_sv = MUTABLE_SV(sv); SvNV(_sv); })
 #  define SvPVx(sv, lp) ({SV *_sv = (sv); SvPV(_sv, lp); })
 #  define SvPVx_const(sv, lp) ({SV *_sv = (sv); SvPV_const(_sv, lp); })
 #  define SvPVx_nolen(sv) ({SV *_sv = (sv); SvPV_nolen(_sv); })