detect sub attributes following a signature
authorDavid Mitchell <davem@iabyn.com>
Mon, 26 Feb 2018 18:52:23 +0000 (18:52 +0000)
committerDavid Mitchell <davem@iabyn.com>
Fri, 2 Mar 2018 13:36:43 +0000 (13:36 +0000)
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.

parser.h
perly.act
perly.h
perly.tab
perly.y
pod/perldiag.pod
t/op/signatures.t
toke.c

index 216e9de..19c5c63 100644 (file)
--- a/parser.h
+++ b/parser.h
@@ -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 */
index d4366a2..fe8a5e9 100644 (file)
--- a/perly.act
+++ b/perly.act
@@ -998,26 +998,35 @@ case 2:
                                                 newSTATEOP(0, NULL, NULL));
 
                             parser->in_my = 0;
-                            parser->expect = XBLOCK;
+                            /* tell the toker that attrributes can follow
+                             * this sig, but only so that the toker
+                             * can skip through any (illegal) trailing
+                             * attribute text then give a useful error
+                             * message about "attributes before sig",
+                             * rather than falling over ina mess at
+                             * unrecognised syntax.
+                             */
+                            parser->expect = XATTRBLOCK;
+                            parser->sig_seen = TRUE;
                             LEAVE;
                        }
 
     break;
 
   case 116:
-#line 809 "perly.y" /* yacc.c:1646  */
+#line 818 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = (ps[0].val.opval); }
 
     break;
 
   case 117:
-#line 810 "perly.y" /* yacc.c:1646  */
+#line 819 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = NULL; }
 
     break;
 
   case 118:
-#line 816 "perly.y" /* yacc.c:1646  */
+#line 825 "perly.y" /* yacc.c:1646  */
     {
                          if (parser->copline > (line_t)(ps[-2].val.ival))
                              parser->copline = (line_t)(ps[-2].val.ival);
@@ -1027,19 +1036,19 @@ case 2:
     break;
 
   case 119:
-#line 826 "perly.y" /* yacc.c:1646  */
+#line 835 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = (ps[0].val.opval); }
 
     break;
 
   case 120:
-#line 827 "perly.y" /* yacc.c:1646  */
+#line 836 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = NULL; }
 
     break;
 
   case 121:
-#line 831 "perly.y" /* yacc.c:1646  */
+#line 840 "perly.y" /* yacc.c:1646  */
     {
                          if (parser->copline > (line_t)(ps[-2].val.ival))
                              parser->copline = (line_t)(ps[-2].val.ival);
@@ -1050,31 +1059,31 @@ case 2:
     break;
 
   case 122:
-#line 842 "perly.y" /* yacc.c:1646  */
+#line 851 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newLOGOP(OP_AND, 0, (ps[-2].val.opval), (ps[0].val.opval)); }
 
     break;
 
   case 123:
-#line 844 "perly.y" /* yacc.c:1646  */
+#line 853 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newLOGOP((ps[-1].val.ival), 0, (ps[-2].val.opval), (ps[0].val.opval)); }
 
     break;
 
   case 124:
-#line 846 "perly.y" /* yacc.c:1646  */
+#line 855 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newLOGOP(OP_DOR, 0, (ps[-2].val.opval), (ps[0].val.opval)); }
 
     break;
 
   case 126:
-#line 852 "perly.y" /* yacc.c:1646  */
+#line 861 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = (ps[-1].val.opval); }
 
     break;
 
   case 127:
-#line 854 "perly.y" /* yacc.c:1646  */
+#line 863 "perly.y" /* yacc.c:1646  */
     {
                          OP* term = (ps[0].val.opval);
                          (yyval.opval) = op_append_elem(OP_LIST, (ps[-2].val.opval), term);
@@ -1083,7 +1092,7 @@ case 2:
     break;
 
   case 129:
-#line 863 "perly.y" /* yacc.c:1646  */
+#line 872 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = op_convert_list((ps[-2].val.ival), OPf_STACKED,
                                op_prepend_elem(OP_LIST, newGVREF((ps[-2].val.ival),(ps[-1].val.opval)), (ps[0].val.opval)) );
                        }
@@ -1091,7 +1100,7 @@ case 2:
     break;
 
   case 130:
-#line 867 "perly.y" /* yacc.c:1646  */
+#line 876 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = op_convert_list((ps[-4].val.ival), OPf_STACKED,
                                op_prepend_elem(OP_LIST, newGVREF((ps[-4].val.ival),(ps[-2].val.opval)), (ps[-1].val.opval)) );
                        }
@@ -1099,7 +1108,7 @@ case 2:
     break;
 
   case 131:
-#line 871 "perly.y" /* yacc.c:1646  */
+#line 880 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = op_convert_list(OP_ENTERSUB, OPf_STACKED,
                                op_append_elem(OP_LIST,
                                    op_prepend_elem(OP_LIST, scalar((ps[-5].val.opval)), (ps[-1].val.opval)),
@@ -1109,7 +1118,7 @@ case 2:
     break;
 
   case 132:
-#line 877 "perly.y" /* yacc.c:1646  */
+#line 886 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = op_convert_list(OP_ENTERSUB, OPf_STACKED,
                                op_append_elem(OP_LIST, scalar((ps[-2].val.opval)),
                                    newMETHOP(OP_METHOD, 0, (ps[0].val.opval))));
@@ -1118,7 +1127,7 @@ case 2:
     break;
 
   case 133:
