Skip to content

Allow for arbitrary (class) attributes in stubs #8839

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions UPGRADING.INTERNALS
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ PHP 8.2 INTERNALS UPGRADE NOTES
- zend_object_do_operation_t
* Added a new zero_position argument to php_stream_fopen_from_fd_rel to reflect
if this a newly created file so the current file offset needs not to be checked.
* zend_internal_attribute_register() no longer takes a flags argument nor
registers the attribute class directly. Instead specify #[Attribute] with the
appropriate target flags in the .stub.php file.

========================
2. Build system changes
Expand Down
43 changes: 19 additions & 24 deletions Zend/zend_attributes.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,27 +317,31 @@ static void free_internal_attribute(zval *v)
pefree(Z_PTR_P(v), 1);
}

ZEND_API zend_internal_attribute *zend_internal_attribute_register(zend_class_entry *ce, uint32_t flags)
ZEND_API zend_internal_attribute *zend_internal_attribute_register(zend_class_entry *ce)
{
zend_internal_attribute *internal_attr;
zend_attribute *attr;

if (ce->type != ZEND_INTERNAL_CLASS) {
zend_error_noreturn(E_ERROR, "Only internal classes can be registered as compiler attribute");
}

internal_attr = pemalloc(sizeof(zend_internal_attribute), 1);
internal_attr->ce = ce;
internal_attr->flags = flags;
internal_attr->validator = NULL;
ZEND_HASH_FOREACH_PTR(ce->attributes, attr) {
if (zend_string_equals(attr->name, zend_ce_attribute->name)) {
internal_attr = pemalloc(sizeof(zend_internal_attribute), 1);
internal_attr->ce = ce;
internal_attr->flags = Z_LVAL(attr->args[0].value);
internal_attr->validator = NULL;

zend_string *lcname = zend_string_tolower_ex(ce->name, 1);
zend_string *lcname = zend_string_tolower_ex(ce->name, 1);
zend_hash_update_ptr(&internal_attributes, lcname, internal_attr);
zend_string_release(lcname);

zend_hash_update_ptr(&internal_attributes, lcname, internal_attr);
zend_attribute *attr = zend_add_class_attribute(ce, zend_ce_attribute->name, 1);
ZVAL_LONG(&attr->args[0].value, flags);
zend_string_release(lcname);
return internal_attr;
}
} ZEND_HASH_FOREACH_END();

return internal_attr;
zend_error_noreturn(E_ERROR, "Classes must be first marked as attribute before being able to be registered as internal attribute class");
}

ZEND_API zend_internal_attribute *zend_internal_attribute_get(zend_string *lcname)
Expand All @@ -352,27 +356,18 @@ void zend_register_attribute_ce(void)
zend_hash_init(&internal_attributes, 8, NULL, free_internal_attribute, 1);

zend_ce_attribute = register_class_Attribute();
attr = zend_internal_attribute_register(zend_ce_attribute, ZEND_ATTRIBUTE_TARGET_CLASS);
attr = zend_internal_attribute_register(zend_ce_attribute);
attr->validator = validate_attribute;

zend_declare_class_constant_long(zend_ce_attribute, ZEND_STRL("TARGET_CLASS"), ZEND_ATTRIBUTE_TARGET_CLASS);
zend_declare_class_constant_long(zend_ce_attribute, ZEND_STRL("TARGET_FUNCTION"), ZEND_ATTRIBUTE_TARGET_FUNCTION);
zend_declare_class_constant_long(zend_ce_attribute, ZEND_STRL("TARGET_METHOD"), ZEND_ATTRIBUTE_TARGET_METHOD);
zend_declare_class_constant_long(zend_ce_attribute, ZEND_STRL("TARGET_PROPERTY"), ZEND_ATTRIBUTE_TARGET_PROPERTY);
zend_declare_class_constant_long(zend_ce_attribute, ZEND_STRL("TARGET_CLASS_CONSTANT"), ZEND_ATTRIBUTE_TARGET_CLASS_CONST);
zend_declare_class_constant_long(zend_ce_attribute, ZEND_STRL("TARGET_PARAMETER"), ZEND_ATTRIBUTE_TARGET_PARAMETER);
zend_declare_class_constant_long(zend_ce_attribute, ZEND_STRL("TARGET_ALL"), ZEND_ATTRIBUTE_TARGET_ALL);
zend_declare_class_constant_long(zend_ce_attribute, ZEND_STRL("IS_REPEATABLE"), ZEND_ATTRIBUTE_IS_REPEATABLE);

zend_ce_return_type_will_change_attribute = register_class_ReturnTypeWillChange();
zend_internal_attribute_register(zend_ce_return_type_will_change_attribute, ZEND_ATTRIBUTE_TARGET_METHOD);
zend_internal_attribute_register(zend_ce_return_type_will_change_attribute);

zend_ce_allow_dynamic_properties = register_class_AllowDynamicProperties();
attr = zend_internal_attribute_register(zend_ce_allow_dynamic_properties, ZEND_ATTRIBUTE_TARGET_CLASS);
attr = zend_internal_attribute_register(zend_ce_allow_dynamic_properties);
attr->validator = validate_allow_dynamic_properties;

zend_ce_sensitive_parameter = register_class_SensitiveParameter();
attr = zend_internal_attribute_register(zend_ce_sensitive_parameter, ZEND_ATTRIBUTE_TARGET_PARAMETER);
zend_internal_attribute_register(zend_ce_sensitive_parameter);

memcpy(&attributes_object_handlers_sensitive_parameter_value, &std_object_handlers, sizeof(zend_object_handlers));
attributes_object_handlers_sensitive_parameter_value.get_properties_for = attributes_sensitive_parameter_value_get_properties_for;
Expand Down
2 changes: 1 addition & 1 deletion Zend/zend_attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ ZEND_API zend_result zend_get_attribute_value(zval *ret, zend_attribute *attr, u
ZEND_API zend_string *zend_get_attribute_target_names(uint32_t targets);
ZEND_API bool zend_is_attribute_repeated(HashTable *attributes, zend_attribute *attr);

ZEND_API zend_internal_attribute *zend_internal_attribute_register(zend_class_entry *ce, uint32_t flags);
ZEND_API zend_internal_attribute *zend_internal_attribute_register(zend_class_entry *ce);
ZEND_API zend_internal_attribute *zend_internal_attribute_get(zend_string *lcname);

ZEND_API zend_attribute *zend_add_attribute(
Expand Down
45 changes: 45 additions & 0 deletions Zend/zend_attributes.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,62 @@

/** @generate-class-entries */

#[Attribute(Attribute::TARGET_CLASS)]
final class Attribute
{
/**
* @var int
* @cname ZEND_ATTRIBUTE_TARGET_CLASS
*/
const TARGET_CLASS = UNKNOWN;
/**
* @var int
* @cname ZEND_ATTRIBUTE_TARGET_FUNCTION
*/
const TARGET_FUNCTION = UNKNOWN;
/**
* @var int
* @cname ZEND_ATTRIBUTE_TARGET_METHOD
*/
const TARGET_METHOD = UNKNOWN;
/**
* @var int
* @cname ZEND_ATTRIBUTE_TARGET_PROPERTY
*/
const TARGET_PROPERTY = UNKNOWN;
/**
* @var int
* @cname ZEND_ATTRIBUTE_TARGET_CLASS_CONST
*/
const TARGET_CLASS_CONSTANT = UNKNOWN;
/**
* @var int
* @cname ZEND_ATTRIBUTE_TARGET_PARAMETER
*/
const TARGET_PARAMETER = UNKNOWN;
/**
* @var int
* @cname ZEND_ATTRIBUTE_TARGET_ALL
*/
const TARGET_ALL = UNKNOWN;
/**
* @var int
* @cname ZEND_ATTRIBUTE_IS_REPEATABLE
*/
const IS_REPEATABLE = UNKNOWN;

public int $flags;

public function __construct(int $flags = Attribute::TARGET_ALL) {}
}

#[Attribute(Attribute::TARGET_METHOD)]
final class ReturnTypeWillChange
{
public function __construct() {}
}

#[Attribute(Attribute::TARGET_CLASS)]
final class AllowDynamicProperties
{
public function __construct() {}
Expand All @@ -22,6 +66,7 @@ public function __construct() {}
/**
* @strict-properties
*/
#[Attribute(Attribute::TARGET_PARAMETER)]
final class SensitiveParameter
{
public function __construct() {}
Expand Down
78 changes: 77 additions & 1 deletion Zend/zend_attributes_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Zend/zend_builtin_functions_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading