Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

for lvalue_sub #6761

Closed
p5pRT opened this issue Sep 12, 2003 · 12 comments
Closed

for lvalue_sub #6761

p5pRT opened this issue Sep 12, 2003 · 12 comments

Comments

@p5pRT
Copy link

p5pRT commented Sep 12, 2003

Migrated from rt.perl.org#23790 (status was 'resolved')

Searchable as RT23790$

@p5pRT
Copy link
Author

p5pRT commented Sep 12, 2003

From @Abigail

Created by @Abigail

  #!/usr/bin/perl

  use strict;
  use warnings;

  my @​foo = qw /one two three/;
  sub foo () : lvalue {@​foo}

  print for foo;
  __END__
  Use of uninitialized value in print at /tmp/bug line 9.

However, I expect it to print "onetwothree" (which is does in 5.6.0).
If I remove the '​: lvalue', or change the print statement to
'print for my @​a = foo', it prints "onetwothree".

This bug occurs from 5.6.1 up to and including bleadperl.

Abigail

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl v5.8.0:

Configured by camel at Mon Oct 28 01:28:45 CET 2002.

Summary of my perl5 (revision 5.0 version 8 subversion 0) configuration:
  Platform:
    osname=linux, osvers=2.4.18-bf2.4, archname=i686-linux-64int-ld
    uname='linux alexandra 2.4.18-bf2.4 #1 son apr 14 09:53:28 cest 2002 i686 unknown '
    config_args='-des -Uversiononly -Dmydomain=.abigail.nl -Dcf_email=camel@abigail.nl -Dperladmin=camel@abigail.nl -Doptimize=-g -Dusemorebits -Dusedevel -Dusenm=false -Dprefix=/opt/perl -Dcc=gcc'
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef
    useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
    use64bitint=define use64bitall=undef uselongdouble=define
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='gcc', ccflags ='-DDEBUGGING -fno-strict-aliasing -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-g',
    cppflags='-DDEBUGGING -fno-strict-aliasing'
    ccversion='', gccversion='3.0.4', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long long', ivsize=8, nvtype='long double', nvsize=12, Off_t='off_t', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='gcc', ldflags =' -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib
    libs=-lnsl -ldl -lm -lc -lcrypt -lutil
    perllibs=-lnsl -ldl -lm -lc -lcrypt -lutil
    libc=/lib/libc-2.2.5.so, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.2.5'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic'
    cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib'

Locally applied patches:
    


@INC for perl v5.8.0:
    /home/abigail/Perl
    /opt/perl/lib/5.8.0/i686-linux-64int-ld
    /opt/perl/lib/5.8.0
    /opt/perl/lib/site_perl/5.8.0/i686-linux-64int-ld
    /opt/perl/lib/site_perl/5.8.0
    /opt/perl/lib/site_perl
    .


Environment for perl v5.8.0:
    HOME=/home/abigail
    LANG=C
    LANGUAGE (unset)
    LD_LIBRARY_PATH=/home/abigail/Lib:/usr/local/lib:/usr/lib:/lib:/usr/X11R6/lib
    LOGDIR (unset)
    PATH=/home/abigail/Bin:/opt/perl/bin:/usr/local/bin:/usr/local/X11/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/games:/usr/share/texmf/bin:/opt/Acrobat/bin:/opt/java/blackdown/j2sdk1.3.1/bin:/usr/local/games/bin
    PERL5LIB=/home/abigail/Perl
    PERLDIR=/opt/perl
    PERL_BADLANG (unset)
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Oct 24, 2010

From kasei@cpan.org

padav is leaving an arrayref on the stack when it told to return an
lvalue. But in an argument list it should be a list, so we need to
expand it somewhere.

@p5pRT
Copy link
Author

p5pRT commented Oct 24, 2010

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Oct 28, 2010

From voropaev.andrey@gmail.com

Created by voropaev.andrey@gmail.com

I know, that lvalue subs are experimental. So this is not really an issue, just
a thing that does not work as one would expect.

The code example

##########################################
my @​a;

sub canmod : lvalue { @​a; }
(canmod()) = qw(a b c);
print "a is ", join(', ', @​a), "\n";
print 'canmod gives', join(', ', canmod()), "\n";
foreach(canmod())
{
  print "In loop​: $_\n";
  $_ .= "ll";
}
print join(',', @​a), "\n";
##########################################

Produces

---------------------------------------------
a is a, b, c
canmod gives a, b, c
In loop​:
zsh​: segmentation fault (core dumped) perl try.pl
-----------------------------------------------

Perl Info

Flags:
    category=core
    severity=none

Site configuration information for perl 5.12.2:

Configured by Gentoo at Mon Oct 25 11:45:43 CEST 2010.

