Skip to content

Commit 618f5d0

Browse files
committed
Allow attributes on internal classes and functions.
1 parent 2d8bea4 commit 618f5d0

File tree

10 files changed

+49
-21
lines changed

10 files changed

+49
-21
lines changed

Zend/zend.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,14 +170,14 @@ struct _zend_class_entry {
170170
zend_class_name *trait_names;
171171
zend_trait_alias **trait_aliases;
172172
zend_trait_precedence **trait_precedences;
173+
HashTable *attributes;
173174

174175
union {
175176
struct {
176177
zend_string *filename;
177178
uint32_t line_start;
178179
uint32_t line_end;
179180
zend_string *doc_comment;
180-
HashTable *attributes;
181181
} user;
182182
struct {
183183
const struct _zend_function_entry *builtin_functions;

Zend/zend_API.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2583,6 +2583,7 @@ static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class
25832583
zend_initialize_class_data(class_entry, 0);
25842584
class_entry->ce_flags = ce_flags | ZEND_ACC_CONSTANTS_UPDATED | ZEND_ACC_LINKED | ZEND_ACC_RESOLVED_PARENT | ZEND_ACC_RESOLVED_INTERFACES;
25852585
class_entry->info.internal.module = EG(current_module);
2586+
class_entry->attributes = NULL;
25862587

25872588
if (class_entry->info.internal.builtin_functions) {
25882589
zend_register_functions(class_entry, class_entry->info.internal.builtin_functions, &class_entry->function_table, EG(current_module)->type);

Zend/zend_attributes.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,38 @@ ZEND_API zend_attribute *zend_get_parameter_attribute_str(HashTable *attributes,
8484
return get_attribute_str(attributes, str, len, offset + 1);
8585
}
8686

87+
static void attribute_ptr_dtor(zval *v) /* {{{ */
88+
{
89+
zend_attribute_free((zend_attribute *) Z_PTR_P(v));
90+
}
91+
/* }}} */
92+
8793
ZEND_API void zend_compiler_attribute_register(zend_class_entry *ce, zend_attributes_internal_validator validator)
8894
{
95+
if (ce->type != ZEND_INTERNAL_CLASS) {
96+
return;
97+
}
98+
8999
zend_string *lcname = zend_string_tolower_ex(ce->name, 1);
100+
zval tmp;
90101

91102
zend_hash_update_ptr(&internal_validators, lcname, validator);
92103
zend_string_release(lcname);
104+
105+
if (ce->attributes == NULL) {
106+
ce->attributes = pemalloc(sizeof(HashTable), 1);
107+
zend_hash_init(ce->attributes, 8, NULL, attribute_ptr_dtor, 1);
108+
}
109+
110+
zend_attribute *attr = emalloc(ZEND_ATTRIBUTE_SIZE(0));
111+
112+
attr->name = zend_string_copy(zend_ce_php_attribute->name);
113+
attr->lcname = zend_string_tolower(attr->name);
114+
attr->offset = 0;
115+
attr->argc = 0;
116+
117+
ZVAL_PTR(&tmp, attr);
118+
zend_hash_next_index_insert(ce->attributes, &tmp);
93119
}
94120

95121
void zend_register_attribute_ce(void)

Zend/zend_compile.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1813,7 +1813,7 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
18131813
} else {
18141814
ZEND_MAP_PTR_INIT(ce->static_members_table, &ce->default_static_members_table);
18151815
ce->info.user.doc_comment = NULL;
1816-
ce->info.user.attributes = NULL;
1816+
ce->attributes = NULL;
18171817
}
18181818

18191819
ce->default_properties_count = 0;
@@ -6800,8 +6800,8 @@ void zend_compile_class_decl(znode *result, zend_ast *ast, zend_bool toplevel) /
68006800
ce->info.user.doc_comment = zend_string_copy(decl->doc_comment);
68016801
}
68026802
if (decl->attributes) {
6803-
ce->info.user.attributes = create_attribute_array();
6804-
zend_compile_attributes(ce->info.user.attributes, decl->attributes, 0, ZEND_ATTRIBUTE_TARGET_CLASS);
6803+
ce->attributes = create_attribute_array();
6804+
zend_compile_attributes(ce->attributes, decl->attributes, 0, ZEND_ATTRIBUTE_TARGET_CLASS);
68056805
}
68066806

68076807
if (UNEXPECTED((decl->flags & ZEND_ACC_ANON_CLASS))) {

Zend/zend_compile.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,7 @@ struct _zend_op_array {
406406
uint32_t num_args;
407407
uint32_t required_num_args;
408408
zend_arg_info *arg_info;
409+
HashTable *attributes;
409410
/* END of common elements */
410411

411412
int cache_size; /* number of run_time_cache_slots * sizeof(void*) */
@@ -430,7 +431,6 @@ struct _zend_op_array {
430431
uint32_t line_start;
431432
uint32_t line_end;
432433
zend_string *doc_comment;
433-
HashTable *attributes;
434434

435435
int last_literal;
436436
zval *literals;
@@ -456,6 +456,7 @@ typedef struct _zend_internal_function {
456456
uint32_t num_args;
457457
uint32_t required_num_args;
458458
zend_internal_arg_info *arg_info;
459+
HashTable *attributes;
459460
/* END of common elements */
460461

461462
zif_handler handler;
@@ -479,6 +480,7 @@ union _zend_function {
479480
uint32_t num_args;
480481
uint32_t required_num_args;
481482
zend_arg_info *arg_info; /* index -1 represents the return value info, if any */
483+
HashTable *attributes;
482484
} common;
483485

484486
zend_op_array op_array;

Zend/zend_opcode.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,8 +357,8 @@ ZEND_API void destroy_zend_class(zval *zv)
357357
if (ce->info.user.doc_comment) {
358358
zend_string_release_ex(ce->info.user.doc_comment, 0);
359359
}
360-
if (ce->info.user.attributes) {
361-
zend_array_release(ce->info.user.attributes);
360+
if (ce->attributes) {
361+
zend_array_release(ce->attributes);
362362
}
363363

364364
if (ce->num_traits > 0) {

ext/opcache/zend_file_cache.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,7 @@ static void zend_file_cache_serialize_class(zval *zv,
726726
zend_file_cache_serialize_hash(&ce->constants_table, script, info, buf, zend_file_cache_serialize_class_constant);
727727
SERIALIZE_STR(ce->info.user.filename);
728728
SERIALIZE_STR(ce->info.user.doc_comment);
729-
SERIALIZE_ATTRIBUTES(ce->info.user.attributes);
729+
SERIALIZE_ATTRIBUTES(ce->attributes);
730730
zend_file_cache_serialize_hash(&ce->properties_info, script, info, buf, zend_file_cache_serialize_prop_info);
731731

732732
if (ce->properties_info_table) {
@@ -1465,7 +1465,7 @@ static void zend_file_cache_unserialize_class(zval *zv,
14651465
script, buf, zend_file_cache_unserialize_class_constant, NULL);
14661466
UNSERIALIZE_STR(ce->info.user.filename);
14671467
UNSERIALIZE_STR(ce->info.user.doc_comment);
1468-
UNSERIALIZE_ATTRIBUTES(ce->info.user.attributes);
1468+
UNSERIALIZE_ATTRIBUTES(ce->attributes);
14691469
zend_file_cache_unserialize_hash(&ce->properties_info,
14701470
script, buf, zend_file_cache_unserialize_prop_info, NULL);
14711471

ext/opcache/zend_persist.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -866,8 +866,8 @@ static void zend_persist_class_entry(zval *zv)
866866
ce->info.user.doc_comment = NULL;
867867
}
868868
}
869-
if (ce->info.user.attributes) {
870-
ce->info.user.attributes = zend_persist_attributes(ce->info.user.attributes);
869+
if (ce->attributes) {
870+
ce->attributes = zend_persist_attributes(ce->attributes);
871871
}
872872
zend_hash_persist(&ce->properties_info);
873873
ZEND_HASH_FOREACH_BUCKET(&ce->properties_info, p) {

ext/opcache/zend_persist_calc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -457,8 +457,8 @@ static void zend_persist_class_entry_calc(zval *zv)
457457
if (ZCG(accel_directives).save_comments && ce->info.user.doc_comment) {
458458
ADD_STRING(ce->info.user.doc_comment);
459459
}
460-
if (ce->info.user.attributes) {
461-
zend_persist_attributes_calc(ce->info.user.attributes);
460+
if (ce->attributes) {
461+
zend_persist_attributes_calc(ce->attributes);
462462
}
463463

464464
zend_hash_persist_calc(&ce->properties_info);

ext/reflection/php_reflection.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,10 @@ static int read_attributes(zval *ret, HashTable *attributes, zend_class_entry *s
11101110
return SUCCESS;
11111111
}
11121112

1113+
if (!attributes) {
1114+
return SUCCESS;
1115+
}
1116+
11131117
ZEND_HASH_FOREACH_PTR(attributes, attr) {
11141118
if (attr->offset != offset) {
11151119
continue;
@@ -4181,10 +4185,8 @@ ZEND_METHOD(ReflectionClass, getAttributes)
41814185

41824186
GET_REFLECTION_OBJECT_PTR(ce);
41834187

4184-
if (ce->type == ZEND_USER_CLASS && ce->info.user.attributes) {
4185-
attributes = ce->info.user.attributes;
4186-
scope = ce;
4187-
}
4188+
attributes = ce->attributes;
4189+
scope = ce;
41884190

41894191
reflect_attributes(INTERNAL_FUNCTION_PARAM_PASSTHRU, attributes, 0, scope);
41904192
}
@@ -6582,12 +6584,9 @@ ZEND_METHOD(ReflectionAttribute, newInstance)
65826584
RETURN_THROWS();
65836585
}
65846586

6585-
if (ce->type == ZEND_USER_CLASS && !zend_get_attribute_str(ce->info.user.attributes, ZEND_STRL("phpattribute"))) {
6587+
if (!zend_get_attribute_str(ce->attributes, ZEND_STRL("phpattribute"))) {
65866588
zend_throw_error(NULL, "Attempting to use class '%s' as attribute that does not have <<PhpAttribute>>.", ZSTR_VAL(attr->data->name));
65876589
RETURN_THROWS();
6588-
} else if (ce->type == ZEND_INTERNAL_CLASS && !zend_attribute_get_validator(attr->data->lcname)) {
6589-
zend_throw_error(NULL, "Attempting to use internal class '%s' as attribute that does not have <<PhpCompilerAttribute>>.", ZSTR_VAL(attr->data->name));
6590-
RETURN_THROWS();
65916590
}
65926591

65936592
if (SUCCESS != object_init_ex(&obj, ce)) {

0 commit comments

Comments
 (0)