Change 13543 by jhi@alpha on 2001/12/09 15:00:50

        Subject: Re: attributes are broken
        From: Spider Boardman <[EMAIL PROTECTED]>
        Date: Sun, 09 Dec 2001 00:09:23 -0500
        Message-Id: <[EMAIL PROTECTED]>              

Affected files ...

.... //depot/perl/dump.c#103 edit
.... //depot/perl/embed.h#313 edit
.... //depot/perl/embed.pl#302 edit
.... //depot/perl/lib/attributes.pm#9 edit
.... //depot/perl/op.c#462 edit
.... //depot/perl/op.h#102 edit
.... //depot/perl/pod/perldelta.pod#273 edit
.... //depot/perl/pod/perltoc.pod#131 edit
.... //depot/perl/proto.h#356 edit
.... //depot/perl/t/op/attrs.t#6 edit
.... //depot/perl/xsutils.c#17 edit

Differences ...

==== //depot/perl/dump.c#103 (text) ====
Index: perl/dump.c
--- perl/dump.c.~1~     Sun Dec  9 08:15:05 2001
+++ perl/dump.c Sun Dec  9 08:15:05 2001
@@ -503,6 +503,8 @@
                    sv_catpv(tmpsv, ",NOPAREN");
                if (o->op_private & OPpENTERSUB_INARGS)
                    sv_catpv(tmpsv, ",INARGS");
+               if (o->op_private & OPpENTERSUB_NOMOD)
+                   sv_catpv(tmpsv, ",NOMOD");
            }
            else {
                switch (o->op_private & OPpDEREF) {
@@ -549,7 +551,8 @@
        else if (o->op_type == OP_FLOP) {
            if (o->op_private & OPpFLIP_LINENUM)
                sv_catpv(tmpsv, ",LINENUM");
-       } else if (o->op_type == OP_RV2CV) {
+       }
+       else if (o->op_type == OP_RV2CV) {
            if (o->op_private & OPpLVAL_INTRO)
                sv_catpv(tmpsv, ",INTRO");
        }
@@ -1381,7 +1384,7 @@
                              "WARNING: %"UVxf" changed from %"UVxf" to %"UVxf"\n",
                              PTR2UV(PL_watchaddr), PTR2UV(PL_watchok),
                              PTR2UV(*PL_watchaddr));
-           if (DEBUG_p_TEST_) debstack();
+           if (DEBUG_s_TEST_) debstack();
            if (DEBUG_t_TEST_) debop(PL_op);
            if (DEBUG_P_TEST_) debprof(PL_op);
        }

==== //depot/perl/embed.h#313 (text+w) ====
Index: perl/embed.h
--- perl/embed.h.~1~    Sun Dec  9 08:15:05 2001
+++ perl/embed.h        Sun Dec  9 08:15:05 2001
@@ -928,6 +928,7 @@
 #define my_kid                 S_my_kid
 #define dup_attrlist           S_dup_attrlist
 #define apply_attrs            S_apply_attrs
+#define apply_attrs_my         S_apply_attrs_my
 #  if defined(PL_OP_SLAB_ALLOC)
 #define Slab_Alloc             S_Slab_Alloc
 #  endif
@@ -2434,9 +2435,10 @@
 #  endif
 #define cv_clone2(a,b)         S_cv_clone2(aTHX_ a,b)
 #define scalar_mod_type(a,b)   S_scalar_mod_type(aTHX_ a,b)
-#define my_kid(a,b)            S_my_kid(aTHX_ a,b)
+#define my_kid(a,b,c)          S_my_kid(aTHX_ a,b,c)
 #define dup_attrlist(a)                S_dup_attrlist(aTHX_ a)
-#define apply_attrs(a,b,c)     S_apply_attrs(aTHX_ a,b,c)
+#define apply_attrs(a,b,c,d)   S_apply_attrs(aTHX_ a,b,c,d)
+#define apply_attrs_my(a,b,c,d)        S_apply_attrs_my(aTHX_ a,b,c,d)
 #  if defined(PL_OP_SLAB_ALLOC)
 #define Slab_Alloc(a,b)                S_Slab_Alloc(aTHX_ a,b)
 #  endif

