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

BEGIN {require 5.011} imports features #9863

Closed
p5pRT opened this issue Sep 8, 2009 · 18 comments
Closed

BEGIN {require 5.011} imports features #9863

p5pRT opened this issue Sep 8, 2009 · 18 comments

Comments

@p5pRT
Copy link

p5pRT commented Sep 8, 2009

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

Searchable as RT69050$

@p5pRT
Copy link
Author

p5pRT commented Sep 8, 2009

From @nwc10

Created by @nwc10

It is documented that C<use 5.011;> (etc) implicitly use feature.

Hence

$ ./perl -Ilib -e 'say "Hi"'
String found where operator expected at -e line 1, near "say "Hi""
  (Do you need to predeclare say?)
syntax error at -e line 1, near "say "Hi""
Execution of -e aborted due to compilation errors.
$ ./perl -Ilib -e 'use 5.011; say "Hi"'
Hi

However, it is not documented that C<require 5.011> does this. Hence this
is a bug​:

$ ./perl -Ilib -e 'BEGIN {require 5.011}; say "Hi"'
Hi

That should fail with the "String found" error.

(Zefram spotted this)

Nicholas Clark

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl 5.11.0:

Configured by nick at Mon Sep  7 22:49:10 BST 2009.

Summary of my perl5 (revision 5 version 11 subversion 0) configuration:
  Commit id: 380d1e906b715974eb33a0beaa622ee519b3b0e0
  Platform:
    osname=linux, osvers=2.6.18-xenu, archname=x86_64-linux
    uname='linux zazen 2.6.18-xenu #1 smp thu oct 4 12:23:41 bst 2007 x86_64 gnulinux '
    config_args='-Dusedevel=y -Dcc=ccache gcc -Dld=gcc -Ubincompat5005 -Uinstallusrbinperl -Dcf_email=nick@ccl4.org -Dperladmin=nick@ccl4.org -Dinc_version_list=  -Dinc_version_list_init=0 -Doptimize=-g -Uusethreads -Uuse64bitall -Uusemymalloc -Duseperlio -Dprefix=~/Sandpit/snap5.9.x-GitLive-blead-2173-g380d1e9 -Uusevendorprefix -Uvendorprefix=~/Sandpit/snap5.9.x-GitLive-blead-2173-g380d1e9 -Dinstallman1dir=none -Dinstallman3dir=none -Uuserelocatableinc -de'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='ccache gcc', ccflags ='-DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-g',
    cppflags='-DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.3.2', 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='gcc', ldflags =' -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib /lib64 /usr/lib64
    libs=-lnsl -ldb -ldl -lm -lcrypt -lutil -lc
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
    libc=/lib/libc-2.7.so, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.7'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -g -L/usr/local/lib -fstack-protector'

Locally applied patches:
    


@INC for perl 5.11.0:
    lib
    /home/nick/Sandpit/snap5.9.x-GitLive-blead-2173-g380d1e9/lib/perl5/site_perl/5.11.0/x86_64-linux
    /home/nick/Sandpit/snap5.9.x-GitLive-blead-2173-g380d1e9/lib/perl5/site_perl/5.11.0
    /home/nick/Sandpit/snap5.9.x-GitLive-blead-2173-g380d1e9/lib/perl5/5.11.0/x86_64-linux
    /home/nick/Sandpit/snap5.9.x-GitLive-blead-2173-g380d1e9/lib/perl5/5.11.0
    .


Environment for perl 5.11.0:
    HOME=/home/nick
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/nick/bin:/usr/local/bin:/usr/bin:/bin:/usr/games:/usr/local/sbin:/sbin:/usr/sbin
    PERL_BADLANG (unset)
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Sep 11, 2009

From Robin.Barker@npl.co.uk

However, it is not documented that C<require 5.011> does this.
Hence this is a bug​:

$ ./perl -Ilib -e 'BEGIN {require 5.011}; say "Hi"'
Hi

That should fail with the "String found" error.

I have fixed this by introducing a separate opcode for use, OP_USE,
used in pp_require to distinguish use from require.

There are lots of collateral changes and this may not be the right
approach.

In particular, Safe.pm will not work as before wrt to require/use

Robin

@p5pRT
Copy link
Author

p5pRT commented Sep 11, 2009

From Robin.Barker@npl.co.uk

0002-add-OP_USE-to-distinguish-use-from-BEGIN-require.patch
From 30ed5a30ebf7db6ac54a838b2d7fa8edd164c842 Mon Sep 17 00:00:00 2001
From: Robin Barker <Robin.Barker@npl.co.uk>
Date: Fri, 11 Sep 2009 15:46:41 +0100
Subject: [PATCH 2/2] add OP_USE to distinguish use from BEGIN{require}

