diff options
-rw-r--r-- | pp_hot.c | 16 | ||||
-rw-r--r-- | t/op/method.t | 20 |
2 files changed, 33 insertions, 3 deletions
@@ -3075,6 +3075,19 @@ S_method_common(pTHX_ SV* meth, U32* hashp) if (SvROK(sv)) ob = MUTABLE_SV(SvRV(sv)); else if (!SvOK(sv)) goto undefined; + else if (isGV_with_GP(sv)) { + if (!GvIO(sv)) + Perl_croak(aTHX_ "Can't call method \"%"SVf"\" " + "without a package or object reference", + SVfARG(meth)); + ob = sv; + if (SvTYPE(ob) == SVt_PVLV && LvTYPE(ob) == 'y') { + assert(!LvTARGLEN(ob)); + ob = LvTARG(ob); + assert(ob); + } + *(PL_stack_base + TOPMARK + 1) = sv_2mortal(newRV(ob)); + } else { /* this isn't a reference */ GV* iogv; @@ -3125,8 +3138,7 @@ S_method_common(pTHX_ SV* meth, U32* hashp) /* if we got here, ob should be an object or a glob */ if (!ob || !(SvOBJECT(ob) - || (SvTYPE(ob) == SVt_PVGV - && isGV_with_GP(ob) + || (isGV_with_GP(ob) && (ob = MUTABLE_SV(GvIO((const GV *)ob))) && SvOBJECT(ob)))) { diff --git a/t/op/method.t b/t/op/method.t index 821f60468d..d206fc75fe 100644 --- a/t/op/method.t +++ b/t/op/method.t @@ -13,7 +13,7 @@ BEGIN { use strict; no warnings 'once'; -plan(tests => 142); +plan(tests => 146); @A::ISA = 'B'; @B::ISA = 'C'; @@ -490,6 +490,24 @@ is "3foo"->CORE::uc, '3FOO', '"3foo"->CORE::uc'; { no strict; @{"3foo::ISA"} = "CORE"; } is "3foo"->uc, '3FOO', '"3foo"->uc (autobox style!)'; +# *foo vs (\*foo) +sub myclass::squeak { 'eek' } +eval { *myclass->squeak }; +like $@, + qr/^Can't call method "squeak" without a package or object reference/, + 'method call on typeglob ignores package'; +eval { (\*myclass)->squeak }; +like $@, + qr/^Can't call method "squeak" on unblessed reference/, + 'method call on \*typeglob'; +*stdout2 = *STDOUT; # stdout2 now stringifies as *main::STDOUT +sub IO::Handle::self { $_[0] } +# This used to stringify the glob: +is *stdout2->self, (\*stdout2)->self, + '*glob->method is equiv to (\*glob)->method'; +sub { $_[0] = *STDOUT; is $_[0]->self, \$::h{k}, '$pvlv_glob->method' } + ->($::h{k}); + # Test that PL_stashcache doesn't change the resolution behaviour for file # handles and package names. SKIP: { |