-#line 882 "perly.y" /* yacc.c:1646  */
+#line 891 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = op_convert_list(OP_ENTERSUB, OPf_STACKED,
                                op_append_elem(OP_LIST,
                                    op_prepend_elem(OP_LIST, (ps[-1].val.opval), (ps[0].val.opval)),
@@ -1128,7 +1137,7 @@ case 2:
     break;
 
   case 134:
-#line 888 "perly.y" /* yacc.c:1646  */
+#line 897 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = op_convert_list(OP_ENTERSUB, OPf_STACKED,
                                op_append_elem(OP_LIST,
                                    op_prepend_elem(OP_LIST, (ps[-3].val.opval), (ps[-1].val.opval)),
@@ -1138,26 +1147,26 @@ case 2:
     break;
 
   case 135:
-#line 894 "perly.y" /* yacc.c:1646  */
+#line 903 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = op_convert_list((ps[-1].val.ival), 0, (ps[0].val.opval)); }
 
     break;
 
   case 136:
-#line 896 "perly.y" /* yacc.c:1646  */
+#line 905 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = op_convert_list((ps[-3].val.ival), 0, (ps[-1].val.opval)); }
 
     break;
 
   case 137:
-#line 898 "perly.y" /* yacc.c:1646  */
+#line 907 "perly.y" /* yacc.c:1646  */
     { SvREFCNT_inc_simple_void(PL_compcv);
                          (yyval.opval) = newANONATTRSUB((ps[-1].val.ival), 0, NULL, (ps[0].val.opval)); }
 
     break;
 
   case 138:
-#line 901 "perly.y" /* yacc.c:1646  */
+#line 910 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                 op_append_elem(OP_LIST,
                                   op_prepend_elem(OP_LIST, (ps[-1].val.opval), (ps[0].val.opval)), (ps[-4].val.opval)));
@@ -1166,20 +1175,20 @@ case 2:
     break;
 
   case 141:
-#line 916 "perly.y" /* yacc.c:1646  */
+#line 925 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newBINOP(OP_GELEM, 0, (ps[-4].val.opval), scalar((ps[-2].val.opval))); }
 
     break;
 
   case 142:
-#line 918 "perly.y" /* yacc.c:1646  */
+#line 927 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newBINOP(OP_AELEM, 0, oopsAV((ps[-3].val.opval)), scalar((ps[-1].val.opval)));
                        }
 
     break;
 
   case 143:
-#line 921 "perly.y" /* yacc.c:1646  */
+#line 930 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newBINOP(OP_AELEM, 0,
                                        ref(newAVREF((ps[-4].val.opval)),OP_RV2AV),
                                        scalar((ps[-1].val.opval)));
@@ -1188,7 +1197,7 @@ case 2:
     break;
 
   case 144:
-#line 926 "perly.y" /* yacc.c:1646  */
+#line 935 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newBINOP(OP_AELEM, 0,
                                        ref(newAVREF((ps[-3].val.opval)),OP_RV2AV),
                                        scalar((ps[-1].val.opval)));
@@ -1197,14 +1206,14 @@ case 2:
     break;
 
   case 145:
-#line 931 "perly.y" /* yacc.c:1646  */
+#line 940 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newBINOP(OP_HELEM, 0, oopsHV((ps[-4].val.opval)), jmaybe((ps[-2].val.opval)));
                        }
 
     break;
 
   case 146:
-#line 934 "perly.y" /* yacc.c:1646  */
+#line 943 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newBINOP(OP_HELEM, 0,
                                        ref(newHVREF((ps[-5].val.opval)),OP_RV2HV),
                                        jmaybe((ps[-2].val.opval))); }
@@ -1212,7 +1221,7 @@ case 2:
     break;
 
   case 147:
-#line 938 "perly.y" /* yacc.c:1646  */
+#line 947 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newBINOP(OP_HELEM, 0,
                                        ref(newHVREF((ps[-4].val.opval)),OP_RV2HV),
                                        jmaybe((ps[-2].val.opval))); }
@@ -1220,7 +1229,7 @@ case 2:
     break;
 
   case 148:
-#line 942 "perly.y" /* yacc.c:1646  */
+#line 951 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                   newCVREF(0, scalar((ps[-3].val.opval))));
                          if (parser->expect == XBLOCK)
@@ -1230,7 +1239,7 @@ case 2:
     break;
 
   case 149:
-#line 948 "perly.y" /* yacc.c:1646  */
+#line 957 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                   op_append_elem(OP_LIST, (ps[-1].val.opval),
                                       newCVREF(0, scalar((ps[-4].val.opval)))));
@@ -1241,7 +1250,7 @@ case 2:
     break;
 
   case 150:
-#line 956 "perly.y" /* yacc.c:1646  */
+#line 965 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                   op_append_elem(OP_LIST, (ps[-1].val.opval),
                                               newCVREF(0, scalar((ps[-3].val.opval)))));
@@ -1252,7 +1261,7 @@ case 2:
     break;
 
   case 151:
-#line 963 "perly.y" /* yacc.c:1646  */
+#line 972 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                   newCVREF(0, scalar((ps[-2].val.opval))));
                          if (parser->expect == XBLOCK)
@@ -1262,37 +1271,37 @@ case 2:
     break;
 
   case 152:
-#line 969 "perly.y" /* yacc.c:1646  */
+#line 978 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newSLICEOP(0, (ps[-1].val.opval), (ps[-4].val.opval)); }
 
     break;
 
   case 153:
-#line 971 "perly.y" /* yacc.c:1646  */
+#line 980 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newSLICEOP(0, (ps[-1].val.opval), (ps[-3].val.opval)); }
 
     break;
 
   case 154:
-#line 973 "perly.y" /* yacc.c:1646  */
+#line 982 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newSLICEOP(0, (ps[-1].val.opval), NULL); }
 
     break;
 
   case 155:
