From c934e2419745baed5daad70c04faaa911682f629 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] Fix GH-9967 Add support for generating custom function, class const, and property attributes in stubs --- Zend/zend_attributes_arginfo.h | 60 ++--- Zend/zend_builtin_functions_arginfo.h | 6 +- Zend/zend_exceptions_arginfo.h | 8 +- build/gen_stub.php | 302 +++++++++++++++++----- 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.c | 13 + ext/zend_test/test.stub.php | 18 ++ ext/zend_test/test_arginfo.h | 186 +++++++++---- ext/zend_test/tests/gen_stub_test_03.phpt | 32 +++ 14 files changed, 486 insertions(+), 173 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 ad5235bfe96..3f0b85726ce 100644 --- a/Zend/zend_attributes_arginfo.h +++ b/Zend/zend_attributes_arginfo.h @@ -134,12 +134,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_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_Attribute_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_Attribute_0, 1); + zend_string_release(attribute_name_Attribute_class_Attribute_0); + zval attribute_Attribute_class_Attribute_0_arg0; + ZVAL_LONG(&attribute_Attribute_class_Attribute_0_arg0, ZEND_ATTRIBUTE_TARGET_CLASS); + ZVAL_COPY_VALUE(&attribute_Attribute_class_Attribute_0->args[0].value, &attribute_Attribute_class_Attribute_0_arg0); return class_entry; } @@ -152,12 +152,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_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_ReturnTypeWillChange_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ReturnTypeWillChange_0, 1); + zend_string_release(attribute_name_Attribute_class_ReturnTypeWillChange_0); + zval attribute_Attribute_class_ReturnTypeWillChange_0_arg0; + ZVAL_LONG(&attribute_Attribute_class_ReturnTypeWillChange_0_arg0, ZEND_ATTRIBUTE_TARGET_METHOD); + ZVAL_COPY_VALUE(&attribute_Attribute_class_ReturnTypeWillChange_0->args[0].value, &attribute_Attribute_class_ReturnTypeWillChange_0_arg0); return class_entry; } @@ -170,12 +170,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_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_AllowDynamicProperties_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_AllowDynamicProperties_0, 1); + zend_string_release(attribute_name_Attribute_class_AllowDynamicProperties_0); + zval attribute_Attribute_class_AllowDynamicProperties_0_arg0; + ZVAL_LONG(&attribute_Attribute_class_AllowDynamicProperties_0_arg0, ZEND_ATTRIBUTE_TARGET_CLASS); + ZVAL_COPY_VALUE(&attribute_Attribute_class_AllowDynamicProperties_0->args[0].value, &attribute_Attribute_class_AllowDynamicProperties_0_arg0); return class_entry; } @@ -188,12 +188,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_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_SensitiveParameter_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_SensitiveParameter_0, 1); + zend_string_release(attribute_name_Attribute_class_SensitiveParameter_0); + zval attribute_Attribute_class_SensitiveParameter_0_arg0; + ZVAL_LONG(&attribute_Attribute_class_SensitiveParameter_0_arg0, ZEND_ATTRIBUTE_TARGET_PARAMETER); + ZVAL_COPY_VALUE(&attribute_Attribute_class_SensitiveParameter_0->args[0].value, &attribute_Attribute_class_SensitiveParameter_0_arg0); return class_entry; } @@ -223,12 +223,12 @@ static zend_class_entry *register_class_Override(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_Override = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); - zend_attribute *attribute_Attribute_class_Override = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_Override, 1); - zend_string_release(attribute_name_Attribute_class_Override); - zval attribute_Attribute_class_Override_arg0; - ZVAL_LONG(&attribute_Attribute_class_Override_arg0, ZEND_ATTRIBUTE_TARGET_METHOD); - ZVAL_COPY_VALUE(&attribute_Attribute_class_Override->args[0].value, &attribute_Attribute_class_Override_arg0); + zend_string *attribute_name_Attribute_class_Override_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_Override_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_Override_0, 1); + zend_string_release(attribute_name_Attribute_class_Override_0); + zval attribute_Attribute_class_Override_0_arg0; + ZVAL_LONG(&attribute_Attribute_class_Override_0_arg0, ZEND_ATTRIBUTE_TARGET_METHOD); + ZVAL_COPY_VALUE(&attribute_Attribute_class_Override_0->args[0].value, &attribute_Attribute_class_Override_0_arg0); return class_entry; } diff --git a/Zend/zend_builtin_functions_arginfo.h b/Zend/zend_builtin_functions_arginfo.h index d451c1a0809..aa28fd47bd2 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_0 = zend_string_init_interned("AllowDynamicProperties", sizeof("AllowDynamicProperties") - 1, 1); + zend_add_class_attribute(class_entry, attribute_name_AllowDynamicProperties_class_stdClass_0, 0); + zend_string_release(attribute_name_AllowDynamicProperties_class_stdClass_0); return class_entry; } diff --git a/Zend/zend_exceptions_arginfo.h b/Zend/zend_exceptions_arginfo.h index bbde13e275d..c0e274d64ef 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 0ab8ca26adf..6050184b2a4 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; @@ -902,8 +903,12 @@ class ArgInfo { } } -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; @@ -951,6 +956,11 @@ class ConstName extends AbstractConstName { { return $this->const; } + + public function getDeclarationName(): string + { + return $this->name->toString(); + } } class ClassConstName extends AbstractConstName { @@ -972,9 +982,14 @@ class ClassConstName extends AbstractConstName { { 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; @@ -988,6 +1003,11 @@ class PropertyName { { return $this->class->toString() . "::$" . $this->property; } + + public function getDeclarationName(): string + { + return $this->property; + } } interface FunctionOrMethodName { @@ -1191,8 +1211,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( @@ -1208,7 +1231,8 @@ class FuncInfo { ReturnInfo $return, int $numRequiredArgs, ?string $cond, - bool $isUndocumentable + bool $isUndocumentable, + array $attributes ) { $this->name = $name; $this->classFlags = $classFlags; @@ -1223,6 +1247,7 @@ class FuncInfo { $this->numRequiredArgs = $numRequiredArgs; $this->cond = $cond; $this->isUndocumentable = $isUndocumentable; + $this->attributes = $attributes; } public function isMethod(): bool @@ -1418,6 +1443,7 @@ class FuncInfo { } public function discardInfoForOldPhpVersions(): void { + $this->attributes = []; $this->return->type = null; foreach ($this->args as $arg) { $arg->type = null; @@ -1632,7 +1658,7 @@ class EvaluatedValue static function (Expr $expr) use ($allConstInfos, &$isUnknownConstValue) { // $expr is a ConstFetch with a name of a C macro here if (!$expr instanceof Expr\ConstFetch) { - throw new Exception($this->getVariableTypeName() . " " . $this->getVariableLikeName() . " has an unsupported value"); + throw new Exception($this->getVariableTypeName() . " " . $this->name->__toString() . " has an unsupported value"); } $constName = $expr->name->__toString(); @@ -1753,27 +1779,32 @@ abstract class VariableLike public ?Type $phpDocType; public ?string $link; public ?int $phpVersionIdMinimumCompatibility; + /** @var AttributeInfo[] */ + public array $attributes; + /** + * @var AttributeInfo[] $attributes + */ public function __construct( int $flags, ?Type $type, ?Type $phpDocType, ?string $link, - ?int $phpVersionIdMinimumCompatibility + ?int $phpVersionIdMinimumCompatibility, + array $attributes ) { $this->flags = $flags; $this->type = $type; $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 getFieldSynopsisDefaultLinkend(): string; abstract protected function getFieldSynopsisName(): string; @@ -1821,7 +1852,6 @@ abstract class VariableLike $variableLikeType = $this->getVariableTypeName(); $typeCode = ""; - if ($this->type) { $arginfoType = $this->type->toArginfoType(); if ($arginfoType->hasClassType()) { @@ -1859,6 +1889,8 @@ abstract class VariableLike } else { $typeCode = "(zend_type) ZEND_TYPE_INIT_MASK(" . $arginfoType->toTypeMask() . ")"; } + } else { + $typeCode = "(zend_type) ZEND_TYPE_INIT_NONE(0)"; } return $typeCode; @@ -1939,6 +1971,9 @@ class ConstInfo extends VariableLike public ?string $cond; public ?string $cValue; + /** + * @var AttributeInfo[] $attributes + */ public function __construct( ConstOrClassConstName $name, int $flags, @@ -1950,7 +1985,8 @@ class ConstInfo extends VariableLike ?string $cond, ?string $cValue, ?string $link, - ?int $phpVersionIdMinimumCompatibility + ?int $phpVersionIdMinimumCompatibility, + array $attributes ) { $this->name = $name; $this->value = $value; @@ -1958,7 +1994,7 @@ class ConstInfo extends VariableLike $this->isDeprecated = $isDeprecated; $this->cond = $cond; $this->cValue = $cValue; - parent::__construct($flags, $type, $phpDocType, $link, $phpVersionIdMinimumCompatibility); + parent::__construct($flags, $type, $phpDocType, $link, $phpVersionIdMinimumCompatibility, $attributes); } /** @@ -1979,11 +2015,6 @@ class ConstInfo extends VariableLike return "constant"; } - protected function getVariableLikeName(): string - { - return $this->name->const; - } - protected function getVariableTypeCode(): string { return "const"; @@ -1993,7 +2024,7 @@ class ConstInfo extends VariableLike { $className = str_replace(["\\", "_"], ["-", "-"], $this->name->class->toLowerString()); - return "$className.constants." . strtolower(str_replace("_", "-", $this->getVariableLikeName())); + return "$className.constants." . strtolower(str_replace("_", "-", $this->name->getDeclarationName())); } protected function getFieldSynopsisName(): string @@ -2024,6 +2055,7 @@ class ConstInfo extends VariableLike $this->type = null; $this->flags &= ~Class_::MODIFIER_FINAL; $this->isDeprecated = false; + $this->attributes = []; } /** @@ -2110,7 +2142,7 @@ class ConstInfo extends VariableLike */ private function getClassConstDeclaration(EvaluatedValue $value, iterable $allConstInfos): string { - $constName = $this->getVariableLikeName(); + $constName = $this->name->getDeclarationName(); $zvalCode = $value->initializeZval("const_{$constName}_value", $allConstInfos); @@ -2127,7 +2159,14 @@ class ConstInfo extends VariableLike if ($this->type) { $typeCode = $this->getTypeCode($constName, $code); - $template = "\tzend_declare_typed_class_constant(class_entry, $nameCode, &const_{$constName}_value, %s, NULL, $typeCode);\n"; + + if (!empty($this->attributes)) { + $template = "\tzend_class_constant *const_" . $this->name->getDeclarationName() . " = "; + } else { + $template = "\t"; + } + $template .= "zend_declare_typed_class_constant(class_entry, $nameCode, &const_{$constName}_value, %s, NULL, $typeCode);\n"; + $flagsCode = generateVersionDependentFlagCode( $template, $this->getFlagsByPhpVersion(), @@ -2141,7 +2180,12 @@ class ConstInfo extends VariableLike } if (!$this->type || !$php83MinimumCompatibility) { - $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(), @@ -2234,6 +2278,9 @@ class PropertyInfo extends VariableLike public ?string $defaultValueString; public bool $isDocReadonly; + /** + * @var AttributeInfo[] $attributes + */ public function __construct( PropertyName $name, int $flags, @@ -2243,13 +2290,14 @@ class PropertyInfo extends VariableLike ?string $defaultValueString, bool $isDocReadonly, ?string $link, - ?int $phpVersionIdMinimumCompatibility + ?int $phpVersionIdMinimumCompatibility, + array $attributes ) { $this->name = $name; $this->defaultValue = $defaultValue; $this->defaultValueString = $defaultValueString; $this->isDocReadonly = $isDocReadonly; - parent::__construct($flags, $type, $phpDocType, $link, $phpVersionIdMinimumCompatibility); + parent::__construct($flags, $type, $phpDocType, $link, $phpVersionIdMinimumCompatibility, $attributes); } protected function getVariableTypeCode(): string @@ -2262,21 +2310,16 @@ class PropertyInfo extends VariableLike return "property"; } - protected function getVariableLikeName(): string - { - return $this->name->property; - } - protected function getFieldSynopsisDefaultLinkend(): string { $className = str_replace(["\\", "_"], ["-", "-"], $this->name->class->toLowerString()); - return "$className.props." . strtolower(str_replace("_", "-", $this->getVariableLikeName())); + return "$className.props." . strtolower(str_replace("_", "-", $this->name->getDeclarationName())); } protected function getFieldSynopsisName(): string { - return $this->getVariableLikeName(); + return $this->name->getDeclarationName(); } /** @@ -2290,6 +2333,7 @@ class PropertyInfo extends VariableLike public function discardInfoForOldPhpVersions(): void { $this->type = null; $this->flags &= ~Class_::MODIFIER_READONLY; + $this->attributes = []; } /** @@ -2298,7 +2342,7 @@ class PropertyInfo extends VariableLike public function getDeclaration(iterable $allConstInfos): string { $code = "\n"; - $propertyName = $this->getVariableLikeName(); + $propertyName = $this->name->getDeclarationName(); if ($this->defaultValue === null) { $defaultValue = EvaluatedValue::null(); @@ -2319,13 +2363,14 @@ class PropertyInfo extends VariableLike $code .= "\tzend_string *property_{$propertyName}_name = zend_string_init(\"$propertyName\", sizeof(\"$propertyName\") - 1, 1);\n"; $nameCode = "property_{$propertyName}_name"; + $typeCode = $this->getTypeCode($propertyName, $code); - if ($this->type !== null) { - $typeCode = $this->getTypeCode($propertyName, $code); - $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(), @@ -2614,8 +2659,13 @@ class ClassInfo { $code .= "\n#if (PHP_VERSION_ID >= " . PHP_80_VERSION_ID . ")"; } - foreach ($this->attributes as $attribute) { - $code .= $attribute->generateCode("zend_add_class_attribute(class_entry", "class_$escapedName", $allConstInfos, $this->phpVersionIdMinimumCompatibility); + foreach ($this->attributes as $key => $attribute) { + $code .= $attribute->generateCode( + "zend_add_class_attribute(class_entry", + "class_{$escapedName}_$key", + $allConstInfos, + $this->phpVersionIdMinimumCompatibility + ); } if (!$php80MinimumCompatibility) { @@ -2623,7 +2673,31 @@ class ClassInfo { } } - if ($attributeInitializationCode = generateAttributeInitialization($this->funcInfos, $allConstInfos, $this->phpVersionIdMinimumCompatibility, $this->cond)) { + if ($attributeInitializationCode = generateConstantAttributeInitialization($this->constInfos, $allConstInfos, $this->phpVersionIdMinimumCompatibility, $this->cond)) { + if (!$php80MinimumCompatibility) { + $code .= "#if (PHP_VERSION_ID >= " . PHP_80_VERSION_ID . ")"; + } + + $code .= "\n" . $attributeInitializationCode; + + if (!$php80MinimumCompatibility) { + $code .= "#endif\n"; + } + } + + if ($attributeInitializationCode = generatePropertyAttributeInitialization($this->propertyInfos, $allConstInfos, $this->phpVersionIdMinimumCompatibility)) { + if (!$php80MinimumCompatibility) { + $code .= "#if (PHP_VERSION_ID >= " . PHP_80_VERSION_ID . ")"; + } + + $code .= "\n" . $attributeInitializationCode; + + if (!$php80MinimumCompatibility) { + $code .= "#endif\n"; + } + } + + if ($attributeInitializationCode = generateFunctionAttributeInitialization($this->funcInfos, $allConstInfos, $this->phpVersionIdMinimumCompatibility, $this->cond)) { if (!$php80MinimumCompatibility) { $code .= "#if (PHP_VERSION_ID >= " . PHP_80_VERSION_ID . ")\n"; } @@ -3381,12 +3455,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])) { @@ -3434,7 +3502,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; @@ -3471,13 +3539,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, @@ -3486,7 +3558,8 @@ function parseConstLike( ?Node $type, ?DocComment $docComment, ?string $cond, - ?int $phpVersionIdMinimumCompatibility + ?int $phpVersionIdMinimumCompatibility, + array $attributes ): ConstInfo { $phpDocType = null; $deprecated = false; @@ -3522,10 +3595,14 @@ function parseConstLike( $cond, $cValue, $link, - $phpVersionIdMinimumCompatibility + $phpVersionIdMinimumCompatibility, + $attributes ); } +/** + * @param array $attributes + */ function parseProperty( Name $class, int $flags, @@ -3533,7 +3610,8 @@ function parseProperty( ?Node $type, ?DocComment $comment, PrettyPrinterAbstract $prettyPrinter, - ?int $phpVersionIdMinimumCompatibility + ?int $phpVersionIdMinimumCompatibility, + array $attributes ): PropertyInfo { $phpDocType = null; $isDocReadonly = false; @@ -3577,7 +3655,8 @@ function parseProperty( $property->default ? $prettyPrinter->prettyPrintExpr($property->default) : null, $isDocReadonly, $link, - $phpVersionIdMinimumCompatibility + $phpVersionIdMinimumCompatibility, + $attributes ); } @@ -3624,14 +3703,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; } } @@ -3689,6 +3766,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()); @@ -3758,7 +3851,8 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac null, $stmt->getDocComment(), $cond, - $fileInfo->generateLegacyArginfoForPhpVersionId + $fileInfo->generateLegacyArginfoForPhpVersionId, + [] ); } continue; @@ -3802,7 +3896,8 @@ function handleStatements(FileInfo $fileInfo, array $stmts, PrettyPrinterAbstrac $classStmt->type, $classStmt->getDocComment(), $cond, - $fileInfo->generateLegacyArginfoForPhpVersionId + $fileInfo->generateLegacyArginfoForPhpVersionId, + createAttributes($classStmt->attrGroups) ); } } else if ($classStmt instanceof Stmt\Property) { @@ -3817,7 +3912,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) { @@ -4123,7 +4219,7 @@ function generateArgInfoCode( $php80MinimumCompatibility = $fileInfo->generateLegacyArginfoForPhpVersionId === null || $fileInfo->generateLegacyArginfoForPhpVersionId >= PHP_80_VERSION_ID; if ($fileInfo->generateClassEntries) { - if ($attributeInitializationCode = generateAttributeInitialization($fileInfo->funcInfos, $allConstInfos, $fileInfo->generateLegacyArginfoForPhpVersionId, null)) { + if ($attributeInitializationCode = generateFunctionAttributeInitialization($fileInfo->funcInfos, $allConstInfos, $fileInfo->generateLegacyArginfoForPhpVersionId, null)) { if (!$php80MinimumCompatibility) { $attributeInitializationCode = "\n#if (PHP_VERSION_ID >= " . PHP_80_VERSION_ID . ")" . $attributeInitializationCode . "#endif\n"; } @@ -4191,25 +4287,40 @@ function generateFunctionEntries(?Name $className, array $funcInfos, ?string $co return $code; } + /** * @param iterable $funcInfos */ -function generateAttributeInitialization(iterable $funcInfos, iterable $allConstInfos, ?int $phpVersionIdMinimumCompatibility, ?string $parentCond = null): string { +function generateFunctionAttributeInitialization(iterable $funcInfos, iterable $allConstInfos, ?int $phpVersionIdMinimumCompatibility, ?string $parentCond = null): string { return generateCodeWithConditions( $funcInfos, "", static function (FuncInfo $funcInfo) use ($allConstInfos, $phpVersionIdMinimumCompatibility) { $code = null; - foreach ($funcInfo->args as $index => $arg) { - if ($funcInfo->name instanceof MethodName) { - $functionTable = "&class_entry->function_table"; - } else { - $functionTable = "CG(function_table)"; - } + if ($funcInfo->name instanceof MethodName) { + $functionTable = "&class_entry->function_table"; + } else { + $functionTable = "CG(function_table)"; + } - 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, $phpVersionIdMinimumCompatibility); + 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", + $allConstInfos, + $phpVersionIdMinimumCompatibility + ); + } + + foreach ($funcInfo->args as $index => $arg) { + 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", + $allConstInfos, + $phpVersionIdMinimumCompatibility + ); } } @@ -4219,6 +4330,59 @@ function generateAttributeInitialization(iterable $funcInfos, iterable $allConst ); } +/** + * @param iterable $constInfos + */ +function generateConstantAttributeInitialization( + iterable $constInfos, + iterable $allConstInfos, + ?int $phpVersionIdMinimumCompatibility, + ?string $parentCond = null +): string { + return generateCodeWithConditions( + $constInfos, + "", + static function (ConstInfo $constInfo) use ($allConstInfos, $phpVersionIdMinimumCompatibility) { + $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", + $allConstInfos, + $phpVersionIdMinimumCompatibility + ); + } + + return $code; + }, + $parentCond + ); +} + +/** + * @param iterable $propertyInfos + */ +function generatePropertyAttributeInitialization( + iterable $propertyInfos, + iterable $allConstInfos, + ?int $phpVersionIdMinimumCompatibility +): 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, + $allConstInfos, + $phpVersionIdMinimumCompatibility + ); + } + } + + 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 1878758671e..76d8b0af2b0 100644 --- a/ext/dom/php_dom_arginfo.h +++ b/ext/dom/php_dom_arginfo.h @@ -1656,7 +1656,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 a6869afd2e6..111cdec7e98 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_0 = zend_string_init_interned("AllowDynamicProperties", sizeof("AllowDynamicProperties") - 1, 1); + zend_add_class_attribute(class_entry, attribute_name_AllowDynamicProperties_class_OCILob_0, 0); + zend_string_release(attribute_name_AllowDynamicProperties_class_OCILob_0); 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_0 = zend_string_init_interned("AllowDynamicProperties", sizeof("AllowDynamicProperties") - 1, 1); + zend_add_class_attribute(class_entry, attribute_name_AllowDynamicProperties_class_OCICollection_0, 0); + zend_string_release(attribute_name_AllowDynamicProperties_class_OCICollection_0); return class_entry; } diff --git a/ext/pdo/pdo_arginfo.h b/ext/pdo/pdo_arginfo.h index 9f8a0c6cc20..15489b7cc23 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 dd1deb1c579..020b294052d 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 36b9cb1b9dc..39500b2b582 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -4005,9 +4005,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_0 = zend_string_init_interned("AllowDynamicProperties", sizeof("AllowDynamicProperties") - 1, 1); + zend_add_class_attribute(class_entry, attribute_name_AllowDynamicProperties_class___PHP_Incomplete_Class_0, 0); + zend_string_release(attribute_name_AllowDynamicProperties_class___PHP_Incomplete_Class_0); return class_entry; } diff --git a/ext/standard/user_filters_arginfo.h b/ext/standard/user_filters_arginfo.h index a7321962412..ccfbc5eadc3 100644 --- a/ext/standard/user_filters_arginfo.h +++ b/ext/standard/user_filters_arginfo.h @@ -59,7 +59,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.c b/ext/zend_test/test.c index 22c4c1340ad..1b294050a8e 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -44,8 +44,10 @@ 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; 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; @@ -763,6 +765,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(); @@ -1003,6 +1011,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); @@ -1013,6 +1023,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 0dad54739ab..b78704f161c 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -62,6 +62,21 @@ namespace { public function returnsThrowable(): Exception {} } + class ZendAttributeTest { + /** @var int */ + #[ZendTestRepeatableAttribute] + #[ZendTestRepeatableAttribute] + public const TEST_CONST = 1; + + /** @var mixed */ + #[ZendTestRepeatableAttribute] + #[ZendTestPropertyAttribute("testProp")] + public $testProp; + + #[ZendTestAttribute] + public function testMethod(): bool {} + } + trait _ZendTestTrait { /** @var mixed */ public $testProp; @@ -72,7 +87,10 @@ namespace { #[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 1b89d2de24c..4a436461728 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: f2d1e5675f75661048645bedc2e73b7d4894f8dc */ + * Stub hash: db7a89e93849c707caa1c536f717e0cf50dcfb74 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -179,6 +179,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) @@ -264,6 +266,7 @@ static ZEND_METHOD(_ZendTestClass, returnsThrowable); static ZEND_METHOD(_ZendTestClass, variadicTest); static ZEND_METHOD(_ZendTestClass, takesUnionType); 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); @@ -356,6 +359,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 @@ -367,6 +376,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 @@ -450,13 +464,13 @@ static void register_test_symbols(int module_number) REGISTER_STRING_CONSTANT("ZendTestNS2\\ZendSubNS\\ZEND_CONSTANT_A", "namespaced", CONST_PERSISTENT); - zend_string *attribute_name_ZendTestParameterAttribute_zend_test_parameter_with_attribute_arg0 = zend_string_init_interned("ZendTestParameterAttribute", sizeof("ZendTestParameterAttribute") - 1, 1); - zend_attribute *attribute_ZendTestParameterAttribute_zend_test_parameter_with_attribute_arg0 = zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "zend_test_parameter_with_attribute", sizeof("zend_test_parameter_with_attribute") - 1), 0, attribute_name_ZendTestParameterAttribute_zend_test_parameter_with_attribute_arg0, 1); - zend_string_release(attribute_name_ZendTestParameterAttribute_zend_test_parameter_with_attribute_arg0); - zval attribute_ZendTestParameterAttribute_zend_test_parameter_with_attribute_arg0_arg0; - zend_string *attribute_ZendTestParameterAttribute_zend_test_parameter_with_attribute_arg0_arg0_str = zend_string_init("value1", strlen("value1"), 1); - ZVAL_STR(&attribute_ZendTestParameterAttribute_zend_test_parameter_with_attribute_arg0_arg0, attribute_ZendTestParameterAttribute_zend_test_parameter_with_attribute_arg0_arg0_str); - ZVAL_COPY_VALUE(&attribute_ZendTestParameterAttribute_zend_test_parameter_with_attribute_arg0->args[0].value, &attribute_ZendTestParameterAttribute_zend_test_parameter_with_attribute_arg0_arg0); + zend_string *attribute_name_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0 = zend_string_init_interned("ZendTestParameterAttribute", sizeof("ZendTestParameterAttribute") - 1, 1); + zend_attribute *attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0 = zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "zend_test_parameter_with_attribute", sizeof("zend_test_parameter_with_attribute") - 1), 0, attribute_name_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0, 1); + zend_string_release(attribute_name_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0); + zval attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0_arg0; + zend_string *attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0_arg0_str = zend_string_init("value1", strlen("value1"), 1); + ZVAL_STR(&attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0_arg0, attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0_arg0_str); + ZVAL_COPY_VALUE(&attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0->args[0].value, &attribute_ZendTestParameterAttribute_func_zend_test_parameter_with_attribute_arg0_0_arg0); } static zend_class_entry *register_class__ZendTestInterface(void) @@ -517,7 +531,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; @@ -588,6 +602,55 @@ static zend_class_entry *register_class__ZendTestChildClass(zend_class_entry *cl return class_entry; } +static zend_class_entry *register_class_ZendAttributeTest(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "ZendAttributeTest", class_ZendAttributeTest_methods); + class_entry = zend_register_internal_class_ex(&ce, NULL); + + 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_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); + + + zend_string *attribute_name_ZendTestRepeatableAttribute_const_TEST_CONST_0 = 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_0, 0); + zend_string_release(attribute_name_ZendTestRepeatableAttribute_const_TEST_CONST_0); + + 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_ZendTestRepeatableAttribute_property_testProp_0 = zend_string_init_interned("ZendTestRepeatableAttribute", sizeof("ZendTestRepeatableAttribute") - 1, 1); + zend_add_property_attribute(class_entry, property_testProp, attribute_name_ZendTestRepeatableAttribute_property_testProp_0, 0); + zend_string_release(attribute_name_ZendTestRepeatableAttribute_property_testProp_0); + + zend_string *attribute_name_ZendTestPropertyAttribute_property_testProp_1 = zend_string_init_interned("ZendTestPropertyAttribute", sizeof("ZendTestPropertyAttribute") - 1, 1); + zend_attribute *attribute_ZendTestPropertyAttribute_property_testProp_1 = zend_add_property_attribute(class_entry, property_testProp, attribute_name_ZendTestPropertyAttribute_property_testProp_1, 1); + zend_string_release(attribute_name_ZendTestPropertyAttribute_property_testProp_1); + zval attribute_ZendTestPropertyAttribute_property_testProp_1_arg0; + zend_string *attribute_ZendTestPropertyAttribute_property_testProp_1_arg0_str = zend_string_init("testProp", strlen("testProp"), 1); + ZVAL_STR(&attribute_ZendTestPropertyAttribute_property_testProp_1_arg0, attribute_ZendTestPropertyAttribute_property_testProp_1_arg0_str); + ZVAL_COPY_VALUE(&attribute_ZendTestPropertyAttribute_property_testProp_1->args[0].value, &attribute_ZendTestPropertyAttribute_property_testProp_1_arg0); + + + zend_string *attribute_name_ZendTestAttribute_func_testmethod_0 = 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_0, 0); + zend_string_release(attribute_name_ZendTestAttribute_func_testmethod_0); + + return class_entry; +} + static zend_class_entry *register_class__ZendTestTrait(void) { zend_class_entry ce, *class_entry; @@ -599,7 +662,7 @@ static zend_class_entry *register_class__ZendTestTrait(void) 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_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); zval property_classUnionProp_default_value; @@ -626,12 +689,30 @@ static zend_class_entry *register_class_ZendTestAttribute(void) class_entry = zend_register_internal_class_ex(&ce, NULL); class_entry->ce_flags |= ZEND_ACC_FINAL; - 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_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_ZendTestAttribute_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ZendTestAttribute_0, 1); + zend_string_release(attribute_name_Attribute_class_ZendTestAttribute_0); + zval attribute_Attribute_class_ZendTestAttribute_0_arg0; + ZVAL_LONG(&attribute_Attribute_class_ZendTestAttribute_0_arg0, ZEND_ATTRIBUTE_TARGET_ALL); + ZVAL_COPY_VALUE(&attribute_Attribute_class_ZendTestAttribute_0->args[0].value, &attribute_Attribute_class_ZendTestAttribute_0_arg0); + + 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; + + zend_string *attribute_name_Attribute_class_ZendTestRepeatableAttribute_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_ZendTestRepeatableAttribute_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ZendTestRepeatableAttribute_0, 1); + zend_string_release(attribute_name_Attribute_class_ZendTestRepeatableAttribute_0); + zval attribute_Attribute_class_ZendTestRepeatableAttribute_0_arg0; + ZVAL_LONG(&attribute_Attribute_class_ZendTestRepeatableAttribute_0_arg0, ZEND_ATTRIBUTE_TARGET_ALL | ZEND_ATTRIBUTE_IS_REPEATABLE); + ZVAL_COPY_VALUE(&attribute_Attribute_class_ZendTestRepeatableAttribute_0->args[0].value, &attribute_Attribute_class_ZendTestRepeatableAttribute_0_arg0); return class_entry; } @@ -650,12 +731,12 @@ static zend_class_entry *register_class_ZendTestParameterAttribute(void) zend_declare_typed_property(class_entry, property_parameter_name, &property_parameter_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); zend_string_release(property_parameter_name); - 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_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_ZendTestParameterAttribute_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ZendTestParameterAttribute_0, 1); + zend_string_release(attribute_name_Attribute_class_ZendTestParameterAttribute_0); + zval attribute_Attribute_class_ZendTestParameterAttribute_0_arg0; + ZVAL_LONG(&attribute_Attribute_class_ZendTestParameterAttribute_0_arg0, ZEND_ATTRIBUTE_TARGET_PARAMETER); + ZVAL_COPY_VALUE(&attribute_Attribute_class_ZendTestParameterAttribute_0->args[0].value, &attribute_Attribute_class_ZendTestParameterAttribute_0_arg0); return class_entry; } @@ -674,12 +755,12 @@ static zend_class_entry *register_class_ZendTestPropertyAttribute(void) zend_declare_typed_property(class_entry, property_parameter_name, &property_parameter_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); zend_string_release(property_parameter_name); - 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_0 = zend_string_init_interned("Attribute", sizeof("Attribute") - 1, 1); + zend_attribute *attribute_Attribute_class_ZendTestPropertyAttribute_0 = zend_add_class_attribute(class_entry, attribute_name_Attribute_class_ZendTestPropertyAttribute_0, 1); + zend_string_release(attribute_name_Attribute_class_ZendTestPropertyAttribute_0); + zval attribute_Attribute_class_ZendTestPropertyAttribute_0_arg0; + ZVAL_LONG(&attribute_Attribute_class_ZendTestPropertyAttribute_0_arg0, ZEND_ATTRIBUTE_TARGET_PROPERTY); + ZVAL_COPY_VALUE(&attribute_Attribute_class_ZendTestPropertyAttribute_0->args[0].value, &attribute_Attribute_class_ZendTestPropertyAttribute_0_arg0); return class_entry; } @@ -692,21 +773,21 @@ static zend_class_entry *register_class_ZendTestClassWithMethodWithParameterAttr class_entry = zend_register_internal_class_ex(&ce, NULL); - zend_string *attribute_name_ZendTestParameterAttribute_ZendTestClassWithMethodWithParameterAttribute_no_override_arg0 = zend_string_init_interned("ZendTestParameterAttribute", sizeof("ZendTestParameterAttribute") - 1, 1); - zend_attribute *attribute_ZendTestParameterAttribute_ZendTestClassWithMethodWithParameterAttribute_no_override_arg0 = zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "no_override", sizeof("no_override") - 1), 0, attribute_name_ZendTestParameterAttribute_ZendTestClassWithMethodWithParameterAttribute_no_override_arg0, 1); - zend_string_release(attribute_name_ZendTestParameterAttribute_ZendTestClassWithMethodWithParameterAttribute_no_override_arg0); - zval attribute_ZendTestParameterAttribute_ZendTestClassWithMethodWithParameterAttribute_no_override_arg0_arg0; - zend_string *attribute_ZendTestParameterAttribute_ZendTestClassWithMethodWithParameterAttribute_no_override_arg0_arg0_str = zend_string_init("value2", strlen("value2"), 1); - ZVAL_STR(&attribute_ZendTestParameterAttribute_ZendTestClassWithMethodWithParameterAttribute_no_override_arg0_arg0, attribute_ZendTestParameterAttribute_ZendTestClassWithMethodWithParameterAttribute_no_override_arg0_arg0_str); - ZVAL_COPY_VALUE(&attribute_ZendTestParameterAttribute_ZendTestClassWithMethodWithParameterAttribute_no_override_arg0->args[0].value, &attribute_ZendTestParameterAttribute_ZendTestClassWithMethodWithParameterAttribute_no_override_arg0_arg0); + zend_string *attribute_name_ZendTestParameterAttribute_func_no_override_arg0_0 = zend_string_init_interned("ZendTestParameterAttribute", sizeof("ZendTestParameterAttribute") - 1, 1); + zend_attribute *attribute_ZendTestParameterAttribute_func_no_override_arg0_0 = zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "no_override", sizeof("no_override") - 1), 0, attribute_name_ZendTestParameterAttribute_func_no_override_arg0_0, 1); + zend_string_release(attribute_name_ZendTestParameterAttribute_func_no_override_arg0_0); + zval attribute_ZendTestParameterAttribute_func_no_override_arg0_0_arg0; + zend_string *attribute_ZendTestParameterAttribute_func_no_override_arg0_0_arg0_str = zend_string_init("value2", strlen("value2"), 1); + ZVAL_STR(&attribute_ZendTestParameterAttribute_func_no_override_arg0_0_arg0, attribute_ZendTestParameterAttribute_func_no_override_arg0_0_arg0_str); + ZVAL_COPY_VALUE(&attribute_ZendTestParameterAttribute_func_no_override_arg0_0->args[0].value, &attribute_ZendTestParameterAttribute_func_no_override_arg0_0_arg0); - zend_string *attribute_name_ZendTestParameterAttribute_ZendTestClassWithMethodWithParameterAttribute_override_arg0 = zend_string_init_interned("ZendTestParameterAttribute", sizeof("ZendTestParameterAttribute") - 1, 1); - zend_attribute *attribute_ZendTestParameterAttribute_ZendTestClassWithMethodWithParameterAttribute_override_arg0 = zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "override", sizeof("override") - 1), 0, attribute_name_ZendTestParameterAttribute_ZendTestClassWithMethodWithParameterAttribute_override_arg0, 1); - zend_string_release(attribute_name_ZendTestParameterAttribute_ZendTestClassWithMethodWithParameterAttribute_override_arg0); - zval attribute_ZendTestParameterAttribute_ZendTestClassWithMethodWithParameterAttribute_override_arg0_arg0; - zend_string *attribute_ZendTestParameterAttribute_ZendTestClassWithMethodWithParameterAttribute_override_arg0_arg0_str = zend_string_init("value3", strlen("value3"), 1); - ZVAL_STR(&attribute_ZendTestParameterAttribute_ZendTestClassWithMethodWithParameterAttribute_override_arg0_arg0, attribute_ZendTestParameterAttribute_ZendTestClassWithMethodWithParameterAttribute_override_arg0_arg0_str); - ZVAL_COPY_VALUE(&attribute_ZendTestParameterAttribute_ZendTestClassWithMethodWithParameterAttribute_override_arg0->args[0].value, &attribute_ZendTestParameterAttribute_ZendTestClassWithMethodWithParameterAttribute_override_arg0_arg0); + zend_string *attribute_name_ZendTestParameterAttribute_func_override_arg0_0 = zend_string_init_interned("ZendTestParameterAttribute", sizeof("ZendTestParameterAttribute") - 1, 1); + zend_attribute *attribute_ZendTestParameterAttribute_func_override_arg0_0 = zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "override", sizeof("override") - 1), 0, attribute_name_ZendTestParameterAttribute_func_override_arg0_0, 1); + zend_string_release(attribute_name_ZendTestParameterAttribute_func_override_arg0_0); + zval attribute_ZendTestParameterAttribute_func_override_arg0_0_arg0; + zend_string *attribute_ZendTestParameterAttribute_func_override_arg0_0_arg0_str = zend_string_init("value3", strlen("value3"), 1); + ZVAL_STR(&attribute_ZendTestParameterAttribute_func_override_arg0_0_arg0, attribute_ZendTestParameterAttribute_func_override_arg0_0_arg0_str); + ZVAL_COPY_VALUE(&attribute_ZendTestParameterAttribute_func_override_arg0_0->args[0].value, &attribute_ZendTestParameterAttribute_func_override_arg0_0_arg0); return class_entry; } @@ -719,13 +800,13 @@ static zend_class_entry *register_class_ZendTestChildClassWithMethodWithParamete class_entry = zend_register_internal_class_ex(&ce, class_entry_ZendTestClassWithMethodWithParameterAttribute); - zend_string *attribute_name_ZendTestParameterAttribute_ZendTestChildClassWithMethodWithParameterAttribute_override_arg0 = zend_string_init_interned("ZendTestParameterAttribute", sizeof("ZendTestParameterAttribute") - 1, 1); - zend_attribute *attribute_ZendTestParameterAttribute_ZendTestChildClassWithMethodWithParameterAttribute_override_arg0 = zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "override", sizeof("override") - 1), 0, attribute_name_ZendTestParameterAttribute_ZendTestChildClassWithMethodWithParameterAttribute_override_arg0, 1); - zend_string_release(attribute_name_ZendTestParameterAttribute_ZendTestChildClassWithMethodWithParameterAttribute_override_arg0); - zval attribute_ZendTestParameterAttribute_ZendTestChildClassWithMethodWithParameterAttribute_override_arg0_arg0; - zend_string *attribute_ZendTestParameterAttribute_ZendTestChildClassWithMethodWithParameterAttribute_override_arg0_arg0_str = zend_string_init("value4", strlen("value4"), 1); - ZVAL_STR(&attribute_ZendTestParameterAttribute_ZendTestChildClassWithMethodWithParameterAttribute_override_arg0_arg0, attribute_ZendTestParameterAttribute_ZendTestChildClassWithMethodWithParameterAttribute_override_arg0_arg0_str); - ZVAL_COPY_VALUE(&attribute_ZendTestParameterAttribute_ZendTestChildClassWithMethodWithParameterAttribute_override_arg0->args[0].value, &attribute_ZendTestParameterAttribute_ZendTestChildClassWithMethodWithParameterAttribute_override_arg0_arg0); + zend_string *attribute_name_ZendTestParameterAttribute_func_override_arg0_0 = zend_string_init_interned("ZendTestParameterAttribute", sizeof("ZendTestParameterAttribute") - 1, 1); + zend_attribute *attribute_ZendTestParameterAttribute_func_override_arg0_0 = zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "override", sizeof("override") - 1), 0, attribute_name_ZendTestParameterAttribute_func_override_arg0_0, 1); + zend_string_release(attribute_name_ZendTestParameterAttribute_func_override_arg0_0); + zval attribute_ZendTestParameterAttribute_func_override_arg0_0_arg0; + zend_string *attribute_ZendTestParameterAttribute_func_override_arg0_0_arg0_str = zend_string_init("value4", strlen("value4"), 1); + ZVAL_STR(&attribute_ZendTestParameterAttribute_func_override_arg0_0_arg0, attribute_ZendTestParameterAttribute_func_override_arg0_0_arg0_str); + ZVAL_COPY_VALUE(&attribute_ZendTestParameterAttribute_func_override_arg0_0->args[0].value, &attribute_ZendTestParameterAttribute_func_override_arg0_0_arg0); return class_entry; } @@ -740,9 +821,14 @@ static zend_class_entry *register_class_ZendTestClassWithPropertyAttribute(void) zval property_attributed_default_value; ZVAL_UNDEF(&property_attributed_default_value); zend_string *property_attributed_name = zend_string_init("attributed", sizeof("attributed") - 1, 1); - zend_declare_typed_property(class_entry, property_attributed_name, &property_attributed_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); + zend_property_info *property_attributed = zend_declare_typed_property(class_entry, property_attributed_name, &property_attributed_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); zend_string_release(property_attributed_name); + + zend_string *attribute_name_ZendTestAttribute_property_attributed_0 = zend_string_init_interned("ZendTestAttribute", sizeof("ZendTestAttribute") - 1, 1); + zend_add_property_attribute(class_entry, property_attributed, attribute_name_ZendTestAttribute_property_attributed_0, 0); + zend_string_release(attribute_name_ZendTestAttribute_property_attributed_0); + 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 00000000000..8d7748f3a5c --- /dev/null +++ b/ext/zend_test/tests/gen_stub_test_03.phpt @@ -0,0 +1,32 @@ +--TEST-- +gen_stub.php: Test that attributes are applied to constants, properties, and methods +--EXTENSIONS-- +zend_test +--FILE-- +getAttributes()[0]->newInstance()); +var_dump($reflectionConstant->getAttributes()[1]->newInstance()); + +$reflectionProperty = new ReflectionProperty(ZendAttributeTest::class, "testProp"); +var_dump($reflectionProperty->getAttributes()[0]->newInstance()); +var_dump($reflectionProperty->getAttributes()[1]->newInstance()); + +$reflectionMethod = new ReflectionMethod(ZendAttributeTest::class, "testMethod"); +var_dump($reflectionMethod->getAttributes()[0]->newInstance()); + +?> +--EXPECTF-- +object(ZendTestRepeatableAttribute)#%d (%d) { +} +object(ZendTestRepeatableAttribute)#%d (%d) { +} +object(ZendTestRepeatableAttribute)#%d (%d) { +} +object(ZendTestPropertyAttribute)#%d (%d) { + ["parameter"]=> + string(%d) "testProp" +} +object(ZendTestAttribute)#%d (%d) { +}