]> git.vpit.fr Git - perl/modules/Scope-Upper.git/commitdiff
Compatibility fix for perl 5.13.10 rt64997
authorVincent Pit <vince@profvince.com>
Sat, 26 Feb 2011 23:03:30 +0000 (00:03 +0100)
committerVincent Pit <vince@profvince.com>
Sat, 26 Feb 2011 23:05:26 +0000 (00:05 +0100)
This solves RT #64997.

Upper.xs
t/20-localize-target.t

index 682aa879f12664483e6d157a5aaeb5d81d32e3b1..999eabaed83fc506825a7dc6659a6934c3e76c0b 100644 (file)
--- a/Upper.xs
+++ b/Upper.xs
@@ -316,6 +316,45 @@ STATIC void su_save_helem(pTHX_ HV *hv, SV *keysv, SV *val) {
  }
 }
 
+/* ... Saving code slots from a glob ....................................... */
+
+#if SU_HAS_PERL(5, 13, 10)
+
+/* Since perl 5.13.10, GvCV() is only a rvalue so we no longer can store a
+ * pointer to the gvcv member of the gv. */
+
+typedef struct {
+ GV *gv;
+ CV *old_cv;
+} su_save_gvcv_ud;
+
+STATIC void su_restore_gvcv(pTHX_ void *ud_) {
+ su_save_gvcv_ud *ud = ud_;
+
+ GvCV_set(ud->gv, ud->old_cv);
+
+ Safefree(ud);
+}
+
+STATIC void su_save_gvcv(pTHX_ GV *gv) {
+#define su_save_gvcv(gv) su_save_gvcv(aTHX_ (gv))
+ su_save_gvcv_ud *ud;
+
+ Newx(ud, 1, su_save_gvcv_ud);
+ ud->gv     = gv;
+ ud->old_cv = GvCV(gv);
+
+ GvCV_set(gv, NULL);
+
+ SAVEDESTRUCTOR_X(su_restore_gvcv, ud);
+}
+
+#else
+
+#define su_save_gvcv(gv) SAVESPTR(GvCV(gv)), GvCV_set((gv), NULL)
+
+#endif
+
 /* --- Actions ------------------------------------------------------------- */
 
 typedef struct {
@@ -549,8 +588,7 @@ STATIC void su_localize(pTHX_ void *ud_) {
    save_gp(gv, 1); /* hide previous entry in symtab */
    break;
   case SVt_PVCV:
-   SAVESPTR(GvCV(gv));
-   GvCV_set(gv, NULL);
+   su_save_gvcv(gv);
    break;
   default:
    gv = (GV *) save_scalar(gv);
index 9bd7a3885fcc6376122bd87515a4ef96dda79f6c..40d8f65b160c171afe5cf0d0bcd32e66f32af482 100644 (file)
@@ -3,7 +3,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 50 + 4;
+use Test::More tests => 61 + 4;
 
 use Scope::Upper qw/localize UP HERE/;
 
@@ -255,6 +255,45 @@ my $xh = { a => 5, c => 7 };
  is foo(), 8, 'localize "&foo", sub { 8 } => UP [ok]';
 }
 
+{
+ local *foo = sub { 'a' };
+ {
+  {
+   localize *foo, sub { 'b' } => UP;
+   is foo(), 'a', 'localize *foo, sub { "b" } => UP [not yet 1]';
+   {
+    no warnings 'redefine';
+    local *foo = sub { 'c' };
+    is foo(), 'c', 'localize *foo, sub { "b" } => UP [localized 1]';
+   }
+   is foo(), 'a', 'localize *foo, sub { "b" } => UP [not yet 2]';
+  }
+  is foo(), 'b', 'localize *foo, sub { "b" } => UP [ok 1]';
+  {
+   no warnings 'redefine';
+   local *foo = sub { 'd' };
+   is foo(), 'd', 'localize *foo, sub { "b" } => UP [localized 2]';
+  }
+  is foo(), 'b', 'localize *foo, sub { "b" } => UP [ok 2]';
+ }
+ is foo(), 'a', 'localize *foo, sub { "b" } => UP [end]';
+}
+
+{
+ local *foo = sub { 'x' };
+ {
+  {
+   localize *foo, sub { 'y' } => UP;
+   is foo(), 'x', 'localize *foo, sub { "y" } => UP [not yet]';
+  }
+  is foo(), 'y', 'localize *foo, sub { "y" } => UP [ok]';
+  no warnings 'redefine';
+  *foo = sub { 'z' };
+  is foo(), 'z', 'localize *foo, sub { "y" } => UP [replaced]';
+ }
+ is foo(), 'x', 'localize *foo, sub { "y" } => UP [end]';
+}
+
 # Invalid
 
 sub invalid_ref { qr/^Invalid \Q$_[0]\E reference as the localization target/ }