diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 00000000..76b70f89 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,8 @@ + + + + + ./phpunit + + + diff --git a/phpunit/bootstrap.php b/phpunit/bootstrap.php new file mode 100644 index 00000000..9bbaf678 --- /dev/null +++ b/phpunit/bootstrap.php @@ -0,0 +1,9 @@ +addFiles([$file]); + $o->convert($file); + } catch (TestError $exception) { + $this->assertStringContainsString('Duplicate static variable', $exception->getMessage()); + return; + } + $this->fail(); + } +} diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index 0fbae6a9..ccf0396e 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -19,6 +19,7 @@ use PhpAot\Php\Exception\DynamicCall; use PhpAot\Php\Exception\PlaceHolder; use PhpAot\Php\Exception\Redo; use PhpAot\Php\Exception\Skip; +use PhpAot\Php\Exception\TestError; use PhpAot\Php\Generator\ClosureGenerator; use PhpAot\Php\Generator\PlaceHolderGenerator; use PhpAot\Php\Generator\PropertyPromotion; @@ -244,6 +245,7 @@ class CompilerBase extends \PhpAot\Core\Translator protected bool $defaultNativeType = false; protected bool $stubFile = false; protected bool $enableProfiler = false; + protected bool $forTest = false; protected Parser $parser; protected PrettyPrinter $printer; @@ -1567,6 +1569,9 @@ class CompilerBase extends \PhpAot\Core\Translator protected function addStaticVar(string $name, string $type): void { $this->context->staticVars[$name] = $type; + if ($this->hasStaticVar($name)) { + $this->error('Duplicate static variable `$' . $name . '`'); + } $this->addGlobalVar($this->getStaticVarName($name), $type); } @@ -2175,9 +2180,13 @@ class CompilerBase extends \PhpAot\Core\Translator protected function error(string $msg): never { - $this->climate->red("Fatal error: {$msg}"); - debug_print_backtrace(); - exit(255); + if ($this->forTest) { + throw new TestError($msg); + } else { + $this->climate->red("Fatal error: {$msg}"); + debug_print_backtrace(); + exit(255); + } } protected function fatalError(Node $node, string $msg): never diff --git a/src/Php/CompilerTest.php b/src/Php/CompilerTest.php new file mode 100644 index 00000000..488671ce --- /dev/null +++ b/src/Php/CompilerTest.php @@ -0,0 +1,23 @@ +forTest = true; + } + return self::$instance; + } +} diff --git a/src/Php/Exception/TestError.php b/src/Php/Exception/TestError.php new file mode 100644 index 00000000..a107cbc2 --- /dev/null +++ b/src/Php/Exception/TestError.php @@ -0,0 +1,8 @@ +hasCppFileCache($file)) { $this->climate->darkGray('skip: ' . $file . ', cache exists'); @@ -148,6 +149,11 @@ class Translator extends Preprocessor $this->targetName = $name; } + public function addFiles(array $files): void + { + $this->sourceDirs = array_merge($this->sourceDirs, $files); + } + public function getFiles(string $path): array { $realpath = realpath($path); diff --git a/tests/core/lang/static_basic_001.phpt b/tests/core/lang/static_basic_001.phpt new file mode 100644 index 00000000..80802f30 --- /dev/null +++ b/tests/core/lang/static_basic_001.phpt @@ -0,0 +1,87 @@ +--TEST-- +Static keyword - basic tests +--FILE-- + +--EXPECT-- +Same variable used as static and non static. +--------- +0 +10 +--------- +0 +11 +--------- +0 +12 + +Lots of initialisations in the same statement. +------------- Call 0 -------------- +Uninitialized : +Initialized to 10: 10 +Initialized to 20: 20 +Uninitialized : +Initialized to 30: 30 +------------- Call 1 -------------- +Uninitialized : 1 +Initialized to 10: 11 +Initialized to 20: 21 +Uninitialized : 1 +Initialized to 30: 31 +------------- Call 2 -------------- +Uninitialized : 2 +Initialized to 10: 12 +Initialized to 20: 22 +Uninitialized : 2 +Initialized to 30: 32 + +Using static keyword at global scope + 10 +1 11 +2 12