fix(optimizer): parenthesize null-check expressions

pull/43/head
韩天峰 4 weeks ago
parent 61388a9bd1
commit d34baca7dc
  1. 17
      phpunit/code/assign-not-identical-null.php
  2. 17
      phpunit/src/OperatorTest.php
  3. 2
      src/Optimizer/FuncCallOptimizer.php
  4. 5
      src/Parser/BinaryOpTrait.php

@ -0,0 +1,17 @@
<?php
class AssignedValueNullCheck
{
public function check(): bool
{
if (!is_null($error = error_get_last()) && $this->isFatal($error['type'])) {
return true;
}
return false;
}
private function isFatal(int $type): bool
{
return $type > 0;
}
}

@ -22,6 +22,23 @@ class OperatorTest extends \BaseTest
$this->assertStringContainsString('php::same(php::true_, value)', $cpp);
}
public function testAssignedValueNotIdenticalToNullIsParenthesized(): void
{
global $translator;
$compiler = \TypePhp\CompilerTest::create(ROOT_PATH);
$translator = $compiler;
$testFile = __DIR__ . '/../code/assign-not-identical-null.php';
$compiler->addFiles([$testFile]);
$compiler->prepareFile($testFile);
$cppFile = $compiler->convertFile($testFile);
$cpp = file_get_contents($cppFile);
$this->assertMatchesRegularExpression(
'/!\(\(error = php::call\([^\n]+\)\)\.isNull\(\)\)/',
$cpp,
);
}
public function testLiteralIntDivideByZeroDoesNotCompile(): void
{
$this->exec('Cannot divide or modulo by zero', 'divide-by-zero-int.php');

@ -612,7 +612,7 @@ trait FuncCallOptimizer
protected function genIsNull(string $n, Node\Expr\FuncCall $e, array $c): string
{
return $this->parseIdentifier($e->args[0]->value) . '.isNull()';
return '(' . $this->parseExprAsValue($e->args[0]->value) . ').isNull()';
}
protected function genIsCallable(string $n, Node\Expr\FuncCall $e, array $c): string|false

@ -388,7 +388,10 @@ trait BinaryOpTrait
$left = $this->parseCompareExpr($expr->left);
$right = $this->parseCompareExpr($expr->right);
if ($right === 'nullptr') {
return $left . '.isNull()';
// The left operand may itself be an assignment or another compound
// expression. Parenthesize it before invoking Variant::isNull(), or
// C++ binds the member access to the assignment's RHS instead.
return '(' . $left . ').isNull()';
}
if ($optimized = $this->optimizeIdenticalOp($expr->left, $expr->right, $left, $right)) {
return $optimized;

Loading…
Cancel
Save