---
 embed.h                    |    2 ++
 ext/B-Deparse/Deparse.pm   |    2 +-
 ext/B/t/optree_specials.t  |   36 ++++++++++++++++++------------------
 ext/Opcode/Opcode.pm       |    2 +-
 ext/Safe/t/safeload.t      |    2 +-
 ext/Safe/t/safeuniversal.t |    2 +-
 ext/Storable/t/code.t      |    2 +-
 op.c                       |    4 +++-
 opcode.h                   |    5 +++++
 opcode.pl                  |    6 +++++-
 opnames.h                  |    3 ++-
 pp.sym                     |    1 +
 pp_ctl.c                   |   29 +++++++++++++++++------------
 pp_proto.h                 |    1 +
 t/lib/feature/implicit     |   14 ++++++++++++++
 15 files changed, 73 insertions(+), 38 deletions(-)

diff --git a/embed.h b/embed.h
index 817c291..e56355b 100644
--- a/embed.h
+++ b/embed.h
@@ -2374,6 +2374,7 @@
 #define pp_unshift		Perl_pp_unshift
 #define pp_unstack		Perl_pp_unstack
 #define pp_untie		Perl_pp_untie
+#define pp_use			Perl_pp_use
 #define pp_utime		Perl_pp_utime
 #define pp_values		Perl_pp_values
 #define pp_vec			Perl_pp_vec
@@ -4741,6 +4742,7 @@
 #define pp_unshift()		Perl_pp_unshift(aTHX)
 #define pp_unstack()		Perl_pp_unstack(aTHX)
 #define pp_untie()		Perl_pp_untie(aTHX)
+#define pp_use()		Perl_pp_use(aTHX)
 #define pp_utime()		Perl_pp_utime(aTHX)
 #define pp_values()		Perl_pp_values(aTHX)
 #define pp_vec()		Perl_pp_vec(aTHX)
