addbits('aelem',
7 => qw(OPpLVAL_INTRO LVINTRO),
- '5..6' => {
+ '4..5' => {
mask_def => 'OPpDEREF',
enum => [ qw(
1 OPpDEREF_AV DREFAV
3 OPpDEREF_SV DREFSV
)],
},
- 4 => qw(OPpLVAL_DEFER LVDEFER),
+ 6 => qw(OPpLVAL_DEFER LVDEFER),
);
Here for the op C<aelem>, bits 4 and 7 (bits are numbered 0..7) are
qw(reverse), # ck_fun(), but most bits stolen
grep !$maxarg{$_} && !$args0{$_},
ops_with_flag('1'), # UNOP
+ ops_with_flag('+'), # UNOP_AUX
ops_with_flag('%'), # BASEOP/UNOP
ops_with_flag('|'), # LOGOP
ops_with_flag('-'), # FILESTATOP
ops_with_flag('}'), # LOOPEXOP
+ ops_with_flag('.'), # METHOP
);
$args2{$_} = 1 for (
ops_with_check('ck_lfun'),
ops_with_check('ck_open'),
ops_with_check('ck_select'),
+ ops_with_check('ck_stringify'),
ops_with_check('ck_tell'),
ops_with_check('ck_trunc'),
;
for (qw(nextstate dbstate)) {
addbits($_,
5 => qw(OPpHUSH_VMSISH HUSH),
- # should match HINT_M_VMSISH_STATUS, HINT_M_VMSISH_TIME
- 6 => qw(OPpHINT_M_VMSISH_STATUS VMSISH_STATUS),
- 7 => qw(OPpHINT_M_VMSISH_TIME VMSISH_TIME),
-
);
}
+# op is in local context, or pad variable is being introduced, e.g.
+# local $h{foo}
+# my $x
addbits($_, 7 => qw(OPpLVAL_INTRO LVINTRO))
- for qw(pos substr vec gvsv rv2sv rv2hv rv2gv rv2av aelem helem aslice
+ for qw(gvsv rv2sv rv2hv rv2gv rv2av aelem helem aslice
hslice delete padsv padav padhv enteriter entersub padrange
- pushmark cond_expr),
+ pushmark cond_expr refassign lvref lvrefslice lvavref multideref),
'list', # this gets set in my_attrs() for some reason
;
# the pp function just updates the SV pointed to by op_targ, and doesn't
# care whether that's a PADTMP or a lexical var.
+# Some comments about when its safe to use T/OPpTARGET_MY.
+#
+# Safe to set if the ppcode uses:
+# tryAMAGICbin, tryAMAGICun, SETn, SETi, SETu, PUSHn, PUSHTARG, SETTARG,
+# SETs(TARG), XPUSHn, XPUSHu,
+# but make sure set-magic is invoked separately for SETs(TARG) (or change
+# it to SETTARG).
+#
+# Unsafe to set if the ppcode uses dTARG or [X]RETPUSH[YES|NO|UNDEF]
+#
+# Only the code paths that handle scalar rvalue context matter. If dTARG
+# or RETPUSHNO occurs only in list or lvalue paths, T is safe.
+#
+# lt and friends do SETs (including ncmp, but not scmp or i_ncmp)
+#
+# Additional mode of failure: the opcode can modify TARG before it "used"
+# all the arguments (or may call an external function which does the same).
+# If the target coincides with one of the arguments ==> kaboom.
+#
+# pp.c pos substr each not OK (RETPUSHUNDEF)
+# ref not OK (RETPUSHNO)
+# trans not OK (target is used for lhs, not retval)
+# ucfirst etc not OK: TMP arg processed inplace
+# quotemeta not OK (unsafe when TARG == arg)
+# pack - unknown whether it is safe
+# sprintf: is calling do_sprintf(TARG,...) which can act on TARG
+# before other args are processed.
+#
+# Suspicious wrt "additional mode of failure" (and only it):
+# schop, chop, postinc/dec, bit_and etc, negate, complement.
+#
+# Also suspicious: 4-arg substr, sprintf, uc/lc (POK_only), reverse, pack.
+#
+# substr/vec: doing TAINT_off()???
+#
+# pp_hot.c
+# readline - unknown whether it is safe
+# match subst not OK (dTARG)
+# grepwhile not OK (not always setting)
+# join not OK (unsafe when TARG == arg)
+#
+# concat - pp_concat special-cases TARG==arg to avoid
+# "additional mode of failure"
+#
+# pp_ctl.c
+# mapwhile flip caller not OK (not always setting)
+#
+# pp_sys.c
+# backtick glob warn die not OK (not always setting)
+# warn not OK (RETPUSHYES)
+# open fileno getc sysread syswrite ioctl accept shutdown
+# ftsize(etc) readlink telldir fork alarm getlogin not OK (RETPUSHUNDEF)
+# umask select not OK (XPUSHs(&PL_sv_undef);)
+# fileno getc sysread syswrite tell not OK (meth("FILENO" "GETC"))
+# sselect shm* sem* msg* syscall - unknown whether they are safe
+# gmtime not OK (list context)
+#
+# Suspicious wrt "additional mode of failure": warn, die, select.
+
+
addbits($_, 4 => qw(OPpTARGET_MY TARGMY))
for ops_with_flag('T'),
# This flag is also used to indicate matches against implicit $_,
# autovivify: Want ref to something
for (qw(rv2gv rv2sv padsv aelem helem entersub)) {
- addbits($_, '5..6' => {
+ addbits($_, '4..5' => {
mask_def => 'OPpDEREF',
enum => [ qw(
1 OPpDEREF_AV DREFAV
# Defer creation of array/hash elem
-addbits($_, 4 => qw(OPpLVAL_DEFER LVDEFER)) for qw(aelem helem);
+addbits($_, 6 => qw(OPpLVAL_DEFER LVDEFER)) for qw(aelem helem multideref);
# XXX Concise seemed to think that OPpOUR_INTRO is used in rv2gv too,
# but I can't see it - DAPM
-addbits($_, 4 => qw(OPpOUR_INTRO OURINTR)) # Variable was in an our()
- for qw(gvsv rv2sv rv2av rv2hv enteriter);
+addbits($_, 6 => qw(OPpOUR_INTRO OURINTR)) # Variable was in an our()
+ for qw(gvsv rv2sv rv2av rv2hv enteriter split);
# We might be an lvalue to return
addbits($_, 3 => qw(OPpMAYBE_LVSUB LVSUB))
for qw(aassign rv2av rv2gv rv2hv padav padhv aelem helem aslice hslice
- av2arylen keys rkeys kvaslice kvhslice substr pos vec);
+ av2arylen keys rkeys kvaslice kvhslice substr pos vec multideref);
for (qw(rv2hv padhv)) {
addbits($_, # e.g. %hash in (%hash || $foo) ...
+ 4 => qw(OPpMAYBE_TRUEBOOL BOOL?), # ... cx not known till run time
5 => qw(OPpTRUEBOOL BOOL), # ... in void cxt
- 6 => qw(OPpMAYBE_TRUEBOOL BOOL?), # ... cx not known till run time
);
}
-addbits($_, 1 => qw(OPpHINT_STRICT_REFS STRICT)) for qw(rv2sv rv2av rv2hv rv2gv);
+addbits($_, 1 => qw(OPpHINT_STRICT_REFS STRICT))
+ for qw(rv2sv rv2av rv2hv rv2gv multideref);
-addbits($_, 4 => qw(OPpPAD_STATE STATE)) for qw(padav padhv padsv pushmark);
+addbits($_, 6 => qw(OPpPAD_STATE STATE)) for qw(padav padhv padsv lvavref
+ lvref refassign pushmark);
# --- ------------- ----- ---------- -----
# 0 OPpENTERSUB_INARGS context
# 1 HINT_STRICT_REFS check HINT_STRICT_REFS check
-# 2 OPpENTERSUB_HASTARG check
+# 2 OPpENTERSUB_HASTARG checki OPpENTERSUB_HASTARG
# 3 OPpENTERSUB_AMPER check OPpENTERSUB_AMPER parser
-# 4 OPpENTERSUB_DB check
-# 5 OPpDEREF_AV context
-# 6 OPpDEREF_HV context OPpMAY_RETURN_CONSTANT parser/context
+# 4 OPpDEREF_AV context
+# 5 OPpDEREF_HV context OPpMAY_RETURN_CONSTANT parser/context
+# 6 OPpENTERSUB_DB check OPpENTERSUB_DB
# 7 OPpLVAL_INTRO context OPpENTERSUB_NOPAREN parser
# NB: OPpHINT_STRICT_REFS must equal HINT_STRICT_REFS
1 => qw(OPpHINT_STRICT_REFS STRICT), # 'use strict' in scope
2 => qw(OPpENTERSUB_HASTARG TARG ), # Called from OP tree
3 => qw(OPpENTERSUB_AMPER AMPER), # Used & form to call
- 4 => qw(OPpENTERSUB_DB DBG ), # Debug subroutine
- # 5..6 => OPpDEREF, already defined above
+ # 4..5 => OPpDEREF, already defined above
+ 6 => qw(OPpENTERSUB_DB DBG ), # Debug subroutine
# 7 => OPpLVAL_INTRO, already defined above
);
-addbits('rv2cv',
- # If a constant sub, return the constant
- 1 => qw(OPpHINT_STRICT_REFS STRICT), # 'use strict' in scope
-
- 3 => qw(OPpENTERSUB_AMPER AMPER), # Used & form to call
-
- 6 => qw(OPpMAY_RETURN_CONSTANT CONST),
- 7 => qw(OPpENTERSUB_NOPAREN NO() ), # bare sub call (without parens)
-);
-# XXX perhaps ought the clear these flags in Perl_doref when converting
-# and entersub into an rv2cv???? Failing that, update the comments above
-# and add them as part of the main addbits('rv2cv'.
+# note that some of these flags are just left-over from when an entersub
+# is converted into an rv2cv, and could probably be cleared/re-assigned
addbits('rv2cv',
- # If a constant sub, return the constant
- 2 => qw(OPpENTERSUB_HASTARG TARG),
- 4 => qw(OPpENTERSUB_DB DBG ), # Debug subroutine
+ 1 => qw(OPpHINT_STRICT_REFS STRICT), # 'use strict' in scope
+ 2 => qw(OPpENTERSUB_HASTARG TARG ), # If const sub, return the const
+ 3 => qw(OPpENTERSUB_AMPER AMPER ), # Used & form to call
+
+ 5 => qw(OPpMAY_RETURN_CONSTANT CONST ),
+ 6 => qw(OPpENTERSUB_DB DBG ), # Debug subroutine
+ 7 => qw(OPpENTERSUB_NOPAREN NO() ), # bare sub call (without parens)
);
2 => qw(OPpDONT_INIT_GV NOINIT), # Call gv_fetchpv with GV_NOINIT
# (Therefore will return whatever is currently in
# the symbol table, not guaranteed to be a PVGV)
- 4 => qw(OPpALLOW_FAKE FAKE), # OK to return fake glob
+ 6 => qw(OPpALLOW_FAKE FAKE), # OK to return fake glob
);
addbits('split', 7 => qw(OPpSPLIT_IMPLIM IMPLIM)); # implicit limit
+
+
+addbits($_,
+ 2 => qw(OPpLVREF_ELEM ELEM ),
+ 3 => qw(OPpLVREF_ITER ITER ),
+'4..5'=> {
+ mask_def => 'OPpLVREF_TYPE',
+ enum => [ qw(
+ 0 OPpLVREF_SV SV
+ 1 OPpLVREF_AV AV
+ 2 OPpLVREF_HV HV
+ 3 OPpLVREF_CV CV
+ )],
+ },
+ #7 => qw(OPpLVAL_INTRO LVINTRO),
+) for 'refassign', 'lvref';
+
+
+
+addbits('multideref',
+ 4 => qw(OPpMULTIDEREF_EXISTS EXISTS), # deref is actually exists
+ 5 => qw(OPpMULTIDEREF_DELETE DELETE), # deref is actually delete
+);
+
1;
# ex: set ts=8 sts=4 sw=4 et: