Skip to content

Commit

Permalink
detect sub attributes following a signature
Browse files Browse the repository at this point in the history
RT #132760

A recent commit (v5.27.7-212-g894f226) moved subroutine attributes back
before the subroutine's signature: e.g.

    sub foo :prototype($$) ($a, $b) { ... }  # 5.18 and 5.28 +
    sub foo ($a, $b) :prototype($$) { ... }  # 5.20 .. 5.26

This change means that any code still using an attribute following the
signature is going to trigger a syntax error. However, the error, followed
by error recovery and further warnings and errors, is very unfriendly and
gives no indication of the root cause. This commit introduces a new error,
"Subroutine attributes must come before the signature".

For example, List::Lazy, the subject of the ticket, failed to compile
tests, with output like:

    Array found where operator expected at blib/lib/List/Lazy.pm line 43,
    near "$$@)" (Missing operator before @)?)
    "my" variable $step masks earlier declaration in same statement at
    blib/lib/List/Lazy.pm line 44.
    syntax error at blib/lib/List/Lazy.pm line 36, near ") :"
    Global symbol "$generator" requires explicit package name (did you
    forget to declare "my $generator"?) at blib/lib/List/Lazy.pm line 38.
    Global symbol "$state" requires explicit package name (did you forget
    to declare "my $state"?) at blib/lib/List/Lazy.pm line 39.
    Global symbol "$min" requires explicit package name (did you forget to
    declare "my $min"?) at blib/lib/List/Lazy.pm line 43.
    Global symbol "$max" requires explicit package name (did you forget to
    declare "my $max"?) at blib/lib/List/Lazy.pm line 43.
    Global symbol "$step" requires explicit package name (did you forget
    to declare "my $step"?) at blib/lib/List/Lazy.pm line 43.
    Invalid separator character '{' in attribute list at
    blib/lib/List/Lazy.pm line 44, near "$step : sub "
    Global symbol "$step" requires explicit package name (did you forget
    to declare "my $step"?) at blib/lib/List/Lazy.pm line 44.

But following this commit, it now just outputs:

    Subroutine attributes must come before the signature at
    blib/lib/List/Lazy.pm line 36.
    Compilation failed in require at t/append.t line 5.
    BEGIN failed--compilation aborted at t/append.t line 5.

It works by:

1) adding a boolean flag (sig_seen) to the parser state to indicate that a
   signature has been parsed;
2) at the end of parsing a signature, PL_expect is set to XATTRBLOCK
   rather than XBLOCK.

Then if something looking like one or more attributes is encountered
by the lexer immediately afterwards, it scans it as if it were an
attribute, but then if sig_seen is true, it croaks.
  • Loading branch information
iabyn committed Feb 26, 2018
1 parent e7c19f7 commit 07431a2
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 174 deletions.
1 change: 1 addition & 0 deletions parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ typedef struct yy_parser {
line_t herelines; /* number of lines in here-doc */
line_t preambling; /* line # when processing $ENV{PERL5DB} */

bool sig_seen; /* the currently parsing sub has a signature */
/* these are valid while parsing a subroutine signature */
IV sig_elems; /* number of signature elements seen so far */
IV sig_optelems; /* number of optional signature elems seen */
Expand Down
Loading

0 comments on commit 07431a2

Please sign in to comment.