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 all 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
49 changes: 26 additions & 23 deletions Zend/zend_attributes.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,27 +317,39 @@ 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_mark_internal_attribute(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);
return internal_attr;
}
} ZEND_HASH_FOREACH_END();

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_register(zend_class_entry *ce, uint32_t flags)
{
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;
return zend_mark_internal_attribute(ce);
}

ZEND_API zend_internal_attribute *zend_internal_attribute_get(zend_string *lcname)
Expand All @@ -352,32 +364,23 @@ 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_mark_internal_attribute(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_mark_internal_attribute(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_mark_internal_attribute(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_mark_internal_attribute(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;

/* This is not an actual attribute, thus the zend_internal_attribute_register() call is missing. */
/* This is not an actual attribute, thus the zend_mark_internal_attribute() call is missing. */
zend_ce_sensitive_parameter_value = register_class_SensitiveParameterValue();
zend_ce_sensitive_parameter_value->create_object = attributes_sensitive_parameter_value_new;
}
Expand Down
1 change: 1 addition & 0 deletions Zend/zend_attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +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_mark_internal_attribute(zend_class_entry *ce);
ZEND_API zend_internal_attribute *zend_internal_attribute_register(zend_class_entry *ce, uint32_t flags);
ZEND_API zend_internal_attribute *zend_internal_attribute_get(zend_string *lcname);

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