Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.85k stars 527 forks source link

void context in string eval is broken #6565

Closed p5pRT closed 20 years ago

p5pRT commented 20 years ago

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

Searchable as RT22708$

p5pRT commented 20 years ago

From @mhx

Created by mhx@cpan.org

Void context is not propagated correctly in blead and maint\, which broke lots of tests in my Convert​::Binary​::C testsuite.

mhx@​r2d2 /tmp $ cat test.pl sub context {   my $w = wantarray;   my $c = defined $w ? ($w ? 'list' : 'scalar') : 'void';   print "$c context\n"; }

  eval { context() }; $a = eval { context() }; @​a = eval { context() };

  eval q{ context() }; $a = eval q{ context() }; @​a = eval q{ context() }; mhx@​r2d2 /tmp $ perl5.8.0 test.pl void context scalar context list context void context \<- correct scalar context list context mhx@​r2d2 /tmp $ maintperl test.pl void context scalar context list context scalar context \<- should be void scalar context list context mhx@​r2d2 /tmp $ bleadperl test.pl void context scalar context list context scalar context \<- should be void scalar context list context mhx@​r2d2 /tmp $

I think the problem is in change #19126​:

==== //depot/perl/pp_ctl.c#351 (text) ====

@​@​ -2884\,7 +2884\,13 @​@​   *startop = PL_eval_root;   } else   SAVEFREEOP(PL_eval_root); - if (gimme & G_VOID) + if (gimme & G_VOID && ! PL_in_eval & EVAL_INREQUIRE) + /* + * EVAL_INREQUIRE (the code is being required) is special-cased : + * in this case we want scalar context to be forced\, instead + * of void context\, so a proper return value is returned from + * C\ via this leaveeval op. + */   scalarvoid(PL_eval_root);   else if (gimme & G_ARRAY)   list(PL_eval_root);

I guess that

  if (gimme & G_VOID && ! PL_in_eval & EVAL_INREQUIRE)

was supposed to be

  if (gimme & G_VOID && ! (PL_in_eval & EVAL_INREQUIRE))

but due to the precedence of ! and & it is actually

  if (gimme & G_VOID && (! PL_in_eval) & EVAL_INREQUIRE)

As PL_in_eval is nonzero most of the time (always?)\, the above condition is always false. Using

  if (gimme & G_VOID && ! (PL_in_eval & EVAL_INREQUIRE))

does fix the general void context problem\, but re-introduces the 'require' problem addressed by change #19126. I have no idea what is going on ;-)

However\, I added some tests to t/op/eval.t in the attached patch\, of which the last one is currently failing.

-- Marcus

Perl Info ``` Flags: category=core severity=critical Site configuration information for perl v5.8.1: Configured by mhx at Sun Jun 15 22:11:23 MEST 2003. Summary of my perl5 (revision 5.0 version 8 subversion 1) configuration: Platform: osname=linux, osvers=2.4.20-gentoo-r2, archname=i686-linux-thread-multi-64int-ld uname='linux r2d2.mhxnet.de 2.4.20-gentoo-r2 #5 die apr 22 07:47:18 mest 2003 i686 intel(r) pentium(r) iii mobile cpu 1000mhz genuineintel gnulinux ' config_args='-de -Uinstallusrbinperl -Dusethreads -Duse64bitint -Duselongdouble -Dcf_email=mhx@cpan.org -Dcc=gcc-3.3 -Doptimize=-O3 -march=pentium3 -Dprefix=/home/mhx/perl/maint' hint=recommended, useposix=true, d_sigaction=define usethreads=define use5005threads=undef useithreads=define usemultiplicity=define useperlio=define d_sfio=undef uselargefiles=define usesocks=undef use64bitint=define use64bitall=undef uselongdouble=define usemymalloc=n, bincompat5005=undef Compiler: cc='gcc-3.3', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -fno-strict-aliasing -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-O3 -march=pentium3', cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -fno-strict-aliasing' ccversion='', gccversion='3.3', 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-3.3', ldflags =' -L/usr/local/lib' libpth=/usr/local/lib /lib /usr/lib libs=-lnsl -lndbm -lgdbm -ldb -ldl -lm -lpthread -lc -lcrypt -lutil -lrt perllibs=-lnsl -ldl -lm -lpthread -lc -lcrypt -lutil -lrt libc=/lib/libc-2.3.1.so, so=so, useshrplib=false, libperl=libperl.a gnulibc_version='2.3.1' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic' cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib' Locally applied patches: MAINT19791 @INC for perl v5.8.1: /home/m5/sw/tool/src_general/tparser/lib /users/patient_data/tool/libs/PERL /home/mhx/perl/maint/lib/5.8.1/i686-linux-thread-multi-64int-ld /home/mhx/perl/maint/lib/5.8.1 /home/mhx/perl/maint/lib/site_perl/5.8.1/i686-linux-thread-multi-64int-ld /home/mhx/perl/maint/lib/site_perl/5.8.1 /home/mhx/perl/maint/lib/site_perl . Environment for perl v5.8.1: HOME=/home/mhx LANG=de_DE LANGUAGE (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=/home/mhx/apps/bin:/bin:/usr/bin/ccache:/usr/bin:/usr/local/bin:/opt/bin:/usr/i686-pc-linux-gnu/gcc-bin/3.2:/opt/intel/compiler 70/ia32/bin:/opt/Acrobat5:/opt/rar/bin:/usr/X11R6/bin:/opt/blackdown-jre-1.4.1/bin:/usr/qt/3/bin:/usr/kde/3.1/bin:/opt/SnapshotCM/bi n:/home/m5/sw/tool/bin PERL5LIB=/home/m5/sw/tool/src_general/tparser/lib PERL_BADLANG (unset) SHELL=/bin/bash ```
p5pRT commented 20 years ago

From @mhx

eval.t.diff

p5pRT commented 20 years ago

From @rgs

Marcus Holland-Moritz wrote​:

Void context is not propagated correctly in blead and maint\, which broke lots of tests in my Convert​::Binary​::C testsuite. [snip evidence] I think the problem is in change #19126​:

Yes\, a poor attempt at fixing #21742.

==== //depot/perl/pp_ctl.c#351 (text) ====

@​@​ -2884\,7 +2884\,13 @​@​ *startop = PL_eval_root; } else SAVEFREEOP(PL_eval_root); - if (gimme & G_VOID) + if (gimme & G_VOID && ! PL_in_eval & EVAL_INREQUIRE) + /* + * EVAL_INREQUIRE (the code is being required) is special-cased : + * in this case we want scalar context to be forced\, instead + * of void context\, so a proper return value is returned from + * C\ via this leaveeval op. + */ scalarvoid(PL_eval_root); else if (gimme & G_ARRAY) list(PL_eval_root);

I guess that

if (gimme & G_VOID && ! PL_in_eval & EVAL_INREQUIRE)

was supposed to be

if (gimme & G_VOID && ! (PL_in_eval & EVAL_INREQUIRE))

but due to the precedence of ! and & it is actually

if (gimme & G_VOID && (! PL_in_eval) & EVAL_INREQUIRE)

As PL_in_eval is nonzero most of the time (always?)\, the above condition is always false.

Duh.

Using

if (gimme & G_VOID && ! (PL_in_eval & EVAL_INREQUIRE))

does fix the general void context problem\, but re-introduces the 'require' problem addressed by change #19126. I have no idea what is going on ;-)

It doesn't work because the require happens after the entereval. And this doeval function is executed twice : once for the entereval\, once for the require. That probably means that bug #21742 should not be fixed there\, but at an upper level.

However\, I added some tests to t/op/eval.t in the attached patch\, of which the last one is currently failing.

I've applied your test patch as #19801\, and reverted the pp_ctl.c part of #19126. Thanks for cleaning up my stables !

p5pRT commented 20 years ago

@rgs - Status changed from 'new' to 'resolved'