Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

14478 lines (12858 sloc) 418.394 kb
#line 2 "op.c"
/* op.c
*
* Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
* 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by Larry Wall and others
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
*
*/
/*
* 'You see: Mr. Drogo, he married poor Miss Primula Brandybuck. She was
* our Mr. Bilbo's first cousin on the mother's side (her mother being the
* youngest of the Old Took's daughters); and Mr. Drogo was his second
* cousin. So Mr. Frodo is his first *and* second cousin, once removed
* either way, as the saying is, if you follow me.' --the Gaffer
*
* [p.23 of _The Lord of the Rings_, I/i: "A Long-Expected Party"]
*/
/* This file contains the functions that create, manipulate and optimize
* the OP structures that hold a compiled perl program.
*
* A Perl program is compiled into a tree of OPs. Each op contains
* structural pointers (eg to its siblings and the next op in the
* execution sequence), a pointer to the function that would execute the
* op, plus any data specific to that op. For example, an OP_CONST op
* points to the pp_const() function and to an SV containing the constant
* value. When pp_const() is executed, its job is to push that SV onto the
* stack.
*
* OPs are mainly created by the newFOO() functions, which are mainly
* called from the parser (in perly.y) as the code is parsed. For example
* the Perl code $a + $b * $c would cause the equivalent of the following
* to be called (oversimplifying a bit):
*
* newBINOP(OP_ADD, flags,
* newSVREF($a),
* newBINOP(OP_MULTIPLY, flags, newSVREF($b), newSVREF($c))
* )
*
* Note that during the build of miniperl, a temporary copy of this file
* is made, called opmini.c.
*/
/*
Perl's compiler is essentially a 3-pass compiler with interleaved phases:
A bottom-up pass
A top-down pass
An execution-order pass
The bottom-up pass is represented by all the "newOP" routines and
the ck_ routines. The bottom-upness is actually driven by yacc.
So at the point that a ck_ routine fires, we have no idea what the
context is, either upward in the syntax tree, or either forward or
backward in the execution order. (The bottom-up parser builds that
part of the execution order it knows about, but if you follow the "next"
links around, you'll find it's actually a closed loop through the
top level node.)
Whenever the bottom-up parser gets to a node that supplies context to
its components, it invokes that portion of the top-down pass that applies
to that part of the subtree (and marks the top node as processed, so
if a node further up supplies context, it doesn't have to take the
plunge again). As a particular subcase of this, as the new node is
built, it takes all the closed execution loops of its subcomponents
and links them into a new closed loop for the higher level node. But
it's still not the real execution order.
The actual execution order is not known till we get a grammar reduction
to a top-level unit like a subroutine or file that will be called by
"name" rather than via a "next" pointer. At that point, we can call
into peep() to do that code's portion of the 3rd pass. It has to be
recursive, but it's recursive on basic blocks, not on tree nodes.
*/
/* To implement user lexical pragmas, there needs to be a way at run time to
get the compile time state of %^H for that block. Storing %^H in every
block (or even COP) would be very expensive, so a different approach is
taken. The (running) state of %^H is serialised into a tree of HE-like
structs. Stores into %^H are chained onto the current leaf as a struct
refcounted_he * with the key and the value. Deletes from %^H are saved
with a value of PL_sv_placeholder. The state of %^H at any point can be
turned back into a regular HV by walking back up the tree from that point's
leaf, ignoring any key you've already seen (placeholder or not), storing
the rest into the HV structure, then removing the placeholders. Hence
memory is only used to store the %^H deltas from the enclosing COP, rather
than the entire %^H on each COP.
To cause actions on %^H to write out the serialisation records, it has
magic type 'H'. This magic (itself) does nothing, but its presence causes
the values to gain magic type 'h', which has entries for set and clear.
C<Perl_magic_sethint> updates C<PL_compiling.cop_hints_hash> with a store
record, with deletes written by C<Perl_magic_clearhint>. C<SAVEHINTS>
saves the current C<PL_compiling.cop_hints_hash> on the save stack, so that
it will be correctly restored when any inner compiling scope is exited.
*/
#include "EXTERN.h"
#define PERL_IN_OP_C
#include "perl.h"
#include "keywords.h"
#include "feature.h"
#include "regcomp.h"
#define CALL_PEEP(o) PL_peepp(aTHX_ o)
#define CALL_RPEEP(o) PL_rpeepp(aTHX_ o)
#define CALL_OPFREEHOOK(o) if (PL_opfreehook) PL_opfreehook(aTHX_ o)
/* Used to avoid recursion through the op tree in scalarvoid() and
op_free()
*/
#define DEFERRED_OP_STEP 100
#define DEFER_OP(o) \
STMT_START { \
if (UNLIKELY(defer_ix == (defer_stack_alloc-1))) { \
defer_stack_alloc += DEFERRED_OP_STEP; \
assert(defer_stack_alloc > 0); \
Renew(defer_stack, defer_stack_alloc, OP *); \
} \
defer_stack[++defer_ix] = o; \
} STMT_END
#define POP_DEFERRED_OP() (defer_ix >= 0 ? defer_stack[defer_ix--] : (OP *)NULL)
/* remove any leading "empty" ops from the op_next chain whose first
* node's address is stored in op_p. Store the updated address of the
* first node in op_p.
*/
STATIC void
S_prune_chain_head(OP** op_p)
{
while (*op_p
&& ( (*op_p)->op_type == OP_NULL
|| (*op_p)->op_type == OP_SCOPE
|| (*op_p)->op_type == OP_SCALAR
|| (*op_p)->op_type == OP_LINESEQ)
)
*op_p = (*op_p)->op_next;
}
/* See the explanatory comments above struct opslab in op.h. */
#ifdef PERL_DEBUG_READONLY_OPS
# define PERL_SLAB_SIZE 128
# define PERL_MAX_SLAB_SIZE 4096
# include <sys/mman.h>
#endif
#ifndef PERL_SLAB_SIZE
# define PERL_SLAB_SIZE 64
#endif
#ifndef PERL_MAX_SLAB_SIZE
# define PERL_MAX_SLAB_SIZE 2048
#endif
/* rounds up to nearest pointer */
#define SIZE_TO_PSIZE(x) (((x) + sizeof(I32 *) - 1)/sizeof(I32 *))
#define DIFF(o,p) ((size_t)((I32 **)(p) - (I32**)(o)))
static OPSLAB *
S_new_slab(pTHX_ size_t sz)
{
#ifdef PERL_DEBUG_READONLY_OPS
OPSLAB *slab = (OPSLAB *) mmap(0, sz * sizeof(I32 *),
PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0);
DEBUG_m(PerlIO_printf(Perl_debug_log, "mapped %lu at %p\n",
(unsigned long) sz, slab));
if (slab == MAP_FAILED) {
perror("mmap failed");
abort();
}
slab->opslab_size = (U16)sz;
#else
OPSLAB *slab = (OPSLAB *)PerlMemShared_calloc(sz, sizeof(I32 *));
#endif
#ifndef WIN32
/* The context is unused in non-Windows */
PERL_UNUSED_CONTEXT;
#endif
slab->opslab_first = (OPSLOT *)((I32 **)slab + sz - 1);
return slab;
}
/* requires double parens and aTHX_ */
#define DEBUG_S_warn(args) \
DEBUG_S( \
PerlIO_printf(Perl_debug_log, "%s", SvPVx_nolen(Perl_mess args)) \
)
void *
Perl_Slab_Alloc(pTHX_ size_t sz)
{
OPSLAB *slab;
OPSLAB *slab2;
OPSLOT *slot;
OP *o;
size_t opsz, space;
/* We only allocate ops from the slab during subroutine compilation.
We find the slab via PL_compcv, hence that must be non-NULL. It could
also be pointing to a subroutine which is now fully set up (CvROOT()
pointing to the top of the optree for that sub), or a subroutine
which isn't using the slab allocator. If our sanity checks aren't met,
don't use a slab, but allocate the OP directly from the heap. */
if (!PL_compcv || CvROOT(PL_compcv)
|| (CvSTART(PL_compcv) && !CvSLABBED(PL_compcv)))
{
o = (OP*)PerlMemShared_calloc(1, sz);
goto gotit;
}
/* While the subroutine is under construction, the slabs are accessed via
CvSTART(), to avoid needing to expand PVCV by one pointer for something
unneeded at runtime. Once a subroutine is constructed, the slabs are
accessed via CvROOT(). So if CvSTART() is NULL, no slab has been
allocated yet. See the commit message for 8be227ab5eaa23f2 for more
details. */
if (!CvSTART(PL_compcv)) {
CvSTART(PL_compcv) =
(OP *)(slab = S_new_slab(aTHX_ PERL_SLAB_SIZE));
CvSLABBED_on(PL_compcv);
slab->opslab_refcnt = 2; /* one for the CV; one for the new OP */
}
else ++(slab = (OPSLAB *)CvSTART(PL_compcv))->opslab_refcnt;
opsz = SIZE_TO_PSIZE(sz);
sz = opsz + OPSLOT_HEADER_P;
/* The slabs maintain a free list of OPs. In particular, constant folding
will free up OPs, so it makes sense to re-use them where possible. A
freed up slot is used in preference to a new allocation. */
if (slab->opslab_freed) {
OP **too = &slab->opslab_freed;
o = *too;
DEBUG_S_warn((aTHX_ "found free op at %p, slab %p", (void*)o, (void*)slab));
while (o && DIFF(OpSLOT(o), OpSLOT(o)->opslot_next) < sz) {
DEBUG_S_warn((aTHX_ "Alas! too small"));
o = *(too = &o->op_next);
if (o) { DEBUG_S_warn((aTHX_ "found another free op at %p", (void*)o)); }
}
if (o) {
*too = o->op_next;
Zero(o, opsz, I32 *);
o->op_slabbed = 1;
goto gotit;
}
}
#define INIT_OPSLOT \
slot->opslot_slab = slab; \
slot->opslot_next = slab2->opslab_first; \
slab2->opslab_first = slot; \
o = &slot->opslot_op; \
o->op_slabbed = 1
/* The partially-filled slab is next in the chain. */
slab2 = slab->opslab_next ? slab->opslab_next : slab;
if ((space = DIFF(&slab2->opslab_slots, slab2->opslab_first)) < sz) {
/* Remaining space is too small. */
/* If we can fit a BASEOP, add it to the free chain, so as not
to waste it. */
if (space >= SIZE_TO_PSIZE(sizeof(OP)) + OPSLOT_HEADER_P) {
slot = &slab2->opslab_slots;
INIT_OPSLOT;
o->op_type = OP_FREED;
o->op_next = slab->opslab_freed;
slab->opslab_freed = o;
}
/* Create a new slab. Make this one twice as big. */
slot = slab2->opslab_first;
while (slot->opslot_next) slot = slot->opslot_next;
slab2 = S_new_slab(aTHX_
(DIFF(slab2, slot)+1)*2 > PERL_MAX_SLAB_SIZE
? PERL_MAX_SLAB_SIZE
: (DIFF(slab2, slot)+1)*2);
slab2->opslab_next = slab->opslab_next;
slab->opslab_next = slab2;
}
assert(DIFF(&slab2->opslab_slots, slab2->opslab_first) >= sz);
/* Create a new op slot */
slot = (OPSLOT *)((I32 **)slab2->opslab_first - sz);
assert(slot >= &slab2->opslab_slots);
if (DIFF(&slab2->opslab_slots, slot)
< SIZE_TO_PSIZE(sizeof(OP)) + OPSLOT_HEADER_P)
slot = &slab2->opslab_slots;
INIT_OPSLOT;
DEBUG_S_warn((aTHX_ "allocating op at %p, slab %p", (void*)o, (void*)slab));
gotit:
/* lastsib == 1, op_sibling == 0 implies a solitary unattached op */
o->op_lastsib = 1;
assert(!o->op_sibling);
return (void *)o;
}
#undef INIT_OPSLOT
#ifdef PERL_DEBUG_READONLY_OPS
void
Perl_Slab_to_ro(pTHX_ OPSLAB *slab)
{
PERL_ARGS_ASSERT_SLAB_TO_RO;
if (slab->opslab_readonly) return;
slab->opslab_readonly = 1;
for (; slab; slab = slab->opslab_next) {
/*DEBUG_U(PerlIO_printf(Perl_debug_log,"mprotect ->ro %lu at %p\n",
(unsigned long) slab->opslab_size, slab));*/
if (mprotect(slab, slab->opslab_size * sizeof(I32 *), PROT_READ))
Perl_warn(aTHX_ "mprotect for %p %lu failed with %d", slab,
(unsigned long)slab->opslab_size, errno);
}
}
void
Perl_Slab_to_rw(pTHX_ OPSLAB *const slab)
{
OPSLAB *slab2;
PERL_ARGS_ASSERT_SLAB_TO_RW;
if (!slab->opslab_readonly) return;
slab2 = slab;
for (; slab2; slab2 = slab2->opslab_next) {
/*DEBUG_U(PerlIO_printf(Perl_debug_log,"mprotect ->rw %lu at %p\n",
(unsigned long) size, slab2));*/
if (mprotect((void *)slab2, slab2->opslab_size * sizeof(I32 *),
PROT_READ|PROT_WRITE)) {
Perl_warn(aTHX_ "mprotect RW for %p %lu failed with %d", slab,
(unsigned long)slab2->opslab_size, errno);
}
}
slab->opslab_readonly = 0;
}
#else
# define Slab_to_rw(op) NOOP
#endif
/* This cannot possibly be right, but it was copied from the old slab
allocator, to which it was originally added, without explanation, in
commit 083fcd5. */
#ifdef NETWARE
# define PerlMemShared PerlMem
#endif
void
Perl_Slab_Free(pTHX_ void *op)
{
OP * const o = (OP *)op;
OPSLAB *slab;
PERL_ARGS_ASSERT_SLAB_FREE;
if (!o->op_slabbed) {
if (!o->op_static)
PerlMemShared_free(op);
return;
}
slab = OpSLAB(o);
/* If this op is already freed, our refcount will get screwy. */
assert(o->op_type != OP_FREED);
o->op_type = OP_FREED;
o->op_next = slab->opslab_freed;
slab->opslab_freed = o;
DEBUG_S_warn((aTHX_ "free op at %p, recorded in slab %p", (void*)o, (void*)slab));
OpslabREFCNT_dec_padok(slab);
}
void
Perl_opslab_free_nopad(pTHX_ OPSLAB *slab)
{
const bool havepad = !!PL_comppad;
PERL_ARGS_ASSERT_OPSLAB_FREE_NOPAD;
if (havepad) {
ENTER;
PAD_SAVE_SETNULLPAD();
}
opslab_free(slab);
if (havepad) LEAVE;
}
void
Perl_opslab_free(pTHX_ OPSLAB *slab)
{
OPSLAB *slab2;
PERL_ARGS_ASSERT_OPSLAB_FREE;
PERL_UNUSED_CONTEXT;
DEBUG_S_warn((aTHX_ "freeing slab %p", (void*)slab));
assert(slab->opslab_refcnt == 1);
for (; slab; slab = slab2) {
slab2 = slab->opslab_next;
#ifdef DEBUGGING
slab->opslab_refcnt = ~(size_t)0;
#endif
#ifdef PERL_DEBUG_READONLY_OPS
DEBUG_m(PerlIO_printf(Perl_debug_log, "Deallocate slab at %p\n",
(void*)slab));
if (munmap(slab, slab->opslab_size * sizeof(I32 *))) {
perror("munmap failed");
abort();
}
#else
PerlMemShared_free(slab);
#endif
}
}
void
Perl_opslab_force_free(pTHX_ OPSLAB *slab)
{
OPSLAB *slab2;
OPSLOT *slot;
#ifdef DEBUGGING
size_t savestack_count = 0;
#endif
PERL_ARGS_ASSERT_OPSLAB_FORCE_FREE;
slab2 = slab;
do {
for (slot = slab2->opslab_first;
slot->opslot_next;
slot = slot->opslot_next) {
if (slot->opslot_op.op_type != OP_FREED
&& !(slot->opslot_op.op_savefree
#ifdef DEBUGGING
&& ++savestack_count
#endif
)
) {
assert(slot->opslot_op.op_slabbed);
op_free(&slot->opslot_op);
if (slab->opslab_refcnt == 1) goto free;
}
}
} while ((slab2 = slab2->opslab_next));
/* > 1 because the CV still holds a reference count. */
if (slab->opslab_refcnt > 1) { /* still referenced by the savestack */
#ifdef DEBUGGING
assert(savestack_count == slab->opslab_refcnt-1);
#endif
/* Remove the CV’s reference count. */
slab->opslab_refcnt--;
return;
}
free:
opslab_free(slab);
}
#ifdef PERL_DEBUG_READONLY_OPS
OP *
Perl_op_refcnt_inc(pTHX_ OP *o)
{
if(o) {
OPSLAB *const slab = o->op_slabbed ? OpSLAB(o) : NULL;
if (slab && slab->opslab_readonly) {
Slab_to_rw(slab);
++o->op_targ;
Slab_to_ro(slab);
} else {
++o->op_targ;
}
}
return o;
}
PADOFFSET
Perl_op_refcnt_dec(pTHX_ OP *o)
{
PADOFFSET result;
OPSLAB *const slab = o->op_slabbed ? OpSLAB(o) : NULL;
PERL_ARGS_ASSERT_OP_REFCNT_DEC;
if (slab && slab->opslab_readonly) {
Slab_to_rw(slab);
result = --o->op_targ;
Slab_to_ro(slab);
} else {
result = --o->op_targ;
}
return result;
}
#endif
/*
* In the following definition, the ", (OP*)0" is just to make the compiler
* think the expression is of the right type: croak actually does a Siglongjmp.
*/
#define CHECKOP(type,o) \
((PL_op_mask && PL_op_mask[type]) \
? ( op_free((OP*)o), \
Perl_croak(aTHX_ "'%s' trapped by operation mask", PL_op_desc[type]), \
(OP*)0 ) \
: PL_check[type](aTHX_ (OP*)o))
#define RETURN_UNLIMITED_NUMBER (PERL_INT_MAX / 2)
#define CHANGE_TYPE(o,type) \
STMT_START { \
o->op_type = (OPCODE)type; \
o->op_ppaddr = PL_ppaddr[type]; \
} STMT_END
STATIC OP *
S_no_fh_allowed(pTHX_ OP *o)
{
PERL_ARGS_ASSERT_NO_FH_ALLOWED;
yyerror(Perl_form(aTHX_ "Missing comma after first argument to %s function",
OP_DESC(o)));
return o;
}
STATIC OP *
S_too_few_arguments_pv(pTHX_ OP *o, const char* name, U32 flags)
{
PERL_ARGS_ASSERT_TOO_FEW_ARGUMENTS_PV;
yyerror_pv(Perl_form(aTHX_ "Not enough arguments for %s", name), flags);
return o;
}
STATIC OP *
S_too_many_arguments_pv(pTHX_ OP *o, const char *name, U32 flags)
{
PERL_ARGS_ASSERT_TOO_MANY_ARGUMENTS_PV;
yyerror_pv(Perl_form(aTHX_ "Too many arguments for %s", name), flags);
return o;
}
STATIC void
S_bad_type_pv(pTHX_ I32 n, const char *t, const OP *o, const OP *kid)
{
PERL_ARGS_ASSERT_BAD_TYPE_PV;
yyerror_pv(Perl_form(aTHX_ "Type of arg %d to %s must be %s (not %s)",
(int)n, PL_op_desc[(o)->op_type], t, OP_DESC(kid)), 0);
}
/* remove flags var, its unused in all callers, move to to right end since gv
and kid are always the same */
STATIC void
S_bad_type_gv(pTHX_ I32 n, GV *gv, const OP *kid, const char *t)
{
SV * const namesv = cv_name((CV *)gv, NULL, 0);
PERL_ARGS_ASSERT_BAD_TYPE_GV;
yyerror_pv(Perl_form(aTHX_ "Type of arg %d to %"SVf" must be %s (not %s)",
(int)n, SVfARG(namesv), t, OP_DESC(kid)), SvUTF8(namesv));
}
STATIC void
S_no_bareword_allowed(pTHX_ OP *o)
{
PERL_ARGS_ASSERT_NO_BAREWORD_ALLOWED;
qerror(Perl_mess(aTHX_
"Bareword \"%"SVf"\" not allowed while \"strict subs\" in use",
SVfARG(cSVOPo_sv)));
o->op_private &= ~OPpCONST_STRICT; /* prevent warning twice about the same OP */
}
/* "register" allocation */
PADOFFSET
Perl_allocmy(pTHX_ const char *const name, const STRLEN len, const U32 flags)
{
PADOFFSET off;
const bool is_our = (PL_parser->in_my == KEY_our);
PERL_ARGS_ASSERT_ALLOCMY;
if (flags & ~SVf_UTF8)
Perl_croak(aTHX_ "panic: allocmy illegal flag bits 0x%" UVxf,
(UV)flags);
/* complain about "my $<special_var>" etc etc */
if (len &&
!(is_our ||
isALPHA(name[1]) ||
((flags & SVf_UTF8) && isIDFIRST_utf8((U8 *)name+1)) ||
(name[1] == '_' && (*name == '$' || len > 2))))
{
if (!(flags & SVf_UTF8 && UTF8_IS_START(name[1]))
&& isASCII(name[1])
&& (!isPRINT(name[1]) || strchr("\t\n\r\f", name[1]))) {
yyerror(Perl_form(aTHX_ "Can't use global %c^%c%.*s in \"%s\"",
name[0], toCTRL(name[1]), (int)(len - 2), name + 2,
PL_parser->in_my == KEY_state ? "state" : "my"));
} else {
yyerror_pv(Perl_form(aTHX_ "Can't use global %.*s in \"%s\"", (int) len, name,
PL_parser->in_my == KEY_state ? "state" : "my"), flags & SVf_UTF8);
}
}
else if (len == 2 && name[1] == '_' && !is_our)
/* diag_listed_as: Use of my $_ is experimental */
Perl_ck_warner_d(aTHX_ packWARN(WARN_EXPERIMENTAL__LEXICAL_TOPIC),
"Use of %s $_ is experimental",
PL_parser->in_my == KEY_state
? "state"
: "my");
/* allocate a spare slot and store the name in that slot */
off = pad_add_name_pvn(name, len,
(is_our ? padadd_OUR :
PL_parser->in_my == KEY_state ? padadd_STATE : 0),
PL_parser->in_my_stash,
(is_our
/* $_ is always in main::, even with our */
? (PL_curstash && !memEQs(name,len,"$_")
? PL_curstash
: PL_defstash)
: NULL
)
);
/* anon sub prototypes contains state vars should always be cloned,
* otherwise the state var would be shared between anon subs */
if (PL_parser->in_my == KEY_state && CvANON(PL_compcv))
CvCLONE_on(PL_compcv);
return off;
}
/*
=head1 Optree Manipulation Functions
=for apidoc alloccopstash
Available only under threaded builds, this function allocates an entry in
C<PL_stashpad> for the stash passed to it.
=cut
*/
#ifdef USE_ITHREADS
PADOFFSET
Perl_alloccopstash(pTHX_ HV *hv)
{
PADOFFSET off = 0, o = 1;
bool found_slot = FALSE;
PERL_ARGS_ASSERT_ALLOCCOPSTASH;
if (PL_stashpad[PL_stashpadix] == hv) return PL_stashpadix;
for (; o < PL_stashpadmax; ++o) {
if (PL_stashpad[o] == hv) return PL_stashpadix = o;
if (!PL_stashpad[o] || SvTYPE(PL_stashpad[o]) != SVt_PVHV)
found_slot = TRUE, off = o;
}
if (!found_slot) {
Renew(PL_stashpad, PL_stashpadmax + 10, HV *);
Zero(PL_stashpad + PL_stashpadmax, 10, HV *);
off = PL_stashpadmax;
PL_stashpadmax += 10;
}
PL_stashpad[PL_stashpadix = off] = hv;
return off;
}
#endif
/* free the body of an op without examining its contents.
* Always use this rather than FreeOp directly */
static void
S_op_destroy(pTHX_ OP *o)
{
FreeOp(o);
}
/* Destructor */
/*
=for apidoc Am|void|op_free|OP *o
Free an op. Only use this when an op is no longer linked to from any
optree.
=cut
*/
void
Perl_op_free(pTHX_ OP *o)
{
dVAR;
OPCODE type;
SSize_t defer_ix = -1;
SSize_t defer_stack_alloc = 0;
OP **defer_stack = NULL;
do {
/* Though ops may be freed twice, freeing the op after its slab is a
big no-no. */
assert(!o || !o->op_slabbed || OpSLAB(o)->opslab_refcnt != ~(size_t)0);
/* During the forced freeing of ops after compilation failure, kidops
may be freed before their parents. */
if (!o || o->op_type == OP_FREED)
continue;
type = o->op_type;
/* an op should only ever acquire op_private flags that we know about.
* If this fails, you may need to fix something in regen/op_private */
if (o->op_ppaddr == PL_ppaddr[o->op_type]) {
assert(!(o->op_private & ~PL_op_private_valid[type]));
}
if (o->op_private & OPpREFCOUNTED) {
switch (type) {
case OP_LEAVESUB:
case OP_LEAVESUBLV:
case OP_LEAVEEVAL:
case OP_LEAVE:
case OP_SCOPE:
case OP_LEAVEWRITE:
{
PADOFFSET refcnt;
OP_REFCNT_LOCK;
refcnt = OpREFCNT_dec(o);
OP_REFCNT_UNLOCK;
if (refcnt) {
/* Need to find and remove any pattern match ops from the list
we maintain for reset(). */
find_and_forget_pmops(o);
continue;
}
}
break;
default:
break;
}
}
/* Call the op_free hook if it has been set. Do it now so that it's called
* at the right time for refcounted ops, but still before all of the kids
* are freed. */
CALL_OPFREEHOOK(o);
if (o->op_flags & OPf_KIDS) {
OP *kid, *nextkid;
for (kid = cUNOPo->op_first; kid; kid = nextkid) {
nextkid = OpSIBLING(kid); /* Get before next freeing kid */
if (!kid || kid->op_type == OP_FREED)
/* During the forced freeing of ops after
compilation failure, kidops may be freed before
their parents. */
continue;
if (!(kid->op_flags & OPf_KIDS))
/* If it has no kids, just free it now */
op_free(kid);
else
DEFER_OP(kid);
}
}
if (type == OP_NULL)
type = (OPCODE)o->op_targ;
if (o->op_slabbed)
Slab_to_rw(OpSLAB(o));
/* COP* is not cleared by op_clear() so that we may track line
* numbers etc even after null() */
if (type == OP_NEXTSTATE || type == OP_DBSTATE) {
cop_free((COP*)o);
}
op_clear(o);
FreeOp(o);
#ifdef DEBUG_LEAKING_SCALARS
if (PL_op == o)
PL_op = NULL;
#endif
} while ( (o = POP_DEFERRED_OP()) );
Safefree(defer_stack);
}
/* S_op_clear_gv(): free a GV attached to an OP */
#ifdef USE_ITHREADS
void S_op_clear_gv(pTHX_ OP *o, PADOFFSET *ixp)
#else
void S_op_clear_gv(pTHX_ OP *o, SV**svp)
#endif
{
GV *gv = (o->op_type == OP_GV || o->op_type == OP_GVSV
|| o->op_type == OP_MULTIDEREF)
#ifdef USE_ITHREADS
&& PL_curpad
? ((GV*)PAD_SVl(*ixp)) : NULL;
#else
? (GV*)(*svp) : NULL;
#endif
/* It's possible during global destruction that the GV is freed
before the optree. Whilst the SvREFCNT_inc is happy to bump from
0 to 1 on a freed SV, the corresponding SvREFCNT_dec from 1 to 0
will trigger an assertion failure, because the entry to sv_clear
checks that the scalar is not already freed. A check of for
!SvIS_FREED(gv) turns out to be invalid, because during global
destruction the reference count can be forced down to zero
(with SVf_BREAK set). In which case raising to 1 and then
dropping to 0 triggers cleanup before it should happen. I
*think* that this might actually be a general, systematic,
weakness of the whole idea of SVf_BREAK, in that code *is*
allowed to raise and lower references during global destruction,
so any *valid* code that happens to do this during global
destruction might well trigger premature cleanup. */
bool still_valid = gv && SvREFCNT(gv);
if (still_valid)
SvREFCNT_inc_simple_void(gv);
#ifdef USE_ITHREADS
if (*ixp > 0) {
pad_swipe(*ixp, TRUE);
*ixp = 0;
}
#else
SvREFCNT_dec(*svp);
*svp = NULL;
#endif
if (still_valid) {
int try_downgrade = SvREFCNT(gv) == 2;
SvREFCNT_dec_NN(gv);
if (try_downgrade)
gv_try_downgrade(gv);
}
}
void
Perl_op_clear(pTHX_ OP *o)
{
dVAR;
PERL_ARGS_ASSERT_OP_CLEAR;
switch (o->op_type) {
case OP_NULL: /* Was holding old type, if any. */
/* FALLTHROUGH */
case OP_ENTERTRY:
case OP_ENTEREVAL: /* Was holding hints. */
o->op_targ = 0;
break;
default:
if (!(o->op_flags & OPf_REF)
|| (PL_check[o->op_type] != Perl_ck_ftst))
break;
/* FALLTHROUGH */
case OP_GVSV:
case OP_GV:
case OP_AELEMFAST:
#ifdef USE_ITHREADS
S_op_clear_gv(aTHX_ o, &(cPADOPx(o)->op_padix));
#else
S_op_clear_gv(aTHX_ o, &(cSVOPx(o)->op_sv));
#endif
break;
case OP_METHOD_REDIR:
case OP_METHOD_REDIR_SUPER:
#ifdef USE_ITHREADS
if (cMETHOPx(o)->op_rclass_targ) {
pad_swipe(cMETHOPx(o)->op_rclass_targ, 1);
cMETHOPx(o)->op_rclass_targ = 0;
}
#else
SvREFCNT_dec(cMETHOPx(o)->op_rclass_sv);
cMETHOPx(o)->op_rclass_sv = NULL;
#endif
case OP_METHOD_NAMED:
case OP_METHOD_SUPER:
SvREFCNT_dec(cMETHOPx(o)->op_u.op_meth_sv);
cMETHOPx(o)->op_u.op_meth_sv = NULL;
#ifdef USE_ITHREADS
if (o->op_targ) {
pad_swipe(o->op_targ, 1);
o->op_targ = 0;
}
#endif
break;
case OP_CONST:
case OP_HINTSEVAL:
SvREFCNT_dec(cSVOPo->op_sv);
cSVOPo->op_sv = NULL;
#ifdef USE_ITHREADS
/** Bug #15654
Even if op_clear does a pad_free for the target of the op,
pad_free doesn't actually remove the sv that exists in the pad;
instead it lives on. This results in that it could be reused as
a target later on when the pad was reallocated.
**/
if(o->op_targ) {
pad_swipe(o->op_targ,1);
o->op_targ = 0;
}
#endif
break;
case OP_DUMP:
case OP_GOTO:
case OP_NEXT:
case OP_LAST:
case OP_REDO:
if (o->op_flags & (OPf_SPECIAL|OPf_STACKED|OPf_KIDS))
break;
/* FALLTHROUGH */
case OP_TRANS:
case OP_TRANSR:
if (o->op_private & (OPpTRANS_FROM_UTF|OPpTRANS_TO_UTF)) {
assert(o->op_type == OP_TRANS || o->op_type == OP_TRANSR);
#ifdef USE_ITHREADS
if (cPADOPo->op_padix > 0) {
pad_swipe(cPADOPo->op_padix, TRUE);
cPADOPo->op_padix = 0;
}
#else
SvREFCNT_dec(cSVOPo->op_sv);
cSVOPo->op_sv = NULL;
#endif
}
else {
PerlMemShared_free(cPVOPo->op_pv);
cPVOPo->op_pv = NULL;
}
break;
case OP_SUBST:
op_free(cPMOPo->op_pmreplrootu.op_pmreplroot);
goto clear_pmop;
case OP_PUSHRE:
#ifdef USE_ITHREADS
if (cPMOPo->op_pmreplrootu.op_pmtargetoff) {
pad_swipe(cPMOPo->op_pmreplrootu.op_pmtargetoff, TRUE);
}
#else
SvREFCNT_dec(MUTABLE_SV(cPMOPo->op_pmreplrootu.op_pmtargetgv));
#endif
/* FALLTHROUGH */
case OP_MATCH:
case OP_QR:
clear_pmop:
if (!(cPMOPo->op_pmflags & PMf_CODELIST_PRIVATE))
op_free(cPMOPo->op_code_list);
cPMOPo->op_code_list = NULL;
forget_pmop(cPMOPo);
cPMOPo->op_pmreplrootu.op_pmreplroot = NULL;
/* we use the same protection as the "SAFE" version of the PM_ macros
* here since sv_clean_all might release some PMOPs
* after PL_regex_padav has been cleared
* and the clearing of PL_regex_padav needs to
* happen before sv_clean_all
*/
#ifdef USE_ITHREADS
if(PL_regex_pad) { /* We could be in destruction */
const IV offset = (cPMOPo)->op_pmoffset;
ReREFCNT_dec(PM_GETRE(cPMOPo));
PL_regex_pad[offset] = &PL_sv_undef;
sv_catpvn_nomg(PL_regex_pad[0], (const char *)&offset,
sizeof(offset));
}
#else
ReREFCNT_dec(PM_GETRE(cPMOPo));
PM_SETRE(cPMOPo, NULL);
#endif
break;
case OP_MULTIDEREF:
{
UNOP_AUX_item *items = cUNOP_AUXo->op_aux;
UV actions = items->uv;
bool last = 0;
bool is_hash = FALSE;
while (!last) {
switch (actions & MDEREF_ACTION_MASK) {
case MDEREF_reload:
actions = (++items)->uv;
continue;
case MDEREF_HV_padhv_helem:
is_hash = TRUE;
case MDEREF_AV_padav_aelem:
pad_free((++items)->pad_offset);
goto do_elem;
case MDEREF_HV_gvhv_helem:
is_hash = TRUE;
case MDEREF_AV_gvav_aelem:
#ifdef USE_ITHREADS
S_op_clear_gv(aTHX_ o, &((++items)->pad_offset));
#else
S_op_clear_gv(aTHX_ o, &((++items)->sv));
#endif
goto do_elem;
case MDEREF_HV_gvsv_vivify_rv2hv_helem:
is_hash = TRUE;
case MDEREF_AV_gvsv_vivify_rv2av_aelem:
#ifdef USE_ITHREADS
S_op_clear_gv(aTHX_ o, &((++items)->pad_offset));
#else
S_op_clear_gv(aTHX_ o, &((++items)->sv));
#endif
goto do_vivify_rv2xv_elem;
case MDEREF_HV_padsv_vivify_rv2hv_helem:
is_hash = TRUE;
case MDEREF_AV_padsv_vivify_rv2av_aelem:
pad_free((++items)->pad_offset);
goto do_vivify_rv2xv_elem;
case MDEREF_HV_pop_rv2hv_helem:
case MDEREF_HV_vivify_rv2hv_helem:
is_hash = TRUE;
do_vivify_rv2xv_elem:
case MDEREF_AV_pop_rv2av_aelem:
case MDEREF_AV_vivify_rv2av_aelem:
do_elem:
switch (actions & MDEREF_INDEX_MASK) {
case MDEREF_INDEX_none:
last = 1;
break;
case MDEREF_INDEX_const:
if (is_hash) {
#ifdef USE_ITHREADS
/* see RT #15654 */
pad_swipe((++items)->pad_offset, 1);
#else
SvREFCNT_dec((++items)->sv);
#endif
}
else
items++;
break;
case MDEREF_INDEX_padsv:
pad_free((++items)->pad_offset);
break;
case MDEREF_INDEX_gvsv:
#ifdef USE_ITHREADS
S_op_clear_gv(aTHX_ o, &((++items)->pad_offset));
#else
S_op_clear_gv(aTHX_ o, &((++items)->sv));
#endif
break;
}
if (actions & MDEREF_FLAG_last)
last = 1;
is_hash = FALSE;
break;
default:
assert(0);
last = 1;
break;
} /* switch */
actions >>= MDEREF_SHIFT;
} /* while */
/* start of malloc is at op_aux[-1], where the length is
* stored */
PerlMemShared_free(cUNOP_AUXo->op_aux - 1);
}
break;
}
if (o->op_targ > 0) {
pad_free(o->op_targ);
o->op_targ = 0;
}
}
STATIC void
S_cop_free(pTHX_ COP* cop)
{
PERL_ARGS_ASSERT_COP_FREE;
CopFILE_free(cop);
if (! specialWARN(cop->cop_warnings))
PerlMemShared_free(cop->cop_warnings);
cophh_free(CopHINTHASH_get(cop));
if (PL_curcop == cop)
PL_curcop = NULL;
}
STATIC void
S_forget_pmop(pTHX_ PMOP *const o
)
{
HV * const pmstash = PmopSTASH(o);
PERL_ARGS_ASSERT_FORGET_PMOP;
if (pmstash && !SvIS_FREED(pmstash) && SvMAGICAL(pmstash)) {
MAGIC * const mg = mg_find((const SV *)pmstash, PERL_MAGIC_symtab);
if (mg) {
PMOP **const array = (PMOP**) mg->mg_ptr;
U32 count = mg->mg_len / sizeof(PMOP**);
U32 i = count;
while (i--) {
if (array[i] == o) {
/* Found it. Move the entry at the end to overwrite it. */
array[i] = array[--count];
mg->mg_len = count * sizeof(PMOP**);
/* Could realloc smaller at this point always, but probably
not worth it. Probably worth free()ing if we're the
last. */
if(!count) {
Safefree(mg->mg_ptr);
mg->mg_ptr = NULL;
}
break;
}
}
}
}
if (PL_curpm == o)
PL_curpm = NULL;
}
STATIC void
S_find_and_forget_pmops(pTHX_ OP *o)
{
PERL_ARGS_ASSERT_FIND_AND_FORGET_PMOPS;
if (o->op_flags & OPf_KIDS) {
OP *kid = cUNOPo->op_first;
while (kid) {
switch (kid->op_type) {
case OP_SUBST:
case OP_PUSHRE:
case OP_MATCH:
case OP_QR:
forget_pmop((PMOP*)kid);
}
find_and_forget_pmops(kid);
kid = OpSIBLING(kid);
}
}
}
/*
=for apidoc Am|void|op_null|OP *o
Neutralizes an op when it is no longer needed, but is still linked to from
other ops.
=cut
*/
void
Perl_op_null(pTHX_ OP *o)
{
dVAR;
PERL_ARGS_ASSERT_OP_NULL;
if (o->op_type == OP_NULL)
return;
op_clear(o);
o->op_targ = o->op_type;
CHANGE_TYPE(o, OP_NULL);
}
void
Perl_op_refcnt_lock(pTHX)
{
#ifdef USE_ITHREADS
dVAR;
#endif
PERL_UNUSED_CONTEXT;
OP_REFCNT_LOCK;
}
void
Perl_op_refcnt_unlock(pTHX)
{
#ifdef USE_ITHREADS
dVAR;
#endif
PERL_UNUSED_CONTEXT;
OP_REFCNT_UNLOCK;
}
/*
=for apidoc op_sibling_splice
A general function for editing the structure of an existing chain of
op_sibling nodes. By analogy with the perl-level splice() function, allows
you to delete zero or more sequential nodes, replacing them with zero or
more different nodes. Performs the necessary op_first/op_last
housekeeping on the parent node and op_sibling manipulation on the
children. The last deleted node will be marked as as the last node by
updating the op_sibling or op_lastsib field as appropriate.
Note that op_next is not manipulated, and nodes are not freed; that is the
responsibility of the caller. It also won't create a new list op for an
empty list etc; use higher-level functions like op_append_elem() for that.
parent is the parent node of the sibling chain.
start is the node preceding the first node to be spliced. Node(s)
following it will be deleted, and ops will be inserted after it. If it is
NULL, the first node onwards is deleted, and nodes are inserted at the
beginning.
del_count is the number of nodes to delete. If zero, no nodes are deleted.
If -1 or greater than or equal to the number of remaining kids, all
remaining kids are deleted.
insert is the first of a chain of nodes to be inserted in place of the nodes.
If NULL, no nodes are inserted.
The head of the chain of deleted ops is returned, or NULL if no ops were
deleted.
For example:
action before after returns
------ ----- ----- -------
P P
splice(P, A, 2, X-Y-Z) | | B-C
A-B-C-D A-X-Y-Z-D
P P
splice(P, NULL, 1, X-Y) | | A
A-B-C-D X-Y-B-C-D
P P
splice(P, NULL, 3, NULL) | | A-B-C
A-B-C-D D
P P
splice(P, B, 0, X-Y) | | NULL
A-B-C-D A-B-X-Y-C-D
=cut
*/
OP *
Perl_op_sibling_splice(OP *parent, OP *start, int del_count, OP* insert)
{
OP *first = start ? OpSIBLING(start) : cLISTOPx(parent)->op_first;
OP *rest;
OP *last_del = NULL;
OP *last_ins = NULL;
PERL_ARGS_ASSERT_OP_SIBLING_SPLICE;
assert(del_count >= -1);
if (del_count && first) {
last_del = first;
while (--del_count && OpHAS_SIBLING(last_del))
last_del = OpSIBLING(last_del);
rest = OpSIBLING(last_del);
OpSIBLING_set(last_del, NULL);
last_del->op_lastsib = 1;
}
else
rest = first;
if (insert) {
last_ins = insert;
while (OpHAS_SIBLING(last_ins))
last_ins = OpSIBLING(last_ins);
OpSIBLING_set(last_ins, rest);
last_ins->op_lastsib = rest ? 0 : 1;
}
else
insert = rest;
if (start) {
OpSIBLING_set(start, insert);
start->op_lastsib = insert ? 0 : 1;
}
else {
cLISTOPx(parent)->op_first = insert;
if (insert)
parent->op_flags |= OPf_KIDS;
else
parent->op_flags &= ~OPf_KIDS;
}
if (!rest) {
/* update op_last etc */
U32 type = parent->op_type;
OP *lastop;
if (type == OP_NULL)
type = parent->op_targ;
type = PL_opargs[type] & OA_CLASS_MASK;
lastop = last_ins ? last_ins : start ? start : NULL;
if ( type == OA_BINOP
|| type == OA_LISTOP
|| type == OA_PMOP
|| type == OA_LOOP
)
cLISTOPx(parent)->op_last = lastop;
if (lastop) {
lastop->op_lastsib = 1;
#ifdef PERL_OP_PARENT
lastop->op_sibling = parent;
#endif
}
}
return last_del ? first : NULL;
}
/*
=for apidoc op_parent
returns the parent OP of o, if it has a parent. Returns NULL otherwise.
(Currently perl must be built with C<-DPERL_OP_PARENT> for this feature to
work.
=cut
*/
OP *
Perl_op_parent(OP *o)
{
PERL_ARGS_ASSERT_OP_PARENT;
#ifdef PERL_OP_PARENT
while (OpHAS_SIBLING(o))
o = OpSIBLING(o);
return o->op_sibling;
#else
PERL_UNUSED_ARG(o);
return NULL;
#endif
}
/* replace the sibling following start with a new UNOP, which becomes
* the parent of the original sibling; e.g.
*
* op_sibling_newUNOP(P, A, unop-args...)
*
* P P
* | becomes |
* A-B-C A-U-C
* |
* B
*
* where U is the new UNOP.
*
* parent and start args are the same as for op_sibling_splice();
* type and flags args are as newUNOP().
*
* Returns the new UNOP.
*/
OP *
S_op_sibling_newUNOP(pTHX_ OP *parent, OP *start, I32 type, I32 flags)
{
OP *kid, *newop;
kid = op_sibling_splice(parent, start, 1, NULL);
newop = newUNOP(type, flags, kid);
op_sibling_splice(parent, start, 0, newop);
return newop;
}
/* lowest-level newLOGOP-style function - just allocates and populates
* the struct. Higher-level stuff should be done by S_new_logop() /
* newLOGOP(). This function exists mainly to avoid op_first assignment
* being spread throughout this file.
*/
LOGOP *
S_alloc_LOGOP(pTHX_ I32 type, OP *first, OP* other)
{
dVAR;
LOGOP *logop;
OP *kid = first;
NewOp(1101, logop, 1, LOGOP);
CHANGE_TYPE(logop, type);
logop->op_first = first;
logop->op_other = other;
logop->op_flags = OPf_KIDS;
while (kid && OpHAS_SIBLING(kid))
kid = OpSIBLING(kid);
if (kid) {
kid->op_lastsib = 1;
#ifdef PERL_OP_PARENT
kid->op_sibling = (OP*)logop;
#endif
}
return logop;
}
/* Contextualizers */
/*
=for apidoc Am|OP *|op_contextualize|OP *o|I32 context
Applies a syntactic context to an op tree representing an expression.
I<o> is the op tree, and I<context> must be C<G_SCALAR>, C<G_ARRAY>,
or C<G_VOID> to specify the context to apply. The modified op tree
is returned.
=cut
*/
OP *
Perl_op_contextualize(pTHX_ OP *o, I32 context)
{
PERL_ARGS_ASSERT_OP_CONTEXTUALIZE;
switch (context) {
case G_SCALAR: return scalar(o);
case G_ARRAY: return list(o);
case G_VOID: return scalarvoid(o);
default:
Perl_croak(aTHX_ "panic: op_contextualize bad context %ld",
(long) context);
}
}
/*
=for apidoc Am|OP*|op_linklist|OP *o
This function is the implementation of the L</LINKLIST> macro. It should
not be called directly.
=cut
*/
OP *
Perl_op_linklist(pTHX_ OP *o)
{
OP *first;
PERL_ARGS_ASSERT_OP_LINKLIST;
if (o->op_next)
return o->op_next;
/* establish postfix order */
first = cUNOPo->op_first;
if (first) {
OP *kid;
o->op_next = LINKLIST(first);
kid = first;
for (;;) {
OP *sibl = OpSIBLING(kid);
if (sibl) {
kid->op_next = LINKLIST(sibl);
kid = sibl;
} else {
kid->op_next = o;
break;
}
}
}
else
o->op_next = o;
return o->op_next;
}
static OP *
S_scalarkids(pTHX_ OP *o)
{
if (o && o->op_flags & OPf_KIDS) {
OP *kid;
for (kid = cLISTOPo->op_first; kid; kid = OpSIBLING(kid))
scalar(kid);
}
return o;
}
STATIC OP *
S_scalarboolean(pTHX_ OP *o)
{
PERL_ARGS_ASSERT_SCALARBOOLEAN;
if (o->op_type == OP_SASSIGN && cBINOPo->op_first->op_type == OP_CONST
&& !(cBINOPo->op_first->op_flags & OPf_SPECIAL)) {
if (ckWARN(WARN_SYNTAX)) {
const line_t oldline = CopLINE(PL_curcop);
if (PL_parser && PL_parser->copline != NOLINE) {
/* This ensures that warnings are reported at the first line
of the conditional, not the last. */
CopLINE_set(PL_curcop, PL_parser->copline);
}
Perl_warner(aTHX_ packWARN(WARN_SYNTAX), "Found = in conditional, should be ==");
CopLINE_set(PL_curcop, oldline);
}
}
return scalar(o);
}
static SV *
S_op_varname(pTHX_ const OP *o)
{
assert(o);
assert(o->op_type == OP_PADAV || o->op_type == OP_RV2AV ||
o->op_type == OP_PADHV || o->op_type == OP_RV2HV);
{
const char funny = o->op_type == OP_PADAV
|| o->op_type == OP_RV2AV ? '@' : '%';
if (o->op_type == OP_RV2AV || o->op_type == OP_RV2HV) {
GV *gv;
if (cUNOPo->op_first->op_type != OP_GV
|| !(gv = cGVOPx_gv(cUNOPo->op_first)))
return NULL;
return varname(gv, funny, 0, NULL, 0, 1);
}
return
varname(MUTABLE_GV(PL_compcv), funny, o->op_targ, NULL, 0, 1);
}
}
static void
S_op_pretty(pTHX_ const OP *o, SV **retsv, const char **retpv)
{ /* or not so pretty :-) */
if (o->op_type == OP_CONST) {
*retsv = cSVOPo_sv;
if (SvPOK(*retsv)) {
SV *sv = *retsv;
*retsv = sv_newmortal();
pv_pretty(*retsv, SvPVX_const(sv), SvCUR(sv), 32, NULL, NULL,
PERL_PV_PRETTY_DUMP |PERL_PV_ESCAPE_UNI_DETECT);
}
else if (!SvOK(*retsv))
*retpv = "undef";
}
else *retpv = "...";
}
static void
S_scalar_slice_warning(pTHX_ const OP *o)
{
OP *kid;
const char lbrack =
o->op_type == OP_HSLICE ? '{' : '[';
const char rbrack =
o->op_type == OP_HSLICE ? '}' : ']';
SV *name;
SV *keysv = NULL; /* just to silence compiler warnings */
const char *key = NULL;
if (!(o->op_private & OPpSLICEWARNING))
return;
if (PL_parser && PL_parser->error_count)
/* This warning can be nonsensical when there is a syntax error. */
return;
kid = cLISTOPo->op_first;
kid = OpSIBLING(kid); /* get past pushmark */
/* weed out false positives: any ops that can return lists */
switch (kid->op_type) {
case OP_BACKTICK:
case OP_GLOB:
case OP_READLINE:
case OP_MATCH:
case OP_RV2AV:
case OP_EACH:
case OP_VALUES:
case OP_KEYS:
case OP_SPLIT:
case OP_LIST:
case OP_SORT:
case OP_REVERSE:
case OP_ENTERSUB:
case OP_CALLER:
case OP_LSTAT:
case OP_STAT:
case OP_READDIR:
case OP_SYSTEM:
case OP_TMS:
case OP_LOCALTIME:
case OP_GMTIME:
case OP_ENTEREVAL:
case OP_REACH:
case OP_RKEYS:
case OP_RVALUES:
return;
}
/* Don't warn if we have a nulled list either. */
if (kid->op_type == OP_NULL && kid->op_targ == OP_LIST)
return;
assert(OpSIBLING(kid));
name = S_op_varname(aTHX_ OpSIBLING(kid));
if (!name) /* XS module fiddling with the op tree */
return;
S_op_pretty(aTHX_ kid, &keysv, &key);
assert(SvPOK(name));
sv_chop(name,SvPVX(name)+1);
if (key)
/* diag_listed_as: Scalar value @%s[%s] better written as $%s[%s] */
Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
"Scalar value @%"SVf"%c%s%c better written as $%"SVf
"%c%s%c",
SVfARG(name), lbrack, key, rbrack, SVfARG(name),
lbrack, key, rbrack);
else
/* diag_listed_as: Scalar value @%s[%s] better written as $%s[%s] */
Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
"Scalar value @%"SVf"%c%"SVf"%c better written as $%"
SVf"%c%"SVf"%c",
SVfARG(name), lbrack, SVfARG(keysv), rbrack,
SVfARG(name), lbrack, SVfARG(keysv), rbrack);
}
OP *
Perl_scalar(pTHX_ OP *o)
{
OP *kid;
/* assumes no premature commitment */
if (!o || (PL_parser && PL_parser->error_count)
|| (o->op_flags & OPf_WANT)
|| o->op_type == OP_RETURN)
{
return o;
}
o->op_flags = (o->op_flags & ~OPf_WANT) | OPf_WANT_SCALAR;
switch (o->op_type) {
case OP_REPEAT:
scalar(cBINOPo->op_first);
if (o->op_private & OPpREPEAT_DOLIST) {
kid = cLISTOPx(cUNOPo->op_first)->op_first;
assert(kid->op_type == OP_PUSHMARK);
if (OpHAS_SIBLING(kid) && !OpHAS_SIBLING(OpSIBLING(kid))) {
op_null(cLISTOPx(cUNOPo->op_first)->op_first);
o->op_private &=~ OPpREPEAT_DOLIST;
}
}
break;
case OP_OR:
case OP_AND:
case OP_COND_EXPR:
for (kid = OpSIBLING(cUNOPo->op_first); kid; kid = OpSIBLING(kid))
scalar(kid);
break;
/* FALLTHROUGH */
case OP_SPLIT:
case OP_MATCH:
case OP_QR:
case OP_SUBST:
case OP_NULL:
default:
if (o->op_flags & OPf_KIDS) {
for (kid = cUNOPo->op_first; kid; kid = OpSIBLING(kid))
scalar(kid);
}
break;
case OP_LEAVE:
case OP_LEAVETRY:
kid = cLISTOPo->op_first;
scalar(kid);
kid = OpSIBLING(kid);
do_kids:
while (kid) {
OP *sib = OpSIBLING(kid);
if (sib && kid->op_type != OP_LEAVEWHEN
&& ( OpHAS_SIBLING(sib) || sib->op_type != OP_NULL
|| ( sib->op_targ != OP_NEXTSTATE
&& sib->op_targ != OP_DBSTATE )))
scalarvoid(kid);
else
scalar(kid);
kid = sib;
}
PL_curcop = &PL_compiling;
break;
case OP_SCOPE:
case OP_LINESEQ:
case OP_LIST:
kid = cLISTOPo->op_first;
goto do_kids;
case OP_SORT:
Perl_ck_warner(aTHX_ packWARN(WARN_VOID), "Useless use of sort in scalar context");
break;
case OP_KVHSLICE:
case OP_KVASLICE:
{
/* Warn about scalar context */
const char lbrack = o->op_type == OP_KVHSLICE ? '{' : '[';
const char rbrack = o->op_type == OP_KVHSLICE ? '}' : ']';
SV *name;
SV *keysv;
const char *key = NULL;
/* This warning can be nonsensical when there is a syntax error. */
if (PL_parser && PL_parser->error_count)
break;
if (!ckWARN(WARN_SYNTAX)) break;
kid = cLISTOPo->op_first;
kid = OpSIBLING(kid); /* get past pushmark */
assert(OpSIBLING(kid));
name = S_op_varname(aTHX_ OpSIBLING(kid));
if (!name) /* XS module fiddling with the op tree */
break;
S_op_pretty(aTHX_ kid, &keysv, &key);
assert(SvPOK(name));
sv_chop(name,SvPVX(name)+1);
if (key)
/* diag_listed_as: %%s[%s] in scalar context better written as $%s[%s] */
Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
"%%%"SVf"%c%s%c in scalar context better written "
"as $%"SVf"%c%s%c",
SVfARG(name), lbrack, key, rbrack, SVfARG(name),
lbrack, key, rbrack);
else
/* diag_listed_as: %%s[%s] in scalar context better written as $%s[%s] */
Perl_warner(aTHX_ packWARN(WARN_SYNTAX),
"%%%"SVf"%c%"SVf"%c in scalar context better "
"written as $%"SVf"%c%"SVf"%c",
SVfARG(name), lbrack, SVfARG(keysv), rbrack,
SVfARG(name), lbrack, SVfARG(keysv), rbrack);
}
}
return o;
}
OP *
Perl_scalarvoid(pTHX_ OP *arg)
{
dVAR;
OP *kid;
SV* sv;
U8 want;
SSize_t defer_stack_alloc = 0;
SSize_t defer_ix = -1;
OP **defer_stack = NULL;
OP *o = arg;
PERL_ARGS_ASSERT_SCALARVOID;
do {
SV *useless_sv = NULL;
const char* useless = NULL;
if (o->op_type == OP_NEXTSTATE
|| o->op_type == OP_DBSTATE
|| (o->op_type == OP_NULL && (o->op_targ == OP_NEXTSTATE
|| o->op_targ == OP_DBSTATE)))
PL_curcop = (COP*)o; /* for warning below */
/* assumes no premature commitment */
want = o->op_flags & OPf_WANT;
if ((want && want != OPf_WANT_SCALAR)
|| (PL_parser && PL_parser->error_count)
|| o->op_type == OP_RETURN || o->op_type == OP_REQUIRE || o->op_type == OP_LEAVEWHEN)
{
continue;
}
if ((o->op_private & OPpTARGET_MY)
&& (PL_opargs[o->op_type] & OA_TARGLEX))/* OPp share the meaning */
{
/* newASSIGNOP has already applied scalar context, which we
leave, as if this op is inside SASSIGN. */
continue;
}
o->op_flags = (o->op_flags & ~OPf_WANT) | OPf_WANT_VOID;
switch (o->op_type) {
default:
if (!(PL_opargs[o->op_type] & OA_FOLDCONST))
break;
/* FALLTHROUGH */
case OP_REPEAT:
if (o->op_flags & OPf_STACKED)
break;
if (o->op_type == OP_REPEAT)
scalar(cBINOPo->op_first);
goto func_ops;
case OP_SUBSTR:
if (o->op_private == 4)
break;
/* FALLTHROUGH */
case OP_WANTARRAY:
case OP_GV:
case OP_SMARTMATCH:
case OP_AV2ARYLEN:
case OP_REF:
case OP_REFGEN:
case OP_SREFGEN:
case OP_DEFINED:
case OP_HEX:
case OP_OCT:
case OP_LENGTH:
case OP_VEC:
case OP_INDEX:
case OP_RINDEX:
case OP_SPRINTF:
case OP_KVASLICE:
case OP_KVHSLICE:
case OP_UNPACK:
case OP_PACK:
case OP_JOIN:
case OP_LSLICE:
case OP_ANONLIST:
case OP_ANONHASH:
case OP_SORT:
case OP_REVERSE:
case OP_RANGE:
case OP_FLIP:
case OP_FLOP:
case OP_CALLER:
case OP_FILENO:
case OP_EOF:
case OP_TELL:
case OP_GETSOCKNAME:
case OP_GETPEERNAME:
case OP_READLINK:
case OP_TELLDIR:
case OP_GETPPID:
case OP_GETPGRP:
case OP_GETPRIORITY:
case OP_TIME:
case OP_TMS:
case OP_LOCALTIME:
case OP_GMTIME:
case OP_GHBYNAME:
case OP_GHBYADDR:
case OP_GHOSTENT:
case OP_GNBYNAME:
case OP_GNBYADDR:
case OP_GNETENT:
case OP_GPBYNAME:
case OP_GPBYNUMBER:
case OP_GPROTOENT:
case OP_GSBYNAME:
case OP_GSBYPORT:
case OP_GSERVENT:
case OP_GPWNAM:
case OP_GPWUID:
case OP_GGRNAM:
case OP_GGRGID:
case OP_GETLOGIN:
case OP_PROTOTYPE:
case OP_RUNCV:
func_ops:
useless = OP_DESC(o);
break;
case OP_GVSV:
case OP_PADSV:
case OP_PADAV:
case OP_PADHV:
case OP_PADANY:
case OP_AELEM:
case OP_AELEMFAST:
case OP_AELEMFAST_LEX:
case OP_ASLICE:
case OP_HELEM:
case OP_HSLICE:
if (!(o->op_private & (OPpLVAL_INTRO|OPpOUR_INTRO)))
/* Otherwise it's "Useless use of grep iterator" */
useless = OP_DESC(o);
break;
case OP_SPLIT:
kid = cLISTOPo->op_first;
if (kid && kid->op_type == OP_PUSHRE
&& !kid->op_targ
&& !(o->op_flags & OPf_STACKED)
#ifdef USE_ITHREADS
&& !((PMOP*)kid)->op_pmreplrootu.op_pmtargetoff
#else
&& !((PMOP*)kid)->op_pmreplrootu.op_pmtargetgv
#endif
)
useless = OP_DESC(o);
break;
case OP_NOT:
kid = cUNOPo->op_first;
if (kid->op_type != OP_MATCH && kid->op_type != OP_SUBST &&
kid->op_type != OP_TRANS && kid->op_type != OP_TRANSR) {
goto func_ops;
}
useless = "negative pattern binding (!~)";
break;
case OP_SUBST:
if (cPMOPo->op_pmflags & PMf_NONDESTRUCT)
useless = "non-destructive substitution (s///r)";
break;
case OP_TRANSR:
useless = "non-destructive transliteration (tr///r)";
break;
case OP_RV2GV:
case OP_RV2SV:
case OP_RV2AV:
case OP_RV2HV:
if (!(o->op_private & (OPpLVAL_INTRO|OPpOUR_INTRO)) &&
(!OpHAS_SIBLING(o) || OpSIBLING(o)->op_type != OP_READLINE))
useless = "a variable";
break;
case OP_CONST:
sv = cSVOPo_sv;
if (cSVOPo->op_private & OPpCONST_STRICT)
no_bareword_allowed(o);
else {
if (ckWARN(WARN_VOID)) {
NV nv;
/* don't warn on optimised away booleans, eg
* use constant Foo, 5; Foo || print; */
if (cSVOPo->op_private & OPpCONST_SHORTCIRCUIT)
useless = NULL;
/* the constants 0 and 1 are permitted as they are
conventionally used as dummies in constructs like
1 while some_condition_with_side_effects; */
else if (SvNIOK(sv) && ((nv = SvNV(sv)) == 0.0 || nv == 1.0))
useless = NULL;
else if (SvPOK(sv)) {
SV * const dsv = newSVpvs("");
useless_sv
= Perl_newSVpvf(aTHX_
"a constant (%s)",
pv_pretty(dsv, SvPVX_const(sv),
SvCUR(sv), 32, NULL, NULL,
PERL_PV_PRETTY_DUMP
| PERL_PV_ESCAPE_NOCLEAR
| PERL_PV_ESCAPE_UNI_DETECT));
SvREFCNT_dec_NN(dsv);
}
else if (SvOK(sv)) {
useless_sv = Perl_newSVpvf(aTHX_ "a constant (%"SVf")", SVfARG(sv));
}
else
useless = "a constant (undef)";
}
}
op_null(o); /* don't execute or even remember it */
break;
case OP_POSTINC:
CHANGE_TYPE(o, OP_PREINC); /* pre-increment is faster */
break;
case OP_POSTDEC:
CHANGE_TYPE(o, OP_PREDEC); /* pre-decrement is faster */
break;
case OP_I_POSTINC:
CHANGE_TYPE(o, OP_I_PREINC); /* pre-increment is faster */
break;
case OP_I_POSTDEC:
CHANGE_TYPE(o, OP_I_PREDEC); /* pre-decrement is faster */
break;
case OP_SASSIGN: {
OP *rv2gv;
UNOP *refgen, *rv2cv;
LISTOP *exlist;
if ((o->op_private & ~OPpASSIGN_BACKWARDS) != 2)
break;
rv2gv = ((BINOP *)o)->op_last;
if (!rv2gv || rv2gv->op_type != OP_RV2GV)
break;
refgen = (UNOP *)((BINOP *)o)->op_first;
if (!refgen || (refgen->op_type != OP_REFGEN
&& refgen->op_type != OP_SREFGEN))
break;
exlist = (LISTOP *)refgen->op_first;
if (!exlist || exlist->op_type != OP_NULL
|| exlist->op_targ != OP_LIST)
break;
if (exlist->op_first->op_type != OP_PUSHMARK
&& exlist->op_first != exlist->op_last)
break;
rv2cv = (UNOP*)exlist->op_last;
if (rv2cv->op_type != OP_RV2CV)
break;
assert ((rv2gv->op_private & OPpDONT_INIT_GV) == 0);
assert ((o->op_private & OPpASSIGN_CV_TO_GV) == 0);
assert ((rv2cv->op_private & OPpMAY_RETURN_CONSTANT) == 0);
o->op_private |= OPpASSIGN_CV_TO_GV;
rv2gv->op_private |= OPpDONT_INIT_GV;
rv2cv->op_private |= OPpMAY_RETURN_CONSTANT;
break;
}
case OP_AASSIGN: {
inplace_aassign(o);
break;
}
case OP_OR:
case OP_AND:
kid = cLOGOPo->op_first;
if (kid->op_type == OP_NOT
&& (kid->op_flags & OPf_KIDS)) {
if (o->op_type == OP_AND) {
CHANGE_TYPE(o, OP_OR);
} else {
CHANGE_TYPE(o, OP_AND);
}
op_null(kid);
}
/* FALLTHROUGH */
case OP_DOR:
case OP_COND_EXPR:
case OP_ENTERGIVEN:
case OP_ENTERWHEN:
for (kid = OpSIBLING(cUNOPo->op_first); kid; kid = OpSIBLING(kid))
if (!(kid->op_flags & OPf_KIDS))
scalarvoid(kid);
else
DEFER_OP(kid);
break;
case OP_NULL:
if (o->op_flags & OPf_STACKED)
break;
/* FALLTHROUGH */
case OP_NEXTSTATE:
case OP_DBSTATE:
case OP_ENTERTRY:
case OP_ENTER:
if (!(o->op_flags & OPf_KIDS))
break;
/* FALLTHROUGH */
case OP_SCOPE:
case OP_LEAVE:
case OP_LEAVETRY:
case OP_LEAVELOOP:
case OP_LINESEQ:
case OP_LEAVEGIVEN:
case OP_LEAVEWHEN:
kids:
for (kid = cLISTOPo->op_first; kid; kid = OpSIBLING(kid))
if (!(kid->op_flags & OPf_KIDS))
scalarvoid(kid);
else
DEFER_OP(kid);
break;
case OP_LIST:
/* If the first kid after pushmark is something that the padrange
optimisation would reject, then null the list and the pushmark.
*/
if ((kid = cLISTOPo->op_first)->op_type == OP_PUSHMARK
&& ( !(kid = OpSIBLING(kid))
|| ( kid->op_type != OP_PADSV
&& kid->op_type != OP_PADAV
&& kid->op_type != OP_PADHV)
|| kid->op_private & ~OPpLVAL_INTRO
|| !(kid = OpSIBLING(kid))
|| ( kid->op_type != OP_PADSV
&& kid->op_type != OP_PADAV
&& kid->op_type != OP_PADHV)
|| kid->op_private & ~OPpLVAL_INTRO)
) {
op_null(cUNOPo->op_first); /* NULL the pushmark */
op_null(o); /* NULL the list */
}
goto kids;
case OP_ENTEREVAL:
scalarkids(o);
break;
case OP_SCALAR:
scalar(o);
break;
}
if (useless_sv) {
/* mortalise it, in case warnings are fatal. */
Perl_ck_warner(aTHX_ packWARN(WARN_VOID),
"Useless use of %"SVf" in void context",
SVfARG(sv_2mortal(useless_sv)));
}
else if (useless) {
Perl_ck_warner(aTHX_ packWARN(WARN_VOID),
"Useless use of %s in void context",
useless);
}
} while ( (o = POP_DEFERRED_OP()) );
Safefree(defer_stack);
return arg;
}
static OP *
S_listkids(pTHX_ OP *o)
{
if (o && o->op_flags & OPf_KIDS) {
OP *kid;
for (kid = cLISTOPo->op_first; kid; kid = OpSIBLING(kid))
list(kid);
}
return o;
}
OP *
Perl_list(pTHX_ OP *o)
{
OP *kid;
/* assumes no premature commitment */
if (!o || (o->op_flags & OPf_WANT)
|| (PL_parser && PL_parser->error_count)
|| o->op_type == OP_RETURN)
{
return o;
}
if ((o->op_private & OPpTARGET_MY)
&& (PL_opargs[o->op_type] & OA_TARGLEX))/* OPp share the meaning */
{
return o; /* As if inside SASSIGN */
}
o->op_flags = (o->op_flags & ~OPf_WANT) | OPf_WANT_LIST;
switch (o->op_type) {
case OP_FLOP:
list(cBINOPo->op_first);
break;
case OP_REPEAT:
if (o->op_private & OPpREPEAT_DOLIST
&& !(o->op_flags & OPf_STACKED))
{
list(cBINOPo->op_first);
kid = cBINOPo->op_last;
if (kid->op_type == OP_CONST && SvIOK(kSVOP_sv)
&& SvIVX(kSVOP_sv) == 1)
{
op_null(o); /* repeat */
op_null(cUNOPx(cBINOPo->op_first)->op_first);/* pushmark */
/* const (rhs): */
op_free(op_sibling_splice(o, cBINOPo->op_first, 1, NULL));
}
}
break;
case OP_OR:
case OP_AND:
case OP_COND_EXPR:
for (kid = OpSIBLING(cUNOPo->op_first); kid; kid = OpSIBLING(kid))
list(kid);
break;
default:
case OP_MATCH:
case OP_QR:
case OP_SUBST:
case OP_NULL:
if (!(o->op_flags & OPf_KIDS))
break;
if (!o->op_next && cUNOPo->op_first->op_type == OP_FLOP) {
list(cBINOPo->op_first);
return gen_constant_list(o);
}
listkids(o);
break;
case OP_LIST:
listkids(o);
if (cLISTOPo->op_first->op_type == OP_PUSHMARK) {
op_null(cUNOPo->op_first); /* NULL the pushmark */
op_null(o); /* NULL the list */
}
break;
case OP_LEAVE:
case OP_LEAVETRY:
kid = cLISTOPo->op_first;
list(kid);
kid = OpSIBLING(kid);
do_kids:
while (kid) {
OP *sib = OpSIBLING(kid);
if (sib && kid->op_type != OP_LEAVEWHEN)
scalarvoid(kid);
else
list(kid);
kid = sib;
}
PL_curcop = &PL_compiling;
break;
case OP_SCOPE:
case OP_LINESEQ:
kid = cLISTOPo->op_first;
goto do_kids;
}
return o;
}
static OP *
S_scalarseq(pTHX_ OP *o)
{
if (o) {
const OPCODE type = o->op_type;
if (type == OP_LINESEQ || type == OP_SCOPE ||
type == OP_LEAVE || type == OP_LEAVETRY)
{
OP *kid, *sib;
for (kid = cLISTOPo->op_first; kid; kid = sib) {
if ((sib = OpSIBLING(kid))
&& ( OpHAS_SIBLING(sib) || sib->op_type != OP_NULL
|| ( sib->op_targ != OP_NEXTSTATE
&& sib->op_targ != OP_DBSTATE )))
{
scalarvoid(kid);
}
}
PL_curcop = &PL_compiling;
}
o->op_flags &= ~OPf_PARENS;
if (PL_hints & HINT_BLOCK_SCOPE)
o->op_flags |= OPf_PARENS;
}
else
o = newOP(OP_STUB, 0);
return o;
}
STATIC OP *
S_modkids(pTHX_ OP *o, I32 type)
{
if (o && o->op_flags & OPf_KIDS) {
OP *kid;
for (kid = cLISTOPo->op_first; kid; kid = OpSIBLING(kid))
op_lvalue(kid, type);
}
return o;
}
/* for a helem/hslice/kvslice, if its a fixed hash, croak on invalid
* const fields. Also, convert CONST keys to HEK-in-SVs.
* rop is the op that retrieves the hash;
* key_op is the first key
*/
void
S_check_hash_fields_and_hekify(pTHX_ UNOP *rop, SVOP *key_op)
{
PADNAME *lexname;
GV **fields;
bool check_fields;
/* find the padsv corresponding to $lex->{} or @{$lex}{} */
if (rop) {
if (rop->op_first->op_type == OP_PADSV)
/* @$hash{qw(keys here)} */
rop = (UNOP*)rop->op_first;
else {
/* @{$hash}{qw(keys here)} */
if (rop->op_first->op_type == OP_SCOPE
&& cLISTOPx(rop->op_first)->op_last->op_type == OP_PADSV)
{
rop = (UNOP*)cLISTOPx(rop->op_first)->op_last;
}
else
rop = NULL;
}
}
lexname = NULL; /* just to silence compiler warnings */
fields = NULL; /* just to silence compiler warnings */
check_fields =
rop
&& (lexname = padnamelist_fetch(PL_comppad_name, rop->op_targ),
SvPAD_TYPED(lexname))
&& (fields = (GV**)hv_fetchs(PadnameTYPE(lexname), "FIELDS", FALSE))
&& isGV(*fields) && GvHV(*fields);
for (; key_op; key_op = (SVOP*)OpSIBLING(key_op)) {
SV **svp, *sv;
if (key_op->op_type != OP_CONST)
continue;
svp = cSVOPx_svp(key_op);
/* Make the CONST have a shared SV */
if ( !SvIsCOW_shared_hash(sv = *svp)
&& SvTYPE(sv) < SVt_PVMG
&& SvOK(sv)
&& !SvROK(sv))
{
SSize_t keylen;
const char * const key = SvPV_const(sv, *(STRLEN*)&keylen);
SV *nsv = newSVpvn_share(key, SvUTF8(sv) ? -keylen : keylen, 0);
SvREFCNT_dec_NN(sv);
*svp = nsv;
}
if ( check_fields
&& !hv_fetch_ent(GvHV(*fields), *svp, FALSE, 0))
{
Perl_croak(aTHX_ "No such class field \"%"SVf"\" "
"in variable %"PNf" of type %"HEKf,
SVfARG(*svp), PNfARG(lexname),
HEKfARG(HvNAME_HEK(PadnameTYPE(lexname))));
}
}
}
/*
=for apidoc finalize_optree
This function finalizes the optree. Should be called directly after
the complete optree is built. It does some additional
checking which can't be done in the normal ck_xxx functions and makes
the tree thread-safe.
=cut
*/
void
Perl_finalize_optree(pTHX_ OP* o)
{
PERL_ARGS_ASSERT_FINALIZE_OPTREE;
ENTER;
SAVEVPTR(PL_curcop);
finalize_op(o);
LEAVE;
}
#ifdef USE_ITHREADS
/* Relocate sv to the pad for thread safety.
* Despite being a "constant", the SV is written to,
* for reference counts, sv_upgrade() etc. */
PERL_STATIC_INLINE void
S_op_relocate_sv(pTHX_ SV** svp, PADOFFSET* targp)
{
PADOFFSET ix;
PERL_ARGS_ASSERT_OP_RELOCATE_SV;
if (!*svp) return;
ix = pad_alloc(OP_CONST, SVf_READONLY);
SvREFCNT_dec(PAD_SVl(ix));
PAD_SETSV(ix, *svp);
/* XXX I don't know how this isn't readonly already. */
if (!SvIsCOW(PAD_SVl(ix))) SvREADONLY_on(PAD_SVl(ix));
*svp = NULL;
*targp = ix;
}
#endif
STATIC void
S_finalize_op(pTHX_ OP* o)
{
PERL_ARGS_ASSERT_FINALIZE_OP;
switch (o->op_type) {
case OP_NEXTSTATE:
case OP_DBSTATE:
PL_curcop = ((COP*)o); /* for warnings */
break;
case OP_EXEC:
if (OpHAS_SIBLING(o)) {
OP *sib = OpSIBLING(o);
if (( sib->op_type == OP_NEXTSTATE || sib->op_type == OP_DBSTATE)
&& ckWARN(WARN_EXEC)
&& OpHAS_SIBLING(sib))
{
const OPCODE type = OpSIBLING(sib)->op_type;
if (type != OP_EXIT && type != OP_WARN && type != OP_DIE) {
const line_t oldline = CopLINE(PL_curcop);
CopLINE_set(PL_curcop, CopLINE((COP*)sib));
Perl_warner(aTHX_ packWARN(WARN_EXEC),
"Statement unlikely to be reached");
Perl_warner(aTHX_ packWARN(WARN_EXEC),
"\t(Maybe you meant system() when you said exec()?)\n");
CopLINE_set(PL_curcop, oldline);
}
}
}
break;
case OP_GV:
if ((o->op_private & OPpEARLY_CV) && ckWARN(WARN_PROTOTYPE)) {
GV * const gv = cGVOPo_gv;
if (SvTYPE(gv) == SVt_PVGV && GvCV(gv) && SvPVX_const(GvCV(gv))) {
/* XXX could check prototype here instead of just carping */
SV * const sv = sv_newmortal();
gv_efullname3(sv, gv, NULL);
Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE),
"%"SVf"() called too early to check prototype",
SVfARG(sv));
}
}
break;
case OP_CONST:
if (cSVOPo->op_private & OPpCONST_STRICT)
no_bareword_allowed(o);
/* FALLTHROUGH */
#ifdef USE_ITHREADS
case OP_HINTSEVAL:
op_relocate_sv(&cSVOPo->op_sv, &o->op_targ);
#endif
break;
#ifdef USE_ITHREADS
/* Relocate all the METHOP's SVs to the pad for thread safety. */
case OP_METHOD_NAMED:
case OP_METHOD_SUPER:
case OP_METHOD_REDIR:
case OP_METHOD_REDIR_SUPER:
op_relocate_sv(&cMETHOPx(o)->op_u.op_meth_sv, &o->op_targ);
break;
#endif
case OP_HELEM: {
UNOP *rop;
SVOP *key_op;
OP *kid;
if ((key_op = cSVOPx(((BINOP*)o)->op_last))->op_type != OP_CONST)
break;
rop = (UNOP*)((BINOP*)o)->op_first;
goto check_keys;
case OP_HSLICE:
S_scalar_slice_warning(aTHX_ o);
/* FALLTHROUGH */
case OP_KVHSLICE:
kid = OpSIBLING(cLISTOPo->op_first);
if (/* I bet there's always a pushmark... */
OP_TYPE_ISNT_AND_WASNT_NN(kid, OP_LIST)
&& OP_TYPE_ISNT_NN(kid, OP_CONST))
{
break;
}
key_op = (SVOP*)(kid->op_type == OP_CONST
? kid
: OpSIBLING(kLISTOP->op_first));
rop = (UNOP*)((LISTOP*)o)->op_last;
check_keys:
if (o->op_private & OPpLVAL_INTRO || rop->op_type != OP_RV2HV)
rop = NULL;
S_check_hash_fields_and_hekify(aTHX_ rop, key_op);
break;
}
case OP_ASLICE:
S_scalar_slice_warning(aTHX_ o);
break;
case OP_SUBST: {
if (cPMOPo->op_pmreplrootu.op_pmreplroot)
finalize_op(cPMOPo->op_pmreplrootu.op_pmreplroot);
break;
}
default:
break;
}
if (o->op_flags & OPf_KIDS) {
OP *kid;
#ifdef DEBUGGING
/* check that op_last points to the last sibling, and that
* the last op_sibling field points back to the parent, and
* that the only ops with KIDS are those which are entitled to
* them */
U32 type = o->op_type;
U32 family;
bool has_last;
if (type == OP_NULL) {
type = o->op_targ;
/* ck_glob creates a null UNOP with ex-type GLOB
* (which is a list op. So pretend it wasn't a listop */
if (type == OP_GLOB)
type = OP_NULL;
}
family = PL_opargs[type] & OA_CLASS_MASK;
has_last = ( family == OA_BINOP
|| family == OA_LISTOP
|| family == OA_PMOP
|| family == OA_LOOP
);
assert( has_last /* has op_first and op_last, or ...
... has (or may have) op_first: */
|| family == OA_UNOP
|| family == OA_UNOP_AUX
|| family == OA_LOGOP
|| family == OA_BASEOP_OR_UNOP
|| family == OA_FILESTATOP
|| family == OA_LOOPEXOP
|| family == OA_METHOP
/* I don't know why SASSIGN is tagged as OA_BASEOP - DAPM */
|| type == OP_SASSIGN
|| type == OP_CUSTOM
|| type == OP_NULL /* new_logop does this */
);
for (kid = cUNOPo->op_first; kid; kid = OpSIBLING(kid)) {
# ifdef PERL_OP_PARENT
if (!OpHAS_SIBLING(kid)) {
if (has_last)
assert(kid == cLISTOPo->op_last);
assert(kid->op_sibling == o);
}
# else
if (OpHAS_SIBLING(kid)) {
assert(!kid->op_lastsib);
}
else {
assert(kid->op_lastsib);
if (has_last)
assert(kid == cLISTOPo->op_last);
}
# endif
}
#endif
for (kid = cUNOPo->op_first; kid; kid = OpSIBLING(kid))
finalize_op(kid);
}
}
/*
=for apidoc Amx|OP *|op_lvalue|OP *o|I32 type
Propagate lvalue ("modifiable") context to an op and its children.
I<type> represents the context type, roughly based on the type of op that
would do the modifying, although C<local()> is represented by OP_NULL,
because it has no op type of its own (it is signalled by a flag on
the lvalue op).
This function detects things that can't be modified, such as C<$x+1>, and
generates errors for them. For example, C<$x+1 = 2> would cause it to be
called with an op of type OP_ADD and a C<type> argument of OP_SASSIGN.
It also flags things that need to behave specially in an lvalue context,
such as C<$$x = 5> which might have to vivify a reference in C<$x>.
=cut
*/
static void
S_mark_padname_lvalue(pTHX_ PADNAME *pn)
{
CV *cv = PL_compcv;
PadnameLVALUE_on(pn);
while (PadnameOUTER(pn) && PARENT_PAD_INDEX(pn)) {
cv = CvOUTSIDE(cv);
assert(cv);
assert(CvPADLIST(cv));
pn =
PadlistNAMESARRAY(CvPADLIST(cv))[PARENT_PAD_INDEX(pn)];
assert(PadnameLEN(pn));
PadnameLVALUE_on(pn);
}
}
static bool
S_vivifies(const OPCODE type)
{
switch(type) {
case OP_RV2AV: case OP_ASLICE:
case OP_RV2HV: case OP_KVASLICE:
case OP_RV2SV: case OP_HSLICE:
case OP_AELEMFAST: case OP_KVHSLICE:
case OP_HELEM:
case OP_AELEM:
return 1;
}
return 0;
}
static void
S_lvref(pTHX_ OP *o, I32 type)
{
dVAR;
OP *kid;
switch (o->op_type) {
case OP_COND_EXPR:
for (kid = OpSIBLING(cUNOPo->op_first); kid;
kid = OpSIBLING(kid))
S_lvref(aTHX_ kid, type);
/* FALLTHROUGH */
case OP_PUSHMARK:
return;
case OP_RV2AV:
if (cUNOPo->op_first->op_type != OP_GV) goto badref;
o->op_flags |= OPf_STACKED;
if (o->op_flags & OPf_PARENS) {
if (o->op_private & OPpLVAL_INTRO) {
yyerror(Perl_form(aTHX_ "Can't modify reference to "
"localized parenthesized array in list assignment"));
return;
}
slurpy:
CHANGE_TYPE(o, OP_LVAVREF);
o->op_private &= OPpLVAL_INTRO|OPpPAD_STATE;
o->op_flags |= OPf_MOD|OPf_REF;
return;
}
o->op_private |= OPpLVREF_AV;
goto checkgv;
case OP_RV2CV:
kid = cUNOPo->op_first;
if (kid->op_type == OP_NULL)
kid = cUNOPx(kUNOP->op_first->op_sibling)
->op_first;
o->op_private = OPpLVREF_CV;
if (kid->op_type == OP_GV)
o->op_flags |= OPf_STACKED;
else if (kid->op_type == OP_PADCV) {
o->op_targ = kid->op_targ;
kid->op_targ = 0;
op_free(cUNOPo->op_first);
cUNOPo->op_first = NULL;
o->op_flags &=~ OPf_KIDS;
}
else goto badref;
break;
case OP_RV2HV:
if (o->op_flags & OPf_PARENS) {
parenhash:
yyerror(Perl_form(aTHX_ "Can't modify reference to "
"parenthesized hash in list assignment"));
return;
}
o->op_private |= OPpLVREF_HV;
/* FALLTHROUGH */
case OP_RV2SV:
checkgv:
if (cUNOPo->op_first->op_type != OP_GV) goto badref;
o->op_flags |= OPf_STACKED;
break;
case OP_PADHV:
if (o->op_flags & OPf_PARENS) goto parenhash;
o->op_private |= OPpLVREF_HV;
/* FALLTHROUGH */
case OP_PADSV:
PAD_COMPNAME_GEN_set(o->op_targ, PERL_INT_MAX);
break;
case OP_PADAV:
PAD_COMPNAME_GEN_set(o->op_targ, PERL_INT_MAX);
if (o->op_flags & OPf_PARENS) goto slurpy;
o->op_private |= OPpLVREF_AV;
break;
case OP_AELEM:
case OP_HELEM:
o->op_private |= OPpLVREF_ELEM;
o->op_flags |= OPf_STACKED;
break;
case OP_ASLICE:
case OP_HSLICE:
CHANGE_TYPE(o, OP_LVREFSLICE);
o->op_private &= OPpLVAL_INTRO|OPpLVREF_ELEM;
return;
case OP_NULL:
if (o->op_flags & OPf_SPECIAL) /* do BLOCK */
goto badref;
else if (!(o->op_flags & OPf_KIDS))
return;
if (o->op_targ != OP_LIST) {
S_lvref(aTHX_ cBINOPo->op_first, type);
return;
}
/* FALLTHROUGH */
case OP_LIST:
for (kid = cLISTOPo->op_first; kid; kid = OpSIBLING(kid)) {
assert((kid->op_flags & OPf_WANT) != OPf_WANT_VOID);
S_lvref(aTHX_ kid, type);
}
return;
case OP_STUB:
if (o->op_flags & OPf_PARENS)
return;
/* FALLTHROUGH */
default:
badref:
/* diag_listed_as: Can't modify reference to %s in %s assignment */
yyerror(Perl_form(aTHX_ "Can't modify reference to %s in %s",
o->op_type == OP_NULL && o->op_flags & OPf_SPECIAL
? "do block"
: OP_DESC(o),
PL_op_desc[type]));
return;
}
CHANGE_TYPE(o, OP_LVREF);
o->op_private &=
OPpLVAL_INTRO|OPpLVREF_ELEM|OPpLVREF_TYPE|OPpPAD_STATE;
if (type == OP_ENTERLOOP)
o->op_private |= OPpLVREF_ITER;
}
OP *
Perl_op_lvalue_flags(pTHX_ OP *o, I32 type, U32 flags)
{
dVAR;
OP *kid;
/* -1 = error on localize, 0 = ignore localize, 1 = ok to localize */
int localize = -1;
if (!o || (PL_parser && PL_parser->error_count))
return o;
if ((o->op_private & OPpTARGET_MY)
&& (PL_opargs[o->op_type] & OA_TARGLEX))/* OPp share the meaning */
{
return o;
}
assert( (o->op_flags & OPf_WANT) != OPf_WANT_VOID );
if (type == OP_PRTF || type == OP_SPRINTF) type = OP_ENTERSUB;
switch (o->op_type) {
case OP_UNDEF:
PL_modcount++;
return o;
case OP_STUB:
if ((o->op_flags & OPf_PARENS))
break;
goto nomod;
case OP_ENTERSUB:
if ((type == OP_UNDEF || type == OP_REFGEN || type == OP_LOCK) &&
!(o->op_flags & OPf_STACKED)) {
CHANGE_TYPE(o, OP_RV2CV); /* entersub => rv2cv */
assert(cUNOPo->op_first->op_type == OP_NULL);
op_null(((LISTOP*)cUNOPo->op_first)->op_first);/* disable pushmark */
break;
}
else { /* lvalue subroutine call */
o->op_private |= OPpLVAL_INTRO;
PL_modcount = RETURN_UNLIMITED_NUMBER;
if (type == OP_GREPSTART || type == OP_ENTERSUB
|| type == OP_REFGEN || type == OP_LEAVESUBLV) {
/* Potential lvalue context: */
o->op_private |= OPpENTERSUB_INARGS;
break;
}
else { /* Compile-time error message: */
OP *kid = cUNOPo->op_first;
CV *cv;
GV *gv;
if (kid->op_type != OP_PUSHMARK) {
if (kid->op_type != OP_NULL || kid->op_targ != OP_LIST)
Perl_croak(aTHX_
"panic: unexpected lvalue entersub "
"args: type/targ %ld:%"UVuf,
(long)kid->op_type, (UV)kid->op_targ);
kid = kLISTOP->op_first;
}
while (OpHAS_SIBLING(kid))
kid = OpSIBLING(kid);
if (!(kid->op_type == OP_NULL && kid->op_targ == OP_RV2CV)) {
break; /* Postpone until runtime */
}
kid = kUNOP->op_first;
if (kid->op_type == OP_NULL && kid->op_targ == OP_RV2SV)
kid = kUNOP->op_first;
if (kid->op_type == OP_NULL)
Perl_croak(aTHX_
"Unexpected constant lvalue entersub "
"entry via type/targ %ld:%"UVuf,
(long)kid->op_type, (UV)kid->op_targ);
if (kid->op_type != OP_GV) {
break;
}
gv = kGVOP_gv;
cv = isGV(gv)
? GvCV(gv)
: SvROK(gv) && SvTYPE(SvRV(gv)) == SVt_PVCV
? MUTABLE_CV(SvRV(gv))
: NULL;
if (!cv)
break;
if (CvLVALUE(cv))
break;
}
}
/* FALLTHROUGH */
default:
nomod:
if (flags & OP_LVALUE_NO_CROAK) return NULL;
/* grep, foreach, subcalls, refgen */
if (type == OP_GREPSTART || type == OP_ENTERSUB
|| type == OP_REFGEN || type == OP_LEAVESUBLV)
break;
yyerror(Perl_form(aTHX_ "Can't modify %s in %s",
(o->op_type == OP_NULL && (o->op_flags & OPf_SPECIAL)
? "do block"
: (o->op_type == OP_ENTERSUB
? "non-lvalue subroutine call"
: OP_DESC(o))),
type ? PL_op_desc[type] : "local"));
return o;
case OP_PREINC:
case OP_PREDEC:
case OP_POW:
case OP_MULTIPLY:
case OP_DIVIDE:
case OP_MODULO:
case OP_ADD:
case OP_SUBTRACT:
case OP_CONCAT:
case OP_LEFT_SHIFT:
case OP_RIGHT_SHIFT:
case OP_BIT_AND:
case OP_BIT_XOR:
case OP_BIT_OR:
case OP_I_MULTIPLY:
case OP_I_DIVIDE:
case OP_I_MODULO:
case OP_I_ADD:
case OP_I_SUBTRACT:
if (!(o->op_flags & OPf_STACKED))
goto nomod;
PL_modcount++;
break;
case OP_REPEAT:
if (o->op_flags & OPf_STACKED) {
PL_modcount++;
break;
}
if (!(o->op_private & OPpREPEAT_DOLIST))
goto nomod;
else {
const I32 mods = PL_modcount;
modkids(cBINOPo->op_first, type);
if (type != OP_AASSIGN)
goto nomod;
kid = cBINOPo->op_last;
if (kid->op_type == OP_CONST && SvIOK(kSVOP_sv)) {
const IV iv = SvIV(kSVOP_sv);
if (PL_modcount != RETURN_UNLIMITED_NUMBER)
PL_modcount =
mods + (PL_modcount - mods) * (iv < 0 ? 0 : iv);
}
else
PL_modcount = RETURN_UNLIMITED_NUMBER;
}
break;
case OP_COND_EXPR:
localize = 1;
for (kid = OpSIBLING(cUNOPo->op_first); kid; kid = OpSIBLING(kid))
op_lvalue(kid, type);
break;
case OP_RV2AV:
case OP_RV2HV:
if (type == OP_REFGEN && o->op_flags & OPf_PARENS) {
PL_modcount = RETURN_UNLIMITED_NUMBER;
return o; /* Treat \(@foo) like ordinary list. */
}
/* FALLTHROUGH */
case OP_RV2GV:
if (scalar_mod_type(o, type))
goto nomod;
ref(cUNOPo->op_first, o->op_type);
/* FALLTHROUGH */
case OP_ASLICE:
case OP_HSLICE:
localize = 1;
/* FALLTHROUGH */
case OP_AASSIGN:
/* Do not apply the lvsub flag for rv2[ah]v in scalar context. */
if (type == OP_LEAVESUBLV && (
(o->op_type != OP_RV2AV && o->op_type != OP_RV2HV)
|| (o->op_flags & OPf_WANT) != OPf_WANT_SCALAR
))
o->op_private |= OPpMAYBE_LVSUB;
/* FALLTHROUGH */
case OP_NEXTSTATE:
case OP_DBSTATE:
PL_modcount = RETURN_UNLIMITED_NUMBER;
break;
case OP_KVHSLICE:
case OP_KVASLICE:
if (type == OP_LEAVESUBLV)
o->op_private |= OPpMAYBE_LVSUB;
goto nomod;
case OP_AV2ARYLEN:
PL_hints |= HINT_BLOCK_SCOPE;
if (type == OP_LEAVESUBLV)
o->op_private |= OPpMAYBE_LVSUB;
PL_modcount++;
break;
case OP_RV2SV:
ref(cUNOPo->op_first, o->op_type);
localize = 1;
/* FALLTHROUGH */
case OP_GV:
PL_hints |= HINT_BLOCK_SCOPE;
/* FALLTHROUGH */
case OP_SASSIGN:
case OP_ANDASSIGN:
case OP_ORASSIGN:
case OP_DORASSIGN:
PL_modcount++;
break;
case OP_AELEMFAST:
case OP_AELEMFAST_LEX:
localize = -1;
PL_modcount++;
break;
case OP_PADAV:
case OP_PADHV:
PL_modcount = RETURN_UNLIMITED_NUMBER;
if (type == OP_REFGEN && o->op_flags & OPf_PARENS)
return o; /* Treat \(@foo) like ordinary list. */
if (scalar_mod_type(o, type))
goto nomod;
if ((o->op_flags & OPf_WANT) != OPf_WANT_SCALAR
&& type == OP_LEAVESUBLV)
o->op_private |= OPpMAYBE_LVSUB;
/* FALLTHROUGH */
case OP_PADSV:
PL_modcount++;
if (!type) /* local() */
Perl_croak(aTHX_ "Can't localize lexical variable %"PNf,
PNfARG(PAD_COMPNAME(o->op_targ)));
if (!(o->op_private & OPpLVAL_INTRO)
|| ( type != OP_SASSIGN && type != OP_AASSIGN
&& PadnameIsSTATE(PAD_COMPNAME_SV(o->op_targ)) ))
S_mark_padname_lvalue(aTHX_ PAD_COMPNAME_SV(o->op_targ));
break;
case OP_PUSHMARK:
localize = 0;
break;
case OP_KEYS:
case OP_RKEYS:
if (type != OP_SASSIGN && type != OP_LEAVESUBLV)
goto nomod;
goto lvalue_func;
case OP_SUBSTR:
if (o->op_private == 4) /* don't allow 4 arg substr as lvalue */
goto nomod;
/* FALLTHROUGH */
case OP_POS:
case OP_VEC:
lvalue_func:
if (type == OP_LEAVESUBLV)
o->op_private |= OPpMAYBE_LVSUB;
if (o->op_flags & OPf_KIDS)
op_lvalue(OpSIBLING(cBINOPo->op_first), type);
break;
case OP_AELEM:
case OP_HELEM:
ref(cBINOPo->op_first, o->op_type);
if (type == OP_ENTERSUB &&
!(o->op_private & (OPpLVAL_INTRO | OPpDEREF)))
o->op_private |= OPpLVAL_DEFER;
if (type == OP_LEAVESUBLV)
o->op_private |= OPpMAYBE_LVSUB;
localize = 1;
PL_modcount++;
break;
case OP_LEAVE:
case OP_LEAVELOOP:
o->op_private |= OPpLVALUE;
/* FALLTHROUGH */
case OP_SCOPE:
case OP_ENTER:
case OP_LINESEQ:
localize = 0;
if (o->op_flags & OPf_KIDS)
op_lvalue(cLISTOPo->op_last, type);
break;
case OP_NULL:
localize = 0;
if (o->op_flags & OPf_SPECIAL) /* do BLOCK */
goto nomod;
else if (!(o->op_flags & OPf_KIDS))
break;
if (o->op_targ != OP_LIST) {
op_lvalue(cBINOPo->op_first, type);
break;
}
/* FALLTHROUGH */
case OP_LIST:
localize = 0;
for (kid = cLISTOPo->op_first; kid; kid = OpSIBLING(kid))
/* elements might be in void context because the list is
in scalar context or because they are attribute sub calls */
if ( (kid->op_flags & OPf_WANT) != OPf_WANT_VOID )
op_lvalue(kid, type);
break;
case OP_COREARGS:
return o;
case OP_AND:
case OP_OR:
if (type == OP_LEAVESUBLV
|| !S_vivifies(cLOGOPo->op_first->op_type))
op_lvalue(cLOGOPo->op_first, type);
if (type == OP_LEAVESUBLV
|| !S_vivifies(OpSIBLING(cLOGOPo->op_first)->op_type))
op_lvalue(OpSIBLING(cLOGOPo->op_first), type);
goto nomod;
case OP_SREFGEN:
if (type != OP_AASSIGN && type != OP_SASSIGN
&& type != OP_ENTERLOOP)
goto nomod;
/* Don’t bother applying lvalue context to the ex-list. */
kid = cUNOPx(cUNOPo->op_first)->op_first;
assert (!OpHAS_SIBLING(kid));
goto kid_2lvref;
case OP_REFGEN:
if (type != OP_AASSIGN) goto nomod;
kid = cUNOPo->op_first;
kid_2lvref:
{
const U8 ec = PL_parser ? PL_parser->error_count : 0;
S_lvref(aTHX_ kid, type);
if (!PL_parser || PL_parser->error_count == ec) {
if (!FEATURE_REFALIASING_IS_ENABLED)
Perl_croak(aTHX_
"Experimental aliasing via reference not enabled");
Perl_ck_warner_d(aTHX_
packWARN(WARN_EXPERIMENTAL__REFALIASING),
"Aliasing via reference is experimental");
}
}
if (o->op_type == OP_REFGEN)
op_null(cUNOPx(cUNOPo->op_first)->op_first); /* pushmark */
op_null(o);
return o;
case OP_SPLIT:
kid = cLISTOPo->op_first;
if (kid && kid->op_type == OP_PUSHRE &&
( kid->op_targ
|| o->op_flags & OPf_STACKED
#ifdef USE_ITHREADS
|| ((PMOP*)kid)->op_pmreplrootu.op_pmtargetoff
#else
|| ((PMOP*)kid)->op_pmreplrootu.op_pmtargetgv
#endif
)) {
/* This is actually @array = split. */
PL_modcount = RETURN_UNLIMITED_NUMBER;
break;
}
goto nomod;
case OP_SCALAR:
op_lvalue(cUNOPo->op_first, OP_ENTERSUB);
goto nomod;
}
/* [20011101.069] File test operators interpret OPf_REF to mean that
their argument is a filehandle; thus \stat(".") should not set
it. AMS 20011102 */
if (type == OP_REFGEN &&
PL_check[o->op_type] == Perl_ck_ftst)
return o;
if (type != OP_LEAVESUBLV)
o->op_flags |= OPf_MOD;
if (type == OP_AASSIGN || type == OP_SASSIGN)
o->op_flags |= OPf_SPECIAL|OPf_REF;
else if (!type) { /* local() */
switch (localize) {
case 1:
o->op_private |= OPpLVAL_INTRO;
o->op_flags &= ~OPf_SPECIAL;
PL_hints |= HINT_BLOCK_SCOPE;
break;
case 0:
break;
case -1:
Perl_ck_warner(aTHX_ packWARN(WARN_SYNTAX),
"Useless localization of %s", OP_DESC(o));
}
}
else if (type != OP_GREPSTART && type != OP_ENTERSUB
&& type != OP_LEAVESUBLV)
o->op_flags |= OPf_REF;
return o;
}
STATIC bool
S_scalar_mod_type(const OP *o, I32 type)
{
switch (type) {
case OP_POS:
case OP_SASSIGN:
if (o && o->op_type == OP_RV2GV)
return FALSE;
/* FALLTHROUGH */
case OP_PREINC:
case OP_PREDEC:
case OP_POSTINC:
case OP_POSTDEC:
case OP_I_PREINC:
case OP_I_PREDEC:
case OP_I_POSTINC:
case OP_I_POSTDEC:
case OP_POW:
case OP_MULTIPLY:
case OP_DIVIDE:
case OP_MODULO:
case OP_REPEAT:
case OP_ADD:
case OP_SUBTRACT:
case OP_I_MULTIPLY:
case OP_I_DIVIDE:
case OP_I_MODULO:
case OP_I_ADD:
case OP_I_SUBTRACT:
case OP_LEFT_SHIFT:
case OP_RIGHT_SHIFT:
case OP_BIT_AND:
case OP_BIT_XOR:
case OP_BIT_OR:
case OP_CONCAT:
case OP_SUBST:
case OP_TRANS:
case OP_TRANSR:
case OP_READ:
case OP_SYSREAD:
case OP_RECV:
case OP_ANDASSIGN:
case OP_ORASSIGN:
case OP_DORASSIGN:
return TRUE;
default:
return FALSE;
}
}
STATIC bool
S_is_handle_constructor(const OP *o, I32 numargs)
{
PERL_ARGS_ASSERT_IS_HANDLE_CONSTRUCTOR;
switch (o->op_type) {
case OP_PIPE_OP:
case OP_SOCKPAIR:
if (numargs == 2)
return TRUE;
/* FALLTHROUGH */
case OP_SYSOPEN:
case OP_OPEN:
case OP_SELECT: /* XXX c.f. SelectSaver.pm */
case OP_SOCKET:
case OP_OPEN_DIR:
case OP_ACCEPT:
if (numargs == 1)
return TRUE;
/* FALLTHROUGH */
default:
return FALSE;
}
}
static OP *
S_refkids(pTHX_ OP *o, I32 type)
{
if (o && o->op_flags & OPf_KIDS) {
OP *kid;
for (kid = cLISTOPo->op_first; kid; kid = OpSIBLING(kid))
ref(kid, type);
}
return o;
}
OP *
Perl_doref(pTHX_ OP *o, I32 type, bool set_op_ref)
{
dVAR;
OP *kid;
PERL_ARGS_ASSERT_DOREF;
if (!o || (PL_parser && PL_parser->error_count))
return o;
switch (o->op_type) {
case OP_ENTERSUB:
if ((type == OP_EXISTS || type == OP_DEFINED) &&
!(o->op_flags & OPf_STACKED)) {
CHANGE_TYPE(o, OP_RV2CV); /* entersub => rv2cv */
assert(cUNOPo->op_first->op_type == OP_NULL);
op_null(((LISTOP*)cUNOPo->op_first)->op_first); /* disable pushmark */
o->op_flags |= OPf_SPECIAL;
}
else if (type == OP_RV2SV || type == OP_RV2AV || type == OP_RV2HV){
o->op_private |= (type == OP_RV2AV ? OPpDEREF_AV
: type == OP_RV2HV ? OPpDEREF_HV
: OPpDEREF_SV);
o->op_flags |= OPf_MOD;
}
break;
case OP_COND_EXPR:
for (kid = OpSIBLING(cUNOPo->op_first); kid; kid = OpSIBLING(kid))
doref(kid, type, set_op_ref);
break;
case OP_RV2SV:
if (type == OP_DEFINED)
o->op_flags |= OPf_SPECIAL; /* don't create GV */
doref(cUNOPo->op_first, o->op_type, set_op_ref);
/* FALLTHROUGH */
case OP_PADSV:
if (type == OP_RV2SV || type == OP_RV2AV || type == OP_RV2HV) {
o->op_private |= (type == OP_RV2AV ? OPpDEREF_AV
: type == OP_RV2HV ? OPpDEREF_HV
: OPpDEREF_SV);
o->op_flags |= OPf_MOD;
}
break;
case OP_RV2AV:
case OP_RV2HV:
if (set_op_ref)
o->op_flags |= OPf_REF;
/* FALLTHROUGH */
case OP_RV2GV:
if (type == OP_DEFINED)
o->op_flags |= OPf_SPECIAL; /* don't create GV */
doref(cUNOPo->op_first, o->op_type, set_op_ref);
break;
case OP_PADAV:
case OP_PADHV:
if (set_op_ref)
o->op_flags |= OPf_REF;
break;
case OP_SCALAR:
case OP_NULL:
if (!(o->op_flags & OPf_KIDS) || type == OP_DEFINED)
break;
doref(cBINOPo->op_first, type, set_op_ref);
break;
case OP_AELEM:
case OP_HELEM:
doref(cBINOPo->op_first, o->op_type, set_op_ref);
if (type == OP_RV2SV || type == OP_RV2AV || type == OP_RV2HV) {
o->op_private |= (type == OP_RV2AV ? OPpDEREF_AV
: type == OP_RV2HV ? OPpDEREF_HV
: OPpDEREF_SV);
o->op_flags |= OPf_MOD;
}
break;
case OP_SCOPE:
case OP_LEAVE:
set_op_ref = FALSE;
/* FALLTHROUGH */
case OP_ENTER:
case OP_LIST:
if (!(o->op_flags & OPf_KIDS))
break;
doref(cLISTOPo->op_last, type, set_op_ref);
break;
default:
break;
}
return scalar(o);
}
STATIC OP *
S_dup_attrlist(pTHX_ OP *o)
{
OP *rop;
PERL_ARGS_ASSERT_DUP_ATTRLIST;
/* An attrlist is either a simple OP_CONST or an OP_LIST with kids,
* where the first kid is OP_PUSHMARK and the remaining ones
* are OP_CONST. We need to push the OP_CONST values.
*/
if (o->op_type == OP_CONST)
rop = newSVOP(OP_CONST, o->op_flags, SvREFCNT_inc_NN(cSVOPo->op_sv));
else {
assert((o->op_type == OP_LIST) && (o->op_flags & OPf_KIDS));
rop = NULL;
for (o = cLISTOPo->op_first; o; o = OpSIBLING(o)) {
if (o->op_type == OP_CONST)
rop = op_append_elem(OP_LIST, rop,
newSVOP(OP_CONST, o->op_flags,
SvREFCNT_inc_NN(cSVOPo->op_sv)));
}
}
return rop;
}
STATIC void
S_apply_attrs(pTHX_ HV *stash, SV *target, OP *attrs)
{
SV * const stashsv = stash ? newSVhek(HvNAME_HEK(stash)) : &PL_sv_no;
PERL_ARGS_ASSERT_APPLY_ATTRS;
/* fake up C<use attributes $pkg,$rv,@attrs> */
#define ATTRSMODULE "attributes"
#define ATTRSMODULE_PM "attributes.pm"
Perl_load_module(aTHX_ PERL_LOADMOD_IMPORT_OPS,
newSVpvs(ATTRSMODULE),
NULL,
op_prepend_elem(OP_LIST,
newSVOP(OP_CONST, 0, stashsv),
op_prepend_elem(OP_LIST,
newSVOP(OP_CONST, 0,
newRV(target)),
dup_attrlist(attrs))));
}
STATIC void
S_apply_attrs_my(pTHX_ HV *stash, OP *target, OP *attrs, OP **imopsp)
{
OP *pack, *imop, *arg;
SV *meth, *stashsv, **svp;
PERL_ARGS_ASSERT_APPLY_ATTRS_MY;
if (!attrs)
return;
assert(target->op_type == OP_PADSV ||
target->op_type == OP_PADHV ||
target->op_type == OP_PADAV);
/* Ensure that attributes.pm is loaded. */
/* Don't force the C<use> if we don't need it. */
svp = hv_fetchs(GvHVn(PL_incgv), ATTRSMODULE_PM, FALSE);
if (svp && *svp != &PL_sv_undef)
NOOP; /* already in %INC */
else
Perl_load_module(aTHX_ PERL_LOADMOD_NOIMPORT,
newSVpvs(ATTRSMODULE), NULL);
/* Need package name for method call. */
pack = newSVOP(OP_CONST, 0, newSVpvs(ATTRSMODULE));
/* Build up the real arg-list. */
stashsv = stash ? newSVhek(HvNAME_HEK(stash)) : &PL_sv_no;
arg = newOP(OP_PADSV, 0);
arg->op_targ = target->op_targ;
arg = op_prepend_elem(OP_LIST,
newSVOP(OP_CONST, 0, stashsv),
op_prepend_elem(OP_LIST,
newUNOP(OP_REFGEN, 0,
op_lvalue(arg, OP_REFGEN)),
dup_attrlist(attrs)));
/* Fake up a method call to import */
meth = newSVpvs_share("import");
imop = op_convert_list(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL|OPf_WANT_VOID,
op_append_elem(OP_LIST,
op_prepend_elem(OP_LIST, pack, arg),
newMETHOP_named(OP_METHOD_NAMED, 0, meth)));
/* Combine the ops. */
*imopsp = op_append_elem(OP_LIST, *imopsp, imop);
}
/*
=notfor apidoc apply_attrs_string
Attempts to apply a list of attributes specified by the C<attrstr> and
C<len> arguments to the subroutine identified by the C<cv> argument which
is expected to be associated with the package identified by the C<stashpv>
argument (see L<attributes>). It gets this wrong, though, in that it
does not correctly identify the boundaries of the individual attribute
specifications within C<attrstr>. This is not really intended for the
public API, but has to be listed here for systems such as AIX which
need an explicit export list for symbols. (It's called from XS code
in support of the C<ATTRS:> keyword from F<xsubpp>.) Patches to fix it
to respect attribute syntax properly would be welcome.
=cut
*/
void
Perl_apply_attrs_string(pTHX_ const char *stashpv, CV *cv,
const char *attrstr, STRLEN len)
{
OP *attrs = NULL;
PERL_ARGS_ASSERT_APPLY_ATTRS_STRING;
if (!len) {
len = strlen(attrstr);
}
while (len) {
for (; isSPACE(*attrstr) && len; --len, ++attrstr) ;
if (len) {
const char * const sstr = attrstr;
for (; !isSPACE(*attrstr) && len; --len, ++attrstr) ;
attrs = op_append_elem(OP_LIST, attrs,
newSVOP(OP_CONST, 0,
newSVpvn(sstr, attrstr-sstr)));
}
}
Perl_load_module(aTHX_ PERL_LOADMOD_IMPORT_OPS,
newSVpvs(ATTRSMODULE),
NULL, op_prepend_elem(OP_LIST,
newSVOP(OP_CONST, 0, newSVpv(stashpv,0)),
op_prepend_elem(OP_LIST,
newSVOP(OP_CONST, 0,
newRV(MUTABLE_SV(cv))),
attrs)));
}
STATIC void
S_move_proto_attr(pTHX_ OP **proto, OP **attrs, const GV * name)
{
OP *new_proto = NULL;
STRLEN pvlen;
char *pv;
OP *o;
PERL_ARGS_ASSERT_MOVE_PROTO_ATTR;
if (!*attrs)
return;
o = *attrs;
if (o->op_type == OP_CONST) {
pv = SvPV(cSVOPo_sv, pvlen);
if (pvlen >= 10 && memEQ(pv, "prototype(", 10)) {
SV * const tmpsv = newSVpvn_flags(pv + 10, pvlen - 11, SvUTF8(cSVOPo_sv));
SV ** const tmpo = cSVOPx_svp(o);
SvREFCNT_dec(cSVOPo_sv);
*tmpo = tmpsv;
new_proto = o;
*attrs = NULL;
}
} else if (o->op_type == OP_LIST) {
OP * lasto;
assert(o->op_flags & OPf_KIDS);
lasto = cLISTOPo->op_first;
assert(lasto->op_type == OP_PUSHMARK);
for (o = OpSIBLING(lasto); o; o = OpSIBLING(o)) {
if (o->op_type == OP_CONST) {
pv = SvPV(cSVOPo_sv, pvlen);
if (pvlen >= 10 && memEQ(pv, "prototype(", 10)) {
SV * const tmpsv = newSVpvn_flags(pv + 10, pvlen - 11, SvUTF8(cSVOPo_sv));
SV ** const tmpo = cSVOPx_svp(o);
SvREFCNT_dec(cSVOPo_sv);
*tmpo = tmpsv;
if (new_proto && ckWARN(WARN_MISC)) {
STRLEN new_len;
const char * newp = SvPV(cSVOPo_sv, new_len);
Perl_warner(aTHX_ packWARN(WARN_MISC),
"Attribute prototype(%"UTF8f") discards earlier prototype attribute in same sub",
UTF8fARG(SvUTF8(cSVOPo_sv), new_len, newp));
op_free(new_proto);
}
else if (new_proto)
op_free(new_proto);
new_proto = o;
/* excise new_proto from the list */
op_sibling_splice(*attrs, lasto, 1, NULL);
o = lasto;
continue;
}
}
lasto = o;
}
/* If the list is now just the PUSHMARK, scrap the whole thing; otherwise attributes.xs
would get pulled in with no real need */
if (!OpHAS_SIBLING(cLISTOPx(*attrs)->op_first)) {
op_free(*attrs);
*attrs = NULL;
}
}
if (new_proto) {
SV *svname;
if (isGV(name)) {
svname = sv_newmortal();
gv_efullname3(svname, name, NULL);
}
else if (SvPOK(name) && *SvPVX((SV *)name) == '&')
svname = newSVpvn_flags(SvPVX((SV *)name)+1, SvCUR(name)-1, SvUTF8(name)|SVs_TEMP);
else
svname = (SV *)name;
if (ckWARN(WARN_ILLEGALPROTO))
(void)validate_proto(svname, cSVOPx_sv(new_proto), TRUE);
if (*proto && ckWARN(WARN_PROTOTYPE)) {
STRLEN old_len, new_len;
const char * oldp = SvPV(cSVOPx_sv(*proto), old_len);
const char * newp = SvPV(cSVOPx_sv(new_proto), new_len);
Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE),
"Prototype '%"UTF8f"' overridden by attribute 'prototype(%"UTF8f")'"
" in %"SVf,
UTF8fARG(SvUTF8(cSVOPx_sv(*proto)), old_len, oldp),
UTF8fARG(SvUTF8(cSVOPx_sv(new_proto)), new_len, newp),
SVfARG(svname));
}
if (*proto)
op_free(*proto);
*proto = new_proto;
}
}
static void
S_cant_declare(pTHX_ OP *o)
{
if (o->op_type == OP_NULL
&& (o->op_flags & (OPf_SPECIAL|OPf_KIDS)) == OPf_KIDS)
o = cUNOPo->op_first;
yyerror(Perl_form(aTHX_ "Can't declare %s in \"%s\"",
o->op_type == OP_NULL
&& o->op_flags & OPf_SPECIAL
? "do block"
: OP_DESC(o),
PL_parser->in_my == KEY_our ? "our" :
PL_parser->in_my == KEY_state ? "state" :
"my"));
}
STATIC OP *
S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp)
{
I32 type;
const bool stately = PL_parser && PL_parser->in_my == KEY_state;
PERL_ARGS_ASSERT_MY_KID;
if (!o || (PL_parser && PL_parser->error_count))
return o;
type = o->op_type;
if (type == OP_LIST) {
OP *kid;
for (kid = cLISTOPo->op_first; kid; kid = OpSIBLING(kid))
my_kid(kid, attrs, imopsp);
return o;
} else if (type == OP_UNDEF || type == OP_STUB) {
return o;
} else if (type == OP_RV2SV || /* "our" declaration */
type == OP_RV2AV ||
type == OP_RV2HV) { /* XXX does this let anything illegal in? */
if (cUNOPo->op_first->op_type != OP_GV) { /* MJD 20011224 */
S_cant_declare(aTHX_ o);
} else if (attrs) {
GV * const gv = cGVOPx_gv(cUNOPo->op_first);
assert(PL_parser);
PL_parser->in_my = FALSE;
PL_parser->in_my_stash = NULL;
apply_attrs(GvSTASH(gv),
(type == OP_RV2SV ? GvSV(gv) :
type == OP_RV2AV ? MUTABLE_SV(GvAV(gv)) :
type == OP_RV2HV ? MUTABLE_SV(GvHV(gv)) : MUTABLE_SV(gv)),
attrs);
}
o->op_private |= OPpOUR_INTRO;
return o;
}
else if (type != OP_PADSV &&
type != OP_PADAV &&
type != OP_PADHV &&
type != OP_PUSHMARK)
{
S_cant_declare(aTHX_ o);
return o;
}
else if (attrs && type != OP_PUSHMARK) {
HV *stash;
assert(PL_parser);
PL_parser->in_my = FALSE;
PL_parser->in_my_stash = NULL;
/* check for C<my Dog $spot> when deciding package */
stash = PAD_COMPNAME_TYPE(o->op_targ);
if (!stash)
stash = PL_curstash;
apply_attrs_my(stash, o, attrs, imopsp);
}
o->op_flags |= OPf_MOD;
o->op_private |= OPpLVAL_INTRO;
if (stately)
o->op_private |= OPpPAD_STATE;
return o;
}
OP *
Perl_my_attrs(pTHX_ OP *o, OP *attrs)
{
OP *rops;
int maybe_scalar = 0;
PERL_ARGS_ASSERT_MY_ATTRS;
/* [perl #17376]: this appears to be premature, and results in code such as
C< our(%x); > executing in list mode rather than void mode */
#if 0
if (o->op_flags & OPf_PARENS)
list(o);
else
maybe_scalar = 1;
#else
maybe_scalar = 1;
#endif
if (attrs)
SAVEFREEOP(attrs);
rops = NULL;
o = my_kid(o, attrs, &rops);
if (rops) {
if (maybe_scalar && o->op_type == OP_PADSV) {
o = scalar(op_append_list(OP_LIST, rops, o));
o->op_private |= OPpLVAL_INTRO;
}
else {
/* The listop in rops might have a pushmark at the beginning,
which will mess up list assignment. */
LISTOP * const lrops = (LISTOP *)rops; /* for brevity */
if (rops->op_type == OP_LIST &&
lrops->op_first && lrops->op_first->op_type == OP_PUSHMARK)
{
OP * const pushmark = lrops->op_first;
/* excise pushmark */
op_sibling_splice(rops, NULL, 1, NULL);
op_free(pushmark);
}
o = op_append_list(OP_LIST, o, rops);
}
}
PL_parser->in_my = FALSE;
PL_parser->in_my_stash = NULL;
return o;
}
OP *
Perl_sawparens(pTHX_ OP *o)
{
PERL_UNUSED_CONTEXT;
if (o)
o->op_flags |= OPf_PARENS;
return o;
}
OP *
Perl_bind_match(pTHX_ I32 type, OP *left, OP *right)
{
OP *o;
bool ismatchop = 0;
const OPCODE ltype = left->op_type;
const OPCODE rtype = right->op_type;
PERL_ARGS_ASSERT_BIND_MATCH;
if ( (ltype == OP_RV2AV || ltype == OP_RV2HV || ltype == OP_PADAV
|| ltype == OP_PADHV) && ckWARN(WARN_MISC))
{
const char * const desc
= PL_op_desc[(
rtype == OP_SUBST || rtype == OP_TRANS
|| rtype == OP_TRANSR
)
? (int)rtype : OP_MATCH];
const bool isary = ltype == OP_RV2AV || ltype == OP_PADAV;
SV * const name =
S_op_varname(aTHX_ left);
if (name)
Perl_warner(aTHX_ packWARN(WARN_MISC),
"Applying %s to %"SVf" will act on scalar(%"SVf")",
desc, SVfARG(name), SVfARG(name));
else {
const char * const sample = (isary
? "@array" : "%hash");
Perl_warner(aTHX_ packWARN(WARN_MISC),
"Applying %s to %s will act on scalar(%s)",
desc, sample, sample);
}
}
if (rtype == OP_CONST &&
cSVOPx(right)->op_private & OPpCONST_BARE &&
cSVOPx(right)->op_private & OPpCONST_STRICT)
{
no_bareword_allowed(right);
}
/* !~ doesn't make sense with /r, so error on it for now */
if (rtype == OP_SUBST && (cPMOPx(right)->op_pmflags & PMf_NONDESTRUCT) &&
type == OP_NOT)
/* diag_listed_as: Using !~ with %s doesn't make sense */
yyerror("Using !~ with s///r doesn't make sense");
if (rtype == OP_TRANSR && type == OP_NOT)
/* diag_listed_as: Using !~ with %s doesn't make sense */
yyerror("Using !~ with tr///r doesn't make sense");
ismatchop = (rtype == OP_MATCH ||
rtype == OP_SUBST ||
rtype == OP_TRANS || rtype == OP_TRANSR)
&& !(right->op_flags & OPf_SPECIAL);
if (ismatchop && right->op_private & OPpTARGET_MY) {
right->op_targ = 0;
right->op_private &= ~OPpTARGET_MY;
}
if (!(right->op_flags & OPf_STACKED) && !right->op_targ && ismatchop) {
if (left->op_type == OP_PADSV
&& !(left->op_private & OPpLVAL_INTRO))
{
right->op_targ = left->op_targ;
op_free(left);
o = right;
}
else {
right->op_flags |= OPf_STACKED;
if (rtype != OP_MATCH && rtype != OP_TRANSR &&
! (rtype == OP_TRANS &&
right->op_private & OPpTRANS_IDENTICAL) &&
! (rtype == OP_SUBST &&
(cPMOPx(right)->op_pmflags & PMf_NONDESTRUCT)))
left = op_lvalue(left, rtype);
if (right->op_type == OP_TRANS || right->op_type == OP_TRANSR)
o = newBINOP(OP_NULL, OPf_STACKED, scalar(left), right);
else
o = op_prepend_elem(rtype, scalar(left), right);
}
if (type == OP_NOT)
return newUNOP(OP_NOT, 0, scalar(o));
return o;
}
else
return bind_match(type, left,
pmruntime(newPMOP(OP_MATCH, 0), right, NULL, 0, 0));
}
OP *
Perl_invert(pTHX_ OP *o)
{
if (!o)
return NULL;
return newUNOP(OP_NOT, OPf_SPECIAL, scalar(o));
}
/*
=for apidoc Amx|OP *|op_scope|OP *o
Wraps up an op tree with some additional ops so that at runtime a dynamic
scope will be created. The original ops run in the new dynamic scope,
and then, provided that they exit normally, the scope will be unwound.
The additional ops used to create and unwind the dynamic scope will
normally be an C<enter>/C<leave> pair, but a C<scope> op may be used
instead if the ops are simple enough to not need the full dynamic scope
structure.
=cut
*/
OP *
Perl_op_scope(pTHX_ OP *o)
{
dVAR;
if (o) {
if (o->op_flags & OPf_PARENS || PERLDB_NOOPT || TAINTING_get) {
o = op_prepend_elem(OP_LINESEQ, newOP(OP_ENTER, 0), o);
CHANGE_TYPE(o, OP_LEAVE);
}
else if (o->op_type == OP_LINESEQ) {
OP *kid;
CHANGE_TYPE(o, OP_SCOPE);
kid = ((LISTOP*)o)->op_first;
if (kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE) {
op_null(kid);
/* The following deals with things like 'do {1 for 1}' */
kid = OpSIBLING(kid);
if (kid &&
(kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE))
op_null(kid);
}
}
else
o = newLISTOP(OP_SCOPE, 0, o, NULL);
}
return o;
}
OP *
Perl_op_unscope(pTHX_ OP *o)
{
if (o && o->op_type == OP_LINESEQ) {
OP *kid = cLISTOPo->op_first;
for(; kid; kid = OpSIBLING(kid))
if (kid->op_type == OP_NEXTSTATE || kid->op_type == OP_DBSTATE)
op_null(kid);
}
return o;
}
/*
=for apidoc Am|int|block_start|int full
Handles compile-time scope entry.
Arranges for hints to be restored on block
exit and also handles pad sequence numbers to make lexical variables scope
right. Returns a savestack index for use with C<block_end>.
=cut
*/
int
Perl_block_start(pTHX_ int full)
{
const int retval = PL_savestack_ix;
PL_compiling.cop_seq = PL_cop_seqmax;
COP_SEQMAX_INC;
pad_block_start(full);
SAVEHINTS();
PL_hints &= ~HINT_BLOCK_SCOPE;
SAVECOMPILEWARNINGS();
PL_compiling.cop_warnings = DUP_WARNINGS(PL_compiling.cop_warnings);
SAVEI32(PL_compiling.cop_seq);
PL_compiling.cop_seq = 0;
CALL_BLOCK_HOOKS(bhk_start, full);
return retval;
}
/*
=for apidoc Am|OP *|block_end|I32 floor|OP *seq
Handles compile-time scope exit. I<floor>
is the savestack index returned by
C<block_start>, and I<seq> is the body of the block. Returns the block,
possibly modified.
=cut
*/
OP*
Perl_block_end(pTHX_ I32 floor, OP *seq)
{
const int needblockscope = PL_hints & HINT_BLOCK_SCOPE;
OP* retval = scalarseq(seq);
OP *o;
/* XXX Is the null PL_parser check necessary here? */
assert(PL_parser); /* Let’s find out under debugging builds. */
if (PL_parser && PL_parser->parsed_sub) {
o = newSTATEOP(0, NULL, NULL);
op_null(o);
retval = op_append_elem(OP_LINESEQ, retval, o);
}
CALL_BLOCK_HOOKS(bhk_pre_end, &retval);
LEAVE_SCOPE(floor);
if (needblockscope)
PL_hints |= HINT_BLOCK_SCOPE; /* propagate out */
o = pad_leavemy();
if (o) {
/* pad_leavemy has created a sequence of introcv ops for all my
subs declared in the block. We have to replicate that list with
clonecv ops, to deal with this situation:
sub {
my sub s1;
my sub s2;
sub s1 { state sub foo { \&s2 } }
}->()
Originally, I was going to have introcv clone the CV and turn
off the stale flag. Since &s1 is declared before &s2, the
introcv op for &s1 is executed (on sub entry) before the one for
&s2. But the &foo sub inside &s1 (which is cloned when &s1 is
cloned, since it is a state sub) closes over &s2 and expects
to see it in its outer CV’s pad. If the introcv op clones &s1,
then &s2 is still marked stale. Since &s1 is not active, and
&foo closes over &s1’s implicit entry for &s2, we get a ‘Varia-
ble will not stay shared’ warning. Because it is the same stub
that will be used when the introcv op for &s2 is executed, clos-
ing over it is safe. Hence, we have to turn off the stale flag
on all lexical subs in the block before we clone any of them.
Hence, having introcv clone the sub cannot work. So we create a
list of ops like this:
lineseq
|
+-- introcv
|
+-- introcv
|
+-- introcv
|
.
.
.
|
+-- clonecv
|
+-- clonecv
|
+-- clonecv
|
.
.
.
*/
OP *kid = o->op_flags & OPf_KIDS ? cLISTOPo->op_first : o;
OP * const last = o->op_flags & OPf_KIDS ? cLISTOPo->op_last : o;
for (;; kid = OpSIBLING(kid)) {
OP *newkid = newOP(OP_CLONECV, 0);
newkid->op_targ = kid->op_targ;
o = op_append_elem(OP_LINESEQ, o, newkid);
if (kid == last) break;
}
retval = op_prepend_elem(OP_LINESEQ, o, retval);
}
CALL_BLOCK_HOOKS(bhk_post_end, &retval);
return retval;
}
/*
=head1 Compile-time scope hooks
=for apidoc Aox||blockhook_register
Register a set of hooks to be called when the Perl lexical scope changes
at compile time. See L<perlguts/"Compile-time scope hooks">.
=cut
*/
void
Perl_blockhook_register(pTHX_ BHK *hk)
{
PERL_ARGS_ASSERT_BLOCKHOOK_REGISTER;
Perl_av_create_and_push(aTHX_ &PL_blockhooks, newSViv(PTR2IV(hk)));
}
void
Perl_newPROG(pTHX_ OP *o)
{
PERL_ARGS_ASSERT_NEWPROG;
if (PL_in_eval) {
PERL_CONTEXT *cx;
I32 i;
if (PL_eval_root)
return;
PL_eval_root = newUNOP(OP_LEAVEEVAL,
((PL_in_eval & EVAL_KEEPERR)