Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Undefined subroutine &%s called, close to label '%s' #22860

Open
wants to merge 2 commits into
base: blead
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions pod/perldelta.pod
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,18 @@ and L</New Warnings>

=item *

L<Undefined subroutine &%s called, close to label '%s'|perldiag/"Undefined subroutine &%s called, close to label '%s'">

(F) The subroutine indicated hasn't been defined, or if it was, it has
since been undefined.

This error could also indicate a mistyped package separator, when a
single colon was typed instead of two colons. For example, C<Foo:bar()>
would be parsed as the label C<Foo> followed by an unqualified function
name: C<foo: bar()>.

=item *

XXX L<message|perldiag/"message">

=back
Expand Down
10 changes: 10 additions & 0 deletions pod/perldiag.pod
Original file line number Diff line number Diff line change
Expand Up @@ -6820,6 +6820,16 @@ Perhaps it's in a different package? See L<perlfunc/sort>.
(F) The subroutine indicated hasn't been defined, or if it was, it has
since been undefined.

=item Undefined subroutine &%s called, close to label '%s'

(F) The subroutine indicated hasn't been defined, or if it was, it has
since been undefined.

This error could also indicate a mistyped package separator, when a
single colon was typed instead of two colons. For example, C<Foo:bar()>
would be parsed as the label C<Foo> followed by an unqualified function
name: C<foo: bar()>.

=item Undefined subroutine called

(F) The anonymous subroutine you're trying to call hasn't been defined,
Expand Down
43 changes: 32 additions & 11 deletions pp_hot.c
Original file line number Diff line number Diff line change
Expand Up @@ -6212,6 +6212,33 @@ Perl_clear_defarray(pTHX_ AV* av, bool abandon)
}
}

/* S_croak_undefined_subroutine is a helper function for pp_entersub.
* It takes assorted DIE() logic out of that hot function.
*/
static void
S_croak_undefined_subroutine(pTHX_ CV const *cv, GV const *gv)
{
if (cv) {
if (CvLEXICAL(cv) && CvHASGV(cv))
croak("Undefined subroutine &%" SVf " called",
SVfARG(cv_name((CV*)cv, NULL, 0)));
else /* pp_entersub triggers when (CvANON(cv) || !CvHASGV(cv)) */
croak("Undefined subroutine called");
} else { /* pp_entersub triggers when (!cv) after `try_autoload` */
SV *sub_name = newSV_type_mortal(SVt_PV);
gv_efullname3(sub_name, gv, NULL);

/* Heuristic to spot BOOP:boop() typo, when the intention was
* to call BOOP::boop(). */
const char * label = CopLABEL(PL_curcop);
if (label) {
croak("Undefined subroutine &%" SVf " called, close to label '%s'",
SVfARG(sub_name), label);
}
croak("Undefined subroutine &%" SVf " called", SVfARG(sub_name));
}
NOT_REACHED; /* NOTREACHED */
}

PP(pp_entersub)
{
Expand Down Expand Up @@ -6306,15 +6333,12 @@ PP(pp_entersub)
assert((void*)&CvROOT(cv) == (void*)&CvXSUB(cv));
while (UNLIKELY(!CvROOT(cv))) {
GV* autogv;
SV* sub_name;

/* anonymous or undef'd function leaves us no recourse */
if (CvLEXICAL(cv) && CvHASGV(cv))
DIE(aTHX_ "Undefined subroutine &%" SVf " called",
SVfARG(cv_name(cv, NULL, 0)));
if (CvANON(cv) || !CvHASGV(cv)) {
DIE(aTHX_ "Undefined subroutine called");
}
S_croak_undefined_subroutine(aTHX_ cv, NULL);
if (CvANON(cv) || !CvHASGV(cv))
S_croak_undefined_subroutine(aTHX_ cv, NULL);

/* autoloaded stub? */
if (cv != GvCV(gv = CvGV(cv))) {
Expand All @@ -6330,11 +6354,8 @@ PP(pp_entersub)
: 0));
cv = autogv ? GvCV(autogv) : NULL;
}
if (!cv) {
sub_name = sv_newmortal();
gv_efullname3(sub_name, gv, NULL);
DIE(aTHX_ "Undefined subroutine &%" SVf " called", SVfARG(sub_name));
}
if (!cv)
S_croak_undefined_subroutine(aTHX_ NULL, gv);
}

/* unrolled "CvCLONE(cv) && ! CvCLONED(cv)" */
Expand Down
9 changes: 9 additions & 0 deletions t/lib/croak/pp_hot
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ Undefined subroutine &main::foo called at - line 3.
&$foosub;
EXPECT
Undefined subroutine &main::foo called at - line 2.
########
# NAME package separator typo, creating a label by accident
package BEEP;
sub boop;
package main;
BEEP:boop();
EXPECT
Undefined subroutine &main::boop called, close to label 'BEEP' at - line 4.

########
# NAME calling undef scalar
&{+undef};
Expand Down
Loading