diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2020-10-07 12:13:52 +0200 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2020-10-07 12:13:52 +0200 |
commit | c96d884d9177354b0e0c522423c560f1e20b38c2 (patch) | |
tree | 5689dc4cd6a9cc15cec2f62bedbd754cc3a3fe2b /build | |
parent | 9c710b1d11bb200d75d295cb78143455403315a1 (diff) | |
download | php-git-c96d884d9177354b0e0c522423c560f1e20b38c2.tar.gz |
Avoid namespaced class symbol clashes in gen_stub
Add the namespace prefix (using underscores) to both the arginfo
name and the method declaration name.
Diffstat (limited to 'build')
-rwxr-xr-x | build/gen_stub.php | 82 |
1 files changed, 52 insertions, 30 deletions
diff --git a/build/gen_stub.php b/build/gen_stub.php index f3e84c27fd..e0dd8a2e24 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -357,6 +357,7 @@ interface FunctionOrMethodName { public function getDeclaration(): string; public function getArgInfoName(): string; public function __toString(): string; + public function isMagicMethod(): bool; } class FunctionName implements FunctionOrMethodName { @@ -374,10 +375,6 @@ class FunctionName implements FunctionOrMethodName { return null; } - public function getShortName(): string { - return $this->name->getLast(); - } - public function getNonNamespacedName(): string { if ($this->name->isQualified()) { throw new Exception("Namespaced name not supported here"); @@ -385,8 +382,12 @@ class FunctionName implements FunctionOrMethodName { return $this->name->toString(); } + public function getDeclarationName(): string { + return $this->name->getLast(); + } + public function getDeclaration(): string { - return "ZEND_FUNCTION({$this->name->getLast()});\n"; + return "ZEND_FUNCTION({$this->getDeclarationName()});\n"; } public function getArgInfoName(): string { @@ -397,29 +398,41 @@ class FunctionName implements FunctionOrMethodName { public function __toString(): string { return $this->name->toString(); } + + public function isMagicMethod(): bool { + return false; + } } class MethodName implements FunctionOrMethodName { + /** @var Name */ + private $className; /** @var string */ - public $className; - /** @var string */ - public $name; + public $methodName; - public function __construct(string $className, string $name) { + public function __construct(Name $className, string $methodName) { $this->className = $className; - $this->name = $name; + $this->methodName = $methodName; + } + + public function getDeclarationClassName(): string { + return implode('_', $this->className->parts); } public function getDeclaration(): string { - return "ZEND_METHOD($this->className, $this->name);\n"; + return "ZEND_METHOD({$this->getDeclarationClassName()}, $this->methodName);\n"; } public function getArgInfoName(): string { - return "arginfo_class_{$this->className}_{$this->name}"; + return "arginfo_class_{$this->getDeclarationClassName()}_{$this->methodName}"; } public function __toString(): string { - return "$this->className::$this->name"; + return "$this->className::$this->methodName"; + } + + public function isMagicMethod(): bool { + return strpos($this->methodName, '__') === 0; } } @@ -526,58 +539,63 @@ class FuncInfo { if ($this->alias instanceof MethodName) { return sprintf( "\tZEND_MALIAS(%s, %s, %s, %s, %s)\n", - $this->alias->className, $this->name->name, $this->alias->name, $this->getArgInfoName(), $this->getFlagsAsString() + $this->alias->getDeclarationClassName(), $this->name->methodName, + $this->alias->methodName, $this->getArgInfoName(), $this->getFlagsAsString() ); } else if ($this->alias instanceof FunctionName) { return sprintf( "\tZEND_ME_MAPPING(%s, %s, %s, %s)\n", - $this->name->name, $this->alias->getNonNamespacedName(), + $this->name->methodName, $this->alias->getNonNamespacedName(), $this->getArgInfoName(), $this->getFlagsAsString() ); } else { throw new Error("Cannot happen"); } } else { + $declarationClassName = $this->name->getDeclarationClassName(); if ($this->flags & Class_::MODIFIER_ABSTRACT) { return sprintf( "\tZEND_ABSTRACT_ME_WITH_FLAGS(%s, %s, %s, %s)\n", - $this->name->className, $this->name->name, $this->getArgInfoName(), $this->getFlagsAsString() + $declarationClassName, $this->name->methodName, $this->getArgInfoName(), + $this->getFlagsAsString() ); } return sprintf( "\tZEND_ME(%s, %s, %s, %s)\n", - $this->name->className, $this->name->name, $this->getArgInfoName(), $this->getFlagsAsString() + $declarationClassName, $this->name->methodName, $this->getArgInfoName(), + $this->getFlagsAsString() ); } } else if ($this->name instanceof FunctionName) { $namespace = $this->name->getNamespace(); - $shortName = $this->name->getShortName(); + $declarationName = $this->name->getDeclarationName(); if ($this->alias && $this->isDeprecated) { return sprintf( "\tZEND_DEP_FALIAS(%s, %s, %s)\n", - $shortName, $this->alias->getNonNamespacedName(), $this->getArgInfoName() + $declarationName, $this->alias->getNonNamespacedName(), $this->getArgInfoName() ); } if ($this->alias) { return sprintf( "\tZEND_FALIAS(%s, %s, %s)\n", - $shortName, $this->alias->getNonNamespacedName(), $this->getArgInfoName() + $declarationName, $this->alias->getNonNamespacedName(), $this->getArgInfoName() ); } if ($this->isDeprecated) { - return sprintf("\tZEND_DEP_FE(%s, %s)\n", $shortName, $this->getArgInfoName()); + return sprintf( + "\tZEND_DEP_FE(%s, %s)\n", $declarationName, $this->getArgInfoName()); } if ($namespace) { return sprintf( "\tZEND_NS_FE(\"%s\", %s, %s)\n", - $namespace, $shortName, $this->getArgInfoName()); + $namespace, $declarationName, $this->getArgInfoName()); } else { - return sprintf("\tZEND_FE(%s, %s)\n", $shortName, $this->getArgInfoName()); + return sprintf("\tZEND_FE(%s, %s)\n", $declarationName, $this->getArgInfoName()); } } else { throw new Error("Cannot happen"); @@ -622,12 +640,12 @@ class FuncInfo { } class ClassInfo { - /** @var string */ + /** @var Name */ public $name; /** @var FuncInfo[] */ public $funcInfos; - public function __construct(string $name, array $funcInfos) { + public function __construct(Name $name, array $funcInfos) { $this->name = $name; $this->funcInfos = $funcInfos; } @@ -741,7 +759,7 @@ function parseFunctionLike( if (count($aliasParts) === 1) { $alias = new FunctionName(new Name($aliasParts[0])); } else { - $alias = new MethodName($aliasParts[0], $aliasParts[1]); + $alias = new MethodName(new Name($aliasParts[0]), $aliasParts[1]); } } else if ($tag->name === 'deprecated') { $isDeprecated = true; @@ -814,7 +832,7 @@ function parseFunctionLike( } $returnType = $func->getReturnType(); - if ($returnType === null && !$haveDocReturnType && strpos($name->name, '__') !== 0) { + if ($returnType === null && !$haveDocReturnType && !$name->isMagicMethod()) { throw new Exception("Missing return type for function $name()"); } @@ -906,7 +924,7 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac } if ($stmt instanceof Stmt\ClassLike) { - $className = $stmt->name->toString(); + $className = $stmt->namespacedName; $methodInfos = []; foreach ($stmt->stmts as $classStmt) { $cond = handlePreprocessorConditions($conds, $classStmt); @@ -1160,10 +1178,14 @@ function generateArgInfoCode(FileInfo $fileInfo, string $stubHash): string { } /** @param FuncInfo[] $funcInfos */ -function generateFunctionEntries(?string $className, array $funcInfos): string { +function generateFunctionEntries(?Name $className, array $funcInfos): string { $code = ""; - $functionEntryName = $className ? "class_{$className}_methods" : "ext_functions"; + $functionEntryName = "ext_functions"; + if ($className) { + $underscoreName = implode("_", $className->parts); + $functionEntryName = "class_{$underscoreName}_methods"; + } $code .= "\n\nstatic const zend_function_entry {$functionEntryName}[] = {\n"; $code .= generateCodeWithConditions($funcInfos, "", function (FuncInfo $funcInfo) { |