In perl.git, the branch blead has been updated

<http://perl5.git.perl.org/perl.git/commitdiff/1e35563a537b4adfc8fe304382ca4593703e1a0e?hp=d68a48384ff2e631bc3a38a3fdb6c2bc75e0ea9f>

- Log -----------------------------------------------------------------
commit 1e35563a537b4adfc8fe304382ca4593703e1a0e
Author: Father Chrysostomos <[email protected]>
Date:   Thu Mar 1 12:32:25 2012 -0800

    attributes.pm: Consistent spaces after dots in pod

M       ext/attributes/attributes.pm

commit c217304d4cf1ab81c53d2d565896c7dd34645864
Author: Father Chrysostomos <[email protected]>
Date:   Thu Mar 1 12:29:26 2012 -0800

    attributes.pm: Add caveat about lvalue subs

M       ext/attributes/attributes.pm

commit 345d70e3f599db40c8311185ac403b1a5b35d2a5
Author: Father Chrysostomos <[email protected]>
Date:   Thu Mar 1 12:24:38 2012 -0800

    [perl #107366] Allow attributes to set :lvalue on defined sub
    
    This provides enough rope for those who want to hang themselves, and
    also for those who know how to use the rope without hanging them-
    selves. :-)
    
    Since this is not generally a reliable thing to be doing, a warning is 
emitted whenever :lvalue is turned on or off on a defined subroutine.
    
    But attributes.pm will flip the flag anyway.  :lvalue in a sub declar-
    ation still refuses to modify a defined Perl sub, as before.

M       ext/attributes/attributes.pm
M       ext/attributes/attributes.xs
M       pod/perldiag.pod
M       t/op/attrs.t
-----------------------------------------------------------------------

Summary of changes:
 ext/attributes/attributes.pm |   32 +++++++++++++++++++++++---------
 ext/attributes/attributes.xs |    7 ++++---
 pod/perldiag.pod             |   22 ++++++++++++++--------
 t/op/attrs.t                 |   22 +++++++++++-----------
 4 files changed, 52 insertions(+), 31 deletions(-)

diff --git a/ext/attributes/attributes.pm b/ext/attributes/attributes.pm
index 4d27f4f..1f6dbae 100644
--- a/ext/attributes/attributes.pm
+++ b/ext/attributes/attributes.pm
@@ -39,8 +39,8 @@ sub _modify_attrs_and_deprecate {
            warnings::warnif(
                'misc',
                "lvalue attribute "
-                  . (/^-/ ? "cannot be removed" : "ignored")
-                  . " after the subroutine has been defined"
+                  . (/^-/ ? "removed from" : "applied to")
+                  . " already-defined subroutine"
            );
            0;
        } : 1
@@ -199,8 +199,9 @@ So you want to know what C<import> actually does?
 
 First of all C<import> gets the type of the third parameter ('CODE' in this 
case).
 C<attributes.pm> checks if there is a subroutine called C<< 
MODIFY_<reftype>_ATTRIBUTES >>
-in the caller's namespace (here: 'main'). In this case a subroutine 
C<MODIFY_CODE_ATTRIBUTES> is
-required. Then this method is called to check if you have used a "bad 
attribute".
+in the caller's namespace (here: 'main').  In this case a
+subroutine C<MODIFY_CODE_ATTRIBUTES> is required.  Then this
+method is called to check if you have used a "bad attribute".
 The subroutine call in this example would look like
 
   MODIFY_CODE_ATTRIBUTES( 'main', \&foo, 'method' );
@@ -219,17 +220,28 @@ The following are the built-in attributes for subroutines:
 =item lvalue
 
 Indicates that the referenced subroutine is a valid lvalue and can
-be assigned to. The subroutine must return a modifiable value such
+be assigned to.  The subroutine must return a modifiable value such
 as a scalar variable, as described in L<perlsub>.
 
+This module allows one to set this attribute on a subroutine that is
+already defined.  For Perl subroutines (XSUBs are fine), it may or may not
+do what you want, depending on the code inside the subroutine, with details
+subject to change in future Perl versions.  You may run into problems with
+lvalue context not being propagated properly into the subroutine, or maybe
+even assertion failures.  For this reason, a warning is emitted if warnings
+are enabled.  In other words, you should only do this if you really know
+what you are doing.  You have been warned.
+
 =item method
 
-Indicates that the referenced subroutine is a method. A subroutine so marked
+Indicates that the referenced subroutine
+is a method.  A subroutine so marked
 will not trigger the "Ambiguous call resolved as CORE::%s" warning.
 
 =item locked
 
-The "locked" attribute has no effect in 5.10.0 and later. It was used as part
+The "locked" attribute has no effect in
+5.10.0 and later.  It was used as part
 of the now-removed "Perl 5.005 threads".
 
 =back
@@ -479,7 +491,8 @@ not your own.
        print "foo\n";
     }
 
-This example runs. At compile time C<MODIFY_CODE_ATTRIBUTES> is called. In that
+This example runs.  At compile time
+C<MODIFY_CODE_ATTRIBUTES> is called.  In that
 subroutine, we check if any attribute is disallowed and we return a list of
 these "bad attributes".
 
@@ -501,7 +514,8 @@ As we return an empty list, everything is fine.
   }
 
 This example is aborted at compile time as we use the attribute "Test" which