==== //depot/perl/embed.pl#302 (xtext) ====
Index: perl/embed.pl
--- perl/embed.pl.~1~   Sun Dec  9 08:15:05 2001
+++ perl/embed.pl       Sun Dec  9 08:15:05 2001
@@ -1123,7 +1123,7 @@
 p      |OP*    |append_elem    |I32 optype|OP* head|OP* tail
 p      |OP*    |append_list    |I32 optype|LISTOP* first|LISTOP* last
 p      |I32    |apply          |I32 type|SV** mark|SV** sp
-Ap     |void   |apply_attrs_string|char *stashpv|CV *cv|char *attrstr|STRLEN len
+ApM    |void   |apply_attrs_string|char *stashpv|CV *cv|char *attrstr|STRLEN len
 Ap     |SV*    |avhv_delete_ent|AV *ar|SV* keysv|I32 flags|U32 hash
 Ap     |bool   |avhv_exists_ent|AV *ar|SV* keysv|U32 hash
 Ap     |SV**   |avhv_fetch_ent |AV *ar|SV* keysv|I32 lval|U32 hash
@@ -2045,9 +2045,10 @@
 #  endif
 s      |CV*    |cv_clone2      |CV *proto|CV *outside
 s      |bool   |scalar_mod_type|OP *o|I32 type
-s      |OP *   |my_kid         |OP *o|OP *attrs
+s      |OP *   |my_kid         |OP *o|OP *attrs|OP **imopsp
 s      |OP *   |dup_attrlist   |OP *o
-s      |void   |apply_attrs    |HV *stash|SV *target|OP *attrs
+s      |void   |apply_attrs    |HV *stash|SV *target|OP *attrs|bool for_my
+s      |void   |apply_attrs_my |HV *stash|OP *target|OP *attrs|OP **imopsp
 #  if defined(PL_OP_SLAB_ALLOC)
 s      |void*  |Slab_Alloc     |int m|size_t sz
 #  endif

==== //depot/perl/lib/attributes.pm#9 (text) ====
Index: perl/lib/attributes.pm
--- perl/lib/attributes.pm.~1~  Sun Dec  9 08:15:05 2001
+++ perl/lib/attributes.pm      Sun Dec  9 08:15:05 2001
@@ -1,6 +1,6 @@
 package attributes;
 
-our $VERSION = 0.04;
+our $VERSION = '0.04_01';
 
 @EXPORT_OK = qw(get reftype);
 @EXPORT = ();
@@ -98,7 +98,7 @@
 =head1 SYNOPSIS
 
   sub foo : method ;
-  my ($x,@y,%z) : Bent ;
+  my ($x,@y,%z) : Bent = 1;
   my $s = sub : method { ... };
 
   use attributes ();   # optional, to get subroutine declarations
@@ -120,25 +120,38 @@
 
 The second example in the synopsis does something equivalent to this:
 
-    use attributes __PACKAGE__, \$x, 'Bent';
-    use attributes __PACKAGE__, \@y, 'Bent';
-    use attributes __PACKAGE__, \%z, 'Bent';
+    use attributes ();
+    my ($x,@y,%z);
+    attributes::->import(__PACKAGE__, \$x, 'Bent');
+    attributes::->import(__PACKAGE__, \@y, 'Bent');
+    attributes::->import(__PACKAGE__, \%z, 'Bent');
+    ($x,@y,%z) = 1;
 
-Yes, that's three invocations.
+Yes, that's a lot of expansion.
 
 B<WARNING>: attribute declarations for variables are an I<experimental>
 feature.  The semantics of such declarations could change or be removed
 in future versions.  They are present for purposes of experimentation
 with what the semantics ought to be.  Do not rely on the current