-#line 978 "perly.y" /* yacc.c:1646  */
+#line 987 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newASSIGNOP(OPf_STACKED, (ps[-2].val.opval), (ps[-1].val.ival), (ps[0].val.opval)); }
 
     break;
 
   case 156:
-#line 980 "perly.y" /* yacc.c:1646  */
+#line 989 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newBINOP((ps[-1].val.ival), 0, scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); }
 
     break;
 
   case 157:
-#line 982 "perly.y" /* yacc.c:1646  */
+#line 991 "perly.y" /* yacc.c:1646  */
     {   if ((ps[-1].val.ival) != OP_REPEAT)
                                scalar((ps[-2].val.opval));
                            (yyval.opval) = newBINOP((ps[-1].val.ival), 0, (ps[-2].val.opval), scalar((ps[0].val.opval)));
@@ -1301,111 +1310,111 @@ case 2:
     break;
 
   case 158:
-#line 987 "perly.y" /* yacc.c:1646  */
+#line 996 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newBINOP((ps[-1].val.ival), 0, scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); }
 
     break;
 
   case 159:
-#line 989 "perly.y" /* yacc.c:1646  */
+#line 998 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newBINOP((ps[-1].val.ival), 0, scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); }
 
     break;
 
   case 160:
-#line 991 "perly.y" /* yacc.c:1646  */
+#line 1000 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newBINOP((ps[-1].val.ival), 0, scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); }
 
     break;
 
   case 161:
-#line 993 "perly.y" /* yacc.c:1646  */
+#line 1002 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newBINOP((ps[-1].val.ival), 0, scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); }
 
     break;
 
   case 162:
-#line 995 "perly.y" /* yacc.c:1646  */
+#line 1004 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newBINOP((ps[-1].val.ival), 0, scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); }
 
     break;
 
   case 163:
-#line 997 "perly.y" /* yacc.c:1646  */
+#line 1006 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newBINOP((ps[-1].val.ival), 0, scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); }
 
     break;
 
   case 164:
-#line 999 "perly.y" /* yacc.c:1646  */
+#line 1008 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newRANGE((ps[-1].val.ival), scalar((ps[-2].val.opval)), scalar((ps[0].val.opval))); }
 
     break;
 
   case 165:
-#line 1001 "perly.y" /* yacc.c:1646  */
+#line 1010 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newLOGOP(OP_AND, 0, (ps[-2].val.opval), (ps[0].val.opval)); }
 
     break;
 
   case 166:
-#line 1003 "perly.y" /* yacc.c:1646  */
+#line 1012 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newLOGOP(OP_OR, 0, (ps[-2].val.opval), (ps[0].val.opval)); }
 
     break;
 
   case 167:
-#line 1005 "perly.y" /* yacc.c:1646  */
+#line 1014 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newLOGOP(OP_DOR, 0, (ps[-2].val.opval), (ps[0].val.opval)); }
 
     break;
 
   case 168:
-#line 1007 "perly.y" /* yacc.c:1646  */
+#line 1016 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = bind_match((ps[-1].val.ival), (ps[-2].val.opval), (ps[0].val.opval)); }
 
     break;
 
   case 169:
-#line 1012 "perly.y" /* yacc.c:1646  */
+#line 1021 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_NEGATE, 0, scalar((ps[0].val.opval))); }
 
     break;
 
   case 170:
-#line 1014 "perly.y" /* yacc.c:1646  */
+#line 1023 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = (ps[0].val.opval); }
 
     break;
 
   case 171:
-#line 1017 "perly.y" /* yacc.c:1646  */
+#line 1026 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_NOT, 0, scalar((ps[0].val.opval))); }
 
     break;
 
   case 172:
-#line 1019 "perly.y" /* yacc.c:1646  */
+#line 1028 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP((ps[-1].val.ival), 0, scalar((ps[0].val.opval))); }
 
     break;
 
   case 173:
-#line 1021 "perly.y" /* yacc.c:1646  */
+#line 1030 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_POSTINC, 0,
                                        op_lvalue(scalar((ps[-1].val.opval)), OP_POSTINC)); }
 
     break;
 
   case 174:
-#line 1024 "perly.y" /* yacc.c:1646  */
+#line 1033 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_POSTDEC, 0,
                                        op_lvalue(scalar((ps[-1].val.opval)), OP_POSTDEC));}
 
     break;
 
   case 175:
-#line 1027 "perly.y" /* yacc.c:1646  */
+#line 1036 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = op_convert_list(OP_JOIN, 0,
                                       op_append_elem(
                                        OP_LIST,
@@ -1420,155 +1429,155 @@ case 2:
     break;
 
   case 176:
-#line 1038 "perly.y" /* yacc.c:1646  */
+#line 1047 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_PREINC, 0,
                                        op_lvalue(scalar((ps[0].val.opval)), OP_PREINC)); }
 
     break;
 
   case 177:
-#line 1041 "perly.y" /* yacc.c:1646  */
+#line 1050 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_PREDEC, 0,
                                        op_lvalue(scalar((ps[0].val.opval)), OP_PREDEC)); }
 
     break;
 
   case 178:
-#line 1048 "perly.y" /* yacc.c:1646  */
+#line 1057 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newANONLIST((ps[-1].val.opval)); }
 
     break;
 
   case 179:
-#line 1050 "perly.y" /* yacc.c:1646  */
+#line 1059 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newANONLIST(NULL);}
 
     break;
 
   case 180:
