Skip to content

Commit

Permalink
Add a macro MUTABLE_PTR(p), which on (non-pedantic) gcc will not cast
Browse files Browse the repository at this point in the history
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
  • Loading branch information
nwc10 committed Oct 27, 2008
1 parent bb5dd93 commit b1bc3f3
Show file tree
Hide file tree
Showing 10 changed files with 77 additions and 70 deletions.
4 changes: 2 additions & 2 deletions av.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down
4 changes: 2 additions & 2 deletions cop.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion gv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)))

Expand Down
7 changes: 7 additions & 0 deletions handy.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
10 changes: 5 additions & 5 deletions hv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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), \
Expand All @@ -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.
Expand Down
8 changes: 4 additions & 4 deletions mg.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions op.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
16 changes: 8 additions & 8 deletions pad.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,48 +37,48 @@ 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); \
assert(SvTYPE(_sv_cop_seq_range_low) != SVt_PVHV); \
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); \
assert(SvTYPE(_sv_cop_seq_range_high) != SVt_PVHV); \
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); \
assert(SvTYPE(_sv_parent_pad_index) != SVt_PVHV); \
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); \
assert(SvTYPE(_sv_parent_fakelex_flags) != SVt_PVHV); \
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) \
Expand Down
10 changes: 5 additions & 5 deletions scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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); \
Expand Down
Loading

0 comments on commit b1bc3f3

Please sign in to comment.