Skip to content

Commit

Permalink
constant folding shouldn't change return value of while [perl #73618]
Browse files Browse the repository at this point in the history
If the expression in while (EXPR) is a false constant, just return that
constant expression rather than OP_NULL during optimization.

Doesn't handle until loops yet, because "until (1)" is converted to
"while (!1)" by the parser, and so "!1" is already constant-folded to ''
by the time the while loop optree is constructed. Not sure what to do
about that.
  • Loading branch information
doy committed Jul 3, 2012
1 parent d68ce4a commit 317f3b6
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 3 deletions.
3 changes: 1 addition & 2 deletions op.c
Expand Up @@ -6279,9 +6279,8 @@ Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop,
scalar(listop);
o = new_logop(OP_AND, 0, &expr, &listop);
if (o == expr && o->op_type == OP_CONST && !SvTRUE(cSVOPo->op_sv)) {
op_free(expr); /* oops, it's a while (0) */
op_free((OP*)loop);
return NULL; /* listop already freed by new_logop */
return expr; /* listop already freed by new_logop */
}
if (listop)
((LISTOP*)listop)->op_last->op_next =
Expand Down
63 changes: 62 additions & 1 deletion t/op/loopctl.t
Expand Up @@ -36,7 +36,7 @@ BEGIN {
}

require "test.pl";
plan( tests => 55 );
plan( tests => 61 );

my $ok;

Expand Down Expand Up @@ -1006,3 +1006,64 @@ cmp_ok($ok,'==',1,'dynamically scoped');
}
ok(!$fail, "perl 112316: Labels with the same prefix don't get mixed up.");
}

# [perl #73618]
{
sub foo_73618_0 {
while (0) { }
}
sub bar_73618_0 {
my $i = 0;
while ($i) { }
}
sub foo_73618_undef {
while (undef) { }
}
sub bar_73618_undef {
my $i = undef;
while ($i) { }
}
sub foo_73618_emptystring {
while ("") { }
}
sub bar_73618_emptystring {
my $i = "";
while ($i) { }
}
sub foo_73618_0float {
while (0.0) { }
}
sub bar_73618_0float {
my $i = 0.0;
while ($i) { }
}
sub foo_73618_0string {
while ("0") { }
}
sub bar_73618_0string {
my $i = "0";
while ($i) { }
}
sub foo_73618_until {
until (1) { }
}
sub bar_73618_until {
my $i = 1;
until ($i) { }
}

is(scalar(foo_73618_0()), scalar(bar_73618_0()),
"constant optimization doesn't change return value");
is(scalar(foo_73618_undef()), scalar(bar_73618_undef()),
"constant optimization doesn't change return value");
is(scalar(foo_73618_emptystring()), scalar(bar_73618_emptystring()),
"constant optimization doesn't change return value");
is(scalar(foo_73618_0float()), scalar(bar_73618_0float()),
"constant optimization doesn't change return value");
is(scalar(foo_73618_0string()), scalar(bar_73618_0string()),
"constant optimization doesn't change return value");
{ local $TODO = "until is still wrongly optimized";
is(scalar(foo_73618_until()), scalar(bar_73618_until()),
"constant optimization doesn't change return value");
}
}

0 comments on commit 317f3b6

Please sign in to comment.