-#line 1052 "perly.y" /* yacc.c:1646  */
+#line 1061 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newANONHASH((ps[-2].val.opval)); }
 
     break;
 
   case 181:
-#line 1054 "perly.y" /* yacc.c:1646  */
+#line 1063 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newANONHASH(NULL); }
 
     break;
 
   case 182:
-#line 1056 "perly.y" /* yacc.c:1646  */
+#line 1065 "perly.y" /* yacc.c:1646  */
     { SvREFCNT_inc_simple_void(PL_compcv);
                          (yyval.opval) = newANONATTRSUB((ps[-3].val.ival), (ps[-2].val.opval), (ps[-1].val.opval), (ps[0].val.opval)); }
 
     break;
 
   case 183:
-#line 1059 "perly.y" /* yacc.c:1646  */
+#line 1068 "perly.y" /* yacc.c:1646  */
     { SvREFCNT_inc_simple_void(PL_compcv);
                          (yyval.opval) = newANONATTRSUB((ps[-2].val.ival), NULL, (ps[-1].val.opval), (ps[0].val.opval)); }
 
     break;
 
   case 184:
-#line 1065 "perly.y" /* yacc.c:1646  */
+#line 1074 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = dofile((ps[0].val.opval), (ps[-1].val.ival));}
 
     break;
 
   case 185:
-#line 1067 "perly.y" /* yacc.c:1646  */
+#line 1076 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_NULL, OPf_SPECIAL, op_scope((ps[0].val.opval)));}
 
     break;
 
   case 190:
-#line 1075 "perly.y" /* yacc.c:1646  */
+#line 1084 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newCONDOP(0, (ps[-4].val.opval), (ps[-2].val.opval), (ps[0].val.opval)); }
 
     break;
 
   case 191:
-#line 1077 "perly.y" /* yacc.c:1646  */
+#line 1086 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_REFGEN, 0, (ps[0].val.opval)); }
 
     break;
 
   case 192:
-#line 1079 "perly.y" /* yacc.c:1646  */
+#line 1088 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_REFGEN, 0, localize((ps[0].val.opval),1)); }
 
     break;
 
   case 193:
-#line 1081 "perly.y" /* yacc.c:1646  */
+#line 1090 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = (ps[0].val.opval); }
 
     break;
 
   case 194:
-#line 1083 "perly.y" /* yacc.c:1646  */
+#line 1092 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = localize((ps[0].val.opval),0); }
 
     break;
 
   case 195:
-#line 1085 "perly.y" /* yacc.c:1646  */
+#line 1094 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = sawparens((ps[-1].val.opval)); }
 
     break;
 
   case 196:
-#line 1087 "perly.y" /* yacc.c:1646  */
+#line 1096 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = (ps[0].val.opval); }
 
     break;
 
   case 197:
-#line 1089 "perly.y" /* yacc.c:1646  */
+#line 1098 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = sawparens(newNULLLIST()); }
 
     break;
 
   case 198:
-#line 1091 "perly.y" /* yacc.c:1646  */
+#line 1100 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = (ps[0].val.opval); }
 
     break;
 
   case 199:
-#line 1093 "perly.y" /* yacc.c:1646  */
+#line 1102 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = (ps[0].val.opval); }
 
     break;
 
   case 200:
-#line 1095 "perly.y" /* yacc.c:1646  */
+#line 1104 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = (ps[0].val.opval); }
 
     break;
 
   case 201:
-#line 1097 "perly.y" /* yacc.c:1646  */
+#line 1106 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = (ps[0].val.opval); }
 
     break;
 
   case 202:
-#line 1099 "perly.y" /* yacc.c:1646  */
+#line 1108 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_AV2ARYLEN, 0, ref((ps[0].val.opval), OP_AV2ARYLEN));}
 
     break;
 
   case 203:
-#line 1101 "perly.y" /* yacc.c:1646  */
+#line 1110 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = (ps[0].val.opval); }
 
     break;
 
   case 204:
