Ignore a lvalue attribute after the subroutine has been defined, and warn about it...
Gerard Goossen [Sun, 27 Dec 2009 16:24:28 +0000 (17:24 +0100)]
op.c
pod/perldiag.pod
t/op/attrs.t
t/op/sub_lval.t

diff --git a/op.c b/op.c
index 88a31d3..db17d14 100644 (file)
--- a/op.c
+++ b/op.c
@@ -5714,7 +5714,9 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block)
                 )&& !attrs) {
                if (CvFLAGS(PL_compcv)) {
                    /* might have had built-in attrs applied */
-                   CvFLAGS(cv) |= (CvFLAGS(PL_compcv) & CVf_BUILTIN_ATTRS);
+                   if (CvLVALUE(PL_compcv) && ! CvLVALUE(cv))
+                       Perl_warner(aTHX_ packWARN(WARN_MISC), "lvalue attribute ignored after the subroutine has been defined");
+                   CvFLAGS(cv) |= (CvFLAGS(PL_compcv) & CVf_BUILTIN_ATTRS & ~CVf_LVALUE);
                }
                /* just a "sub foo;" when &foo is already defined */
                SAVEFREESV(PL_compcv);
index 6656148..2b8d2c0 100644 (file)
@@ -2307,6 +2307,14 @@ You may wish to switch to using L<Math::BigInt> explicitly.
 by that?  lstat() makes sense only on filenames.  (Perl did a fstat()
 instead on the filehandle.)
 
+=item lvalue attribute ignored after the subroutine has been defined
+
+(W) Making a subroutine an lvalue subroutine after it has been defined
+by declaring the subroutine with a lvalue attribute is not
+possible. To make the the subroutine a lvalue subroutine add the
+lvalue attribute to the definition, or put the the declaration before
+the definition.
+
 =item Lvalue subs returning %s not implemented yet
 
 (F) Due to limitations in the current implementation, array and hash
index 8f059b0..8239572 100644 (file)
@@ -115,15 +115,15 @@ eval 'package A; sub PS : lvalue';
 is "@attrs", "lvalue";
 
 # Test ability to modify existing sub's (or XSUB's) attributes.
-eval 'package A; sub X { $_[0] } sub X : lvalue';
+eval 'package A; sub X { $_[0] } sub X : method';
 @attrs = eval 'attributes::get \&A::X';
-is "@attrs", "lvalue";
+is "@attrs", "method";
 
 # Above not with just 'pure' built-in attributes.
 sub Z::MODIFY_CODE_ATTRIBUTES { (); }
-eval 'package Z; sub L { $_[0] } sub L : Z lvalue';
+eval 'package Z; sub L { $_[0] } sub L : Z method';
 @attrs = eval 'attributes::get \&Z::L';
-is "@attrs", "lvalue Z";
+is "@attrs", "method Z";
 
 # Begin testing attributes that tie
 
index a159bac..d2e70fe 100644 (file)
@@ -3,7 +3,7 @@ BEGIN {
     @INC = '../lib';
     require './test.pl';
 }
-plan tests=>69;
+plan tests=>70;
 
 sub a : lvalue { my $a = 34; ${\(bless \$a)} }  # Return a temporary
 sub b : lvalue { ${\shift} }
@@ -550,3 +550,15 @@ TODO: {
     $foo->bar;
     is ($result, 'bar', "RT #41550");
 }
+
+fresh_perl_is(<<'----', <<'====', "lvalue can not be set after definition. [perl #68758]");
+use warnings;
+our $x;
+sub foo { $x }
+sub foo : lvalue;
+foo = 3;
+----
+lvalue attribute ignored after the subroutine has been defined at - line 4.
+Can't modify non-lvalue subroutine call in scalar assignment at - line 5, near "3;"
+Execution of - aborted due to compilation errors.
+====