diff --git a/ext/B-Deparse/Deparse.pm b/ext/B-Deparse/Deparse.pm
index df7ed31..6c5adbf 100644
--- a/ext/B-Deparse/Deparse.pm
+++ b/ext/B-Deparse/Deparse.pm
@@ -372,7 +372,7 @@ sub begin_is_use {
     return if $lineseq->name ne "lineseq";
 
     my $req_op = $lineseq->first->sibling;
-    return if $req_op->name ne "require";
+    return if $req_op->name ne "use";
 
     my $module;
     if ($req_op->first->private & OPpCONST_BARE) {
diff --git a/ext/B/t/optree_specials.t b/ext/B/t/optree_specials.t
index 1f81323..e38a2fd 100644
--- a/ext/B/t/optree_specials.t
+++ b/ext/B/t/optree_specials.t
@@ -51,7 +51,7 @@ checkOptree ( name	=> 'BEGIN',
 # b  <1> leavesub[1 ref] K/REFC,1 ->(end)
 # -     <@> lineseq KP ->b
 # 1        <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$ ->2
-# 3        <1> require sK/1 ->4
+# 3        <1> use sK/1 ->4
 # 2           <$> const[PV "strict.pm"] s/BARE ->3
 # 4        <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$ ->5
 # -        <@> lineseq K ->-
@@ -65,7 +65,7 @@ checkOptree ( name	=> 'BEGIN',
 # m  <1> leavesub[1 ref] K/REFC,1 ->(end)
 # -     <@> lineseq K ->m
 # c        <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ ->d
-# e        <1> require sK/1 ->f
+# e        <1> use sK/1 ->f
 # d           <$> const[PV "strict.pm"] s/BARE ->e
 # f        <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ ->g
 # -        <@> lineseq K ->-
@@ -79,7 +79,7 @@ checkOptree ( name	=> 'BEGIN',
 # x  <1> leavesub[1 ref] K/REFC,1 ->(end)
 # -     <@> lineseq KP ->x
 # n        <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ ->o
-# p        <1> require sK/1 ->q
+# p        <1> use sK/1 ->q
 # o           <$> const[PV "warnings.pm"] s/BARE ->p
 # q        <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ ->r
 # -        <@> lineseq K ->-
@@ -101,7 +101,7 @@ EOT_EOT
 # b  <1> leavesub[1 ref] K/REFC,1 ->(end)
 # -     <@> lineseq KP ->b
 # 1        <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$ ->2
-# 3        <1> require sK/1 ->4
+# 3        <1> use sK/1 ->4
 # 2           <$> const(PV "strict.pm") s/BARE ->3
 # 4        <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$ ->5
 # -        <@> lineseq K ->-
@@ -115,7 +115,7 @@ EOT_EOT
 # m  <1> leavesub[1 ref] K/REFC,1 ->(end)
 # -     <@> lineseq K ->m
 # c        <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ ->d
-# e        <1> require sK/1 ->f
+# e        <1> use sK/1 ->f
 # d           <$> const(PV "strict.pm") s/BARE ->e
 # f        <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ ->g
 # -        <@> lineseq K ->-
@@ -129,7 +129,7 @@ EOT_EOT
 # x  <1> leavesub[1 ref] K/REFC,1 ->(end)
 # -     <@> lineseq KP ->x
 # n        <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ ->o
-# p        <1> require sK/1 ->q
+# p        <1> use sK/1 ->q
 # o           <$> const(PV "warnings.pm") s/BARE ->p
 # q        <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ ->r
 # -        <@> lineseq K ->-
@@ -251,7 +251,7 @@ checkOptree ( name	=> 'all of BEGIN END INIT CHECK UNITCHECK -exec',
 # BEGIN 1:
 # 1  <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$
 # 2  <$> const[PV "strict.pm"] s/BARE
-# 3  <1> require sK/1
+# 3  <1> use sK/1
 # 4  <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$
 # 5  <;> nextstate(B::Concise -275 Concise.pm:356) :*,&,{,$
 # 6  <0> pushmark s
@@ -263,7 +263,7 @@ checkOptree ( name	=> 'all of BEGIN END INIT CHECK UNITCHECK -exec',
 # BEGIN 2:
 # c  <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$
 # d  <$> const[PV "strict.pm"] s/BARE
-# e  <1> require sK/1
+# e  <1> use sK/1
 # f  <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$
 # g  <;> nextstate(B::Concise -265 Concise.pm:367) :*,&,$
 # h  <0> pushmark s
@@ -275,7 +275,7 @@ checkOptree ( name	=> 'all of BEGIN END INIT CHECK UNITCHECK -exec',
 # BEGIN 3:
 # n  <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$
 # o  <$> const[PV "warnings.pm"] s/BARE
-# p  <1> require sK/1
+# p  <1> use sK/1
 # q  <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$
 # r  <;> nextstate(B::Concise -254 Concise.pm:386) :*,&,{,$
 # s  <0> pushmark s
@@ -313,7 +313,7 @@ EOT_EOT
 # BEGIN 1:
 # 1  <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$
 # 2  <$> const(PV "strict.pm") s/BARE
-# 3  <1> require sK/1
+# 3  <1> use sK/1
 # 4  <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$
 # 5  <;> nextstate(B::Concise -275 Concise.pm:356) :*,&,{,$
 # 6  <0> pushmark s
@@ -325,7 +325,7 @@ EOT_EOT
 # BEGIN 2:
 # c  <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$
 # d  <$> const(PV "strict.pm") s/BARE
-# e  <1> require sK/1
+# e  <1> use sK/1
 # f  <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$
 # g  <;> nextstate(B::Concise -265 Concise.pm:367) :*,&,$
 # h  <0> pushmark s
@@ -337,7 +337,7 @@ EOT_EOT
 # BEGIN 3:
 # n  <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$
 # o  <$> const(PV "warnings.pm") s/BARE
-# p  <1> require sK/1
+# p  <1> use sK/1
 # q  <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$
 # r  <;> nextstate(B::Concise -254 Concise.pm:386) :*,&,{,$
 # s  <0> pushmark s
@@ -386,7 +386,7 @@ checkOptree ( name	=> 'regression test for patch 25352',
 # BEGIN 1:
 # 1  <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$
 # 2  <$> const[PV "strict.pm"] s/BARE
-# 3  <1> require sK/1
+# 3  <1> use sK/1
 # 4  <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$
 # 5  <;> nextstate(B::Concise -275 Concise.pm:356) :*,&,{,$
 # 6  <0> pushmark s
@@ -398,7 +398,7 @@ checkOptree ( name	=> 'regression test for patch 25352',
 # BEGIN 2:
 # c  <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$
 # d  <$> const[PV "strict.pm"] s/BARE
-# e  <1> require sK/1
+# e  <1> use sK/1
 # f  <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$
 # g  <;> nextstate(B::Concise -265 Concise.pm:367) :*,&,$
 # h  <0> pushmark s
@@ -410,7 +410,7 @@ checkOptree ( name	=> 'regression test for patch 25352',
 # BEGIN 3:
 # n  <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$
 # o  <$> const[PV "warnings.pm"] s/BARE
-# p  <1> require sK/1
+# p  <1> use sK/1
 # q  <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$
 # r  <;> nextstate(B::Concise -254 Concise.pm:386) :*,&,{,$
 # s  <0> pushmark s
@@ -423,7 +423,7 @@ EOT_EOT
 # BEGIN 1:
 # 1  <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$
 # 2  <$> const(PV "strict.pm") s/BARE
-# 3  <1> require sK/1
+# 3  <1> use sK/1
 # 4  <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$
 # 5  <;> nextstate(B::Concise -275 Concise.pm:356) :*,&,{,$
 # 6  <0> pushmark s
@@ -435,7 +435,7 @@ EOT_EOT
 # BEGIN 2:
 # c  <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$
 # d  <$> const(PV "strict.pm") s/BARE
-# e  <1> require sK/1
+# e  <1> use sK/1
 # f  <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$
 # g  <;> nextstate(B::Concise -265 Concise.pm:367) :*,&,$
 # h  <0> pushmark s
@@ -447,7 +447,7 @@ EOT_EOT
 # BEGIN 3:
 # n  <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$
 # o  <$> const(PV "warnings.pm") s/BARE
-# p  <1> require sK/1
+# p  <1> use sK/1
 # q  <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$
 # r  <;> nextstate(B::Concise -254 Concise.pm:386) :*,&,{,$
 # s  <0> pushmark s
diff --git a/ext/Opcode/Opcode.pm b/ext/Opcode/Opcode.pm
index d778294..e9ca4bb 100644
--- a/ext/Opcode/Opcode.pm
+++ b/ext/Opcode/Opcode.pm
@@ -541,7 +541,7 @@ SystemV Interprocess Communications:
 This tag holds opcodes related to loading modules and getting information
 about calling environment and args.
 
-    require dofile 
+    require dofile use
     caller
 
 =item :still_to_be_decided
diff --git a/ext/Safe/t/safeload.t b/ext/Safe/t/safeload.t
index 2d2c3cc..a3f2f04 100644
--- a/ext/Safe/t/safeload.t
+++ b/ext/Safe/t/safeload.t
@@ -21,6 +21,6 @@ use Safe;
 plan(tests => 1);
 
 my $c = new Safe;
-$c->permit(qw(require caller entereval unpack));
+$c->permit(qw(:load entereval unpack));
 my $r = $c->reval(q{ use version; 1 });
 ok( defined $r, "Can load version.pm in a Safe compartment" ) or diag $@;
diff --git a/ext/Safe/t/safeuniversal.t b/ext/Safe/t/safeuniversal.t
index 95867c5..30b987a 100644
--- a/ext/Safe/t/safeuniversal.t
+++ b/ext/Safe/t/safeuniversal.t
@@ -16,7 +16,7 @@ use Safe;
 plan(tests => 6);
 
 my $c = new Safe;
-$c->permit(qw(require caller));
+$c->permit(qw(:load));
 
 my $no_warn_redef = ($] != 5.008009)
     ? q(no warnings 'redefine';)
diff --git a/ext/Storable/t/code.t b/ext/Storable/t/code.t
index dd2a96e..336e316 100644
--- a/ext/Storable/t/code.t
+++ b/ext/Storable/t/code.t
@@ -237,7 +237,7 @@ ok(prototype($thawed->[4]), prototype($obj[0]->[4]));
 {
     my $safe = new Safe;
     # because of opcodes used in "use strict":
-    $safe->permit(qw(:default require caller));
+    $safe->permit(qw(:default :load));
     local $Storable::Eval = sub { $safe->reval(shift) };
 
     $freezed = freeze $obj[0]->[1];
diff --git a/op.c b/op.c
index c6f38fa..255af94 100644
--- a/op.c
+++ b/op.c
@@ -1186,6 +1186,7 @@ Perl_scalarvoid(pTHX_ OP *o)
 	scalarkids(o);
 	break;
     case OP_REQUIRE:
+    case OP_USE:
 	/* all requires must return a boolean value */
 	o->op_flags &= ~OPf_WANT;
 	/* FALL THROUGH */
@@ -1284,6 +1285,7 @@ Perl_list(pTHX_ OP *o)
 	PL_curcop = &PL_compiling;
 	break;
     case OP_REQUIRE:
+    case OP_USE:
 	/* all requires must return a boolean value */
 	o->op_flags &= ~OPf_WANT;
 	return scalar(o);
@@ -3914,7 +3916,7 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg)
 	NULL,
 	append_elem(OP_LINESEQ,
 	    append_elem(OP_LINESEQ,
-	        newSTATEOP(0, NULL, newUNOP(OP_REQUIRE, 0, idop)),
+	        newSTATEOP(0, NULL, newUNOP(OP_USE, 0, idop)),
 	        newSTATEOP(0, NULL, veop)),
 	    newSTATEOP(0, NULL, imop) ));
 
diff --git a/opcode.h b/opcode.h
index aa57e21..9b2279f 100644
--- a/opcode.h
+++ b/opcode.h
@@ -398,6 +398,7 @@ EXTCONST char* const PL_op_name[] = {
 	"lock",
 	"once",
 	"custom",
+	"use",
 };
 #endif
 
@@ -770,6 +771,7 @@ EXTCONST char* const PL_op_desc[] = {
 	"lock",
 	"once",
 	"unknown custom operator",
+	"use",
 };
 #endif
 
@@ -1156,6 +1158,7 @@ EXT Perl_ppaddr_t PL_ppaddr[] /* or perlvars.h */
 	MEMBER_TO_FPTR(Perl_pp_lock),
 	MEMBER_TO_FPTR(Perl_pp_once),
 	MEMBER_TO_FPTR(Perl_unimplemented_op),	/* Perl_pp_custom */
+	MEMBER_TO_FPTR(Perl_pp_require),	/* Perl_pp_use */
 }
 #endif
 #ifdef PERL_PPADDR_INITED
@@ -1539,6 +1542,7 @@ EXT Perl_check_t PL_check[] /* or perlvars.h */
 	MEMBER_TO_FPTR(Perl_ck_rfun),	/* lock */
 	MEMBER_TO_FPTR(Perl_ck_null),	/* once */
 	MEMBER_TO_FPTR(Perl_ck_null),	/* custom */
+	MEMBER_TO_FPTR(Perl_ck_require),	/* use */
 }
 #endif
 #ifdef PERL_CHECK_INITED
@@ -1916,6 +1920,7 @@ EXTCONST U32 PL_opargs[] = {
 	0x0000f604,	/* lock */
 	0x00000600,	/* once */
 	0x00000000,	/* custom */
+	0x000136c0,	/* use */
 };
 #endif
 
diff --git a/opcode.pl b/opcode.pl
index 2cc242f..3ab91e1 100755
--- a/opcode.pl
+++ b/opcode.pl
@@ -65,7 +65,7 @@ my @raw_alias = (
 		 Perl_pp_null => [qw(scalar regcmaybe lineseq scope)],
 
 		 Perl_pp_goto => ['dump'],
-		 Perl_pp_require => ['dofile'],
+		 Perl_pp_require => ['dofile', 'use'],
 		 Perl_pp_untie => ['dbmclose'],
 		 Perl_pp_sysread => [qw(read recv)],
 		 Perl_pp_sysseek => ['seek'],
@@ -1116,3 +1116,7 @@ lock		lock			ck_rfun		s%	R
 once		once			ck_null		|	
 
 custom		unknown custom operator		ck_null		0
+
+# To distinguish 'use' from 'BEGIN{require}'
+
+use		use			ck_require	du%	S?
diff --git a/opnames.h b/opnames.h
index 3914ea8..802b55b 100644
--- a/opnames.h
+++ b/opnames.h
@@ -380,10 +380,11 @@ typedef enum opcode {
 	OP_LOCK		 = 362,
 	OP_ONCE		 = 363,
 	OP_CUSTOM	 = 364,
+	OP_USE		 = 365,
 	OP_max		
 } opcode;
 
-#define MAXO 365
+#define MAXO 366
 #define OP_phoney_INPUT_ONLY -1
 #define OP_phoney_OUTPUT_ONLY -2
 
diff --git a/pp.sym b/pp.sym
index 9a2a6b2..ba427cf 100644
--- a/pp.sym
+++ b/pp.sym
@@ -408,5 +408,6 @@ Perl_pp_getlogin
 Perl_pp_syscall
 Perl_pp_lock
 Perl_pp_once
+Perl_pp_use
 
 # ex: set ro:
diff --git a/pp_ctl.c b/pp_ctl.c
index e69bf0c..80ea2f6 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1600,7 +1600,7 @@ Perl_die_where(pTHX_ const char *message, STRLEN msglen)
 	     * minimal fix --GSAR */
 	    PL_curcop = cx->blk_oldcop;
 
-	    if (optype == OP_REQUIRE) {
+	    if (optype == OP_REQUIRE || optype == OP_USE) {
                 const char* const msg = SvPVx_nolen_const(ERRSV);
 		SV * const nsv = cx->blk_eval.old_namesv;
                 (void)hv_store(GvHVn(PL_incgv), SvPVX_const(nsv), SvCUR(nsv),
@@ -2112,7 +2112,7 @@ PP(pp_return)
 	if (CxTRYBLOCK(cx))
 	    break;
 	lex_end();
-	if (optype == OP_REQUIRE &&
+	if ((optype == OP_REQUIRE || optype == OP_USE) &&
 	    (MARK == SP || (gimme == G_SCALAR && !SvTRUE(*SP))) )
 	{
 	    /* Unassume the success we assumed earlier. */
@@ -2980,7 +2980,8 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq)
     dVAR; dSP;
     OP * const saveop = PL_op;
 
-    PL_in_eval = ((saveop && saveop->op_type == OP_REQUIRE)
+    PL_in_eval = ((saveop && (saveop->op_type == OP_REQUIRE
+			    || saveop->op_type == OP_USE))
 		  ? (EVAL_INREQUIRE | (PL_in_eval & EVAL_INEVAL))
 		  : EVAL_INEVAL);
 
@@ -3028,7 +3029,8 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq)
     PL_eval_root = NULL;
     PL_curcop = &PL_compiling;
     CopARYBASE_set(PL_curcop, 0);
-    if (saveop && (saveop->op_type != OP_REQUIRE) && (saveop->op_flags & OPf_SPECIAL))
+    if (saveop && !(saveop->op_type == OP_REQUIRE || saveop->op_type == OP_USE)
+	    && (saveop->op_flags & OPf_SPECIAL))
 	PL_in_eval |= EVAL_KEEPERR;
     else
 	CLEAR_ERRSV();
@@ -3052,7 +3054,7 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq)
 	LEAVE; /* pp_entereval knows about this LEAVE.  */
 
 	msg = SvPVx_nolen_const(ERRSV);
-	if (optype == OP_REQUIRE) {
+	if (optype == OP_REQUIRE || optype == OP_USE) {
 	    const SV * const nsv = cx->blk_eval.old_namesv;
 	    (void)hv_store(GvHVn(PL_incgv), SvPVX_const(nsv), SvCUR(nsv),
                           &PL_sv_undef, 0);
@@ -3086,8 +3088,10 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq)
      * Otherwise, propagate the context from the eval(). */
     if (PL_eval_root->op_type == OP_LEAVEEVAL
 	    && cUNOPx(PL_eval_root)->op_first->op_type == OP_LINESEQ
-	    && cLISTOPx(cUNOPx(PL_eval_root)->op_first)->op_last->op_type
-	    == OP_REQUIRE)
+	    && (cLISTOPx(cUNOPx(PL_eval_root)->op_first)->op_last->op_type
+		    == OP_REQUIRE
+	    || cLISTOPx(cUNOPx(PL_eval_root)->op_first)->op_last->op_type
+		    == OP_USE) )
 	scalar(PL_eval_root);
     else if ((gimme & G_WANT) == G_VOID)
 	scalarvoid(PL_eval_root);
@@ -3099,7 +3103,8 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq)
     DEBUG_x(dump_eval());
 
     /* Register with debugger: */
-    if (PERLDB_INTER && saveop && saveop->op_type == OP_REQUIRE) {
+    if (PERLDB_INTER && saveop && (saveop->op_type == OP_REQUIRE
+				    || saveop->op_type == OP_USE) ) {
 	CV * const cv = get_cvs("DB::postponed", 0);
 	if (cv) {
 	    dSP;
@@ -3249,7 +3254,7 @@ PP(pp_require)
 	}
 
         /* We do this only with use, not require. */
-	if (PL_compcv &&
+	if ( (PL_op->op_type == OP_USE) &&
 	  /* If we request a version >= 5.9.5, load feature.pm with the
 	   * feature bundle that corresponds to the required version. */
 		vcmp(sv, sv_2mortal(upg_version(newSVnv(5.009005), FALSE))) >= 0) {
@@ -3293,7 +3298,7 @@ PP(pp_require)
 	unixname = (char *) name;
 	unixlen = len;
     }
-    if (PL_op->op_type == OP_REQUIRE) {
+    if (PL_op->op_type == OP_REQUIRE || PL_op->op_type == OP_USE) {
 	SV * const * const svp = hv_fetch(GvHVn(PL_incgv),
 					  unixname, unixlen, 0);
 	if ( svp ) {
@@ -3516,7 +3521,7 @@ PP(pp_require)
     CopFILE_set(&PL_compiling, tryrsfp ? tryname : name);
     SvREFCNT_dec(namesv);
     if (!tryrsfp) {
-	if (PL_op->op_type == OP_REQUIRE) {
+	if (PL_op->op_type == OP_REQUIRE || PL_op->op_type == OP_USE) {
 	    const char *msgstr = name;
 	    if(errno == EMFILE) {
 		SV * const msg
@@ -3783,7 +3788,7 @@ PP(pp_leaveeval)
     CvDEPTH(PL_compcv) = 0;
     lex_end();
 
-    if (optype == OP_REQUIRE &&
+    if ((optype == OP_REQUIRE || optype == OP_USE) &&
 	!(gimme == G_SCALAR ? SvTRUE(*SP) : SP > newsp))
     {
 	/* Unassume the success we assumed earlier. */
diff --git a/pp_proto.h b/pp_proto.h
index 0c1829a..9998434 100644
--- a/pp_proto.h
+++ b/pp_proto.h
@@ -409,5 +409,6 @@ PERL_PPDEF(Perl_pp_getlogin)
 PERL_PPDEF(Perl_pp_syscall)
 PERL_PPDEF(Perl_pp_lock)
 PERL_PPDEF(Perl_pp_once)
+PERL_PPDEF(Perl_pp_use)
 
 /* ex: set ro: */
diff --git a/t/lib/feature/implicit b/t/lib/feature/implicit
index 0632770..6c8f508 100644
--- a/t/lib/feature/implicit
+++ b/t/lib/feature/implicit
@@ -60,3 +60,17 @@ BEGIN {
 }
 EXPECT
 Helloworld
+########
+# VERSION requirement in BLOCK - feature is lexical
+{ use 5.9.5; }
+say "Hello", "world";
+EXPECT
+OPTION regex
+^String found where operator expected
+########
+# VERSION requirement as require - bug perl RT #69050
+BEGIN { require 5.9.5; }
+say "Hello", "world";
+EXPECT
+OPTION regex
+^String found where operator expected
-- 
1.6.1

@p5pRT
Copy link
Author

p5pRT commented Sep 11, 2009

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

@p5pRT
Copy link
Author

p5pRT commented Sep 11, 2009

From @davidnicol

On Fri, Sep 11, 2009 at 10​:11 AM, Robin Barker <Robin.Barker@​npl.co.uk> wrote​:

I have fixed this by introducing a separate opcode for use, OP_USE,
used in pp_require to distinguish use from require.

There are lots of collateral changes and this may not be the right
approach.

In particular, Safe.pm will not work as before wrt to require/use

Robin

Does this mean that

  use MyMagicTieingModule my $VariableIntendedToBeVisibileInThisScope;

will start DWIW?

--
"As if you could kill time without injuring eternity!" -- Henry David Thoreau

@p5pRT
Copy link
Author

p5pRT commented Sep 11, 2009

From zefram@fysh.org

Robin Barker wrote​:

There are lots of collateral changes and this may not be the right
approach.

I think a better approach is​:

* "require 5.010" ceases to do anything other than the version check

* "use 5.010" expands (in the optree) to something like
  BEGIN {
  require 5.010;
  require feature;
  feature->import("​:5.010");
  }
  (where previously it only expanded to "BEGIN { require 5.010 }")

That is, the feature magic goes into the parsing of the "use" instruction,
not into execution.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Jul 3, 2010

From @briandfoy

Created by brian@mimibean.local

The feature.pm docs notes that it's implicitly loaded by -E
or use VERSION. However, it's also implicitly loaded by

  BEGIN { require VERSION }

It is not loaded with just a plain require though​:

  require VERSION;

What's the right behavior? I don't expect require ever to do
an implicit import of anything. If I know what its supposed to
do, I can update the use, require, and feature docs.

Perl Info

Flags:
    category=core
    severity=medium

Site configuration information for perl 5.12.1:

Configured by brian at Wed Jun 16 15:54:54 PDT 2010.

Summary of my perl5 (revision 5 version 12 subversion 1) configuration:

  Platform:
    osname=darwin, osvers=9.8.0, archname=darwin-2level
    uname='darwin mimibean.local 9.8.0 darwin kernel version 9.8.0:
wed jul 15 16:55:01 pdt 2009; root:xnu-1228.15.4~1release_i386 i386
i386 '
    config_args='-des -Dprefix=/usr/local/perls/perl-5.12.1'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=undef, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-fno-common -DPERL_DARWIN -no-cpp-precomp
-fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include',
    optimize='-O3',
    cppflags='-no-cpp-precomp -fno-common -DPERL_DARWIN
-no-cpp-precomp -fno-strict-aliasing -pipe -fstack-protector
-I/usr/local/include'
    ccversion='', gccversion='4.0.1 (Apple Inc. build 5490)', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t',
lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='env MACOSX_DEPLOYMENT_TARGET=10.3 cc', ldflags ='
-fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /usr/lib
    libs=-ldbm -ldl -lm -lutil -lc
    perllibs=-ldl -lm -lutil -lc
    libc=/usr/lib/libc.dylib, so=dylib, useshrplib=false, libperl=libperl.a
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=bundle, d_dlsymun=undef, ccdlflags=' '
    cccdlflags=' ', lddlflags=' -bundle -undefined dynamic_lookup
-L/usr/local/lib -fstack-protector'

Locally applied patches:



@INC for perl 5.12.1:
    /usr/local/perls/perl-5.12.1/lib/site_perl/5.12.1/darwin-2level
    /usr/local/perls/perl-5.12.1/lib/site_perl/5.12.1
    /usr/local/perls/perl-5.12.1/lib/5.12.1/darwin-2level
    /usr/local/perls/perl-5.12.1/lib/5.12.1
    .


Environment for perl 5.12.1:
    DYLD_LIBRARY_PATH (unset)
    HOME=/Users/brian
    LANG=en_US
    LANGUAGE (unset)
    LC_ALL=C
    LC_COLLATE=en_US.UTF-8
    LC_CTYPE=en_US.UTF-8
    LC_MESSAGES=en_US.UTF-8
    LC_MONETARY=en_US.UTF-8
    LC_NUMERIC=en_US.UTF-8
    LC_TIME=en_US.UTF-8
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/Users/brian/bin:/usr/local/bin:/opt/local/bin:/Users/brian/TPR/scripts:/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/mysql/bin:/usr/X11R6/bin:/usr/local/teTeX/bin/powerpc-apple-darwin-current:/usr/local/pgsql/bin:/usr/local/gcj/bin:/Library/Frameworks/Python.framework/Versions/Current/bin
    PERL_BADLANG (unset)
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Jul 6, 2010

From @xdg

The feature.pm docs notes that it's implicitly loaded by -E
or use VERSION. However, it's also implicitly loaded by

    BEGIN { require VERSION }

It is not loaded with just a plain require though​:

       require VERSION;

What's the right behavior?

That's a tricky question. Since "use VERSION" is effectively
equivalent to "BEGIN { require VERSION }", they have the same
behavior. On the other hand, I also generally expect "require" to
have no import-like action.

The relevant "if" clause in pp_ctl.c is this​:

  if (PL_compcv && !(cUNOP->op_first->op_private & OPpCONST_NOVER)) {

I don't know know enough of the guts to know how to differentiate
between use and BEGIN+require, but if someone does, then I think the
change is appropriate to make.

-- David

@p5pRT
Copy link
Author

p5pRT commented Jul 6, 2010

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

@p5pRT
Copy link
Author

p5pRT commented Jul 6, 2010

From @briandfoy

On Tue, Jul 6, 2010 at 5​:01 AM, David Golden via RT
<perlbug-followup@​perl.org> wrote​:

The feature.pm docs notes that it's implicitly loaded by -E
or use VERSION. However, it's also implicitly loaded by

    BEGIN { require VERSION }

It is not loaded with just a plain require though​:

       require VERSION;

What's the right behavior?

That's a tricky question.  Since "use VERSION" is effectively
equivalent to "BEGIN { require VERSION }",

It may be effectively the same (meaning that's what actually happens),
but it's not what anyone should expect given that use is explicitly
documented as separate require and import steps when you use it with a
module name.

--
brian d foy <brian.d.foy@​gmail.com>
http​://www.pair.com/~comdog/

@p5pRT
Copy link
Author

p5pRT commented Jul 6, 2010

From ben@morrow.me.uk

Quoth brian.d.foy@​gmail.com (brian d foy)​:

On Tue, Jul 6, 2010 at 5​:01 AM, David Golden via RT
<perlbug-followup@​perl.org> wrote​:

The feature.pm docs notes that it's implicitly loaded by -E
or use VERSION. However, it's also implicitly loaded by

� � BEGIN { require VERSION }

It is not loaded with just a plain require though​:

� � � �require VERSION;

What's the right behavior?

That's a tricky question. �Since "use VERSION" is effectively
equivalent to "BEGIN { require VERSION }",

It may be effectively the same (meaning that's what actually happens),
but it's not what anyone should expect given that use is explicitly
documented as separate require and import steps when you use it with a
module name.

I quite like the idea of BEGIN { require VERSION } being a side-effect-
free way of requesting a version. I would also quite like

  use 5.12 ();

to do the same thing, though I don't know if the parser can handle that.

Ben

@p5pRT
Copy link
Author

p5pRT commented Jul 6, 2010

From @xdg

On Tue, Jul 6, 2010 at 2​:35 PM, Ben Morrow <ben@​morrow.me.uk> wrote​:

I quite like the idea of BEGIN { require VERSION } being a side-effect-
free way of requesting a version. I would also quite like

   use 5.12 ();

to do the same thing, though I don't know if the parser can handle that.

Not easily. It's trivial to make toke.c take it, but the way
features/strict are implemented, the action is in pp_require which
doesn't know about the import list. The right thing to do is to move
feature/strict enablement to be a separate action after the require
operation the same way that a regular import method call is set up by
Perl_utilize. That should also fix the BEGIN { require VERSION }
issue that brian points out.

It's beyond my own skill to do quickly, but I encourage others to take
up the challenge if they have the round tuits for it. :-)

-- David

@p5pRT
Copy link
Author

p5pRT commented Jul 8, 2010

From r.m.barker@btinternet.com

This was discussed here as "perl version checks" on 8 Septermber 2009.
I had a patch that involved separate tokens for "require" and "use", but it was
not used (or required) :)

Robin

@p5pRT
Copy link
Author

p5pRT commented Jul 8, 2010

From zefram@fysh.org

Robin Barker wrote​:

I had a patch that involved separate tokens for "require" and "use",

I think that would be a bad idea. Instead, the special casing that's
currently in pp_require should move into the compilation of "use". So

  use 5.012;

should compile as

  BEGIN {
  require 5.012;
  require feature;
  "feature"->import("​:5.012");
  }

with "require 5.012" doing only the version check.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Jul 8, 2010

From @demerphq

On 8 July 2010 11​:51, Zefram <zefram@​fysh.org> wrote​:

Robin Barker wrote​:

I had a patch that involved separate tokens for "require" and "use",

I think that would be a bad idea.  Instead, the special casing that's
currently in pp_require should move into the compilation of "use".  So

       use 5.012;

should compile as

       BEGIN {
               require 5.012;
               require feature;
               "feature"->import("​:5.012");
       }

with "require 5.012" doing only the version check.

+1

yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

@p5pRT
Copy link
Author

p5pRT commented Jul 8, 2010

From frank.wiegand@gmail.com

2010/7/8 Zefram <zefram@​fysh.org>​:

       use 5.012;

should compile as

       BEGIN {
               require 5.012;
               require feature;
               "feature"->import("​:5.012");
       }

with "require 5.012" doing only the version check.

Great! But feature.pm bundles are like '​:5.12'. So it should be

       BEGIN {
               require 5.012;
               require feature;
               "feature"->import("​:5.12");
       }

Thanks, Frank

@p5pRT
Copy link
Author

p5pRT commented Nov 25, 2010

From @cpansprout

Fixed by 88e9444.

@p5pRT
Copy link
Author

p5pRT commented Nov 25, 2010

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

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