-#line 1103 "perly.y" /* yacc.c:1646  */
+#line 1112 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = op_prepend_elem(OP_ASLICE,
                                newOP(OP_PUSHMARK, 0),
                                    newLISTOP(OP_ASLICE, 0,
@@ -1582,7 +1591,7 @@ case 2:
     break;
 
   case 205:
-#line 1113 "perly.y" /* yacc.c:1646  */
+#line 1122 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = op_prepend_elem(OP_KVASLICE,
                                newOP(OP_PUSHMARK, 0),
                                    newLISTOP(OP_KVASLICE, 0,
@@ -1596,7 +1605,7 @@ case 2:
     break;
 
   case 206:
-#line 1123 "perly.y" /* yacc.c:1646  */
+#line 1132 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = op_prepend_elem(OP_HSLICE,
                                newOP(OP_PUSHMARK, 0),
                                    newLISTOP(OP_HSLICE, 0,
@@ -1610,7 +1619,7 @@ case 2:
     break;
 
   case 207:
-#line 1133 "perly.y" /* yacc.c:1646  */
+#line 1142 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = op_prepend_elem(OP_KVHSLICE,
                                newOP(OP_PUSHMARK, 0),
                                    newLISTOP(OP_KVHSLICE, 0,
@@ -1624,26 +1633,26 @@ case 2:
     break;
 
   case 208:
-#line 1143 "perly.y" /* yacc.c:1646  */
+#line 1152 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = (ps[0].val.opval); }
 
     break;
 
   case 209:
-#line 1145 "perly.y" /* yacc.c:1646  */
+#line 1154 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_ENTERSUB, 0, scalar((ps[0].val.opval))); }
 
     break;
 
   case 210:
-#line 1147 "perly.y" /* yacc.c:1646  */
+#line 1156 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar((ps[-2].val.opval)));
                        }
 
     break;
 
   case 211:
-#line 1150 "perly.y" /* yacc.c:1646  */
+#line 1159 "perly.y" /* yacc.c:1646  */
     {
                          (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                                op_append_elem(OP_LIST, (ps[-1].val.opval), scalar((ps[-3].val.opval))));
@@ -1652,7 +1661,7 @@ case 2:
     break;
 
   case 212:
-#line 1155 "perly.y" /* yacc.c:1646  */
+#line 1164 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                            op_append_elem(OP_LIST, (ps[0].val.opval), scalar((ps[-1].val.opval))));
                        }
@@ -1660,130 +1669,130 @@ case 2:
     break;
 
   case 213:
-#line 1159 "perly.y" /* yacc.c:1646  */
+#line 1168 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newSVREF((ps[-3].val.opval)); }
 
     break;
 
   case 214:
-#line 1161 "perly.y" /* yacc.c:1646  */
+#line 1170 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newAVREF((ps[-3].val.opval)); }
 
     break;
 
   case 215:
-#line 1163 "perly.y" /* yacc.c:1646  */
+#line 1172 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newHVREF((ps[-3].val.opval)); }
 
     break;
 
   case 216:
-#line 1165 "perly.y" /* yacc.c:1646  */
+#line 1174 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_ENTERSUB, 0,
                                       scalar(newCVREF((ps[-1].val.ival),(ps[-3].val.opval)))); }
 
     break;
 
   case 217:
-#line 1168 "perly.y" /* yacc.c:1646  */
+#line 1177 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newGVREF(0,(ps[-3].val.opval)); }
 
     break;
 
   case 218:
-#line 1170 "perly.y" /* yacc.c:1646  */
+#line 1179 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newOP((ps[0].val.ival), OPf_SPECIAL);
                            PL_hints |= HINT_BLOCK_SCOPE; }
 
     break;
 
   case 219:
-#line 1173 "perly.y" /* yacc.c:1646  */
+#line 1182 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newLOOPEX((ps[-1].val.ival),(ps[0].val.opval)); }
 
     break;
 
   case 220:
-#line 1175 "perly.y" /* yacc.c:1646  */
+#line 1184 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_NOT, 0, scalar((ps[0].val.opval))); }
 
     break;
 
   case 221:
-#line 1177 "perly.y" /* yacc.c:1646  */
+#line 1186 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newOP((ps[0].val.ival), 0); }
 
     break;
 
   case 222:
-#line 1179 "perly.y" /* yacc.c:1646  */
+#line 1188 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP((ps[-1].val.ival), 0, (ps[0].val.opval)); }
 
     break;
 
   case 223:
-#line 1181 "perly.y" /* yacc.c:1646  */
+#line 1190 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP((ps[-1].val.ival), 0, (ps[0].val.opval)); }
 
     break;
 
   case 224:
-#line 1183 "perly.y" /* yacc.c:1646  */
+#line 1192 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newOP(OP_REQUIRE, (ps[0].val.ival) ? OPf_SPECIAL : 0); }
 
     break;
 
   case 225:
-#line 1185 "perly.y" /* yacc.c:1646  */
+#line 1194 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_REQUIRE, (ps[-1].val.ival) ? OPf_SPECIAL : 0, (ps[0].val.opval)); }
 
     break;
 
   case 226:
-#line 1187 "perly.y" /* yacc.c:1646  */
+#line 1196 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar((ps[0].val.opval))); }
 
     break;
 
   case 227:
-#line 1189 "perly.y" /* yacc.c:1646  */
+#line 1198 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED,
                            op_append_elem(OP_LIST, (ps[0].val.opval), scalar((ps[-1].val.opval)))); }
 
     break;
 
   case 228:
-#line 1192 "perly.y" /* yacc.c:1646  */
+#line 1201 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newOP((ps[0].val.ival), 0); }
 
     break;
 
   case 229:
-#line 1194 "perly.y" /* yacc.c:1646  */
+#line 1203 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newOP((ps[-2].val.ival), 0);}
 
     break;
 
   case 230:
-#line 1196 "perly.y" /* yacc.c:1646  */
+#line 1205 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = (ps[0].val.opval); }
 
     break;
 
   case 231:
-#line 1198 "perly.y" /* yacc.c:1646  */
+#line 1207 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = (ps[-2].val.opval); }
 
     break;
 
   case 232:
-#line 1200 "perly.y" /* yacc.c:1646  */
+#line 1209 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_ENTERSUB, OPf_STACKED, scalar((ps[0].val.opval))); }
 
     break;
 
   case 233:
-#line 1202 "perly.y" /* yacc.c:1646  */
+#line 1211 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = ((ps[-2].val.ival) == OP_NOT)
                           ? newUNOP((ps[-2].val.ival), 0, newSVOP(OP_CONST, 0, newSViv(0)))
                           : newOP((ps[-2].val.ival), OPf_SPECIAL); }
@@ -1791,13 +1800,13 @@ case 2:
     break;
 
   case 234:
-#line 1206 "perly.y" /* yacc.c:1646  */
+#line 1215 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP((ps[-3].val.ival), 0, (ps[-1].val.opval)); }
 
     break;
 
   case 235:
-#line 1208 "perly.y" /* yacc.c:1646  */
+#line 1217 "perly.y" /* yacc.c:1646  */
     {
                            if (   (ps[0].val.opval)->op_type != OP_TRANS
                                && (ps[0].val.opval)->op_type != OP_TRANSR
@@ -1812,115 +1821,115 @@ case 2:
     break;
 
   case 236:
-#line 1219 "perly.y" /* yacc.c:1646  */
+#line 1228 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = pmruntime((ps[-5].val.opval), (ps[-2].val.opval), (ps[-1].val.opval), 1, (ps[-4].val.ival)); }
 
     break;
 
   case 240:
-#line 1227 "perly.y" /* yacc.c:1646  */
+#line 1236 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = my_attrs((ps[-1].val.opval),(ps[0].val.opval)); }
 
     break;
 
   case 241:
-#line 1229 "perly.y" /* yacc.c:1646  */
+#line 1238 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = localize((ps[0].val.opval),1); }
 
     break;
 
   case 242:
-#line 1231 "perly.y" /* yacc.c:1646  */
+#line 1240 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newUNOP(OP_REFGEN, 0, my_attrs((ps[-1].val.opval),(ps[0].val.opval))); }
 
     break;
 
   case 243:
-#line 1236 "perly.y" /* yacc.c:1646  */
+#line 1245 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = sawparens((ps[-1].val.opval)); }
 
     break;
 
   case 244:
-#line 1238 "perly.y" /* yacc.c:1646  */
+#line 1247 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = sawparens(newNULLLIST()); }
 
     break;
 
   case 245:
-#line 1241 "perly.y" /* yacc.c:1646  */
+#line 1250 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = (ps[0].val.opval); }
 
     break;
 
   case 246:
-#line 1243 "perly.y" /* yacc.c:1646  */
+#line 1252 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = (ps[0].val.opval); }
 
     break;
 
   case 247:
-#line 1245 "perly.y" /* yacc.c:1646  */
+#line 1254 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = (ps[0].val.opval); }
 
     break;
 
   case 248:
-#line 1250 "perly.y" /* yacc.c:1646  */
+#line 1259 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = NULL; }
 
     break;
 
   case 249:
-#line 1252 "perly.y" /* yacc.c:1646  */
+#line 1261 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = (ps[0].val.opval); }
 
     break;
 
   case 250:
-#line 1256 "perly.y" /* yacc.c:1646  */
+#line 1265 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = NULL; }
 
     break;
 
   case 251:
-#line 1258 "perly.y" /* yacc.c:1646  */
+#line 1267 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = (ps[0].val.opval); }
 
     break;
 
   case 252:
-#line 1262 "perly.y" /* yacc.c:1646  */
+#line 1271 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = NULL; }
 
     break;
 
   case 253:
-#line 1264 "perly.y" /* yacc.c:1646  */
+#line 1273 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = (ps[0].val.opval); }
 
     break;
 
   case 254:
-#line 1270 "perly.y" /* yacc.c:1646  */
+#line 1279 "perly.y" /* yacc.c:1646  */
     { parser->in_my = 0; (yyval.opval) = my((ps[0].val.opval)); }
 
     break;
 
   case 262:
-#line 1287 "perly.y" /* yacc.c:1646  */
+#line 1296 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newCVREF((ps[-1].val.ival),(ps[0].val.opval)); }
 
     break;
 
   case 263:
-#line 1291 "perly.y" /* yacc.c:1646  */
+#line 1300 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newSVREF((ps[0].val.opval)); }
 
     break;
 
   case 264:
-#line 1295 "perly.y" /* yacc.c:1646  */
+#line 1304 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newAVREF((ps[0].val.opval));
                          if ((yyval.opval)) (yyval.opval)->op_private |= (ps[-1].val.ival);
                        }
@@ -1928,7 +1937,7 @@ case 2:
     break;
 
   case 265:
-#line 1301 "perly.y" /* yacc.c:1646  */
+#line 1310 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newHVREF((ps[0].val.opval));
                          if ((yyval.opval)) (yyval.opval)->op_private |= (ps[-1].val.ival);
                        }
@@ -1936,61 +1945,61 @@ case 2:
     break;
 
   case 266:
-#line 1307 "perly.y" /* yacc.c:1646  */
+#line 1316 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newAVREF((ps[0].val.opval)); }
 
     break;
 
   case 267:
-#line 1309 "perly.y" /* yacc.c:1646  */
+#line 1318 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newAVREF((ps[-3].val.opval)); }
 
     break;
 
   case 268:
-#line 1313 "perly.y" /* yacc.c:1646  */
+#line 1322 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newGVREF(0,(ps[0].val.opval)); }
 
     break;
 
   case 270:
-#line 1318 "perly.y" /* yacc.c:1646  */
+#line 1327 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newAVREF((ps[-2].val.opval)); }
 
     break;
 
   case 272:
-#line 1323 "perly.y" /* yacc.c:1646  */
+#line 1332 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newHVREF((ps[-2].val.opval)); }
 
     break;
 
   case 274:
-#line 1328 "perly.y" /* yacc.c:1646  */
+#line 1337 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = newGVREF(0,(ps[-2].val.opval)); }
 
     break;
 
   case 275:
-#line 1333 "perly.y" /* yacc.c:1646  */
+#line 1342 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = scalar((ps[0].val.opval)); }
 
     break;
 
   case 276:
-#line 1335 "perly.y" /* yacc.c:1646  */
+#line 1344 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = scalar((ps[0].val.opval)); }
 
     break;
 
   case 277:
-#line 1337 "perly.y" /* yacc.c:1646  */
+#line 1346 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = op_scope((ps[0].val.opval)); }
 
     break;
 
   case 278:
-#line 1340 "perly.y" /* yacc.c:1646  */
+#line 1349 "perly.y" /* yacc.c:1646  */
     { (yyval.opval) = (ps[0].val.opval); }
 
     break;
@@ -2001,6 +2010,6 @@ case 2:
     
 
 /* Generated from:
- * 1464f62136e1c8980247e644a1b280abdab234c9615dcbc70e089ab38123122b perly.y
+ * ac323bb6f3cacf4eb8eda6403a58c41f30954d07a4a6d6f7f00de81577b2c79a perly.y
  * b6fae5748f9bef6db4740aa5e122b84ac5181852d42474d0ecad621fa4253306 regen_perly.pl
  * ex: set ro: */
diff --git a/perly.h b/perly.h
index 6677122..7727e7b 100644 (file)
--- a/perly.h
+++ b/perly.h
@@ -183,6 +183,6 @@ int yyparse (void);
 
 
 /* Generated from:
- * 1464f62136e1c8980247e644a1b280abdab234c9615dcbc70e089ab38123122b perly.y
+ * ac323bb6f3cacf4eb8eda6403a58c41f30954d07a4a6d6f7f00de81577b2c79a perly.y
  * b6fae5748f9bef6db4740aa5e122b84ac5181852d42474d0ecad621fa4253306 regen_perly.pl
  * ex: set ro: */
index db040cd..d918aa6 100644 (file)
--- a/perly.tab
+++ b/perly.tab
@@ -80,23 +80,23 @@ static const yytype_uint16 yyrline[] =
      559,   563,   567,   568,   572,   578,   583,   588,   589,   594,
      595,   600,   601,   603,   608,   610,   622,   623,   628,   630,
      634,   654,   655,   657,   663,   728,   730,   736,   738,   742,
-     748,   749,   754,   755,   760,   759,   809,   810,   815,   826,
-     827,   830,   841,   843,   845,   847,   851,   853,   858,   862,
-     866,   870,   876,   881,   887,   893,   895,   898,   897,   908,
-     909,   913,   917,   920,   925,   930,   933,   937,   941,   947,
-     955,   962,   968,   970,   972,   977,   979,   981,   986,   988,
-     990,   992,   994,   996,   998,  1000,  1002,  1004,  1006,  1011,
-    1013,  1016,  1018,  1020,  1023,  1026,  1037,  1040,  1047,  1049,
-    1051,  1053,  1055,  1058,  1064,  1066,  1070,  1071,  1072,  1073,
-    1074,  1076,  1078,  1080,  1082,  1084,  1086,  1088,  1090,  1092,
-    1094,  1096,  1098,  1100,  1102,  1112,  1122,  1132,  1142,  1144,
-    1146,  1149,  1154,  1158,  1160,  1162,  1164,  1167,  1169,  1172,
-    1174,  1176,  1178,  1180,  1182,  1184,  1186,  1188,  1191,  1193,
-    1195,  1197,  1199,  1201,  1205,  1208,  1207,  1220,  1221,  1222,
-    1226,  1228,  1230,  1235,  1237,  1240,  1242,  1244,  1249,  1251,
-    1256,  1257,  1262,  1263,  1269,  1273,  1274,  1275,  1278,  1279,
-    1282,  1283,  1286,  1290,  1294,  1300,  1306,  1308,  1312,  1316,
-    1317,  1321,  1322,  1326,  1327,  1332,  1334,  1336,  1339
+     748,   749,   754,   755,   760,   759,   818,   819,   824,   835,
+     836,   839,   850,   852,   854,   856,   860,   862,   867,   871,
+     875,   879,   885,   890,   896,   902,   904,   907,   906,   917,
+     918,   922,   926,   929,   934,   939,   942,   946,   950,   956,
+     964,   971,   977,   979,   981,   986,   988,   990,   995,   997,
+     999,  1001,  1003,  1005,  1007,  1009,  1011,  1013,  1015,  1020,
+    1022,  1025,  1027,  1029,  1032,  1035,  1046,  1049,  1056,  1058,
+    1060,  1062,  1064,  1067,  1073,  1075,  1079,  1080,  1081,  1082,
+    1083,  1085,  1087,  1089,  1091,  1093,  1095,  1097,  1099,  1101,
+    1103,  1105,  1107,  1109,  1111,  1121,  1131,  1141,  1151,  1153,
+    1155,  1158,  1163,  1167,  1169,  1171,  1173,  1176,  1178,  1181,
+    1183,  1185,  1187,  1189,  1191,  1193,  1195,  1197,  1200,  1202,
+    1204,  1206,  1208,  1210,  1214,  1217,  1216,  1229,  1230,  1231,
+    1235,  1237,  1239,  1244,  1246,  1249,  1251,  1253,  1258,  1260,
+    1265,  1266,  1271,  1272,  1278,  1282,  1283,  1284,  1287,  1288,
+    1291,  1292,  1295,  1299,  1303,  1309,  1315,  1317,  1321,  1325,
+    1326,  1330,  1331,  1335,  1336,  1341,  1343,  1345,  1348
 };
 #endif
 
@@ -1130,6 +1130,6 @@ static const toketypes yy_type_tab[] =
 };
 
 /* Generated from:
- * 1464f62136e1c8980247e644a1b280abdab234c9615dcbc70e089ab38123122b perly.y
+ * ac323bb6f3cacf4eb8eda6403a58c41f30954d07a4a6d6f7f00de81577b2c79a perly.y
  * b6fae5748f9bef6db4740aa5e122b84ac5181852d42474d0ecad621fa4253306 regen_perly.pl
  * ex: set ro: */
diff --git a/perly.y b/perly.y
index 2af1b5b..da0b3e3 100644 (file)
--- a/perly.y
+++ b/perly.y
@@ -800,7 +800,16 @@ subsignature:      '('
                                                 newSTATEOP(0, NULL, NULL));
 
                             parser->in_my = 0;