-implementation of this feature. Variable attributes are currently
-not usable for tieing.
+implementation of this feature.
 
 There are only a few attributes currently handled by Perl itself (or
 directly by this module, depending on how you look at it.)  However,
 package-specific attributes are allowed by an extension mechanism.
 (See L<"Package-specific Attribute Handling"> below.)
 
-The setting of attributes happens at compile time.  An attempt to set
+The setting of subroutine attributes happens at compile time.
+Variable attributes in C<our> declarations are also applied at compile time.
+However, C<my> variables get their attributes applied at run-time.
+This means that you have to I<reach> the run-time component of the C<my>
+before those attributes will get applied.  For example:
+
+    my $x : Bent = 42 if 0;
+
+will neither assign 42 to $x I<nor> will it apply the C<Bent> attribute
+to the variable.
+
+An attempt to set
 an unrecognized attribute is a fatal error.  (The error is trappable, but
 it still stops the compilation within that C<eval>.)  Setting an attribute
 with a name that's all lowercase letters that's not a built-in attribute
@@ -180,6 +193,9 @@
 
 There are no built-in attributes for anything other than subroutines.
 
+=for hackers
+What about C<unique>?
+
 =head2 Available Subroutines
 
 The following subroutines are available for general use once this module
@@ -330,7 +346,8 @@
 
 Effect:
 
-    use attributes Canine => \$spot, "Watchful";
+    use attributes ();
+    attributes::->import(Canine => \$spot, "Watchful");
 
 =item 2.
 
@@ -341,7 +358,8 @@
 
 Effect:
 
-    use attributes Felis => \$cat, "Nervous";
+    use attributes ();
+    attributes::->import(Felis => \$cat, "Nervous");
 
 =item 3.
 

==== //depot/perl/op.c#462 (text) ====
Index: perl/op.c
--- perl/op.c.~1~       Sun Dec  9 08:15:05 2001
+++ perl/op.c   Sun Dec  9 08:15:05 2001
@@ -1416,6 +1416,8 @@
            op_null(((LISTOP*)cUNOPo->op_first)->op_first);/* disable pushmark */
            break;
        }
+       else if (o->op_private & OPpENTERSUB_NOMOD)
+           return o;
        else {                          /* lvalue subroutine call */
            o->op_private |= OPpLVAL_INTRO;
            PL_modcount = RETURN_UNLIMITED_NUMBER;
@@ -1886,7 +1888,7 @@
 }
 
 STATIC void
-S_apply_attrs(pTHX_ HV *stash, SV *target, OP *attrs)
+S_apply_attrs(pTHX_ HV *stash, SV *target, OP *attrs, bool for_my)
 {
     SV *stashsv;
 
@@ -1899,19 +1901,99 @@
        stashsv = &PL_sv_no;
 
 #define ATTRSMODULE "attributes"
+#define ATTRSMODULE_PM "attributes.pm"
 
-    Perl_load_module(aTHX_ PERL_LOADMOD_IMPORT_OPS,
-                    newSVpvn(ATTRSMODULE, sizeof(ATTRSMODULE)-1),
-                    Nullsv,
-                    prepend_elem(OP_LIST,
-                                 newSVOP(OP_CONST, 0, stashsv),
-                                 prepend_elem(OP_LIST,
-                                              newSVOP(OP_CONST, 0,
-                                                      newRV(target)),
-                                              dup_attrlist(attrs))));
+    if (for_my) {
+       SV **svp;
+       /* Don't force the C<use> if we don't need it. */
+       svp = hv_fetch(GvHVn(PL_incgv), ATTRSMODULE_PM,
+                      sizeof(ATTRSMODULE_PM)-1, 0);
+       if (svp && *svp != &PL_sv_undef)
+           ;           /* already in %INC */
+       else
+           Perl_load_module(aTHX_ PERL_LOADMOD_NOIMPORT,
+                            newSVpvn(ATTRSMODULE, sizeof(ATTRSMODULE)-1),
+                            Nullsv);
+    }
+    else {
+       Perl_load_module(aTHX_ PERL_LOADMOD_IMPORT_OPS,
+                        newSVpvn(ATTRSMODULE, sizeof(ATTRSMODULE)-1),
+                        Nullsv,
+                        prepend_elem(OP_LIST,
+                                     newSVOP(OP_CONST, 0, stashsv),
+                                     prepend_elem(OP_LIST,
+                                                  newSVOP(OP_CONST, 0,
+                                                          newRV(target)),
+                                                  dup_attrlist(attrs))));
+    }
     LEAVE;
 }
 
