From 13bb8bbd31690eb1a26a5a5b4cbd665034ff560f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Mon, 26 Dec 2022 22:47:36 +0100 Subject: [PATCH 1/3] Fix GH-9967 Add support for generating custom function, class const, and property attributes in stubs --- Zend/zend_attributes_arginfo.h | 48 ++-- Zend/zend_builtin_functions_arginfo.h | 6 +- Zend/zend_exceptions_arginfo.h | 8 +- build/gen_stub.php | 270 +++++++++++++++++----- ext/dom/php_dom_arginfo.h | 2 +- ext/oci8/oci8_arginfo.h | 12 +- ext/pdo/pdo_arginfo.h | 2 +- ext/soap/soap_arginfo.h | 10 +- ext/standard/basic_functions_arginfo.h | 6 +- ext/standard/user_filters_arginfo.h | 2 +- ext/zend_test/test.stub.php | 10 +- ext/zend_test/test_arginfo.h | 78 +++++-- ext/zend_test/tests/gen_stub_test_03.phpt | 33 +++ 13 files changed, 355 insertions(+), 132 deletions(-) create mode 100644 ext/zend_test/tests/gen_stub_test_03.phpt diff --git a/Zend/zend_attributes_arginfo.h b/Zend/zend_attributes_arginfo.h index 3bcdcd707410c..3873c903913eb 100644 --- a/Zend/zend_attributes_arginfo.h +++ b/Zend/zend_attributes_arginfo.h @@ -125,12 +125,12 @@ static zend_class_entry *register_class_Attribute(void) zend_declare_typed_property(class_entry, property_flags_name, &property_flags_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); zend_string_release(property_flags_name); - zend_string *attribute_name_Attribute_class_Attribute = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); - zend_attribute *attribute_Attribute_class_Attribute = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_Attribute, 1); - zend_string_release(attribute_name_Attribute_class_Attribute); - zval attribute_Attribute_class_Attribute_arg0; - ZVAL_LONG(&attribute_Attribute_class_Attribute_arg0, ZEND_ATTRIBUTE_TARGET_CLASS); - ZVAL_COPY_VALUE(&attribute_Attribute_class_Attribute->args[0].value, &attribute_Attribute_class_Attribute_arg0); + zend_string *attribute_name_Attribute_class_Attribute_1 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_Attribute_1 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_Attribute_1, 1); + zend_string_release(attribute_name_Attribute_class_Attribute_1); + zval attribute_Attribute_class_Attribute_1_arg0; + ZVAL_LONG(&attribute_Attribute_class_Attribute_1_arg0, ZEND_ATTRIBUTE_TARGET_CLASS); + ZVAL_COPY_VALUE(&attribute_Attribute_class_Attribute_1->args[0].value, &attribute_Attribute_class_Attribute_1_arg0); return class_entry; } @@ -143,12 +143,12 @@ static zend_class_entry *register_class_ReturnTypeWillChange(void) class_entry = zend_register_internal_class_ex(&ce, NULL); class_entry->ce_flags |= ZEND_ACC_FINAL; - zend_string *attribute_name_Attribute_class_ReturnTypeWillChange = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); - zend_attribute *attribute_Attribute_class_ReturnTypeWillChange = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ReturnTypeWillChange, 1); - zend_string_release(attribute_name_Attribute_class_ReturnTypeWillChange); - zval attribute_Attribute_class_ReturnTypeWillChange_arg0; - ZVAL_LONG(&attribute_Attribute_class_ReturnTypeWillChange_arg0, ZEND_ATTRIBUTE_TARGET_METHOD); - ZVAL_COPY_VALUE(&attribute_Attribute_class_ReturnTypeWillChange->args[0].value, &attribute_Attribute_class_ReturnTypeWillChange_arg0); + zend_string *attribute_name_Attribute_class_ReturnTypeWillChange_1 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_ReturnTypeWillChange_1 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ReturnTypeWillChange_1, 1); + zend_string_release(attribute_name_Attribute_class_ReturnTypeWillChange_1); + zval attribute_Attribute_class_ReturnTypeWillChange_1_arg0; + ZVAL_LONG(&attribute_Attribute_class_ReturnTypeWillChange_1_arg0, ZEND_ATTRIBUTE_TARGET_METHOD); + ZVAL_COPY_VALUE(&attribute_Attribute_class_ReturnTypeWillChange_1->args[0].value, &attribute_Attribute_class_ReturnTypeWillChange_1_arg0); return class_entry; } @@ -161,12 +161,12 @@ static zend_class_entry *register_class_AllowDynamicProperties(void) class_entry = zend_register_internal_class_ex(&ce, NULL); class_entry->ce_flags |= ZEND_ACC_FINAL; - zend_string *attribute_name_Attribute_class_AllowDynamicProperties = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); - zend_attribute *attribute_Attribute_class_AllowDynamicProperties = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_AllowDynamicProperties, 1); - zend_string_release(attribute_name_Attribute_class_AllowDynamicProperties); - zval attribute_Attribute_class_AllowDynamicProperties_arg0; - ZVAL_LONG(&attribute_Attribute_class_AllowDynamicProperties_arg0, ZEND_ATTRIBUTE_TARGET_CLASS); - ZVAL_COPY_VALUE(&attribute_Attribute_class_AllowDynamicProperties->args[0].value, &attribute_Attribute_class_AllowDynamicProperties_arg0); + zend_string *attribute_name_Attribute_class_AllowDynamicProperties_1 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_AllowDynamicProperties_1 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_AllowDynamicProperties_1, 1); + zend_string_release(attribute_name_Attribute_class_AllowDynamicProperties_1); + zval attribute_Attribute_class_AllowDynamicProperties_1_arg0; + ZVAL_LONG(&attribute_Attribute_class_AllowDynamicProperties_1_arg0, ZEND_ATTRIBUTE_TARGET_CLASS); + ZVAL_COPY_VALUE(&attribute_Attribute_class_AllowDynamicProperties_1->args[0].value, &attribute_Attribute_class_AllowDynamicProperties_1_arg0); return class_entry; } @@ -179,12 +179,12 @@ static zend_class_entry *register_class_SensitiveParameter(void) class_entry = zend_register_internal_class_ex(&ce, NULL); class_entry->ce_flags |= ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES; - zend_string *attribute_name_Attribute_class_SensitiveParameter = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); - zend_attribute *attribute_Attribute_class_SensitiveParameter = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_SensitiveParameter, 1); - zend_string_release(attribute_name_Attribute_class_SensitiveParameter); - zval attribute_Attribute_class_SensitiveParameter_arg0; - ZVAL_LONG(&attribute_Attribute_class_SensitiveParameter_arg0, ZEND_ATTRIBUTE_TARGET_PARAMETER); - ZVAL_COPY_VALUE(&attribute_Attribute_class_SensitiveParameter->args[0].value, &attribute_Attribute_class_SensitiveParameter_arg0); + zend_string *attribute_name_Attribute_class_SensitiveParameter_1 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_SensitiveParameter_1 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_SensitiveParameter_1, 1); + zend_string_release(attribute_name_Attribute_class_SensitiveParameter_1); + zval attribute_Attribute_class_SensitiveParameter_1_arg0; + ZVAL_LONG(&attribute_Attribute_class_SensitiveParameter_1_arg0, ZEND_ATTRIBUTE_TARGET_PARAMETER); + ZVAL_COPY_VALUE(&attribute_Attribute_class_SensitiveParameter_1->args[0].value, &attribute_Attribute_class_SensitiveParameter_1_arg0); return class_entry; } diff --git a/Zend/zend_builtin_functions_arginfo.h b/Zend/zend_builtin_functions_arginfo.h index 838084418871c..c10f72d71f0fe 100644 --- a/Zend/zend_builtin_functions_arginfo.h +++ b/Zend/zend_builtin_functions_arginfo.h @@ -355,9 +355,9 @@ static zend_class_entry *register_class_stdClass(void) class_entry = zend_register_internal_class_ex(&ce, NULL); class_entry->ce_flags |= ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES; - zend_string *attribute_name_AllowDynamicProperties_class_stdClass = zend_string_init_interned("AllowDynamicProperties", sizeof("AllowDynamicProperties") - 1, 1); - zend_add_class_attribute(class_entry, attribute_name_AllowDynamicProperties_class_stdClass, 0); - zend_string_release(attribute_name_AllowDynamicProperties_class_stdClass); + zend_string *attribute_name_AllowDynamicProperties_class_stdClass_1 = zend_string_init_interned("AllowDynamicProperties", sizeof("AllowDynamicProperties") - 1, 1); + zend_add_class_attribute(class_entry, attribute_name_AllowDynamicProperties_class_stdClass_1, 0); + zend_string_release(attribute_name_AllowDynamicProperties_class_stdClass_1); return class_entry; } diff --git a/Zend/zend_exceptions_arginfo.h b/Zend/zend_exceptions_arginfo.h index 58538905a6a89..dd3d6d859261a 100644 --- a/Zend/zend_exceptions_arginfo.h +++ b/Zend/zend_exceptions_arginfo.h @@ -209,7 +209,7 @@ static zend_class_entry *register_class_Exception(zend_class_entry *class_entry_ zval property_message_default_value; ZVAL_EMPTY_STRING(&property_message_default_value); zend_string *property_message_name = zend_string_init("message", sizeof("message") - 1, 1); - zend_declare_property_ex(class_entry, property_message_name, &property_message_default_value, ZEND_ACC_PROTECTED, NULL); + zend_declare_typed_property(class_entry, property_message_name, &property_message_default_value, ZEND_ACC_PROTECTED, NULL, (zend_type) ZEND_TYPE_INIT_NONE(0)); zend_string_release(property_message_name); zval property_string_default_value; @@ -221,7 +221,7 @@ static zend_class_entry *register_class_Exception(zend_class_entry *class_entry_ zval property_code_default_value; ZVAL_LONG(&property_code_default_value, 0); zend_string *property_code_name = zend_string_init("code", sizeof("code") - 1, 1); - zend_declare_property_ex(class_entry, property_code_name, &property_code_default_value, ZEND_ACC_PROTECTED, NULL); + zend_declare_typed_property(class_entry, property_code_name, &property_code_default_value, ZEND_ACC_PROTECTED, NULL, (zend_type) ZEND_TYPE_INIT_NONE(0)); zend_string_release(property_code_name); zval property_file_default_value; @@ -279,7 +279,7 @@ static zend_class_entry *register_class_Error(zend_class_entry *class_entry_Thro zval property_message_default_value; ZVAL_EMPTY_STRING(&property_message_default_value); zend_string *property_message_name = zend_string_init("message", sizeof("message") - 1, 1); - zend_declare_property_ex(class_entry, property_message_name, &property_message_default_value, ZEND_ACC_PROTECTED, NULL); + zend_declare_typed_property(class_entry, property_message_name, &property_message_default_value, ZEND_ACC_PROTECTED, NULL, (zend_type) ZEND_TYPE_INIT_NONE(0)); zend_string_release(property_message_name); zval property_string_default_value; @@ -291,7 +291,7 @@ static zend_class_entry *register_class_Error(zend_class_entry *class_entry_Thro zval property_code_default_value; ZVAL_LONG(&property_code_default_value, 0); zend_string *property_code_name = zend_string_init("code", sizeof("code") - 1, 1); - zend_declare_property_ex(class_entry, property_code_name, &property_code_default_value, ZEND_ACC_PROTECTED, NULL); + zend_declare_typed_property(class_entry, property_code_name, &property_code_default_value, ZEND_ACC_PROTECTED, NULL, (zend_type) ZEND_TYPE_INIT_NONE(0)); zend_string_release(property_code_name); zval property_file_default_value; diff --git a/build/gen_stub.php b/build/gen_stub.php index 7df5290883691..a2ee463f4135d 100755 --- a/build/gen_stub.php +++ b/build/gen_stub.php @@ -4,6 +4,7 @@ use PhpParser\Comment\Doc as DocComment; use PhpParser\ConstExprEvaluator; use PhpParser\Node; +use PhpParser\Node\AttributeGroup; use PhpParser\Node\Expr; use PhpParser\Node\Name; use PhpParser\Node\Stmt; @@ -908,8 +909,12 @@ private function setTypes(?Type $type, ?Type $phpDocType): void } } -interface ConstOrClassConstName { +interface VariableLikeName { public function __toString(): string; + public function getDeclarationName(): string; +} + +interface ConstOrClassConstName extends VariableLikeName { public function equals(ConstOrClassConstName $const): bool; public function isClassConst(): bool; public function isUnknown(): bool; @@ -957,6 +962,11 @@ public function __toString(): string { return $this->const; } + + public function getDeclarationName(): string + { + return $this->name->toString(); + } } class ClassConstName extends AbstractConstName { @@ -978,9 +988,14 @@ public function __toString(): string { return $this->class->toString() . "::" . $this->const; } + + public function getDeclarationName(): string + { + return $this->const; + } } -class PropertyName { +class PropertyName implements VariableLikeName { public Name $class; public string $property; @@ -994,6 +1009,11 @@ public function __toString() { return $this->class->toString() . "::$" . $this->property; } + + public function getDeclarationName(): string + { + return $this->property; + } } interface FunctionOrMethodName { @@ -1197,8 +1217,11 @@ class FuncInfo { public int $numRequiredArgs; public ?string $cond; public bool $isUndocumentable; + /** @var AttributeInfo[] */ + public array $attributes; /** + * @param AttributeInfo[] $attributes * @param ArgInfo[] $args */ public function __construct( @@ -1214,7 +1237,8 @@ public function __construct( ReturnInfo $return, int $numRequiredArgs, ?string $cond, - bool $isUndocumentable + bool $isUndocumentable, + array $attributes ) { $this->name = $name; $this->classFlags = $classFlags; @@ -1229,6 +1253,7 @@ public function __construct( $this->numRequiredArgs = $numRequiredArgs; $this->cond = $cond; $this->isUndocumentable = $isUndocumentable; + $this->attributes = $attributes; } public function isMethod(): bool @@ -1424,6 +1449,7 @@ public function getOptimizerInfo(): ?string { } public function discardInfoForOldPhpVersions(): void { + $this->attributes = []; $this->return->type = null; foreach ($this->args as $arg) { $arg->type = null; @@ -1593,7 +1619,7 @@ public static function createFromExpression(Expr $expr, ?SimpleType $constType, $evaluator = new ConstExprEvaluator( function (Expr $expr) use ($allConstInfos, &$constType, &$originatingConst, &$isUnknownConstValue) { if (!$expr instanceof Expr\ConstFetch && !$expr instanceof Expr\ClassConstFetch) { - throw new Exception($this->getVariableTypeName() . " " . $this->getVariableLikeName() . " has an unsupported value"); + throw new Exception($this->getVariableTypeName() . " " . $this->name->__toString() . " has an unsupported value"); } if ($expr instanceof Expr\ClassConstFetch) { @@ -1717,25 +1743,30 @@ abstract class VariableLike public int $flags; public ?string $link; public ?int $phpVersionIdMinimumCompatibility; + /** @var AttributeInfo[] */ + public array $attributes; + /** + * @var AttributeInfo[] $attributes + */ public function __construct( int $flags, ?Type $phpDocType, ?string $link, - ?int $phpVersionIdMinimumCompatibility + ?int $phpVersionIdMinimumCompatibility, + array $attributes ) { $this->flags = $flags; $this->phpDocType = $phpDocType; $this->link = $link; $this->phpVersionIdMinimumCompatibility = $phpVersionIdMinimumCompatibility; + $this->attributes = $attributes; } abstract protected function getVariableTypeCode(): string; abstract protected function getVariableTypeName(): string; - abstract protected function getVariableLikeName(): string; - abstract protected function addTypeToFieldSynopsis(DOMDocument $doc, DOMElement $fieldsynopsisElement): void; abstract protected function getFieldSynopsisDefaultLinkend(): string; @@ -1844,6 +1875,9 @@ class ConstInfo extends VariableLike public ?string $cond; public ?string $cValue; + /** + * @var AttributeInfo[] $attributes + */ public function __construct( ConstOrClassConstName $name, int $flags, @@ -1854,7 +1888,8 @@ public function __construct( ?string $cond, ?string $cValue, ?string $link, - ?int $phpVersionIdMinimumCompatibility + ?int $phpVersionIdMinimumCompatibility, + array $attributes ) { $this->name = $name; $this->value = $value; @@ -1862,7 +1897,7 @@ public function __construct( $this->isDeprecated = $isDeprecated; $this->cond = $cond; $this->cValue = $cValue; - parent::__construct($flags, $phpDocType, $link, $phpVersionIdMinimumCompatibility); + parent::__construct($flags, $phpDocType, $link, $phpVersionIdMinimumCompatibility, $attributes); } /** @@ -1883,11 +1918,6 @@ protected function getVariableTypeName(): string return "constant"; } - protected function getVariableLikeName(): string - { - return $this->name->const; - } - protected function getVariableTypeCode(): string { return "const"; @@ -1933,6 +1963,7 @@ protected function getFieldSynopsisValueString(iterable $allConstInfos): ?string public function discardInfoForOldPhpVersions(): void { $this->flags &= ~Class_::MODIFIER_FINAL; $this->isDeprecated = false; + $this->attributes = []; } /** @@ -2014,7 +2045,7 @@ private function getGlobalConstDeclaration(EvaluatedValue $value, iterable $allC */ private function getClassConstDeclaration(EvaluatedValue $value, iterable $allConstInfos): string { - $constName = $this->getVariableLikeName(); + $constName = $this->name->getDeclarationName(); $zvalCode = $value->initializeZval("const_{$constName}_value", $allConstInfos); @@ -2023,7 +2054,13 @@ private function getClassConstDeclaration(EvaluatedValue $value, iterable $allCo $code .= "\tzend_string *const_{$constName}_name = zend_string_init_interned(\"$constName\", sizeof(\"$constName\") - 1, 1);\n"; $nameCode = "const_{$constName}_name"; - $template = "\tzend_declare_class_constant_ex(class_entry, $nameCode, &const_{$constName}_value, %s, NULL);\n"; + if (!empty($this->attributes)) { + $template = "\tzend_class_constant *const_" . $this->name->getDeclarationName() . " = "; + } else { + $template = "\t"; + } + + $template .= "zend_declare_class_constant_ex(class_entry, $nameCode, &const_{$constName}_value, %s, NULL);\n"; $flagsCode = generateVersionDependentFlagCode( $template, $this->getFlagsByPhpVersion(), @@ -2111,6 +2148,9 @@ class PropertyInfo extends VariableLike public ?string $defaultValueString; public bool $isDocReadonly; + /** + * @var AttributeInfo[] $attributes + */ public function __construct( PropertyName $name, int $flags, @@ -2120,14 +2160,15 @@ public function __construct( ?string $defaultValueString, bool $isDocReadonly, ?string $link, - ?int $phpVersionIdMinimumCompatibility + ?int $phpVersionIdMinimumCompatibility, + array $attributes ) { $this->name = $name; $this->type = $type; $this->defaultValue = $defaultValue; $this->defaultValueString = $defaultValueString; $this->isDocReadonly = $isDocReadonly; - parent::__construct($flags, $phpDocType, $link, $phpVersionIdMinimumCompatibility); + parent::__construct($flags, $phpDocType, $link, $phpVersionIdMinimumCompatibility, $attributes); } protected function getVariableTypeCode(): string @@ -2140,11 +2181,6 @@ protected function getVariableTypeName(): string return "property"; } - protected function getVariableLikeName(): string - { - return $this->name->property; - } - protected function getFieldSynopsisDefaultLinkend(): string { $className = str_replace(["\\", "_"], ["-", "-"], $this->name->class->toLowerString()); @@ -2168,6 +2204,7 @@ protected function getFieldSynopsisValueString(iterable $allConstInfos): ?string public function discardInfoForOldPhpVersions(): void { $this->type = null; $this->flags &= ~Class_::MODIFIER_READONLY; + $this->attributes = []; } /** @@ -2226,6 +2263,8 @@ public function getDeclaration(iterable $allConstInfos): string { } else { $typeCode = "(zend_type) ZEND_TYPE_INIT_MASK(" . $arginfoType->toTypeMask() . ")"; } + } else { + $typeCode = "(zend_type) ZEND_TYPE_INIT_NONE(0)"; } $zvalName = "property_{$this->name->property}_default_value"; @@ -2238,11 +2277,13 @@ public function getDeclaration(iterable $allConstInfos): string { $code .= "\tzend_string *property_{$propertyName}_name = zend_string_init(\"$propertyName\", sizeof(\"$propertyName\") - 1, 1);\n"; $nameCode = "property_{$propertyName}_name"; - if ($this->type !== null) { - $template = "\tzend_declare_typed_property(class_entry, $nameCode, &$zvalName, %s, NULL, $typeCode);\n"; + if (!empty($this->attributes)) { + $template = "\tzend_property_info *property_" . $this->name->getDeclarationName() . " = "; } else { - $template = "\tzend_declare_property_ex(class_entry, $nameCode, &$zvalName, %s, NULL);\n"; + $template = "\t"; } + + $template .= "zend_declare_typed_property(class_entry, $nameCode, &$zvalName, %s, NULL, $typeCode);\n"; $flagsCode = generateVersionDependentFlagCode( $template, $this->getFlagsByPhpVersion(), @@ -2538,18 +2579,46 @@ function (Name $item) { $code .= "\n#if (PHP_VERSION_ID >= " . PHP_82_VERSION_ID . ")"; } - foreach ($this->attributes as $attribute) { - $code .= $attribute->generateCode("zend_add_class_attribute(class_entry", "class_$escapedName", $allConstInfos); + foreach ($this->attributes as $key => $attribute) { + $code .= $attribute->generateCode( + "zend_add_class_attribute(class_entry", + "class_{$escapedName}_" . ($key + 1), + $allConstInfos + ); + } + + if (!$php82MinimumCompatibility) { + $code .= "#endif\n"; + } + } + + if ($attributeInitializationCode = generateConstantAttributeInitialization($this->constInfos, $allConstInfos, $this->cond)) { + if (!$php82MinimumCompatibility) { + $code .= "#if (PHP_VERSION_ID >= " . PHP_82_VERSION_ID . ")"; + } + + $code .= "\n" . $attributeInitializationCode; + + if (!$php82MinimumCompatibility) { + $code .= "#endif\n"; + } + } + + if ($attributeInitializationCode = generatePropertyAttributeInitialization($this->propertyInfos, $allConstInfos)) { + if (!$php82MinimumCompatibility) { + $code .= "#if (PHP_VERSION_ID >= " . PHP_82_VERSION_ID . ")"; } + $code .= "\n" . $attributeInitializationCode; + if (!$php82MinimumCompatibility) { $code .= "#endif\n"; } } - if ($attributeInitializationCode = generateAttributeInitialization($this->funcInfos, $allConstInfos, $this->cond)) { + if ($attributeInitializationCode = generateFunctionAttributeInitialization($this->funcInfos, $allConstInfos, $this->cond)) { if (!$php82MinimumCompatibility) { - $code .= "#if (PHP_VERSION_ID >= " . PHP_82_VERSION_ID . ")\n"; + $code .= "#if (PHP_VERSION_ID >= " . PHP_82_VERSION_ID . ")"; } $code .= "\n" . $attributeInitializationCode; @@ -3273,12 +3342,6 @@ function parseFunctionLike( foreach ($func->getParams() as $i => $param) { $varName = $param->var->name; $preferRef = !empty($paramMeta[$varName]['prefer-ref']); - $attributes = []; - foreach ($param->attrGroups as $attrGroup) { - foreach ($attrGroup->attrs as $attr) { - $attributes[] = new AttributeInfo($attr->name->toString(), $attr->args); - } - } unset($paramMeta[$varName]); if (isset($varNameSet[$varName])) { @@ -3326,7 +3389,7 @@ function parseFunctionLike( $type, isset($docParamTypes[$varName]) ? Type::fromString($docParamTypes[$varName]) : null, $param->default ? $prettyPrinter->prettyPrintExpr($param->default) : null, - $attributes + createAttributes($param->attrGroups) ); if (!$param->default && !$param->variadic) { $numRequiredArgs = $i + 1; @@ -3363,13 +3426,17 @@ function parseFunctionLike( $return, $numRequiredArgs, $cond, - $isUndocumentable + $isUndocumentable, + createAttributes($func->attrGroups) ); } catch (Exception $e) { throw new Exception($name . "(): " .$e->getMessage()); } } +/** + * @param array $attributes + */ function parseConstLike( PrettyPrinterAbstract $prettyPrinter, ConstOrClassConstName $name, @@ -3377,7 +3444,8 @@ function parseConstLike( int $flags, ?DocComment $docComment, ?string $cond, - ?int $phpVersionIdMinimumCompatibility + ?int $phpVersionIdMinimumCompatibility, + array $attributes ): ConstInfo { $phpDocType = null; $deprecated = false; @@ -3412,10 +3480,14 @@ function parseConstLike( $cond, $cValue, $link, - $phpVersionIdMinimumCompatibility + $phpVersionIdMinimumCompatibility, + $attributes ); } +/** + * @param array $attributes + */ function parseProperty( Name $class, int $flags, @@ -3423,7 +3495,8 @@ function parseProperty( ?Node $type, ?DocComment $comment, PrettyPrinterAbstract $prettyPrinter, - ?int $phpVersionIdMinimumCompatibility + ?int $phpVersionIdMinimumCompatibility, + array $attributes ): PropertyInfo { $phpDocType = null; $isDocReadonly = false; @@ -3467,7 +3540,8 @@ function parseProperty( $property->default ? $prettyPrinter->prettyPrintExpr($property->default) : null, $isDocReadonly, $link, - $phpVersionIdMinimumCompatibility + $phpVersionIdMinimumCompatibility, + $attributes ); } @@ -3514,14 +3588,12 @@ function parseClass( } } - foreach ($class->attrGroups as $attrGroup) { - foreach ($attrGroup->attrs as $attr) { - $attributes[] = new AttributeInfo($attr->name->toString(), $attr->args); - switch ($attr->name->toString()) { - case 'AllowDynamicProperties': - $allowsDynamicProperties = true; - break; - } + $attributes = createAttributes($class->attrGroups); + foreach ($attributes as $attribute) { + switch ($attribute->class) { + case 'AllowDynamicProperties': + $allowsDynamicProperties = true; + break 2; } } @@ -3579,6 +3651,22 @@ function parseClass( ); } +/** + * @param array> $attributeGroups + * @return Attribute[] + */ +function createAttributes(array $attributeGroups): array { + $attributes = []; + + foreach ($attributeGroups as $attrGroup) { + foreach ($attrGroup->attrs as $attr) { + $attributes[] = new AttributeInfo($attr->name->toString(), $attr->args); + } + } + + return $attributes; +} + function handlePreprocessorConditions(array &$conds, Stmt $stmt): ?string { foreach ($stmt->getComments() as $comment) { $text = trim($comment->getText()); @@ -3647,7 +3735,8 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac 0, $stmt->getDocComment(), $cond, - $fileInfo->generateLegacyArginfoForPhpVersionId + $fileInfo->generateLegacyArginfoForPhpVersionId, + [] ); } continue; @@ -3690,7 +3779,8 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac $classStmt->flags, $classStmt->getDocComment(), $cond, - $fileInfo->generateLegacyArginfoForPhpVersionId + $fileInfo->generateLegacyArginfoForPhpVersionId, + createAttributes($classStmt->attrGroups) ); } } else if ($classStmt instanceof Stmt\Property) { @@ -3705,7 +3795,8 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac $classStmt->type, $classStmt->getDocComment(), $prettyPrinter, - $fileInfo->generateLegacyArginfoForPhpVersionId + $fileInfo->generateLegacyArginfoForPhpVersionId, + createAttributes($classStmt->attrGroups) ); } } else if ($classStmt instanceof Stmt\ClassMethod) { @@ -4007,7 +4098,7 @@ static function (FuncInfo $funcInfo) use ($fileInfo, &$generatedFunctionDeclarat $php82MinimumCompatibility = $fileInfo->generateLegacyArginfoForPhpVersionId === null || $fileInfo->generateLegacyArginfoForPhpVersionId >= PHP_82_VERSION_ID; if ($fileInfo->generateClassEntries) { - if ($attributeInitializationCode = generateAttributeInitialization($fileInfo->funcInfos, $allConstInfos, null)) { + if ($attributeInitializationCode = generateFunctionAttributeInitialization($fileInfo->funcInfos, $allConstInfos, null)) { if (!$php82MinimumCompatibility) { $attributeInitializationCode = "\n#if (PHP_VERSION_ID >= " . PHP_82_VERSION_ID . ")" . $attributeInitializationCode . "#endif\n"; } @@ -4075,26 +4166,63 @@ function generateFunctionEntries(?Name $className, array $funcInfos, ?string $co return $code; } + /** * @param iterable $funcInfos */ -function generateAttributeInitialization(iterable $funcInfos, iterable $allConstInfos, ?string $parentCond = null): string { +function generateFunctionAttributeInitialization(iterable $funcInfos, iterable $allConstInfos, ?string $parentCond = null): string { return generateCodeWithConditions( $funcInfos, "", static function (FuncInfo $funcInfo) use ($allConstInfos) { $code = null; + if ($funcInfo->name instanceof MethodName) { + $functionTable = "&class_entry->function_table"; + } else { + $functionTable = "CG(function_table)"; + } + + foreach ($funcInfo->attributes as $key => $attribute) { + $code .= $attribute->generateCode( + "zend_add_function_attribute(zend_hash_str_find_ptr($functionTable, \"" . $funcInfo->name->getNameForAttributes() . "\", sizeof(\"" . $funcInfo->name->getNameForAttributes() . "\") - 1)", + "func_" . $funcInfo->name->getNameForAttributes() . "_" . ($key + 1), + $allConstInfos + ); + } + foreach ($funcInfo->args as $index => $arg) { - if ($funcInfo->name instanceof MethodName) { - $functionTable = "&class_entry->function_table"; - } else { - $functionTable = "CG(function_table)"; + foreach ($arg->attributes as $key => $attribute) { + $code .= $attribute->generateCode( + "zend_add_parameter_attribute(zend_hash_str_find_ptr($functionTable, \"" . $funcInfo->name->getNameForAttributes() . "\", sizeof(\"" . $funcInfo->name->getNameForAttributes() . "\") - 1), $index", + "func_{$funcInfo->name->getNameForAttributes()}_arg{$index}_" . ($key + 1), + $allConstInfos + ); } + } - foreach ($arg->attributes as $attribute) { - $code .= $attribute->generateCode("zend_add_parameter_attribute(zend_hash_str_find_ptr($functionTable, \"" . $funcInfo->name->getNameForAttributes() . "\", sizeof(\"" . $funcInfo->name->getNameForAttributes() . "\") - 1), $index", "{$funcInfo->name->getMethodSynopsisFilename()}_arg{$index}", $allConstInfos); - } + return $code; + }, + $parentCond + ); +} + +/** + * @param iterable $constInfos + */ +function generateConstantAttributeInitialization(iterable $constInfos, iterable $allConstInfos, ?string $parentCond = null): string { + return generateCodeWithConditions( + $constInfos, + "", + static function (ConstInfo $constInfo) use ($allConstInfos) { + $code = null; + + foreach ($constInfo->attributes as $key => $attribute) { + $code .= $attribute->generateCode( + "zend_add_class_constant_attribute(class_entry, const_" . $constInfo->name->getDeclarationName(), + "const_" . $constInfo->name->getDeclarationName() . "_" . ($key + 1), + $allConstInfos + ); } return $code; @@ -4103,6 +4231,24 @@ static function (FuncInfo $funcInfo) use ($allConstInfos) { ); } +/** + * @param iterable $propertyInfos + */ +function generatePropertyAttributeInitialization(iterable $propertyInfos, iterable $allConstInfos): string { + $code = ""; + foreach ($propertyInfos as $propertyInfo) { + foreach ($propertyInfo->attributes as $key => $attribute) { + $code .= $attribute->generateCode( + "zend_add_property_attribute(class_entry, property_" . $propertyInfo->name->getDeclarationName(), + "property_" . $propertyInfo->name->getDeclarationName() . "_" . ($key + 1), + $allConstInfos + ); + } + } + + return $code; +} + /** @param array $funcMap */ function generateOptimizerInfo(array $funcMap): string { diff --git a/ext/dom/php_dom_arginfo.h b/ext/dom/php_dom_arginfo.h index d7c6c4496e90d..136593dbc75ac 100644 --- a/ext/dom/php_dom_arginfo.h +++ b/ext/dom/php_dom_arginfo.h @@ -1555,7 +1555,7 @@ static zend_class_entry *register_class_DOMException(zend_class_entry *class_ent zval property_code_default_value; ZVAL_LONG(&property_code_default_value, 0); zend_string *property_code_name = zend_string_init("code", sizeof("code") - 1, 1); - zend_declare_property_ex(class_entry, property_code_name, &property_code_default_value, ZEND_ACC_PUBLIC, NULL); + zend_declare_typed_property(class_entry, property_code_name, &property_code_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_NONE(0)); zend_string_release(property_code_name); return class_entry; diff --git a/ext/oci8/oci8_arginfo.h b/ext/oci8/oci8_arginfo.h index a6869afd2e64b..be4357688abc1 100644 --- a/ext/oci8/oci8_arginfo.h +++ b/ext/oci8/oci8_arginfo.h @@ -901,9 +901,9 @@ static zend_class_entry *register_class_OCILob(void) class_entry = zend_register_internal_class_ex(&ce, NULL); class_entry->ce_flags |= ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES; - zend_string *attribute_name_AllowDynamicProperties_class_OCILob = zend_string_init_interned("AllowDynamicProperties", sizeof("AllowDynamicProperties") - 1, 1); - zend_add_class_attribute(class_entry, attribute_name_AllowDynamicProperties_class_OCILob, 0); - zend_string_release(attribute_name_AllowDynamicProperties_class_OCILob); + zend_string *attribute_name_AllowDynamicProperties_class_OCILob_1 = zend_string_init_interned("AllowDynamicProperties", sizeof("AllowDynamicProperties") - 1, 1); + zend_add_class_attribute(class_entry, attribute_name_AllowDynamicProperties_class_OCILob_1, 0); + zend_string_release(attribute_name_AllowDynamicProperties_class_OCILob_1); return class_entry; } @@ -916,9 +916,9 @@ static zend_class_entry *register_class_OCICollection(void) class_entry = zend_register_internal_class_ex(&ce, NULL); class_entry->ce_flags |= ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES; - zend_string *attribute_name_AllowDynamicProperties_class_OCICollection = zend_string_init_interned("AllowDynamicProperties", sizeof("AllowDynamicProperties") - 1, 1); - zend_add_class_attribute(class_entry, attribute_name_AllowDynamicProperties_class_OCICollection, 0); - zend_string_release(attribute_name_AllowDynamicProperties_class_OCICollection); + zend_string *attribute_name_AllowDynamicProperties_class_OCICollection_1 = zend_string_init_interned("AllowDynamicProperties", sizeof("AllowDynamicProperties") - 1, 1); + zend_add_class_attribute(class_entry, attribute_name_AllowDynamicProperties_class_OCICollection_1, 0); + zend_string_release(attribute_name_AllowDynamicProperties_class_OCICollection_1); return class_entry; } diff --git a/ext/pdo/pdo_arginfo.h b/ext/pdo/pdo_arginfo.h index 9f8a0c6cc208c..15489b7cc23f9 100644 --- a/ext/pdo/pdo_arginfo.h +++ b/ext/pdo/pdo_arginfo.h @@ -28,7 +28,7 @@ static zend_class_entry *register_class_PDOException(zend_class_entry *class_ent zval property_code_default_value; ZVAL_LONG(&property_code_default_value, 0); zend_string *property_code_name = zend_string_init("code", sizeof("code") - 1, 1); - zend_declare_property_ex(class_entry, property_code_name, &property_code_default_value, ZEND_ACC_PROTECTED, NULL); + zend_declare_typed_property(class_entry, property_code_name, &property_code_default_value, ZEND_ACC_PROTECTED, NULL, (zend_type) ZEND_TYPE_INIT_NONE(0)); zend_string_release(property_code_name); zval property_errorInfo_default_value; diff --git a/ext/soap/soap_arginfo.h b/ext/soap/soap_arginfo.h index 5305b6e9891b1..2257e0621e4f0 100644 --- a/ext/soap/soap_arginfo.h +++ b/ext/soap/soap_arginfo.h @@ -541,25 +541,25 @@ static zend_class_entry *register_class_SoapClient(void) zval property_sdl_default_value; ZVAL_NULL(&property_sdl_default_value); zend_string *property_sdl_name = zend_string_init("sdl", sizeof("sdl") - 1, 1); - zend_declare_property_ex(class_entry, property_sdl_name, &property_sdl_default_value, ZEND_ACC_PRIVATE, NULL); + zend_declare_typed_property(class_entry, property_sdl_name, &property_sdl_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_NONE(0)); zend_string_release(property_sdl_name); zval property_typemap_default_value; ZVAL_NULL(&property_typemap_default_value); zend_string *property_typemap_name = zend_string_init("typemap", sizeof("typemap") - 1, 1); - zend_declare_property_ex(class_entry, property_typemap_name, &property_typemap_default_value, ZEND_ACC_PRIVATE, NULL); + zend_declare_typed_property(class_entry, property_typemap_name, &property_typemap_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_NONE(0)); zend_string_release(property_typemap_name); zval property_httpsocket_default_value; ZVAL_NULL(&property_httpsocket_default_value); zend_string *property_httpsocket_name = zend_string_init("httpsocket", sizeof("httpsocket") - 1, 1); - zend_declare_property_ex(class_entry, property_httpsocket_name, &property_httpsocket_default_value, ZEND_ACC_PRIVATE, NULL); + zend_declare_typed_property(class_entry, property_httpsocket_name, &property_httpsocket_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_NONE(0)); zend_string_release(property_httpsocket_name); zval property_httpurl_default_value; ZVAL_NULL(&property_httpurl_default_value); zend_string *property_httpurl_name = zend_string_init("httpurl", sizeof("httpurl") - 1, 1); - zend_declare_property_ex(class_entry, property_httpurl_name, &property_httpurl_default_value, ZEND_ACC_PRIVATE, NULL); + zend_declare_typed_property(class_entry, property_httpurl_name, &property_httpurl_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_NONE(0)); zend_string_release(property_httpurl_name); zval property__login_default_value; @@ -643,7 +643,7 @@ static zend_class_entry *register_class_SoapClient(void) zval property__stream_context_default_value; ZVAL_NULL(&property__stream_context_default_value); zend_string *property__stream_context_name = zend_string_init("_stream_context", sizeof("_stream_context") - 1, 1); - zend_declare_property_ex(class_entry, property__stream_context_name, &property__stream_context_default_value, ZEND_ACC_PRIVATE, NULL); + zend_declare_typed_property(class_entry, property__stream_context_name, &property__stream_context_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_NONE(0)); zend_string_release(property__stream_context_name); zval property__user_agent_default_value; diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index d7eb83b55690a..536e39ec6abfa 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -3730,9 +3730,9 @@ static zend_class_entry *register_class___PHP_Incomplete_Class(void) class_entry = zend_register_internal_class_ex(&ce, NULL); class_entry->ce_flags |= ZEND_ACC_FINAL|ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES; - zend_string *attribute_name_AllowDynamicProperties_class___PHP_Incomplete_Class = zend_string_init_interned("AllowDynamicProperties", sizeof("AllowDynamicProperties") - 1, 1); - zend_add_class_attribute(class_entry, attribute_name_AllowDynamicProperties_class___PHP_Incomplete_Class, 0); - zend_string_release(attribute_name_AllowDynamicProperties_class___PHP_Incomplete_Class); + zend_string *attribute_name_AllowDynamicProperties_class___PHP_Incomplete_Class_1 = zend_string_init_interned("AllowDynamicProperties", sizeof("AllowDynamicProperties") - 1, 1); + zend_add_class_attribute(class_entry, attribute_name_AllowDynamicProperties_class___PHP_Incomplete_Class_1, 0); + zend_string_release(attribute_name_AllowDynamicProperties_class___PHP_Incomplete_Class_1); return class_entry; } diff --git a/ext/standard/user_filters_arginfo.h b/ext/standard/user_filters_arginfo.h index c7d33f78b61c4..2f8a9aa060b94 100644 --- a/ext/standard/user_filters_arginfo.h +++ b/ext/standard/user_filters_arginfo.h @@ -49,7 +49,7 @@ static zend_class_entry *register_class_php_user_filter(void) zval property_stream_default_value; ZVAL_NULL(&property_stream_default_value); zend_string *property_stream_name = zend_string_init("stream", sizeof("stream") - 1, 1); - zend_declare_property_ex(class_entry, property_stream_name, &property_stream_default_value, ZEND_ACC_PUBLIC, NULL); + zend_declare_typed_property(class_entry, property_stream_name, &property_stream_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_NONE(0)); zend_string_release(property_stream_name); return class_entry; diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php index 814e1945eab7d..9d591c09482bd 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -53,13 +53,21 @@ public function returnsThrowable(): Exception {} } trait _ZendTestTrait { + /** @var int */ + #[ZendTestAttribute] + #[ZendTestAttribute] + public const TEST_CONST = 1; + /** @var mixed */ + #[ZendTestAttribute] + #[ZendTestPropertyAttribute("testProp")] public $testProp; + #[ZendTestAttribute] public function testMethod(): bool {} } - #[Attribute(Attribute::TARGET_ALL)] + #[Attribute(Attribute::TARGET_ALL|Attribute::IS_REPEATABLE)] final class ZendTestAttribute { } diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h index 688102898f65a..af99f81dcbc81 100644 --- a/ext/zend_test/test_arginfo.h +++ b/ext/zend_test/test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 07600e864a4b1e5187d26a1716a2e96e92b8093e */ + * Stub hash: 7f239260963adbe9a2cff186d1677302bdebaa6d */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -400,7 +400,7 @@ static zend_class_entry *register_class__ZendTestClass(zend_class_entry *class_e zval property__StaticProp_default_value; ZVAL_NULL(&property__StaticProp_default_value); zend_string *property__StaticProp_name = zend_string_init("_StaticProp", sizeof("_StaticProp") - 1, 1); - zend_declare_property_ex(class_entry, property__StaticProp_name, &property__StaticProp_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL); + zend_declare_typed_property(class_entry, property__StaticProp_name, &property__StaticProp_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC, NULL, (zend_type) ZEND_TYPE_INIT_NONE(0)); zend_string_release(property__StaticProp_name); zval property_staticIntProp_default_value; @@ -479,11 +479,47 @@ static zend_class_entry *register_class__ZendTestTrait(void) class_entry = zend_register_internal_class_ex(&ce, NULL); class_entry->ce_flags |= ZEND_ACC_TRAIT; + zval const_TEST_CONST_value; + ZVAL_LONG(&const_TEST_CONST_value, 1); + zend_string *const_TEST_CONST_name = zend_string_init_interned("TEST_CONST", sizeof("TEST_CONST") - 1, 1); + zend_class_constant *const_TEST_CONST = zend_declare_class_constant_ex(class_entry, const_TEST_CONST_name, &const_TEST_CONST_value, ZEND_ACC_PUBLIC, NULL); + zend_string_release(const_TEST_CONST_name); + zval property_testProp_default_value; ZVAL_NULL(&property_testProp_default_value); zend_string *property_testProp_name = zend_string_init("testProp", sizeof("testProp") - 1, 1); - zend_declare_property_ex(class_entry, property_testProp_name, &property_testProp_default_value, ZEND_ACC_PUBLIC, NULL); + zend_property_info *property_testProp = zend_declare_typed_property(class_entry, property_testProp_name, &property_testProp_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_NONE(0)); zend_string_release(property_testProp_name); +#if (PHP_VERSION_ID >= 80200) + + zend_string *attribute_name_ZendTestAttribute_const_TEST_CONST_1 = zend_string_init_interned("ZendTestAttribute", sizeof("ZendTestAttribute") - 1, 1); + zend_add_class_constant_attribute(class_entry, const_TEST_CONST, attribute_name_ZendTestAttribute_const_TEST_CONST_1, 0); + zend_string_release(attribute_name_ZendTestAttribute_const_TEST_CONST_1); + + zend_string *attribute_name_ZendTestAttribute_const_TEST_CONST_2 = zend_string_init_interned("ZendTestAttribute", sizeof("ZendTestAttribute") - 1, 1); + zend_add_class_constant_attribute(class_entry, const_TEST_CONST, attribute_name_ZendTestAttribute_const_TEST_CONST_2, 0); + zend_string_release(attribute_name_ZendTestAttribute_const_TEST_CONST_2); +#endif +#if (PHP_VERSION_ID >= 80200) + + zend_string *attribute_name_ZendTestAttribute_property_testProp_1 = zend_string_init_interned("ZendTestAttribute", sizeof("ZendTestAttribute") - 1, 1); + zend_add_property_attribute(class_entry, property_testProp, attribute_name_ZendTestAttribute_property_testProp_1, 0); + zend_string_release(attribute_name_ZendTestAttribute_property_testProp_1); + + zend_string *attribute_name_ZendTestPropertyAttribute_property_testProp_2 = zend_string_init_interned("ZendTestPropertyAttribute", sizeof("ZendTestPropertyAttribute") - 1, 1); + zend_attribute *attribute_ZendTestPropertyAttribute_property_testProp_2 = zend_add_property_attribute(class_entry, property_testProp, attribute_name_ZendTestPropertyAttribute_property_testProp_2, 1); + zend_string_release(attribute_name_ZendTestPropertyAttribute_property_testProp_2); + zval attribute_ZendTestPropertyAttribute_property_testProp_2_arg0; + zend_string *attribute_ZendTestPropertyAttribute_property_testProp_2_arg0_str = zend_string_init("testProp", strlen("testProp"), 1); + ZVAL_STR(&attribute_ZendTestPropertyAttribute_property_testProp_2_arg0, attribute_ZendTestPropertyAttribute_property_testProp_2_arg0_str); + ZVAL_COPY_VALUE(&attribute_ZendTestPropertyAttribute_property_testProp_2->args[0].value, &attribute_ZendTestPropertyAttribute_property_testProp_2_arg0); +#endif +#if (PHP_VERSION_ID >= 80200) + + zend_string *attribute_name_ZendTestAttribute_func_testmethod_1 = zend_string_init_interned("ZendTestAttribute", sizeof("ZendTestAttribute") - 1, 1); + zend_add_function_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "testmethod", sizeof("testmethod") - 1), attribute_name_ZendTestAttribute_func_testmethod_1, 0); + zend_string_release(attribute_name_ZendTestAttribute_func_testmethod_1); +#endif return class_entry; } @@ -497,12 +533,12 @@ static zend_class_entry *register_class_ZendTestAttribute(void) class_entry->ce_flags |= ZEND_ACC_FINAL; #if (PHP_VERSION_ID >= 80200) - zend_string *attribute_name_Attribute_class_ZendTestAttribute = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); - zend_attribute *attribute_Attribute_class_ZendTestAttribute = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ZendTestAttribute, 1); - zend_string_release(attribute_name_Attribute_class_ZendTestAttribute); - zval attribute_Attribute_class_ZendTestAttribute_arg0; - ZVAL_LONG(&attribute_Attribute_class_ZendTestAttribute_arg0, ZEND_ATTRIBUTE_TARGET_ALL); - ZVAL_COPY_VALUE(&attribute_Attribute_class_ZendTestAttribute->args[0].value, &attribute_Attribute_class_ZendTestAttribute_arg0); + zend_string *attribute_name_Attribute_class_ZendTestAttribute_1 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_ZendTestAttribute_1 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ZendTestAttribute_1, 1); + zend_string_release(attribute_name_Attribute_class_ZendTestAttribute_1); + zval attribute_Attribute_class_ZendTestAttribute_1_arg0; + ZVAL_LONG(&attribute_Attribute_class_ZendTestAttribute_1_arg0, ZEND_ATTRIBUTE_IS_REPEATABLE); + ZVAL_COPY_VALUE(&attribute_Attribute_class_ZendTestAttribute_1->args[0].value, &attribute_Attribute_class_ZendTestAttribute_1_arg0); #endif return class_entry; @@ -523,12 +559,12 @@ static zend_class_entry *register_class_ZendTestParameterAttribute(void) zend_string_release(property_parameter_name); #if (PHP_VERSION_ID >= 80200) - zend_string *attribute_name_Attribute_class_ZendTestParameterAttribute = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); - zend_attribute *attribute_Attribute_class_ZendTestParameterAttribute = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ZendTestParameterAttribute, 1); - zend_string_release(attribute_name_Attribute_class_ZendTestParameterAttribute); - zval attribute_Attribute_class_ZendTestParameterAttribute_arg0; - ZVAL_LONG(&attribute_Attribute_class_ZendTestParameterAttribute_arg0, ZEND_ATTRIBUTE_TARGET_PARAMETER); - ZVAL_COPY_VALUE(&attribute_Attribute_class_ZendTestParameterAttribute->args[0].value, &attribute_Attribute_class_ZendTestParameterAttribute_arg0); + zend_string *attribute_name_Attribute_class_ZendTestParameterAttribute_1 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_ZendTestParameterAttribute_1 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ZendTestParameterAttribute_1, 1); + zend_string_release(attribute_name_Attribute_class_ZendTestParameterAttribute_1); + zval attribute_Attribute_class_ZendTestParameterAttribute_1_arg0; + ZVAL_LONG(&attribute_Attribute_class_ZendTestParameterAttribute_1_arg0, ZEND_ATTRIBUTE_TARGET_PARAMETER); + ZVAL_COPY_VALUE(&attribute_Attribute_class_ZendTestParameterAttribute_1->args[0].value, &attribute_Attribute_class_ZendTestParameterAttribute_1_arg0); #endif return class_entry; @@ -549,12 +585,12 @@ static zend_class_entry *register_class_ZendTestPropertyAttribute(void) zend_string_release(property_parameter_name); #if (PHP_VERSION_ID >= 80200) - zend_string *attribute_name_Attribute_class_ZendTestPropertyAttribute = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); - zend_attribute *attribute_Attribute_class_ZendTestPropertyAttribute = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ZendTestPropertyAttribute, 1); - zend_string_release(attribute_name_Attribute_class_ZendTestPropertyAttribute); - zval attribute_Attribute_class_ZendTestPropertyAttribute_arg0; - ZVAL_LONG(&attribute_Attribute_class_ZendTestPropertyAttribute_arg0, ZEND_ATTRIBUTE_TARGET_PROPERTY); - ZVAL_COPY_VALUE(&attribute_Attribute_class_ZendTestPropertyAttribute->args[0].value, &attribute_Attribute_class_ZendTestPropertyAttribute_arg0); + zend_string *attribute_name_Attribute_class_ZendTestPropertyAttribute_1 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_ZendTestPropertyAttribute_1 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ZendTestPropertyAttribute_1, 1); + zend_string_release(attribute_name_Attribute_class_ZendTestPropertyAttribute_1); + zval attribute_Attribute_class_ZendTestPropertyAttribute_1_arg0; + ZVAL_LONG(&attribute_Attribute_class_ZendTestPropertyAttribute_1_arg0, ZEND_ATTRIBUTE_TARGET_PROPERTY); + ZVAL_COPY_VALUE(&attribute_Attribute_class_ZendTestPropertyAttribute_1->args[0].value, &attribute_Attribute_class_ZendTestPropertyAttribute_1_arg0); #endif return class_entry; diff --git a/ext/zend_test/tests/gen_stub_test_03.phpt b/ext/zend_test/tests/gen_stub_test_03.phpt new file mode 100644 index 0000000000000..19d82cb1590a8 --- /dev/null +++ b/ext/zend_test/tests/gen_stub_test_03.phpt @@ -0,0 +1,33 @@ +--TEST-- +gen_stub.php: Test that attributes are applied to constants, properties, and methods +--EXTENSIONS-- +zend_test +--FILE-- +getAttributes()[0]->newInstance()); + +$reflectionProperty = new ReflectionProperty(Foo::class, "testProp"); +var_dump($reflectionProperty->getAttributes()[0]->newInstance()); +var_dump($reflectionProperty->getAttributes()[1]->newInstance()); + +$reflectionMethod = new ReflectionMethod(Foo::class, "testMethod"); +var_dump($reflectionMethod->getAttributes()[0]->newInstance()); + +?> +--EXPECTF-- +object(ZendTestAttribute)#%d (%d) { +} +object(ZendTestAttribute)#%d (%d) { +} +object(ZendTestPropertyAttribute)#%d (%d) { + ["parameter"]=> + string(%d) "testProp" +} +object(ZendTestAttribute)#%d (%d) { +} From d16c6fe710cac6cef390ee2d617decb5157ac640 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Tue, 17 Jan 2023 20:59:01 +0100 Subject: [PATCH 2/3] Fix unrelated test failure and apply suggestion from code review --- ext/zend_test/test.c | 4 ++ ext/zend_test/test.stub.php | 11 ++++-- ext/zend_test/test_arginfo.h | 47 +++++++++++++++++------ ext/zend_test/tests/gen_stub_test_03.phpt | 7 +++- 4 files changed, 52 insertions(+), 17 deletions(-) diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 3b8dffaa3f1f8..dfd94d99f1910 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -39,6 +39,7 @@ static zend_class_entry *zend_test_class; static zend_class_entry *zend_test_child_class; static zend_class_entry *zend_test_trait; static zend_class_entry *zend_test_attribute; +static zend_class_entry *zend_test_repeatable_attribute; static zend_class_entry *zend_test_parameter_attribute; static zend_class_entry *zend_test_property_attribute; static zend_class_entry *zend_test_class_with_method_with_parameter_attribute; @@ -736,6 +737,9 @@ PHP_MINIT_FUNCTION(zend_test) attr->validator = zend_attribute_validate_zendtestattribute; } + zend_test_repeatable_attribute = register_class_ZendTestRepeatableAttribute(); + zend_mark_internal_attribute(zend_test_repeatable_attribute); + zend_test_parameter_attribute = register_class_ZendTestParameterAttribute(); zend_mark_internal_attribute(zend_test_parameter_attribute); diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php index 9d591c09482bd..3edf828164da1 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -54,12 +54,12 @@ public function returnsThrowable(): Exception {} trait _ZendTestTrait { /** @var int */ - #[ZendTestAttribute] - #[ZendTestAttribute] + #[ZendTestRepeatableAttribute] + #[ZendTestRepeatableAttribute] public const TEST_CONST = 1; /** @var mixed */ - #[ZendTestAttribute] + #[ZendTestRepeatableAttribute] #[ZendTestPropertyAttribute("testProp")] public $testProp; @@ -67,9 +67,12 @@ trait _ZendTestTrait { public function testMethod(): bool {} } - #[Attribute(Attribute::TARGET_ALL|Attribute::IS_REPEATABLE)] + #[Attribute(Attribute::TARGET_ALL)] final class ZendTestAttribute { + } + #[Attribute(Attribute::TARGET_ALL|Attribute::IS_REPEATABLE)] + final class ZendTestRepeatableAttribute { } #[Attribute(Attribute::TARGET_PARAMETER)] diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h index af99f81dcbc81..e102ef469c701 100644 --- a/ext/zend_test/test_arginfo.h +++ b/ext/zend_test/test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 7f239260963adbe9a2cff186d1677302bdebaa6d */ + * Stub hash: 83b3d7beb8424627b1171a9190e06163b8a03450 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -294,6 +294,11 @@ static const zend_function_entry class_ZendTestAttribute_methods[] = { }; +static const zend_function_entry class_ZendTestRepeatableAttribute_methods[] = { + ZEND_FE_END +}; + + static const zend_function_entry class_ZendTestParameterAttribute_methods[] = { ZEND_ME(ZendTestParameterAttribute, __construct, arginfo_class_ZendTestParameterAttribute___construct, ZEND_ACC_PUBLIC) ZEND_FE_END @@ -492,19 +497,19 @@ static zend_class_entry *register_class__ZendTestTrait(void) zend_string_release(property_testProp_name); #if (PHP_VERSION_ID >= 80200) - zend_string *attribute_name_ZendTestAttribute_const_TEST_CONST_1 = zend_string_init_interned("ZendTestAttribute", sizeof("ZendTestAttribute") - 1, 1); - zend_add_class_constant_attribute(class_entry, const_TEST_CONST, attribute_name_ZendTestAttribute_const_TEST_CONST_1, 0); - zend_string_release(attribute_name_ZendTestAttribute_const_TEST_CONST_1); + zend_string *attribute_name_ZendTestRepeatableAttribute_const_TEST_CONST_1 = zend_string_init_interned("ZendTestRepeatableAttribute", sizeof("ZendTestRepeatableAttribute") - 1, 1); + zend_add_class_constant_attribute(class_entry, const_TEST_CONST, attribute_name_ZendTestRepeatableAttribute_const_TEST_CONST_1, 0); + zend_string_release(attribute_name_ZendTestRepeatableAttribute_const_TEST_CONST_1); - zend_string *attribute_name_ZendTestAttribute_const_TEST_CONST_2 = zend_string_init_interned("ZendTestAttribute", sizeof("ZendTestAttribute") - 1, 1); - zend_add_class_constant_attribute(class_entry, const_TEST_CONST, attribute_name_ZendTestAttribute_const_TEST_CONST_2, 0); - zend_string_release(attribute_name_ZendTestAttribute_const_TEST_CONST_2); + zend_string *attribute_name_ZendTestRepeatableAttribute_const_TEST_CONST_2 = zend_string_init_interned("ZendTestRepeatableAttribute", sizeof("ZendTestRepeatableAttribute") - 1, 1); + zend_add_class_constant_attribute(class_entry, const_TEST_CONST, attribute_name_ZendTestRepeatableAttribute_const_TEST_CONST_2, 0); + zend_string_release(attribute_name_ZendTestRepeatableAttribute_const_TEST_CONST_2); #endif #if (PHP_VERSION_ID >= 80200) - zend_string *attribute_name_ZendTestAttribute_property_testProp_1 = zend_string_init_interned("ZendTestAttribute", sizeof("ZendTestAttribute") - 1, 1); - zend_add_property_attribute(class_entry, property_testProp, attribute_name_ZendTestAttribute_property_testProp_1, 0); - zend_string_release(attribute_name_ZendTestAttribute_property_testProp_1); + zend_string *attribute_name_ZendTestRepeatableAttribute_property_testProp_1 = zend_string_init_interned("ZendTestRepeatableAttribute", sizeof("ZendTestRepeatableAttribute") - 1, 1); + zend_add_property_attribute(class_entry, property_testProp, attribute_name_ZendTestRepeatableAttribute_property_testProp_1, 0); + zend_string_release(attribute_name_ZendTestRepeatableAttribute_property_testProp_1); zend_string *attribute_name_ZendTestPropertyAttribute_property_testProp_2 = zend_string_init_interned("ZendTestPropertyAttribute", sizeof("ZendTestPropertyAttribute") - 1, 1); zend_attribute *attribute_ZendTestPropertyAttribute_property_testProp_2 = zend_add_property_attribute(class_entry, property_testProp, attribute_name_ZendTestPropertyAttribute_property_testProp_2, 1); @@ -537,13 +542,33 @@ static zend_class_entry *register_class_ZendTestAttribute(void) zend_attribute *attribute_Attribute_class_ZendTestAttribute_1 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ZendTestAttribute_1, 1); zend_string_release(attribute_name_Attribute_class_ZendTestAttribute_1); zval attribute_Attribute_class_ZendTestAttribute_1_arg0; - ZVAL_LONG(&attribute_Attribute_class_ZendTestAttribute_1_arg0, ZEND_ATTRIBUTE_IS_REPEATABLE); + ZVAL_LONG(&attribute_Attribute_class_ZendTestAttribute_1_arg0, ZEND_ATTRIBUTE_TARGET_ALL); ZVAL_COPY_VALUE(&attribute_Attribute_class_ZendTestAttribute_1->args[0].value, &attribute_Attribute_class_ZendTestAttribute_1_arg0); #endif return class_entry; } +static zend_class_entry *register_class_ZendTestRepeatableAttribute(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "ZendTestRepeatableAttribute", class_ZendTestRepeatableAttribute_methods); + class_entry = zend_register_internal_class_ex(&ce, NULL); + class_entry->ce_flags |= ZEND_ACC_FINAL; + +#if (PHP_VERSION_ID >= 80200) + zend_string *attribute_name_Attribute_class_ZendTestRepeatableAttribute_1 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_ZendTestRepeatableAttribute_1 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ZendTestRepeatableAttribute_1, 1); + zend_string_release(attribute_name_Attribute_class_ZendTestRepeatableAttribute_1); + zval attribute_Attribute_class_ZendTestRepeatableAttribute_1_arg0; + ZVAL_LONG(&attribute_Attribute_class_ZendTestRepeatableAttribute_1_arg0, ZEND_ATTRIBUTE_IS_REPEATABLE); + ZVAL_COPY_VALUE(&attribute_Attribute_class_ZendTestRepeatableAttribute_1->args[0].value, &attribute_Attribute_class_ZendTestRepeatableAttribute_1_arg0); +#endif + + return class_entry; +} + static zend_class_entry *register_class_ZendTestParameterAttribute(void) { zend_class_entry ce, *class_entry; diff --git a/ext/zend_test/tests/gen_stub_test_03.phpt b/ext/zend_test/tests/gen_stub_test_03.phpt index 19d82cb1590a8..da29df1ce5cbd 100644 --- a/ext/zend_test/tests/gen_stub_test_03.phpt +++ b/ext/zend_test/tests/gen_stub_test_03.phpt @@ -11,6 +11,7 @@ class Foo { $reflectionConstant = new ReflectionClassConstant(Foo::class, "TEST_CONST"); var_dump($reflectionConstant->getAttributes()[0]->newInstance()); +var_dump($reflectionConstant->getAttributes()[1]->newInstance()); $reflectionProperty = new ReflectionProperty(Foo::class, "testProp"); var_dump($reflectionProperty->getAttributes()[0]->newInstance()); @@ -21,9 +22,11 @@ var_dump($reflectionMethod->getAttributes()[0]->newInstance()); ?> --EXPECTF-- -object(ZendTestAttribute)#%d (%d) { +object(ZendTestRepeatableAttribute)#%d (%d) { } -object(ZendTestAttribute)#%d (%d) { +object(ZendTestRepeatableAttribute)#%d (%d) { +} +object(ZendTestRepeatableAttribute)#%d (%d) { } object(ZendTestPropertyAttribute)#%d (%d) { ["parameter"]=> From 2abe28bb923634941adf6c6541e59d0cee0fefb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Sat, 1 Jul 2023 12:38:09 +0200 Subject: [PATCH 3/3] Remove trait test --- ext/zend_test/test.c | 9 +++++++ ext/zend_test/test.stub.php | 9 ++++++- ext/zend_test/test_arginfo.h | 33 ++++++++++++++++++++--- ext/zend_test/tests/gen_stub_test_03.phpt | 10 +++---- 4 files changed, 49 insertions(+), 12 deletions(-) diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index dfd94d99f1910..2b3f47a7e181a 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -37,6 +37,7 @@ ZEND_DECLARE_MODULE_GLOBALS(zend_test) static zend_class_entry *zend_test_interface; static zend_class_entry *zend_test_class; static zend_class_entry *zend_test_child_class; +static zend_class_entry *zend_attribute_test_class; static zend_class_entry *zend_test_trait; static zend_class_entry *zend_test_attribute; static zend_class_entry *zend_test_repeatable_attribute; @@ -597,6 +598,12 @@ static ZEND_METHOD(_ZendTestChildClass, returnsThrowable) zend_throw_error(NULL, "Dummy"); } +static ZEND_METHOD(ZendAttributeTest, testMethod) +{ + ZEND_PARSE_PARAMETERS_NONE(); + RETURN_TRUE; +} + static ZEND_METHOD(_ZendTestTrait, testMethod) { ZEND_PARSE_PARAMETERS_NONE(); @@ -727,6 +734,8 @@ PHP_MINIT_FUNCTION(zend_test) memcpy(&zend_test_class_handlers, &std_object_handlers, sizeof(zend_object_handlers)); zend_test_class_handlers.get_method = zend_test_class_method_get; + zend_attribute_test_class = register_class_ZendAttributeTest(); + zend_test_trait = register_class__ZendTestTrait(); register_test_symbols(module_number); diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php index 3edf828164da1..0b194fe26a157 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -52,7 +52,7 @@ class _ZendTestChildClass extends _ZendTestClass public function returnsThrowable(): Exception {} } - trait _ZendTestTrait { + class ZendAttributeTest { /** @var int */ #[ZendTestRepeatableAttribute] #[ZendTestRepeatableAttribute] @@ -67,6 +67,13 @@ trait _ZendTestTrait { public function testMethod(): bool {} } + trait _ZendTestTrait { + /** @var mixed */ + public $testProp; + + public function testMethod(): bool {} + } + #[Attribute(Attribute::TARGET_ALL)] final class ZendTestAttribute { } diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h index e102ef469c701..ae47fda5d9d43 100644 --- a/ext/zend_test/test_arginfo.h +++ b/ext/zend_test/test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 83b3d7beb8424627b1171a9190e06163b8a03450 */ + * Stub hash: fed29c0792c3d4d3ef9a1f5cedd8380fbf86e972 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -138,6 +138,8 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class__ZendTestChildClass_returnsThrowable, 0, 0, Exception, 0) ZEND_END_ARG_INFO() +#define arginfo_class_ZendAttributeTest_testMethod arginfo_ZendTestNS2_namespaced_func + #define arginfo_class__ZendTestTrait_testMethod arginfo_ZendTestNS2_namespaced_func ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ZendTestParameterAttribute___construct, 0, 0, 1) @@ -207,6 +209,7 @@ static ZEND_METHOD(_ZendTestClass, returnsStatic); static ZEND_METHOD(_ZendTestClass, returnsThrowable); static ZEND_METHOD(_ZendTestClass, variadicTest); static ZEND_METHOD(_ZendTestChildClass, returnsThrowable); +static ZEND_METHOD(ZendAttributeTest, testMethod); static ZEND_METHOD(_ZendTestTrait, testMethod); static ZEND_METHOD(ZendTestParameterAttribute, __construct); static ZEND_METHOD(ZendTestPropertyAttribute, __construct); @@ -283,6 +286,12 @@ static const zend_function_entry class__ZendTestChildClass_methods[] = { }; +static const zend_function_entry class_ZendAttributeTest_methods[] = { + ZEND_ME(ZendAttributeTest, testMethod, arginfo_class_ZendAttributeTest_testMethod, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + + static const zend_function_entry class__ZendTestTrait_methods[] = { ZEND_ME(_ZendTestTrait, testMethod, arginfo_class__ZendTestTrait_testMethod, ZEND_ACC_PUBLIC) ZEND_FE_END @@ -476,13 +485,12 @@ static zend_class_entry *register_class__ZendTestChildClass(zend_class_entry *cl return class_entry; } -static zend_class_entry *register_class__ZendTestTrait(void) +static zend_class_entry *register_class_ZendAttributeTest(void) { zend_class_entry ce, *class_entry; - INIT_CLASS_ENTRY(ce, "_ZendTestTrait", class__ZendTestTrait_methods); + INIT_CLASS_ENTRY(ce, "ZendAttributeTest", class_ZendAttributeTest_methods); class_entry = zend_register_internal_class_ex(&ce, NULL); - class_entry->ce_flags |= ZEND_ACC_TRAIT; zval const_TEST_CONST_value; ZVAL_LONG(&const_TEST_CONST_value, 1); @@ -529,6 +537,23 @@ static zend_class_entry *register_class__ZendTestTrait(void) return class_entry; } +static zend_class_entry *register_class__ZendTestTrait(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "_ZendTestTrait", class__ZendTestTrait_methods); + class_entry = zend_register_internal_class_ex(&ce, NULL); + class_entry->ce_flags |= ZEND_ACC_TRAIT; + + zval property_testProp_default_value; + ZVAL_NULL(&property_testProp_default_value); + zend_string *property_testProp_name = zend_string_init("testProp", sizeof("testProp") - 1, 1); + zend_declare_typed_property(class_entry, property_testProp_name, &property_testProp_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_NONE(0)); + zend_string_release(property_testProp_name); + + return class_entry; +} + static zend_class_entry *register_class_ZendTestAttribute(void) { zend_class_entry ce, *class_entry; diff --git a/ext/zend_test/tests/gen_stub_test_03.phpt b/ext/zend_test/tests/gen_stub_test_03.phpt index da29df1ce5cbd..8d7748f3a5c72 100644 --- a/ext/zend_test/tests/gen_stub_test_03.phpt +++ b/ext/zend_test/tests/gen_stub_test_03.phpt @@ -5,19 +5,15 @@ zend_test --FILE-- getAttributes()[0]->newInstance()); var_dump($reflectionConstant->getAttributes()[1]->newInstance()); -$reflectionProperty = new ReflectionProperty(Foo::class, "testProp"); +$reflectionProperty = new ReflectionProperty(ZendAttributeTest::class, "testProp"); var_dump($reflectionProperty->getAttributes()[0]->newInstance()); var_dump($reflectionProperty->getAttributes()[1]->newInstance()); -$reflectionMethod = new ReflectionMethod(Foo::class, "testMethod"); +$reflectionMethod = new ReflectionMethod(ZendAttributeTest::class, "testMethod"); var_dump($reflectionMethod->getAttributes()[0]->newInstance()); ?>