diff --git a/Zend/zend_attributes_arginfo.h b/Zend/zend_attributes_arginfo.h index 3bcdcd707410..3873c903913e 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 838084418871..c10f72d71f0f 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 58538905a6a8..dd3d6d859261 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 7df529088369..a2ee463f4135 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 d7c6c4496e90..136593dbc75a 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 a6869afd2e64..be4357688abc 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 9f8a0c6cc208..15489b7cc23f 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 5305b6e9891b..2257e0621e4f 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 d7eb83b55690..536e39ec6abf 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 c7d33f78b61c..2f8a9aa060b9 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.c b/ext/zend_test/test.c index 3b8dffaa3f1f..2b3f47a7e181 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -37,8 +37,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; @@ -596,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(); @@ -726,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); @@ -736,6 +746,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 814e1945eab7..0b194fe26a15 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -52,6 +52,21 @@ class _ZendTestChildClass extends _ZendTestClass 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; @@ -61,7 +76,10 @@ public function testMethod(): bool {} #[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 688102898f65..ae47fda5d9d4 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: 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 @@ -294,6 +303,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 @@ -400,7 +414,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; @@ -471,6 +485,58 @@ 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); +#if (PHP_VERSION_ID >= 80200) + + 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_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_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); + 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; +} + static zend_class_entry *register_class__ZendTestTrait(void) { zend_class_entry ce, *class_entry; @@ -482,7 +548,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); return class_entry; @@ -497,12 +563,32 @@ 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_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; @@ -523,12 +609,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 +635,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 000000000000..8d7748f3a5c7 --- /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) { +}