summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Morrow <ben@morrow.me.uk>2010-08-20 18:35:58 +0100
committerJan Dubois <jand@activestate.com>2010-08-22 10:38:23 -0700
commit324abfcf8bbc42a546afc1cbb06fd4ecd90518bb (patch)
treeb51f0539028157b9d45c46be6ce60f71a101aea7
parent1e8437c2d7ac7eb71adb45330d4ba6a954e94994 (diff)
downloadperl-324abfcf8bbc42a546afc1cbb06fd4ecd90518bb.tar.gz
Fix my $x = 3; $x = length(undef);.
Assignment of length() to a lexical is optimized by passing the assigned-to variable as TARG, avoiding a pp_padsv and pp_sassign. 9f621b which changed length(undef) to return undef didn't take this into account, and used SETs (which doesn't set TARG), so the code above left $x == 3. (cherry picked from commit d88e091f660036722622a815efa9ef3779605ea6) (but hand-edited to adjust the test count)
-rw-r--r--pp.c9
-rw-r--r--t/op/length.t17
2 files changed, 22 insertions, 4 deletions
diff --git a/pp.c b/pp.c
index df8f048b2e..09d03661ee 100644
--- a/pp.c
+++ b/pp.c
@@ -3056,8 +3056,10 @@ PP(pp_length)
= sv_2pv_flags(sv, &len,
SV_UNDEF_RETURNS_NULL|SV_CONST_RETURN|SV_GMAGIC);
- if (!p)
- SETs(&PL_sv_undef);
+ if (!p) {
+ sv_setsv(TARG, &PL_sv_undef);
+ SETTARG;
+ }
else if (DO_UTF8(sv)) {
SETi(utf8_length((U8*)p, (U8*)p + len));
}
@@ -3070,7 +3072,8 @@ PP(pp_length)
else
SETi(sv_len(sv));
} else {
- SETs(&PL_sv_undef);
+ sv_setsv_nomg(TARG, &PL_sv_undef);
+ SETTARG;
}
RETURN;
}
diff --git a/t/op/length.t b/t/op/length.t
index eb357203ec..8e442dc96e 100644
--- a/t/op/length.t
+++ b/t/op/length.t
@@ -6,7 +6,7 @@ BEGIN {
@INC = '../lib';
}
-plan (tests => 28);
+plan (tests => 34);
print "not " unless length("") == 0;
print "ok 1\n";
@@ -193,6 +193,21 @@ my $uo = bless [], 'U';
is(length($uo), undef, "Length of overloaded reference");
+my $ul = 3;
+is(($ul = length(undef)), undef,
+ "Returned length of undef with result in TARG");
+is($ul, undef, "Assigned length of undef with result in TARG");
+
+$ul = 3;
+is(($ul = length($u)), undef,
+ "Returned length of tied undef with result in TARG");
+is($ul, undef, "Assigned length of tied undef with result in TARG");
+
+$ul = 3;
+is(($ul = length($uo)), undef,
+ "Returned length of overloaded undef with result in TARG");
+is($ul, undef, "Assigned length of overloaded undef with result in TARG");
+
# ok(!defined $uo); Turns you can't test this. FIXME for pp_defined?
is($warnings, 0, "There were no warnings");