fix: reject unsupported Decimal round modes

master
韩天峰 2 days ago
parent 4b72242749
commit 643e49d56e
  1. 14
      phpunit/code/round-decimal-native-path.php
  2. 24
      phpunit/src/NegativeCompatibilityTest.php
  3. 7
      phpunit/src/RoundModeTest.php
  4. 7
      src/Optimizer/FuncCallOptimizer.php

@ -0,0 +1,14 @@
<?php
/**
* This file is part of TypePHP(AOT).
*
* @link https://www.swoole.com/aot/
* @contact service@swoole.com
*/
function main(): void
{
$decimal = std::decimal('2.567');
$whole = round($decimal);
$precise = round($decimal, 2);
}

@ -145,6 +145,30 @@ function main(): void
PHP,
];
yield 'Decimal round mode' => [
'convert',
'round() with Decimal supports at most 2 arguments',
<<<'PHP'
<?php
function main(): void
{
round(std::decimal('2.5'), 0, PHP_ROUND_HALF_DOWN); // @diagnostic
}
PHP,
];
yield 'round excessive arguments with Decimal' => [
'convert',
'round() expects at most 3 argument(s), 4 given',
<<<'PHP'
<?php
function main(): void
{
round(std::decimal('2.5'), 0, PHP_ROUND_HALF_DOWN, 4); // @diagnostic
}
PHP,
];
yield 'break level exceeds enclosing depth' => [
'convert',
"Cannot 'break' 2 levels",

@ -56,6 +56,13 @@ class RoundModeTest extends TestCase
self::assertSame(2, substr_count($cpp, 'php::fn::round('));
}
public function testDecimalCallsWithoutAModeKeepTheDecimalFastPath(): void
{
$cpp = $this->compileToCpp('round-decimal-native-path.php');
self::assertSame(2, substr_count($cpp, 'php::Decimal::round('));
}
private function compileToCpp(string $file): string
{
global $translator;

@ -1015,6 +1015,13 @@ trait FuncCallOptimizer
}
$type = $this->detectTypeOfExpr($e->args[0]->value);
if ($type === Type::DECIMAL) {
// Decimal is a PHPX Box resource at the Zend boundary, so the
// generic round() function cannot implement its rounding mode.
// Reject the unsupported extension form instead of silently
// dropping the explicit argument or producing a resource TypeError.
if (count($e->args) > 2) {
$this->fatalError($e, 'round() with Decimal supports at most 2 arguments');
}
$a0 = $this->parseExpr($e->args[0]->value);
if (count($e->args) >= 2) {
return 'php::Decimal::round(' . $a0 . ', ' . $this->parseExpr($e->args[1]->value) . ')';

Loading…
Cancel
Save