-                            parser->expect = XBLOCK;
+                            /* tell the toker that attrributes can follow
+                             * this sig, but only so that the toker
+                             * can skip through any (illegal) trailing
+                             * attribute text then give a useful error
+                             * message about "attributes before sig",
+                             * rather than falling over ina mess at
+                             * unrecognised syntax.
+                             */
+                            parser->expect = XATTRBLOCK;
+                            parser->sig_seen = TRUE;
                             LEAVE;
                        }
        ;
index b2a9eb3..c24be8a 100644 (file)
@@ -5856,6 +5856,15 @@ model on-disk files and can only contain bytes.
 stubs.  Stubs should never be implicitly created, but explicit calls to
 C<can> may break this.
 
+=item Subroutine attributes must come before the signature
+
+(F) When subroutine signatures are enabled, any subroutine attributes must
+come before the signature. Note that this order was the opposite in
+versions 5.20..5.26. So:
+
+    sub foo :lvalue ($a, $b) { ... }  # 5.18 and 5.28 +
+    sub foo ($a, $b) :lvalue { ... }  # 5.20 .. 5.26
+
 =item Subroutine "&%s" is not available
 
 (W closure) During compilation, an inner named subroutine or eval is
index 616b6a1..37fe166 100644 (file)
@@ -1535,6 +1535,23 @@ while(<$kh>) {
     is $x, "Xbc", "RT #132141";
 }
 
+# RT #132760
+# attributes have been moved back before signatures for 5.28. Ensure that
+# code doing it the old wrong way get a meaningful error message.
+
+{
+    my @errs;
+    local $SIG{__WARN__} = sub { push @errs, @_};
+    eval q{
+        sub rt132760 ($a, $b) :prototype($$) { $a + $b }
+    };
+
+    @errs = split /\n/, $@;
+    is +@errs, 1, "RT 132760 expect 1 error";
+    like $errs[0],
+        qr/^Subroutine attributes must come before the signature at/,
+        "RT 132760 err 0";
+}
 
 done_testing;
 
diff --git a/toke.c b/toke.c
index df1d7fe..9dbad98 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -5944,9 +5944,17 @@ Perl_yylex(pTHX)
        case XATTRTERM:
            PL_expect = XTERMBLOCK;
         grabattrs:
+            /* NB: as well as parsing normal attributes, we also end up
+             * here if there is something looking like attributes
+             * following a signature (which is illegal, but used to be
+             * legal in 5.20..5.26). If the latter, we still parse the
+             * attributes so that error messages(s) are less confusing,
+             * but ignore them (parser->sig_seen).
+             */
            s = skipspace(s);
            attrs = NULL;
             while (isIDFIRST_lazy_if_safe(s, PL_bufend, UTF)) {
+                bool sig = PL_parser->sig_seen;
                I32 tmp;
                SV *sv;
                d = scan_word(s, PL_tokenbuf, sizeof PL_tokenbuf, FALSE, &len);
@@ -5989,23 +5997,27 @@ Perl_yylex(pTHX)
                       the CVf_BUILTIN_ATTRS define in cv.h! */
                    if (!PL_in_my && memEQs(SvPVX(sv), len, "lvalue")) {
                        sv_free(sv);
-                       CvLVALUE_on(PL_compcv);
+                       if (!sig)
+                            CvLVALUE_on(PL_compcv);
                    }
                    else if (!PL_in_my && memEQs(SvPVX(sv), len, "method")) {
                        sv_free(sv);
-                       CvMETHOD_on(PL_compcv);
+                       if (!sig)
+                            CvMETHOD_on(PL_compcv);
                    }
                    else if (!PL_in_my && memEQs(SvPVX(sv), len, "const"))
                    {
                        sv_free(sv);
-                       Perl_ck_warner_d(aTHX_
-                           packWARN(WARN_EXPERIMENTAL__CONST_ATTR),
-                          ":const is experimental"
-                       );
-                       CvANONCONST_on(PL_compcv);
-                       if (!CvANON(PL_compcv))
-                           yyerror(":const is not permitted on named "
-                                   "subroutines");
+                        if (!sig) {
+                            Perl_ck_warner_d(aTHX_
+                                packWARN(WARN_EXPERIMENTAL__CONST_ATTR),
+                               ":const is experimental"
+                            );
+                            CvANONCONST_on(PL_compcv);
+                            if (!CvANON(PL_compcv))
+                                yyerror(":const is not permitted on named "
+                                        "subroutines");
+                        }
                    }
                    /* After we've set the flags, it could be argued that
                       we don't need to do the attributes.pm-based setting
@@ -6058,6 +6070,14 @@ Perl_yylex(pTHX)
                }
            }
        got_attrs:
+            if (PL_parser->sig_seen) {
+                /* see comment about about sig_seen and parser error
+                 * handling */
+                if (attrs)
+                    op_free(attrs);
+                Perl_croak(aTHX_ "Subroutine attributes must come "
+                                 "before the signature");
+                }
            if (attrs) {
                NEXTVAL_NEXTTOKE.opval = attrs;
                force_next(THING);
@@ -8669,6 +8689,9 @@ Perl_yylex(pTHX)
                s = skipspace(s);
                 d = SvPVX(PL_linestr)+off;
 
+                SAVEBOOL(PL_parser->sig_seen);
+                PL_parser->sig_seen = FALSE;
+
                 if (   isIDFIRST_lazy_if_safe(s, PL_bufend, UTF)
                     || *s == '\''
                     || (*s == ':' && s[1] == ':'))