-isn't allowed. C<MODIFY_CODE_ATTRIBUTES> returns a list that contains a single
+isn't allowed.  C<MODIFY_CODE_ATTRIBUTES>
+returns a list that contains a single
 element ('Test').
 
 =back
diff --git a/ext/attributes/attributes.xs b/ext/attributes/attributes.xs
index d771889..e92f793 100644
--- a/ext/attributes/attributes.xs
+++ b/ext/attributes/attributes.xs
@@ -48,14 +48,15 @@ modify_SV_attributes(pTHX_ SV *sv, SV **retlist, SV 
**attrlist, int numattrs)
                switch (name[3]) {
                case 'l':
                    if (memEQ(name, "lvalue", 6)) {
-                       if (!CvISXSUB(MUTABLE_CV(sv))
+                       bool warn =
+                           !CvISXSUB(MUTABLE_CV(sv))
                         && CvROOT(MUTABLE_CV(sv))
-                        && !CvLVALUE(MUTABLE_CV(sv)) != negated)
-                           break;
+                        && !CvLVALUE(MUTABLE_CV(sv)) != negated;
                        if (negated)
                            CvFLAGS(MUTABLE_CV(sv)) &= ~CVf_LVALUE;
                        else
                            CvFLAGS(MUTABLE_CV(sv)) |= CVf_LVALUE;
+                       if (warn) break;
                        continue;
                    }
                    break;
diff --git a/pod/perldiag.pod b/pod/perldiag.pod
index 1b67ccd..5f6ed83 100644
--- a/pod/perldiag.pod
+++ b/pod/perldiag.pod
@@ -2627,18 +2627,24 @@ 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 cannot be removed after the subroutine has been defined
+=item lvalue attribute %s already-defined subroutine
 
-(W misc) The lvalue attribute on a Perl subroutine cannot be turned off
-once the subroutine is defined.
+(W misc) Although L<attributes.pm|attributes> allows this, turning the lvalue
+attribute on or off on a Perl subroutine that is already defined
+does not always work properly.  It may or may not do what you
+want, depending on what code is inside the subroutine, with exact
+details subject to change between Perl versions.  Only do this
+if you really know what you are doing.
 
 =item lvalue attribute ignored after the subroutine has been defined
 
-(W misc) Making a Perl subroutine an lvalue subroutine after it has been
-defined, whether by declaring the subroutine with an lvalue attribute
-or by using L<attributes.pm|attributes>, is not possible.  To make the 
subroutine an
-lvalue subroutine, add the lvalue attribute to the definition, or put
-the declaration before the definition.
+(W misc) Using the C<:lvalue> declarative syntax to make a Perl
+subroutine an lvalue subroutine after it has been defined is
+not permitted.  To make the subroutine an lvalue subroutine,
+add the lvalue attribute to the definition, or put the C<sub
+foo :lvalue;> declaration before the definition.
+
+See also L<attributes.pm|attributes>.
 
 =item Malformed integer in [] in pack
 
diff --git a/t/op/attrs.t b/t/op/attrs.t
index f3d1165..79ef361 100644
--- a/t/op/attrs.t
+++ b/t/op/attrs.t
@@ -341,28 +341,28 @@ foreach my $test (@tests) {
   sub  ent         {}
   sub lent :lvalue {}
   my $posmsg =
-      'lvalue attribute ignored after the subroutine has been defined at '
+      'lvalue attribute applied to already-defined subroutine at '
      .'\(eval';
   my $negmsg =
-      'lvalue attribute cannot be removed after the subroutine has been '
-     .'defined at \(eval';
+      'lvalue attribute removed from already-defined subroutine at '
+     .'\(eval';
   eval 'use attributes __PACKAGE__, \&ent, "lvalue"';
   like $w, qr/^$posmsg/, 'lvalue attr warning on def sub';
-  is join("",&attributes::get(\&ent)), "",'lvalue attr ignored on def sub';
+  is join("",&attributes::get(\&ent)), "lvalue",':lvalue applied anyway';
   $w = '';
   eval 'use attributes __PACKAGE__, \&lent, "lvalue"; 1' or die;
   is $w, "", 'no lvalue warning on def lvalue sub';
   eval 'use attributes __PACKAGE__, \&lent, "-lvalue"';
-  like $w, qr/^$negmsg/, 'lvalue attr warning on def sub';
-  is join("",&attributes::get(\&lent)), "lvalue",
-       '-lvalue ignored on def sub';
+  like $w, qr/^$negmsg/, '-lvalue attr warning on def sub';
+  is join("",&attributes::get(\&lent)), "",
+       'lvalue attribute removed anyway';
   $w = '';
-  eval 'use attributes __PACKAGE__, \&ent, "-lvalue"; 1' or die;
-  is $w, "", 'no lvalue warning on def lvalue sub';
+  eval 'use attributes __PACKAGE__, \&lent, "-lvalue"; 1' or die;
+  is $w, "", 'no -lvalue warning on def non-lvalue sub';
   no warnings 'misc';
-  eval 'use attributes __PACKAGE__, \&ent, "lvalue"';
+  eval 'use attributes __PACKAGE__, \&lent, "lvalue"';
   is $w, "", 'no lvalue warnings under no warnings misc';
-  eval 'use attributes __PACKAGE__, \&lent, "-lvalue"';
+  eval 'use attributes __PACKAGE__, \&ent, "-lvalue"';
   is $w, "", 'no -lvalue warnings under no warnings misc';
 }
 

--
Perl5 Master Repository

Reply via email to