fix(optimizer): fold function aliases using resolved names (#88)

master
yavon007 1 month ago committed by GitHub
parent cbd100f906
commit 5488805baf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 25
      src/Optimizer/FuncCallOptimizer.php
  2. 37
      tests/compiler/namespace/use-function-alias-constant-folding.phpt

@ -505,7 +505,7 @@ trait FuncCallOptimizer
} }
if (isset($config['constFold'])) { if (isset($config['constFold'])) {
$folded = $this->tryConstFold($config['constFold'], $config['constFoldExtra'] ?? null, $expr); $folded = $this->tryConstFold($name, $config['constFold'], $config['constFoldExtra'] ?? null, $expr);
if ($folded !== false) { if ($folded !== false) {
return $folded; return $folded;
} }
@ -896,13 +896,13 @@ trait FuncCallOptimizer
// Constant folding // Constant folding
// ========================================================================= // =========================================================================
protected function tryConstFold(int $rule, mixed $extra, Node\Expr\FuncCall $expr): string|false protected function tryConstFold(string $name, int $rule, mixed $extra, Node\Expr\FuncCall $expr): string|false
{ {
return match ($rule) { return match ($rule) {
self::FOLD_STRING_LEN => $this->doFoldStringLen($expr), self::FOLD_STRING_LEN => $this->doFoldStringLen($expr),
self::FOLD_STRING_CASE => $this->doFoldStringCase($expr), self::FOLD_STRING_CASE => $this->doFoldStringCase($name, $expr),
self::FOLD_CMP2 => $this->doFoldCmp2($expr), self::FOLD_CMP2 => $this->doFoldCmp2($name, $expr),
self::FOLD_CMP3 => $this->doFoldCmp3($expr), self::FOLD_CMP3 => $this->doFoldCmp3($name, $expr),
self::FOLD_COUNT_LITERAL => $this->doFoldCountLiteral($expr), self::FOLD_COUNT_LITERAL => $this->doFoldCountLiteral($expr),
self::FOLD_KNOWN_CLASS => $this->doFoldKnownClass($expr), self::FOLD_KNOWN_CLASS => $this->doFoldKnownClass($expr),
self::FOLD_KNOWN_CONSTANT => $this->doFoldKnownConstant($expr), self::FOLD_KNOWN_CONSTANT => $this->doFoldKnownConstant($expr),
@ -919,32 +919,30 @@ trait FuncCallOptimizer
: false; : false;
} }
protected function doFoldStringCase(Node\Expr\FuncCall $expr): string|false protected function doFoldStringCase(string $name, Node\Expr\FuncCall $expr): string|false
{ {
$arg = $expr->args[0]->value; $arg = $expr->args[0]->value;
if (!$this->isScalarString($arg)) { if (!$this->isScalarString($arg)) {
return false; return false;
} }
$func = $expr->name instanceof Node\Name ? $expr->name->toLowerString() : ''; $val = $name === 'strtoupper' ? strtoupper($arg->value) : strtolower($arg->value);
$val = $func === 'strtoupper' ? strtoupper($arg->value) : strtolower($arg->value);
return $this->getLiteralString($val); return $this->getLiteralString($val);
} }
protected function doFoldCmp2(Node\Expr\FuncCall $expr): string|false protected function doFoldCmp2(string $name, Node\Expr\FuncCall $expr): string|false
{ {
$a0 = $expr->args[0]->value; $a0 = $expr->args[0]->value;
$a1 = $expr->args[1]->value; $a1 = $expr->args[1]->value;
if (!$this->isScalarString($a0) || !$this->isScalarString($a1)) { if (!$this->isScalarString($a0) || !$this->isScalarString($a1)) {
return false; return false;
} }
$func = $expr->name instanceof Node\Name ? $expr->name->toLowerString() : ''; $result = $name === 'strcasecmp'
$result = $func === 'strcasecmp'
? strcasecmp($a0->value, $a1->value) ? strcasecmp($a0->value, $a1->value)
: strcmp($a0->value, $a1->value); : strcmp($a0->value, $a1->value);
return $result . $this->getPlatform()->getIntegerLiteralSuffix(); return $result . $this->getPlatform()->getIntegerLiteralSuffix();
} }
protected function doFoldCmp3(Node\Expr\FuncCall $expr): string|false protected function doFoldCmp3(string $name, Node\Expr\FuncCall $expr): string|false
{ {
$a0 = $expr->args[0]->value; $a0 = $expr->args[0]->value;
$a1 = $expr->args[1]->value; $a1 = $expr->args[1]->value;
@ -952,8 +950,7 @@ trait FuncCallOptimizer
if (!$this->isScalarString($a0) || !$this->isScalarString($a1) || !$this->isScalarInt($a2)) { if (!$this->isScalarString($a0) || !$this->isScalarString($a1) || !$this->isScalarInt($a2)) {
return false; return false;
} }
$func = $expr->name instanceof Node\Name ? $expr->name->toLowerString() : ''; $result = $name === 'strncasecmp'
$result = $func === 'strncasecmp'
? strncasecmp($a0->value, $a1->value, (int) $a2->value) ? strncasecmp($a0->value, $a1->value, (int) $a2->value)
: strncmp($a0->value, $a1->value, (int) $a2->value); : strncmp($a0->value, $a1->value, (int) $a2->value);
return $result . $this->getPlatform()->getIntegerLiteralSuffix(); return $result . $this->getPlatform()->getIntegerLiteralSuffix();

@ -0,0 +1,37 @@
--TEST--
Constant folding uses resolved function names for imported aliases
--FILE--
<?php
namespace FunctionAliasFolding {
use function strtoupper as upper;
use function strtolower as strtoupper;
use function strcasecmp as compare;
use function strcmp as strcasecmp;
use function strncasecmp as compare_prefix;
use function strncmp as strncasecmp;
function run(): void
{
var_dump(upper('MiXeD'));
var_dump(strtoupper('MiXeD'));
var_dump(compare('A', 'a'));
var_dump(strcasecmp('A', 'a') !== 0);
var_dump(compare_prefix('A', 'a', 1));
var_dump(strncasecmp('A', 'a', 1) !== 0);
}
}
namespace {
function main(): void
{
FunctionAliasFolding\run();
}
}
?>
--EXPECT--
string(5) "MIXED"
string(5) "mixed"
int(0)
bool(true)
int(0)
bool(true)
Loading…
Cancel
Save