+STATIC void
+S_apply_attrs_my(pTHX_ HV *stash, OP *target, OP *attrs, OP **imopsp)
+{
+    OP *pack, *imop, *arg;
+    SV *meth, *stashsv;
+
+    if (!attrs)
+       return;
+
+    assert(target->op_type == OP_PADSV ||
+          target->op_type == OP_PADHV ||
+          target->op_type == OP_PADAV);
+
+    /* Ensure that attributes.pm is loaded. */
+    apply_attrs(stash, pad_sv(target->op_targ), attrs, TRUE);
+
+    /* Need package name for method call. */
+    pack = newSVOP(OP_CONST, 0, newSVpvn(ATTRSMODULE, sizeof(ATTRSMODULE)-1));
+
+    /* Build up the real arg-list. */
+    if (stash)
+       stashsv = newSVpv(HvNAME(stash), 0);
+    else
+       stashsv = &PL_sv_no;
+    arg = newOP(OP_PADSV, 0);
+    arg->op_targ = target->op_targ;
+    arg = prepend_elem(OP_LIST,
+                      newSVOP(OP_CONST, 0, stashsv),
+                      prepend_elem(OP_LIST,
+                                   newUNOP(OP_REFGEN, 0,
+                                           mod(arg, OP_REFGEN)),
+                                   dup_attrlist(attrs)));
+
+    /* Fake up a method call to import */
+    meth = newSVpvn("import", 6);
+    (void)SvUPGRADE(meth, SVt_PVIV);
+    (void)SvIOK_on(meth);
+    PERL_HASH(SvUVX(meth), SvPVX(meth), SvCUR(meth));
+    imop = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL|OPf_WANT_VOID,
+                  append_elem(OP_LIST,
+                              prepend_elem(OP_LIST, pack, list(arg)),
+                              newSVOP(OP_METHOD_NAMED, 0, meth)));
+    imop->op_private |= OPpENTERSUB_NOMOD;
+
+    /* Combine the ops. */
+    *imopsp = append_elem(OP_LIST, *imopsp, imop);
+}
+
+/*
+=notfor apidoc apply_attrs_string
+
+Attempts to apply a list of attributes specified by the C<attrstr> and
+C<len> arguments to the subroutine identified by the C<cv> argument which
+is expected to be associated with the package identified by the C<stashpv>
+argument (see L<attributes>).  It gets this wrong, though, in that it
+does not correctly identify the boundaries of the individual attribute
+specifications within C<attrstr>.  This is not really intended for the
+public API, but has to be listed here for systems such as AIX which
+need an explicit export list for symbols.  (It's called from XS code
+in support of the C<ATTRS:> keyword from F<xsubpp>.)  Patches to fix it
+to respect attribute syntax properly would be welcome.
+
+=cut
+*/
+
 void
 Perl_apply_attrs_string(pTHX_ char *stashpv, CV *cv,
                         char *attrstr, STRLEN len)
@@ -1944,7 +2026,7 @@
 }
 
 STATIC OP *
-S_my_kid(pTHX_ OP *o, OP *attrs)
+S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp)
 {
     OP *kid;
     I32 type;
@@ -1955,7 +2037,7 @@
     type = o->op_type;
     if (type == OP_LIST) {
        for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling)
-           my_kid(kid, attrs);
+           my_kid(kid, attrs, imopsp);
     } else if (type == OP_UNDEF) {
        return o;
     } else if (type == OP_RV2SV ||     /* "our" declaration */
@@ -1969,11 +2051,12 @@
                         (type == OP_RV2SV ? GvSV(gv) :
                          type == OP_RV2AV ? (SV*)GvAV(gv) :
                          type == OP_RV2HV ? (SV*)GvHV(gv) : (SV*)gv),
-                        attrs);
+                        attrs, FALSE);
         }
        o->op_private |= OPpOUR_INTRO;
        return o;
-    } else if (type != OP_PADSV &&
+    }
+    else if (type != OP_PADSV &&
             type != OP_PADAV &&
             type != OP_PADHV &&
             type != OP_PUSHMARK)
@@ -1985,7 +2068,6 @@
     }
     else if (attrs && type != OP_PUSHMARK) {
        HV *stash;
-       SV *padsv;
        SV **namesvp;
 
        PL_in_my = FALSE;
@@ -1997,8 +2079,7 @@
            stash = SvSTASH(*namesvp);
        else
            stash = PL_curstash;
-       padsv = PAD_SV(o->op_targ);
-       apply_attrs(stash, padsv, attrs);
+       apply_attrs_my(stash, o, attrs, imopsp);
     }
     o->op_flags |= OPf_MOD;
     o->op_private |= OPpLVAL_INTRO;
@@ -2008,11 +2089,24 @@
 OP *
 Perl_my_attrs(pTHX_ OP *o, OP *attrs)
 {
+    OP *rops = Nullop;
+    int maybe_scalar = 0;
+
     if (o->op_flags & OPf_PARENS)
        list(o);
+    else
+       maybe_scalar = 1;
     if (attrs)
        SAVEFREEOP(attrs);
-    o = my_kid(o, attrs);
+    o = my_kid(o, attrs, &rops);
+    if (rops) {
+       if (maybe_scalar && o->op_type == OP_PADSV) {
+           o = scalar(append_list(OP_LIST, (LISTOP*)rops, (LISTOP*)o));
+           o->op_private |= OPpLVAL_INTRO;
+       }
+       else
+           o = append_list(OP_LIST, (LISTOP*)o, (LISTOP*)rops);
+    }
     PL_in_my = FALSE;
     PL_in_my_stash = Nullhv;
     return o;
@@ -2021,7 +2115,7 @@
 OP *
 Perl_my(pTHX_ OP *o)
 {
-    return my_kid(o, Nullop);
+    return my_attrs(o, Nullop);
 }
 
 OP *
@@ -3474,6 +3568,11 @@
        return FALSE;
     }
 
+    if (o->op_type == OP_LIST &&
+       (o->op_flags & OPf_WANT) == OPf_WANT_SCALAR &&
+       o->op_private & OPpLVAL_INTRO)
+       return FALSE;
+
     if (o->op_type == OP_LIST || o->op_flags & OPf_PARENS ||
        o->op_type == OP_RV2AV || o->op_type == OP_RV2HV ||
        o->op_type == OP_ASLICE || o->op_type == OP_HSLICE)
@@ -4766,7 +4865,7 @@
            else
                stash = PL_curstash;
        }
