#endif
p |void |cv_ckproto |NN const CV* cv|NULLOK const GV* gv|NULLOK const char* p
pd |CV* |cv_clone |NN CV* proto
+ApdR |SV* |gv_const_sv |NN GV* gv
ApdR |SV* |cv_const_sv |NULLOK CV* cv
pR |SV* |op_const_sv |NULLOK const OP* o|NULLOK CV* cv
Apd |void |cv_undef |NN CV* cv
s |bool |feature_is_enabled|NN char* name|STRLEN namelen
s |void |force_ident |NN const char *s|int kind
s |void |incline |NN char *s
-s |int |intuit_method |NN char *s|NULLOK GV *gv
+s |int |intuit_method |NN char *s|NULLOK GV *gv|NULLOK CV *cv
s |int |intuit_more |NN char *s
s |I32 |lop |I32 f|int x|NN char *s
rs |void |missingterm |NULLOK char *s
#define cv_ckproto Perl_cv_ckproto
#define cv_clone Perl_cv_clone
#endif
+#define gv_const_sv Perl_gv_const_sv
#define cv_const_sv Perl_cv_const_sv
#ifdef PERL_CORE
#define op_const_sv Perl_op_const_sv
#define cv_ckproto(a,b,c) Perl_cv_ckproto(aTHX_ a,b,c)
#define cv_clone(a) Perl_cv_clone(aTHX_ a)
#endif
+#define gv_const_sv(a) Perl_gv_const_sv(aTHX_ a)
#define cv_const_sv(a) Perl_cv_const_sv(aTHX_ a)
#ifdef PERL_CORE
#define op_const_sv(a,b) Perl_op_const_sv(aTHX_ a,b)
#define feature_is_enabled(a,b) S_feature_is_enabled(aTHX_ a,b)
#define force_ident(a,b) S_force_ident(aTHX_ a,b)
#define incline(a) S_incline(aTHX_ a)
-#define intuit_method(a,b) S_intuit_method(aTHX_ a,b)
+#define intuit_method(a,b,c) S_intuit_method(aTHX_ a,b,c)
#define intuit_more(a) S_intuit_more(aTHX_ a)
#define lop(a,b,c) S_lop(aTHX_ a,b,c)
#define missingterm(a) S_missingterm(aTHX_ a)
return gv;
}
+/*
+=for apidoc gv_const_sv
+
+If C<gv> is a typeglob whose subroutine entry is a constant sub eligible for
+inlining, or C<gv> is a placeholder reference that would be promoted to such
+a typeglob, then returns the value returned by the sub. Otherwise, returns
+NULL.
+
+=cut
+*/
+
+SV *
+Perl_gv_const_sv(pTHX_ GV *gv)
+{
+ if (SvTYPE(gv) == SVt_PVGV)
+ return cv_const_sv(GvCVu(gv));
+ return SvROK(gv) ? SvRV(gv) : NULL;
+}
+
void
Perl_gv_init(pTHX_ GV *gv, HV *stash, const char *name, STRLEN len, int multi)
{
PERL_CALLCONV CV* Perl_cv_clone(pTHX_ CV* proto)
__attribute__nonnull__(pTHX_1);
+PERL_CALLCONV SV* Perl_gv_const_sv(pTHX_ GV* gv)
+ __attribute__warn_unused_result__
+ __attribute__nonnull__(pTHX_1);
+
PERL_CALLCONV SV* Perl_cv_const_sv(pTHX_ CV* cv)
__attribute__warn_unused_result__;
STATIC void S_incline(pTHX_ char *s)
__attribute__nonnull__(pTHX_1);
-STATIC int S_intuit_method(pTHX_ char *s, GV *gv)
+STATIC int S_intuit_method(pTHX_ char *s, GV *gv, CV *cv)
__attribute__nonnull__(pTHX_1);
STATIC int S_intuit_more(pTHX_ char *s)
*/
STATIC int
-S_intuit_method(pTHX_ char *start, GV *gv)
+S_intuit_method(pTHX_ char *start, GV *gv, CV *cv)
{
char *s = start + (*start == '$');
char tmpbuf[sizeof PL_tokenbuf];
GV* indirgv;
if (gv) {
- CV *cv;
- if (GvIO(gv))
+ if (SvTYPE(gv) == SVt_PVGV && GvIO(gv))
return 0;
- if ((cv = GvCVu(gv))) {
- const char *proto = SvPVX_const(cv);
- if (proto) {
- if (*proto == ';')
- proto++;
- if (*proto == '*')
- return 0;
+ if (cv) {
+ if (SvPOK(cv)) {
+ const char *proto = SvPVX_const(cv);
+ if (proto) {
+ if (*proto == ';')
+ proto++;
+ if (*proto == '*')
+ return 0;
+ }
}
} else
gv = 0;
}
else {
len = 0;
- if (!gv)
- gv = gv_fetchpv(PL_tokenbuf, 0, SVt_PVCV);
+ if (!gv) {
+ /* Mustn't actually add anything to a symbol table.
+ But also don't want to "initialise" any placeholder
+ constants that might already be there into full
+ blown PVGVs with attached PVCV. */
+ gv = gv_fetchpv(PL_tokenbuf, GV_NOADD_NOINIT,
+ SVt_PVCV);
+ }
}
/* if we saw a global override before, get the right name */
/* Two barewords in a row may indicate method call. */
- if ((isIDFIRST_lazy_if(s,UTF) || *s == '$') && (tmp=intuit_method(s,gv)))
+ if ((isIDFIRST_lazy_if(s,UTF) || *s == '$') &&
+ (tmp = intuit_method(s, gv, cv)))
return REPORT(tmp);
/* If not a declared subroutine, it's an indirect object. */
CLINE;
if (cv) {
for (d = s + 1; SPACE_OR_TAB(*d); d++) ;
- if (*d == ')' && (sv = cv_const_sv(cv))) {
+ if (*d == ')' && (sv = gv_const_sv(gv))) {
s = d + 1;
goto its_constant;
}
/* If followed by var or block, call it a method (unless sub) */
- if ((*s == '$' || *s == '{') && (!gv || !GvCVu(gv))) {
+ if ((*s == '$' || *s == '{') && (!gv || !cv)) {
PL_last_lop = PL_oldbufptr;
PL_last_lop_op = OP_METHOD;
PREBLOCK(METHOD);
if (!orig_keyword
&& (isIDFIRST_lazy_if(s,UTF) || *s == '$')
- && (tmp = intuit_method(s,gv)))
+ && (tmp = intuit_method(s, gv, cv)))
return REPORT(tmp);
/* Not a method, so call it a subroutine (if defined) */
"Ambiguous use of -%s resolved as -&%s()",
PL_tokenbuf, PL_tokenbuf);
/* Check for a constant sub */
- if ((sv = cv_const_sv(cv))) {
+ if ((sv = gv_const_sv(gv))) {
its_constant:
SvREFCNT_dec(((SVOP*)yylval.opval)->op_sv);
((SVOP*)yylval.opval)->op_sv = SvREFCNT_inc(sv);
}
/* Resolve to GV now. */
+ if (SvTYPE(gv) != SVt_PVGV) {
+ gv = gv_fetchpv(PL_tokenbuf, 0, SVt_PVCV);
+ assert (SvTYPE(gv) == SVt_PVGV);
+ /* cv must have been some sort of placeholder, so
+ now needs replacing with a real code reference. */
+ cv = GvCV(gv);
+ }
+
op_free(yylval.opval);
yylval.opval = newCVREF(0, newGVOP(OP_GV, 0, gv));
yylval.opval->op_private |= OPpENTERSUB_NOPAREN;