Summary of my perl5 (revision 5 version 12 subversion 2) configuration:
   
  Platform:
    osname=linux, osvers=2.6.34-gentoo-r11, archname=x86_64-linux
    uname='linux vandal 2.6.34-gentoo-r11 #2 mon oct 11 16:13:47 cest 2010 x86_64 amd athlon(tm) 64 processor 3200+ authenticamd gnulinux '
    config_args='-des -Duseshrplib -Darchname=x86_64-linux -Dcc=x86_64-pc-linux-gnu-gcc -Doptimize=-march=athlon64 -O2 -pipe -Dldflags=-Wl,-O1 -Wl,--as-needed -Dprefix=/usr -Dsiteprefix=/usr -Dvendorprefix=/usr -Dscriptdir=/usr/bin -Dprivlib=/usr/lib64/perl5/5.12.2 -Darchlib=/usr/lib64/perl5/5.12.2/x86_64-linux -Dsitelib=/usr/lib64/perl5/site_perl/5.12.2 -Dsitearch=/usr/lib64/perl5/site_perl/5.12.2/x86_64-linux -Dvendorlib=/usr/lib64/perl5/vendor_perl/5.12.2 -Dvendorarch=/usr/lib64/perl5/vendor_perl/5.12.2/x86_64-linux -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/share/man/man1 -Dsiteman3dir=/usr/share/man/man3 -Dvendorman1dir=/usr/share/man/man1 -Dvendorman3dir=/usr/share/man/man3 -Dman1ext=1 -Dman3ext=3pm -Dlibperl=libperl.so.5.12.2 -Dlocincpth=  -Duselargefiles -Dd_semctl_semun -Dcf_by=Gentoo -Dmyhostname=localhost -Dperladmin=root@localhost -Dinstallusrbinperl=n -Ud_csh -Uusenm -Di_ndbm -Di_gdbm -Di_db -DDEBUGGING=none -Dinc_version_list=
 5.12.1/x86_64-linux 5.12.1 5.12.0/x86_64-linux 5.12.0  -Dusrinc=/usr/include -Dlibpth=/usr/local/lib64 /lib64 /usr/lib64'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='x86_64-pc-linux-gnu-gcc', ccflags ='-fno-strict-aliasing -pipe -fstack-protector -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-march=athlon64 -O2 -pipe',
    cppflags='-fno-strict-aliasing -pipe -fstack-protector'
    ccversion='', gccversion='4.4.4', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='x86_64-pc-linux-gnu-gcc', ldflags ='-Wl,-O1 -Wl,--as-needed -fstack-protector'
    libpth=/usr/local/lib64 /lib64 /usr/lib64
    libs=-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc -lgdbm_compat
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
    libc=/lib/libc-2.11.2.so, so=so, useshrplib=true, libperl=libperl.so.5.12.2
    gnulibc_version='2.11.2'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -march=athlon64 -O2 -pipe -fstack-protector -Wl,-O1 -Wl,--as-needed'

Locally applied patches:
    0001-gentoo_MakeMaker-RUNPATH.diff
    0002-gentoo_config_over.diff
    0003-gentoo_cpan_definstalldirs.diff
    0004-gentoo_cpanplus_definstalldirs.diff
    0005-gentoo_create-libperl-soname.diff
    0006-gentoo_MakeMaker-delete_packlist.diff
    0007-fixes_8d66b3f9_h2hp_fix.diff


@INC for perl 5.12.2:
    /usr/lib64/perl5/site_perl/5.12.2/x86_64-linux
    /usr/lib64/perl5/site_perl/5.12.2
    /usr/lib64/perl5/vendor_perl/5.12.2/x86_64-linux
    /usr/lib64/perl5/vendor_perl/5.12.2
    /usr/lib64/perl5/5.12.2/x86_64-linux
    /usr/lib64/perl5/5.12.2
    /usr/lib64/perl5/site_perl
    /usr/lib64/perl5/vendor_perl
    .


Environment for perl 5.12.2:
    HOME=/home/andrei
    LANG (unset)
    LANGUAGE (unset)
    LC_CTYPE=en_US.UTF-8
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/usr/local/bin:/usr/bin:/bin:/opt/bin:/usr/x86_64-pc-linux-gnu/gcc-bin/4.4.3:/usr/games/bin:/opt/Adobe/Reader8/bin:/opt/java/jdk1.6.0_03/bin:/opt/Adobe/Reader8/bin:/opt/java/jdk1.6.0_03/bin
    PERL_BADLANG (unset)
    SHELL=/bin/zsh

@p5pRT
Copy link
Author

p5pRT commented Nov 1, 2010

From kasei@cpan.org

Attached a fix for lvalue subs returning an array into the args of
another sub call or for loop.

I've modified leavesublv in that case to convert the returned arrayref
to a non-ref.

@p5pRT
Copy link
Author

p5pRT commented Nov 1, 2010

From kasei@cpan.org

0001-fix-for-23790.patch
From ba8f5d50c4a9a94867872ba5c341fa7e5b546e48 Mon Sep 17 00:00:00 2001
From: Marty Pauley <marty@martian.org>
Date: Sun, 24 Oct 2010 18:02:40 +0900
Subject: [PATCH] fix for #23790.

padav is leaving an arrayref on the stack when producing the return value for an
lvalue sub.  But when this is in an argument list it really should be a array,
not a ref.  So, in leavesublv I check for this case and expand the arrayref to
an array.
---
 pp_hot.c        |   23 +++++++++++++++++++++++
 t/op/sub_lval.t |   12 +++++++++---
 2 files changed, 32 insertions(+), 3 deletions(-)