-       apply_attrs(stash, rcv, attrs);
+       apply_attrs(stash, rcv, attrs, FALSE);
     }
     if (cv) {                          /* must reuse cv if autoloaded */
        if (!block) {

==== //depot/perl/op.h#102 (text) ====
Index: perl/op.h
--- perl/op.h.~1~       Sun Dec  9 08:15:05 2001
+++ perl/op.h   Sun Dec  9 08:15:05 2001
@@ -153,6 +153,7 @@
   /* OP_ENTERSUB only */
 #define OPpENTERSUB_DB         16      /* Debug subroutine. */
 #define OPpENTERSUB_HASTARG    32      /* Called from OP tree. */
+#define OPpENTERSUB_NOMOD      64      /* Immune to mod() for :attrlist. */
   /* OP_RV2CV only */
 #define OPpENTERSUB_AMPER      8       /* Used & form to call. */
 #define OPpENTERSUB_NOPAREN    128     /* bare sub call (without parens) */

==== //depot/perl/pod/perldelta.pod#273 (text) ====
Index: perl/pod/perldelta.pod
--- perl/pod/perldelta.pod.~1~  Sun Dec  9 08:15:05 2001
+++ perl/pod/perldelta.pod      Sun Dec  9 08:15:05 2001
@@ -65,6 +65,14 @@
 modules.  The change was made to make Perl more compliant with other
 applications like modperl which are using the AIX native interface.
 
+=head2 Attributes for C<my> variables now handled at run-time.
+
+The C<my EXPR : ATTRS> syntax now applies variable attributes at
+run-time.  (Subroutine and C<our> variables still get attributes applied
+at compile-time.)  See L<attributes> for additional details.  In particular,
+however, this allows variable attributes to be useful for C<tie> interfaces,
+which was a deficiency of earlier releaes.
+
 =head2 Socket Extension Dynamic in VMS
 
 The Socket extension is now dynamically loaded instead of being
@@ -681,7 +689,7 @@
 =item *
 
 C<Pod::ParseLink>, by Russ Allbery, has been added,
-to parse L&lt;&gt; links in pods as described in the new
+to parse LZ<><> links in pods as described in the new
 perlpodspec.
 
 =item *
@@ -2221,7 +2229,8 @@
 
 =item *
 
-Now xsubs can have attributes just like subs.
+Now xsubs can have attributes just like subs.  (Well, at least the
+built-in attributes.)
 
 =item *
 
@@ -2509,15 +2518,6 @@
 frustrated at the mysterious results (core dumps, most often) it is
 for now forbidden (you will get a fatal error even from an attempt).
 
-=head2 Variable Attributes are not Currently Usable for Tieing
-
-This limitation will hopefully be fixed in future.  (Subroutine
-attributes work fine for tieing, see L<Attribute::Handlers>).
-
-One way to run into this limitation is to have a loop variable with
-attributes within a loop: the tie is called only once, not for each
-iteration of the loop.
-
 =head2 Building Extensions Can Fail Because Of Largefiles
 
 Some extensions like mod_perl are known to have issues with

==== //depot/perl/pod/perltoc.pod#131 (text+w) ====
Index: perl/pod/perltoc.pod
--- perl/pod/perltoc.pod.~1~    Sun Dec  9 08:15:05 2001
+++ perl/pod/perltoc.pod        Sun Dec  9 08:15:05 2001
@@ -4991,6 +4991,8 @@
 
 =item AIX Dynaloading
 
+=item Attributes for C<my> variables now handled at run-time.
+
 =item Socket Extension Dynamic in VMS
 
 =item IEEE-format Floating Point Default on OpenVMS Alpha
@@ -5101,8 +5103,6 @@
 
 =item Self-tying of Arrays and Hashes Is Forbidden
 
-=item Variable Attributes are not Currently Usable for Tieing
-
 =item Building Extensions Can Fail Because Of Largefiles
 
 =item Unicode Support on EBCDIC Still Spotty

==== //depot/perl/proto.h#356 (text+w) ====
Index: perl/proto.h
--- perl/proto.h.~1~    Sun Dec  9 08:15:05 2001
+++ perl/proto.h        Sun Dec  9 08:15:05 2001
@@ -1033,9 +1033,10 @@
 #  endif
 STATIC CV*     S_cv_clone2(pTHX_ CV *proto, CV *outside);
 STATIC bool    S_scalar_mod_type(pTHX_ OP *o, I32 type);
-STATIC OP *    S_my_kid(pTHX_ OP *o, OP *attrs);
+STATIC OP *    S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp);
 STATIC OP *    S_dup_attrlist(pTHX_ OP *o);
-STATIC void    S_apply_attrs(pTHX_ HV *stash, SV *target, OP *attrs);
+STATIC void    S_apply_attrs(pTHX_ HV *stash, SV *target, OP *attrs, bool for_my);
+STATIC void    S_apply_attrs_my(pTHX_ HV *stash, OP *target, OP *attrs, OP **imopsp);
 #  if defined(PL_OP_SLAB_ALLOC)
 STATIC void*   S_Slab_Alloc(pTHX_ int m, size_t sz);
 #  endif

==== //depot/perl/t/op/attrs.t#6 (text) ====
Index: perl/t/op/attrs.t
--- perl/t/op/attrs.t.~1~       Sun Dec  9 08:15:05 2001
+++ perl/t/op/attrs.t   Sun Dec  9 08:15:05 2001
@@ -19,6 +19,7 @@
 $SIG{__WARN__} = sub { die @_ };
 
 sub mytest {
+    my $bad = '';
     if (!$@ ne !$_[0] || $_[0] && $@ !~ $_[0]) {
        if ($@) {
            my $x = $@;
@@ -35,15 +36,15 @@
            print "# Expected success\n";
        }
        $failed = 1;
-       print "not ";
+       $bad = 'not ';
     }
     elsif (@_ == 3 && $_[1] ne $_[2]) {
        print "# Got: $_[1]\n";
        print "# Expected: $_[2]\n";
        $failed = 1;
-       print "not ";
+       $bad = 'not ';
     }
-    print "ok ",++$test,"\n";
+    print $bad."ok ".++$test."\n";
 }
 
 eval 'sub t1 ($) : locked { $_[0]++ }';
@@ -173,6 +174,31 @@
 mytest '', "@attrs", "locked method Z";
 BEGIN {++$ntests}
 
+# Begin testing attributes that tie
+
+{
+    package Ttie;
+    sub DESTROY {}
+    sub TIESCALAR { my $x = $_[1]; bless \$x, $_[0]; }
+    sub FETCH { ${$_[0]} }
+    sub STORE {
+       #print "# In Ttie::STORE\n";
+       ::mytest '';
+       ${$_[0]} = $_[1]*2;
+    }
+    package Tloop;
+    sub MODIFY_SCALAR_ATTRIBUTES { tie ${$_[1]}, 'Ttie', -1; (); }
+}
+
+eval '
+    package Tloop;
+    for my $i (0..2) {
+       my $x : TieLoop = $i;
+       $x != $i*2 and ::mytest "", $x, $i*2;
+    }
+';
+mytest;
+BEGIN {$ntests += 4}
 
 # Other tests should be added above this line
 

==== //depot/perl/xsutils.c#17 (text) ====
Index: perl/xsutils.c
--- perl/xsutils.c.~1~  Sun Dec  9 08:15:05 2001
+++ perl/xsutils.c      Sun Dec  9 08:15:05 2001
@@ -84,8 +84,8 @@
                        continue;
                    }
                    break;
