summaryrefslogtreecommitdiff
path: root/op.c
diff options
context:
space:
mode:
Diffstat (limited to 'op.c')
-rw-r--r--op.c326
1 files changed, 220 insertions, 106 deletions
diff --git a/op.c b/op.c
index 915dd78907..b3c5f86f31 100644
--- a/op.c
+++ b/op.c
@@ -365,7 +365,7 @@ S_bad_type(pTHX_ I32 n, const char *t, const char *name, const OP *kid)
}
STATIC void
-S_no_bareword_allowed(pTHX_ const OP *o)
+S_no_bareword_allowed(pTHX_ OP *o)
{
PERL_ARGS_ASSERT_NO_BAREWORD_ALLOWED;
@@ -374,6 +374,7 @@ S_no_bareword_allowed(pTHX_ const OP *o)
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 */
@@ -1445,14 +1446,15 @@ S_finalize_op(pTHX_ OP* o)
PL_curcop = ((COP*)o); /* for warnings */
break;
case OP_EXEC:
- if (o->op_next && o->op_next->op_type == OP_NEXTSTATE
+ if ( o->op_sibling
+ && (o->op_sibling->op_type == OP_NEXTSTATE || o->op_sibling->op_type == OP_DBSTATE)
&& ckWARN(WARN_SYNTAX))
{
- if (o->op_next->op_sibling) {
- const OPCODE type = o->op_next->op_sibling->op_type;
+ if (o->op_sibling->op_sibling) {
+ const OPCODE type = o->op_sibling->op_sibling->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*)o->op_next));
+ CopLINE_set(PL_curcop, CopLINE((COP*)o->op_sibling));
Perl_warner(aTHX_ packWARN(WARN_EXEC),
"Statement unlikely to be reached");
Perl_warner(aTHX_ packWARN(WARN_EXEC),
@@ -1478,6 +1480,9 @@ S_finalize_op(pTHX_ OP* o)
break;
case OP_CONST:
+ if (cSVOPo->op_private & OPpCONST_STRICT)
+ no_bareword_allowed(o);
+ /* FALLTHROUGH */
#ifdef USE_ITHREADS
case OP_HINTSEVAL:
case OP_METHOD_NAMED:
@@ -1700,7 +1705,7 @@ Perl_op_lvalue_flags(pTHX_ OP *o, I32 type, U32 flags)
break;
goto nomod;
case OP_ENTERSUB:
- if ((type == OP_UNDEF || type == OP_REFGEN) &&
+ if ((type == OP_UNDEF || type == OP_REFGEN || type == OP_LOCK) &&
!(o->op_flags & OPf_STACKED)) {
o->op_type = OP_RV2CV; /* entersub => rv2cv */
/* Both ENTERSUB and RV2CV use this bit, but for different pur-
@@ -2011,14 +2016,6 @@ Perl_op_lvalue_flags(pTHX_ OP *o, I32 type, U32 flags)
return o;
}
-/* Do not use this. It will be removed after 5.14. */
-OP *
-Perl_mod(pTHX_ OP *o, I32 type)
-{
- return op_lvalue(o,type);
-}
-
-
STATIC bool
S_scalar_mod_type(const OP *o, I32 type)
{
@@ -2711,11 +2708,23 @@ Perl_newPROG(pTHX_ OP *o)
PERL_ARGS_ASSERT_NEWPROG;
if (PL_in_eval) {
+ PERL_CONTEXT *cx;
if (PL_eval_root)
return;
PL_eval_root = newUNOP(OP_LEAVEEVAL,
((PL_in_eval & EVAL_KEEPERR)
? OPf_SPECIAL : 0), o);
+
+ cx = &cxstack[cxstack_ix];
+ assert(CxTYPE(cx) == CXt_EVAL);
+
+ if ((cx->blk_gimme & G_WANT) == G_VOID)
+ scalarvoid(PL_eval_root);
+ else if ((cx->blk_gimme & G_WANT) == G_ARRAY)
+ list(PL_eval_root);
+ else
+ scalar(PL_eval_root);
+
/* don't use LINKLIST, since PL_eval_root might indirect through
* a rather expensive function call and LINKLIST evaluates its
* argument more than once */
@@ -2724,6 +2733,8 @@ Perl_newPROG(pTHX_ OP *o)
OpREFCNT_set(PL_eval_root, 1);
PL_eval_root->op_next = 0;
CALL_PEEP(PL_eval_start);
+ finalize_optree(PL_eval_root);
+
}
else {
if (o->op_type == OP_STUB) {
@@ -4807,6 +4818,76 @@ S_is_list_assignment(pTHX_ register const OP *o)
}
/*
+ Helper function for newASSIGNOP to detection commonality between the
+ lhs and the rhs. Marks all variables with PL_generation. If it
+ returns TRUE the assignment must be able to handle common variables.
+*/
+PERL_STATIC_INLINE bool
+S_aassign_common_vars(pTHX_ OP* o)
+{
+ OP *curop;
+ for (curop = cUNOPo->op_first; curop; curop=curop->op_sibling) {
+ if (PL_opargs[curop->op_type] & OA_DANGEROUS) {
+ if (curop->op_type == OP_GV) {
+ GV *gv = cGVOPx_gv(curop);
+ if (gv == PL_defgv
+ || (int)GvASSIGN_GENERATION(gv) == PL_generation)
+ return TRUE;
+ GvASSIGN_GENERATION_set(gv, PL_generation);
+ }
+ else if (curop->op_type == OP_PADSV ||
+ curop->op_type == OP_PADAV ||
+ curop->op_type == OP_PADHV ||
+ curop->op_type == OP_PADANY)
+ {
+ if (PAD_COMPNAME_GEN(curop->op_targ)
+ == (STRLEN)PL_generation)
+ return TRUE;
+ PAD_COMPNAME_GEN_set(curop->op_targ, PL_generation);
+
+ }
+ else if (curop->op_type == OP_RV2CV)
+ return TRUE;
+ else if (curop->op_type == OP_RV2SV ||
+ curop->op_type == OP_RV2AV ||
+ curop->op_type == OP_RV2HV ||
+ curop->op_type == OP_RV2GV) {
+ if (cUNOPx(curop)->op_first->op_type != OP_GV) /* funny deref? */
+ return TRUE;
+ }
+ else if (curop->op_type == OP_PUSHRE) {
+#ifdef USE_ITHREADS
+ if (((PMOP*)curop)->op_pmreplrootu.op_pmtargetoff) {
+ GV *const gv = MUTABLE_GV(PAD_SVl(((PMOP*)curop)->op_pmreplrootu.op_pmtargetoff));
+ if (gv == PL_defgv
+ || (int)GvASSIGN_GENERATION(gv) == PL_generation)
+ return TRUE;
+ GvASSIGN_GENERATION_set(gv, PL_generation);
+ }
+#else
+ GV *const gv
+ = ((PMOP*)curop)->op_pmreplrootu.op_pmtargetgv;
+ if (gv) {
+ if (gv == PL_defgv
+ || (int)GvASSIGN_GENERATION(gv) == PL_generation)
+ return TRUE;
+ GvASSIGN_GENERATION_set(gv, PL_generation);
+ }
+#endif
+ }
+ else
+ return TRUE;
+ }
+
+ if (curop->op_flags & OPf_KIDS) {
+ if (aassign_common_vars(curop))
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*
=for apidoc Am|OP *|newASSIGNOP|I32 flags|OP *left|I32 optype|OP *right
Constructs, checks, and returns an assignment op. I<left> and I<right>
@@ -4944,64 +5025,10 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
*/
if (maybe_common_vars) {
- OP *lastop = o;
PL_generation++;
- for (curop = LINKLIST(o); curop != o; curop = LINKLIST(curop)) {
- if (PL_opargs[curop->op_type] & OA_DANGEROUS) {
- if (curop->op_type == OP_GV) {
- GV *gv = cGVOPx_gv(curop);
- if (gv == PL_defgv
- || (int)GvASSIGN_GENERATION(gv) == PL_generation)
- break;
- GvASSIGN_GENERATION_set(gv, PL_generation);
- }
- else if (curop->op_type == OP_PADSV ||
- curop->op_type == OP_PADAV ||
- curop->op_type == OP_PADHV ||
- curop->op_type == OP_PADANY)
- {
- if (PAD_COMPNAME_GEN(curop->op_targ)
- == (STRLEN)PL_generation)
- break;
- PAD_COMPNAME_GEN_set(curop->op_targ, PL_generation);
-
- }
- else if (curop->op_type == OP_RV2CV)
- break;
- else if (curop->op_type == OP_RV2SV ||
- curop->op_type == OP_RV2AV ||
- curop->op_type == OP_RV2HV ||
- curop->op_type == OP_RV2GV) {
- if (lastop->op_type != OP_GV) /* funny deref? */
- break;
- }
- else if (curop->op_type == OP_PUSHRE) {
-#ifdef USE_ITHREADS
- if (((PMOP*)curop)->op_pmreplrootu.op_pmtargetoff) {
- GV *const gv = MUTABLE_GV(PAD_SVl(((PMOP*)curop)->op_pmreplrootu.op_pmtargetoff));
- if (gv == PL_defgv
- || (int)GvASSIGN_GENERATION(gv) == PL_generation)
- break;
- GvASSIGN_GENERATION_set(gv, PL_generation);
- }
-#else
- GV *const gv
- = ((PMOP*)curop)->op_pmreplrootu.op_pmtargetgv;
- if (gv) {
- if (gv == PL_defgv
- || (int)GvASSIGN_GENERATION(gv) == PL_generation)
- break;
- GvASSIGN_GENERATION_set(gv, PL_generation);
- }
-#endif
- }
- else
- break;
- }
- lastop = curop;
- }
- if (curop != o)
+ if (aassign_common_vars(o))
o->op_private |= OPpASSIGN_COMMON;
+ LINKLIST(o);
}
if (right && right->op_type == OP_SPLIT && !PL_madskills) {
@@ -5542,6 +5569,12 @@ Perl_newRANGE(pTHX_ I32 flags, OP *left, OP *right)
flip->op_private = left->op_type == OP_CONST ? OPpFLIP_LINENUM : 0;
flop->op_private = right->op_type == OP_CONST ? OPpFLIP_LINENUM : 0;
+ /* check barewords before they might be optimized aways */
+ if (flip->op_private && cSVOPx(left)->op_private & OPpCONST_STRICT)
+ no_bareword_allowed(left);
+ if (flop->op_private && cSVOPx(right)->op_private & OPpCONST_STRICT)
+ no_bareword_allowed(right);
+
flip->op_next = o;
if (!flip->op_private || !flop->op_private)
LINKLIST(o); /* blow off optimizer unless constant */
@@ -6998,6 +7031,7 @@ Perl_newFORM(pTHX_ I32 floor, OP *o, OP *block)
CvSTART(cv) = LINKLIST(CvROOT(cv));
CvROOT(cv)->op_next = 0;
CALL_PEEP(CvSTART(cv));
+ finalize_optree(CvROOT(cv));
#ifdef PERL_MAD
op_getmad(o,pegop,'n');
op_getmad_weak(block, pegop, 'b');
@@ -7907,7 +7941,6 @@ Perl_ck_glob(pTHX_ OP *o)
}
#if !defined(PERL_EXTERNAL_GLOB)
- /* XXX this can be tightened up and made more failsafe. */
if (!(gv && GvCVu(gv) && GvIMPORTED_CV(gv))) {
GV *glob_gv;
ENTER;
@@ -9188,6 +9221,95 @@ Perl_ck_entersub_args_proto_or_list(pTHX_ OP *entersubop,
return ck_entersub_args_list(entersubop);
}
+OP *
+Perl_ck_entersub_args_core(pTHX_ OP *entersubop, GV *namegv, SV *protosv)
+{
+ int opnum = SvTYPE(protosv) == SVt_PVCV ? 0 : (int)SvUV(protosv);
+ OP *aop = cUNOPx(entersubop)->op_first;
+
+ PERL_ARGS_ASSERT_CK_ENTERSUB_ARGS_CORE;
+
+ if (!opnum) {
+ OP *prev, *cvop;
+ if (!aop->op_sibling)
+ aop = cUNOPx(aop)->op_first;
+ prev = aop;
+ aop = aop->op_sibling;
+ for (cvop = aop; cvop->op_sibling; cvop = cvop->op_sibling) ;
+ if (PL_madskills) while (aop != cvop && aop->op_type == OP_STUB) {
+ aop = aop->op_sibling;
+ continue;
+ }
+ if (aop != cvop)
+ (void)too_many_arguments(entersubop, GvNAME(namegv));
+
+ op_free(entersubop);
+ switch(GvNAME(namegv)[2]) {
+ case 'F': return newSVOP(OP_CONST, 0,
+ newSVpv(CopFILE(PL_curcop),0));
+ case 'L': return newSVOP(
+ OP_CONST, 0,
+ Perl_newSVpvf(aTHX_
+ "%"IVdf, (IV)CopLINE(PL_curcop)
+ )
+ );
+ case 'P': return newSVOP(OP_CONST, 0,
+ (PL_curstash
+ ? newSVhek(HvNAME_HEK(PL_curstash))
+ : &PL_sv_undef
+ )
+ );
+ }
+ assert(0);
+ }
+ else {
+ OP *prev, *cvop;
+ U32 paren;
+#ifdef PERL_MAD
+ bool seenarg = FALSE;
+#endif
+ if (!aop->op_sibling)
+ aop = cUNOPx(aop)->op_first;
+
+ prev = aop;
+ aop = aop->op_sibling;
+ prev->op_sibling = NULL;
+ for (cvop = aop;
+ cvop->op_sibling;
+ prev=cvop, cvop = cvop->op_sibling)
+#ifdef PERL_MAD
+ if (PL_madskills && cvop->op_sibling
+ && cvop->op_type != OP_STUB) seenarg = TRUE
+#endif
+ ;
+ prev->op_sibling = NULL;
+ paren = OPf_SPECIAL * !(cvop->op_private & OPpENTERSUB_NOPAREN);
+ op_free(cvop);
+ if (aop == cvop) aop = NULL;
+ op_free(entersubop);
+
+ switch (PL_opargs[opnum] & OA_CLASS_MASK) {
+ case OA_UNOP:
+ case OA_BASEOP_OR_UNOP:
+ case OA_FILESTATOP:
+ return aop ? newUNOP(opnum,paren,aop) : newOP(opnum,paren);
+ case OA_BASEOP:
+ if (aop) {
+#ifdef PERL_MAD
+ if (!PL_madskills || seenarg)
+#endif
+ (void)too_many_arguments(aop, GvNAME(namegv));
+ op_free(aop);
+ }
+ return newOP(opnum,0);
+ default:
+ return convert(opnum,0,aop);
+ }
+ }
+ assert(0);
+ return entersubop;
+}
+
/*
=for apidoc Am|void|cv_get_call_checker|CV *cv|Perl_call_checker *ckfun_p|SV **ckobj_p
@@ -9646,11 +9768,6 @@ Perl_rpeep(pTHX_ register OP *o)
}
break;
- case OP_CONST:
- if (cSVOPo->op_private & OPpCONST_STRICT)
- no_bareword_allowed(o);
- break;
-
case OP_CONCAT:
if (o->op_next && o->op_next->op_type == OP_STRINGIFY) {
if (o->op_next->op_private & OPpTARGET_MY) {
@@ -10216,77 +10333,72 @@ Perl_custom_op_register(pTHX_ Perl_ppaddr_t ppaddr, const XOP *xop)
=for apidoc core_prototype
This function assigns the prototype of the named core function to C<sv>, or
to a new mortal SV if C<sv> is NULL. It returns the modified C<sv>, or
-NULL if the core function has no prototype.
-
-If the C<name> is not a Perl keyword, it croaks if C<croak> is true, or
-returns NULL if C<croak> is false.
+NULL if the core function has no prototype. C<code> is a code as returned
+by C<keyword()>. It must be negative and unequal to -KEY_CORE.
=cut
*/
SV *
-Perl_core_prototype(pTHX_ SV *sv, const char *name, const STRLEN len,
- const bool croak)
+Perl_core_prototype(pTHX_ SV *sv, const char *name, const int code,
+ int * const opnum)
{
- const int code = keyword(name, len, 1);
int i = 0, n = 0, seen_question = 0, defgv = 0;
I32 oa;
#define MAX_ARGS_OP ((sizeof(I32) - 1) * 2)
char str[ MAX_ARGS_OP * 2 + 2 ]; /* One ';', one '\0' */
+ bool nullret = FALSE;
PERL_ARGS_ASSERT_CORE_PROTOTYPE;
- if (!code) {
- if (croak)
- return (SV *)Perl_die(aTHX_
- "Can't find an opnumber for \"%s\"", name
- );
- return NULL;
- }
-
- if (code > 0) return NULL; /* Not overridable */
+ assert (code < 0 && code != -KEY_CORE);
if (!sv) sv = sv_newmortal();
-#define retsetpvs(x) sv_setpvs(sv, x); return sv
+#define retsetpvs(x,y) sv_setpvs(sv, x); if(opnum) *opnum=(y); return sv
switch (-code) {
case KEY_and : case KEY_chop: case KEY_chomp:
case KEY_cmp : case KEY_exec: case KEY_eq :
case KEY_ge : case KEY_gt : case KEY_le :
- case KEY_lstat : case KEY_lt : case KEY_ne : case KEY_or :
- case KEY_stat : case KEY_system: case KEY_x : case KEY_xor:
- return NULL;
- case KEY_keys: case KEY_values: case KEY_each:
- retsetpvs("+");
- case KEY_push: case KEY_unshift:
- retsetpvs("+@");
- case KEY_pop: case KEY_shift:
- retsetpvs(";+");
+ case KEY_lt : case KEY_ne : case KEY_or :
+ case KEY_select: case KEY_system: case KEY_x : case KEY_xor:
+ if (!opnum) return NULL; nullret = TRUE; goto findopnum;
+ case KEY_keys: retsetpvs("+", OP_KEYS);
+ case KEY_values: retsetpvs("+", OP_VALUES);
+ case KEY_each: retsetpvs("+", OP_EACH);
+ case KEY_push: retsetpvs("+@", OP_PUSH);
+ case KEY_unshift: retsetpvs("+@", OP_UNSHIFT);
+ case KEY_pop: retsetpvs(";+", OP_POP);
+ case KEY_shift: retsetpvs(";+", OP_SHIFT);
case KEY_splice:
- retsetpvs("+;$$@");
+ retsetpvs("+;$$@", OP_SPLICE);
case KEY___FILE__: case KEY___LINE__: case KEY___PACKAGE__:
- retsetpvs("");
+ retsetpvs("", 0);
case KEY_readpipe:
name = "backtick";
}
#undef retsetpvs
+ findopnum:
while (i < MAXO) { /* The slow way. */
if (strEQ(name, PL_op_name[i])
|| strEQ(name, PL_op_desc[i]))
{
+ if (nullret) { assert(opnum); *opnum = i; return NULL; }
goto found;
}
i++;
}
- return NULL; /* Should not happen... */
+ assert(0); return NULL; /* Should not happen... */
found:
defgv = PL_opargs[i] & OA_DEFGV;
oa = PL_opargs[i] >> OASHIFT;
while (oa) {
- if (oa & OA_OPTIONAL && !seen_question && (!defgv || n)) {
+ if (oa & OA_OPTIONAL && !seen_question && (
+ !defgv || n || (oa & (OA_OPTIONAL - 1)) == OA_FILEREF
+ )) {
seen_question = 1;
str[n++] = ';';
}
@@ -10303,6 +10415,7 @@ Perl_core_prototype(pTHX_ SV *sv, const char *name, const STRLEN len,
str[n++] = '$';
str[n++] = '@';
str[n++] = '%';
+ if (i == OP_LOCK) str[n++] = '&';
str[n++] = '*';
str[n++] = ']';
}
@@ -10313,6 +10426,7 @@ Perl_core_prototype(pTHX_ SV *sv, const char *name, const STRLEN len,
str[0] = '_';
str[n++] = '\0';
sv_setpvn(sv, str, n - 1);
+ if (opnum) *opnum = i;
return sv;
}