commit
6543dfccce
21 changed files with 441 additions and 15 deletions
@ -0,0 +1,7 @@ |
||||
<?php |
||||
|
||||
function main(): void |
||||
{ |
||||
$value = 10; |
||||
$value /= 0; |
||||
} |
||||
@ -0,0 +1,7 @@ |
||||
<?php |
||||
|
||||
function main(): void |
||||
{ |
||||
$value = 10; |
||||
$value %= 0; |
||||
} |
||||
@ -0,0 +1,6 @@ |
||||
<?php |
||||
|
||||
function main(): void |
||||
{ |
||||
var_dump(1.0 / 0.0); |
||||
} |
||||
@ -0,0 +1,6 @@ |
||||
<?php |
||||
|
||||
function main(): void |
||||
{ |
||||
var_dump(10 / 0); |
||||
} |
||||
@ -0,0 +1,6 @@ |
||||
<?php |
||||
|
||||
function main(): void |
||||
{ |
||||
var_dump(10 / '0.00'); |
||||
} |
||||
@ -0,0 +1,6 @@ |
||||
<?php |
||||
|
||||
function main(): void |
||||
{ |
||||
var_dump(10 % 0); |
||||
} |
||||
@ -0,0 +1,76 @@ |
||||
<?php |
||||
|
||||
namespace NativePropSource { |
||||
use native_types; |
||||
|
||||
class Target |
||||
{ |
||||
public static int $count = 1; |
||||
public int $value = 2; |
||||
protected int $protectedValue = 3; |
||||
} |
||||
} |
||||
|
||||
namespace NativePropSource\Target { |
||||
use native_types; |
||||
use NativePropSource\Target; |
||||
|
||||
class Child extends Target |
||||
{ |
||||
public function readThis(): int |
||||
{ |
||||
return $this->value; |
||||
} |
||||
|
||||
public function readInheritedProtected(Target $target): int |
||||
{ |
||||
return $target->protectedValue; |
||||
} |
||||
|
||||
public static function readSelf(): int |
||||
{ |
||||
return self::$count; |
||||
} |
||||
|
||||
public static function readStatic(): int |
||||
{ |
||||
return static::$count; |
||||
} |
||||
|
||||
public static function writeStatic(int $value): int |
||||
{ |
||||
static::$count = $value; |
||||
return static::$count; |
||||
} |
||||
|
||||
public static function readParent(): int |
||||
{ |
||||
return parent::$count; |
||||
} |
||||
} |
||||
|
||||
function readObject(): int |
||||
{ |
||||
$target = new Target(); |
||||
return $target->value; |
||||
} |
||||
|
||||
function readStaticByUse(): int |
||||
{ |
||||
return Target::$count; |
||||
} |
||||
} |
||||
|
||||
namespace { |
||||
function main(): void |
||||
{ |
||||
$child = new \NativePropSource\Target\Child(); |
||||
var_dump($child->readThis()); |
||||
var_dump(\NativePropSource\Target\readObject()); |
||||
var_dump(\NativePropSource\Target\readStaticByUse()); |
||||
var_dump(\NativePropSource\Target\Child::readSelf()); |
||||
var_dump(\NativePropSource\Target\Child::readStatic()); |
||||
var_dump(\NativePropSource\Target\Child::writeStatic(4)); |
||||
var_dump(\NativePropSource\Target\Child::readParent()); |
||||
} |
||||
} |
||||
@ -0,0 +1,20 @@ |
||||
<?php |
||||
|
||||
use native_types; |
||||
|
||||
class NativePrivateOwner |
||||
{ |
||||
private int $value = 1; |
||||
} |
||||
|
||||
class NativePrivateReader |
||||
{ |
||||
public function read(NativePrivateOwner $owner): int |
||||
{ |
||||
return $owner->value; |
||||
} |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
} |
||||
@ -0,0 +1,20 @@ |
||||
<?php |
||||
|
||||
use native_types; |
||||
|
||||
class NativeProtectedOwner |
||||
{ |
||||
protected int $value = 1; |
||||
} |
||||
|
||||
class NativeProtectedReader |
||||
{ |
||||
public function read(NativeProtectedOwner $owner): int |
||||
{ |
||||
return $owner->value; |
||||
} |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
} |
||||
@ -0,0 +1,54 @@ |
||||
<?php |
||||
|
||||
use PhpAot\Php\CompilerTest; |
||||
use PhpAot\Php\Exception\TestError; |
||||
|
||||
class NativePropertyTest extends \BaseTest |
||||
{ |
||||
private function compile(string $file): string |
||||
{ |
||||
global $translator; |
||||
|
||||
$compiler = CompilerTest::create(ROOT_PATH); |
||||
$translator = $compiler; |
||||
$testFile = __DIR__ . '/../code/' . $file; |
||||
$compiler->addFiles([$testFile]); |
||||
$compiler->prepareFile($testFile); |
||||
$compiler->convertFile($testFile); |
||||
|
||||
$this->addToAssertionCount(1); |
||||
return ROOT_PATH . '/build/phpunit/code/' . basename($file, '.php') . '.cc'; |
||||
} |
||||
|
||||
public function testFindNativePropertyUsesFullClassNameAcrossBranches(): void |
||||
{ |
||||
try { |
||||
$this->compile('native-property-full-name.php'); |
||||
} catch (TestError $e) { |
||||
$this->fail($e->getMessage()); |
||||
} |
||||
} |
||||
|
||||
public function testStaticStaticPropertyUsesDynamicCalledClassPath(): void |
||||
{ |
||||
try { |
||||
$outputFile = $this->compile('native-property-full-name.php'); |
||||
} catch (TestError $e) { |
||||
$this->fail($e->getMessage()); |
||||
} |
||||
|
||||
$code = file_get_contents($outputFile); |
||||
$this->assertStringContainsString('php::getStaticProperty(php_get_called_class(this_), "count")', $code); |
||||
$this->assertStringContainsString('php::getStaticProperty(php_get_called_class(this_), "count") = php::toInt(value)', $code); |
||||
} |
||||
|
||||
public function testCannotAccessPrivateNativePropertyFromUnrelatedClass(): void |
||||
{ |
||||
$this->exec('Cannot access private property `value` of class `NativePrivateOwner`', 'native-property-private-other-class.php'); |
||||
} |
||||
|
||||
public function testCannotAccessProtectedNativePropertyFromUnrelatedClass(): void |
||||
{ |
||||
$this->exec('Cannot access protected property `value` of class `NativeProtectedOwner`', 'native-property-protected-unrelated-class.php'); |
||||
} |
||||
} |
||||
@ -0,0 +1,34 @@ |
||||
<?php |
||||
|
||||
class OperatorTest extends \BaseTest |
||||
{ |
||||
public function testLiteralIntDivideByZeroDoesNotCompile(): void |
||||
{ |
||||
$this->exec('Cannot divide or modulo by zero', 'divide-by-zero-int.php'); |
||||
} |
||||
|
||||
public function testLiteralFloatDivideByZeroDoesNotCompile(): void |
||||
{ |
||||
$this->exec('Cannot divide or modulo by zero', 'divide-by-zero-float.php'); |
||||
} |
||||
|
||||
public function testLiteralStringDivideByZeroDoesNotCompile(): void |
||||
{ |
||||
$this->exec('Cannot divide or modulo by zero', 'divide-by-zero-string.php'); |
||||
} |
||||
|
||||
public function testLiteralModuloByZeroDoesNotCompile(): void |
||||
{ |
||||
$this->exec('Cannot divide or modulo by zero', 'modulo-by-zero-int.php'); |
||||
} |
||||
|
||||
public function testLiteralDivideAssignByZeroDoesNotCompile(): void |
||||
{ |
||||
$this->exec('Cannot divide or modulo by zero', 'assign-divide-by-zero.php'); |
||||
} |
||||
|
||||
public function testLiteralModuloAssignByZeroDoesNotCompile(): void |
||||
{ |
||||
$this->exec('Cannot divide or modulo by zero', 'assign-modulo-by-zero.php'); |
||||
} |
||||
} |
||||
@ -0,0 +1,15 @@ |
||||
--TEST-- |
||||
Constant with the same name (case-insensitive) resolve independently |
||||
--FILE-- |
||||
<?php |
||||
const a = 123; |
||||
const A = 456; |
||||
|
||||
function main(): void |
||||
{ |
||||
var_dump(a, A); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
int(123) |
||||
int(456) |
||||
@ -0,0 +1,15 @@ |
||||
--TEST-- |
||||
Constant and variable with the same name (case-insensitive) resolve independently |
||||
--FILE-- |
||||
<?php |
||||
const a = 123; |
||||
|
||||
function main(): void |
||||
{ |
||||
$a = 456; |
||||
var_dump(a, $a); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
int(123) |
||||
int(456) |
||||
@ -0,0 +1,52 @@ |
||||
--TEST-- |
||||
use class A\B (without alias) inside namespace A\B, call B::$v |
||||
--FILE-- |
||||
<?php |
||||
namespace A { |
||||
class B |
||||
{ |
||||
public static $v = 123; |
||||
} |
||||
} |
||||
|
||||
namespace A\B { |
||||
|
||||
use A\B; |
||||
|
||||
function testProp(): int { |
||||
return B::$v; |
||||
} |
||||
|
||||
class C extends B { |
||||
public static function testSelf(): int |
||||
{ |
||||
return self::$v; |
||||
} |
||||
|
||||
public static function testStatic(): int |
||||
{ |
||||
return static::$v; |
||||
} |
||||
|
||||
public static function testParent(): int |
||||
{ |
||||
return parent::$v; |
||||
} |
||||
} |
||||
} |
||||
|
||||
namespace { |
||||
function main() { |
||||
var_dump(\A\B\testProp()); |
||||
var_dump(\A\B\C::testSelf()); |
||||
var_dump(\A\B\C::testStatic()); |
||||
var_dump(\A\B\C::testParent()); |
||||
} |
||||
} |
||||
|
||||
?> |
||||
--EXPECT-- |
||||
int(123) |
||||
int(123) |
||||
int(123) |
||||
int(123) |
||||
@ -0,0 +1,39 @@ |
||||
--TEST-- |
||||
Static native properties use late static binding for static::$prop |
||||
--FILE-- |
||||
<?php |
||||
use native_types; |
||||
|
||||
class StaticPropBase { |
||||
public static int $v = 1; |
||||
|
||||
public static function get(): int { |
||||
return static::$v; |
||||
} |
||||
|
||||
public static function set(int $v): void { |
||||
static::$v = $v; |
||||
} |
||||
} |
||||
|
||||
class StaticPropChild extends StaticPropBase { |
||||
public static int $v = 2; |
||||
} |
||||
|
||||
function main(): void { |
||||
var_dump(StaticPropBase::get()); |
||||
var_dump(StaticPropChild::get()); |
||||
|
||||
StaticPropChild::set(9); |
||||
|
||||
var_dump(StaticPropBase::$v); |
||||
var_dump(StaticPropChild::$v); |
||||
var_dump(StaticPropChild::get()); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
int(1) |
||||
int(2) |
||||
int(1) |
||||
int(9) |
||||
int(9) |
||||
Loading…
Reference in new issue