-               case 's':
-      if (strEQ(name, "unique")) {
+               case 'u':
+                   if (strEQ(name, "unique")) {
                        if (negated)
                            GvUNIQUE_off(CvGV((CV*)sv));
                        else
@@ -99,11 +99,17 @@
            break;
        default:
            switch ((int)len) {
-              case 6:
+           case 6:
                switch (*name) {
-                  case 's':
-      if (strEQ(name, "unique")) {
-                        /* toke.c has already marked as GVf_UNIQUE */
+               case 'u':
+                   if (strEQ(name, "unique")) {
+                       if (SvTYPE(sv) == SVt_PVGV) {
+                           if (negated)
+                               GvUNIQUE_off(sv);
+                           else
+                               GvUNIQUE_on(sv);
+                       }
+                       /* Hope this came from toke.c if not a GV. */
                         continue;
                     }
                 }
@@ -190,7 +196,11 @@
        if (cvflags & CVf_METHOD)
            XPUSHs(sv_2mortal(newSVpvn("method", 6)));
         if (GvUNIQUE(CvGV((CV*)sv)))
-     XPUSHs(sv_2mortal(newSVpvn("unique", 6)));
+           XPUSHs(sv_2mortal(newSVpvn("unique", 6)));
+       break;
+    case SVt_PVGV:
+       if (GvUNIQUE(sv))
+           XPUSHs(sv_2mortal(newSVpvn("unique", 6)));
        break;
     default:
        break;
End of Patch.

Reply via email to