diff --git a/pp_hot.c b/pp_hot.c
index 34542c2..2d6cba9 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -2598,6 +2598,29 @@ PP(pp_leavesublv)
 	if (gimme == G_SCALAR)
 	    goto temporise;
 	if (gimme == G_ARRAY) {
+	    mark = newsp + 1;
+	    /* We want an array here, but padav will have left us an arrayref for an lvalue,
+	     * so we need to expand it */
+	    if(SvTYPE(*mark) == SVt_PVAV) {
+		AV *const av = MUTABLE_AV(*mark);
+		const I32 maxarg = AvFILL(av) + 1;
+		(void)POPs; /* get rid of the array ref */
+		EXTEND(SP, maxarg);
+		if (SvRMAGICAL(av)) {
+		    U32 i;
+		    for (i=0; i < (U32)maxarg; i++) {
+			SV ** const svp = av_fetch(av, i, FALSE);
+			SP[i+1] = svp
+			    ? SvGMAGICAL(*svp) ? (mg_get(*svp), *svp) : *svp
+			    : &PL_sv_undef;
+		    }
+		}
+		else {
+		    Copy(AvARRAY(av), SP+1, maxarg, SV*);
+		}
+		SP += maxarg;
+		PUTBACK;
+	    }
 	    if (!CvLVALUE(cx->blk_sub.cv))
 		goto temporise_array;
 	    EXTEND_MORTAL(SP - newsp);
diff --git a/t/op/sub_lval.t b/t/op/sub_lval.t
index aedaba0..d0ba84a 100644
--- a/t/op/sub_lval.t
+++ b/t/op/sub_lval.t
@@ -3,7 +3,7 @@ BEGIN {
     @INC = '../lib';
     require './test.pl';
 }
-plan tests=>74;
+plan tests=>76;
 
 sub a : lvalue { my $a = 34; ${\(bless \$a)} }  # Return a temporary
 sub b : lvalue { ${\shift} }
@@ -527,8 +527,7 @@ TODO: {
     is($blah, 8, "yada");
 }
 
-TODO: {
-    local $TODO = "bug #23790";
+{ # bug #23790
     my @arr  = qw /one two three/;
     my $line = "zero";
     sub lval_array () : lvalue {@arr}
@@ -538,6 +537,13 @@ TODO: {
     }
 
     is($line, "zeroonetwothree");
+
+    sub trythislval { scalar(@_)."x".join "", @_ }
+    is(trythislval(lval_array()), "3xonetwothree");
+
+    sub changeme { $_[2] = "free" }
+    changeme(lval_array);
+    is("@arr", "one two free");
 }
 
 {
-- 
1.7.2.3

@p5pRT
Copy link
Author

p5pRT commented Nov 4, 2010

From @cpansprout

On Mon Nov 01 08​:46​:20 2010, maokt wrote​:

Attached a fix for lvalue subs returning an array into the args of
another sub call or for loop.

I've modified leavesublv in that case to convert the returned arrayref
to a non-ref.

Thank you. Applied as 91e34d8.

@p5pRT
Copy link
Author

p5pRT commented Nov 4, 2010

@cpansprout - Status changed from 'open' to 'resolved'

@p5pRT p5pRT closed this as completed Nov 4, 2010
@p5pRT
Copy link
Author

p5pRT commented Nov 4, 2010

From @cpansprout

On Thu Oct 28 02​:23​:36 2010, voropaev.andrey@​gmail.com wrote​:

The code example

##########################################
my @​a;

sub canmod : lvalue { @​a; }
(canmod()) = qw(a b c);
print "a is ", join(', ', @​a), "\n";
print 'canmod gives', join(', ', canmod()), "\n";
foreach(canmod())
{
print "In loop​: $_\n";
$_ .= "ll";
}
print join(',', @​a), "\n";
##########################################

Produces

---------------------------------------------
a is a, b, c
canmod gives a, b, c
In loop​:
zsh​: segmentation fault (core dumped) perl try.pl
-----------------------------------------------

Thank you for the report. This is the same as bug #23790, which has just
been fixed by change 91e34d8.

@p5pRT
Copy link
Author

p5pRT commented Nov 4, 2010

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Nov 4, 2010

@cpansprout - Status changed from 'open' to 'resolved'

@p5pRT
Copy link
Author

p5pRT commented Jun 4, 2011

From @cpansprout

On Thu Nov 04 00​:35​:16 2010, sprout wrote​:

On Mon Nov 01 08​:46​:20 2010, maokt wrote​:

Attached a fix for lvalue subs returning an array into the args of
another sub call or for loop.

I've modified leavesublv in that case to convert the returned arrayref
to a non-ref.

Thank you. Applied as 91e34d8.

For the record​: That patch only worked if the array were the first thing
returned, so it did not fix sub​:lvalue{ $x,@​x } sub​:lvalue{ @​x,@​y }, and
sub​:lvalue { %x }. I’ve found a more general way to fix it, which I’ve
applied as commit 40c94d1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant