Correctly parse class name in 'for my class $foo
authorHio <hio@hio.jp>
Fri, 18 Oct 2013 15:48:47 +0000 (16:48 +0100)
committerDavid Mitchell <davem@iabyn.com>
Fri, 18 Oct 2013 15:48:47 +0000 (16:48 +0100)
The code in toke.c on encountering 'for my' or for our',
skips past any optional package name, then checks that the next thing is a
'$', so that it can give a "Missing $ on loop variable" error if
necessary.

However, the code to skip the package name was using scan_ident() rather
than scan_word(); the latter assumes that the first char was the sigil,
and starts scanning from the second char onwards. So in something like

    for my a1b $x (...)

scan_ident() starts scanning at '1b' in 'a1b', thinks it scanning $1 or
similar, and stops at the first non-digit char, in this case the b.

The fix is to use parse_word() instead.

AUTHORS
t/comp/parser.t
toke.c

diff --git a/AUTHORS b/AUTHORS
index b84a6e4..58d9ce5 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -460,6 +460,7 @@ Henrik Tougaard                     <ht.000@foa.dk>
 Herbert Breunung               <lichtkind@cpan.org>
 Hernan Perez Masci             <hmasci@uolsinectis.com.ar>
 Hershel Walters                        <walters@smd4d.wes.army.mil>
+Hio                             <hio@hio.jp>
 Hojung Youn                    <amoc.yn@gmail.com>
 Holger Bechtold
 Hongwen Qiu                    <qiuhongwen@gmail.com>
index 8fd7e85..7caa116 100644 (file)
@@ -8,7 +8,7 @@ BEGIN {
     chdir 't';
 }
 
-print "1..168\n";
+print "1..169\n";
 
 sub failed {
     my ($got, $expected, $name) = @_;
@@ -333,10 +333,10 @@ like($@, qr/BEGIN failed--compilation aborted/, 'BEGIN 7' );
   eval qq[ *$xFD ];
   like($@, qr/Identifier too long/, "too long id in glob ctx");
 
-  eval qq[ for $xFD ];
+  eval qq[ for $xFC ];
   like($@, qr/Missing \$ on loop variable/,
-       "253 char id ok, but a different error");
-  eval qq[ for $xFE; ];
+       "252 char id ok, but a different error");
+  eval qq[ for $xFD; ];
   like($@, qr/Identifier too long/, "too long id in for ctx");
 
   # the specific case from the ticket
@@ -495,6 +495,10 @@ eval 'Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo'
     .'ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo';
 like $@, "^Identifier too long at ", 'ident buffer overflow';
 
+eval 'for my a1b $i (1) {}';
+# ng: 'Missing $ on loop variable'
+like $@, "^No such class a1b at ", 'TYPE of my of for statement';
+
 # Add new tests HERE (above this line)
 
 # bug #74022: Loop on characters in \p{OtherIDContinue}
diff --git a/toke.c b/toke.c
index 28e3511..1ab57f3 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -8035,7 +8035,7 @@ Perl_yylex(pTHX)
                    p += 3;
                p = PEEKSPACE(p);
                if (isIDFIRST_lazy_if(p,UTF)) {
-                   p = scan_ident(p, PL_tokenbuf, sizeof PL_tokenbuf, TRUE);
+                   p = scan_word(p, PL_tokenbuf, sizeof PL_tokenbuf, TRUE, &len);
                    p = PEEKSPACE(p);
                }
                if (*p != '$')