Skip to content

Commit ed76308

Browse files
committed
Tinkering around to evaluate constant AST when accessing attributes.
1 parent 5b5e895 commit ed76308

File tree

6 files changed

+126
-55
lines changed

6 files changed

+126
-55
lines changed

Zend/tests/attributes_002.phpt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,21 @@ namespace Doctrine\ORM {
1616
$attrs = $reflClass->getAttributes();
1717
foreach ($attrs as $name => &$values) {
1818
$name = "Doctrine\\" . $name;
19-
$values = new $name(...$values);
19+
$values = new $name($values);
2020
}
2121
return $attrs;
2222
}
2323
}
2424

25+
namespace Doctrine\ORM\Mapping {
26+
class Entity {
27+
}
28+
}
29+
2530
namespace {
26-
<<ORM\Entity("user")>>
31+
use Doctrine\ORM\Mapping as ORM;
32+
33+
<<ORM\Entity(["tableName" => "user", "repository" => UserRepository::class])>>
2734
class User {}
2835

2936
var_dump(Doctrine\ORM\GetClassAttributes("User"));

Zend/tests/attributes_003.phpt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Resolve attribute names
3+
--FILE--
4+
<?php
5+
6+
namespace Doctrine\ORM\Mapping {
7+
class Entity {
8+
}
9+
}
10+
11+
namespace {
12+
use Doctrine\ORM\Mapping\Entity;
13+
14+
<<Entity(["foo"])>>
15+
function foo() {
16+
}
17+
var_dump((new ReflectionFunction('foo'))->getAttributes());
18+
}
19+
--EXPECTF--

Zend/zend_ast.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2119,7 +2119,27 @@ ZEND_API ZEND_COLD zend_string *zend_ast_export(const char *prefix, zend_ast *as
21192119
ZEND_API zend_class_entry *zend_ast_node_ce = NULL;
21202120
ZEND_API zend_class_entry *zend_ast_decl_ce = NULL;
21212121

2122-
ZEND_API void zend_ast_convert_attributes(zval *ret, HashTable *attributes)
2122+
ZEND_API void zend_ast_convert_to_object(zval *p, zend_ast *ast, zend_class_entry *ce)
2123+
{
2124+
if (ast->kind == ZEND_AST_CONSTANT) {
2125+
zend_string *name = zend_ast_get_constant_name(ast);
2126+
zval *zv = zend_get_constant_ex(name, ce, ast->attr);
2127+
if (UNEXPECTED(zv == NULL)) {
2128+
return;
2129+
}
2130+
2131+
ZVAL_COPY_OR_DUP(p, zv);
2132+
} else {
2133+
zval tmp;
2134+
2135+
if (UNEXPECTED(zend_ast_evaluate(&tmp, ast, ce) != SUCCESS)) {
2136+
return;
2137+
}
2138+
ZVAL_COPY_VALUE(p, &tmp);
2139+
}
2140+
}
2141+
2142+
ZEND_API void zend_ast_convert_attributes(zval *ret, HashTable *attributes, zend_class_entry *ce)
21232143
{
21242144
zval *val, tmp;
21252145
HashTable *ht, *ht2, *res_ht;
@@ -2149,6 +2169,7 @@ ZEND_API void zend_ast_convert_attributes(zval *ret, HashTable *attributes)
21492169
res_ht = Z_ARR_P(ret);
21502170
ZEND_HASH_FOREACH_STR_KEY_VAL(attributes, key, val) {
21512171
if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
2172+
zend_ast_convert_to_object(&tmp, Z_ASTVAL_P(val), ce);
21522173
zend_hash_add_new(res_ht, key, &tmp);
21532174
} else if (Z_TYPE_P(val) == IS_ARRAY) {
21542175
ht = Z_ARR_P(val);
@@ -2157,6 +2178,7 @@ ZEND_API void zend_ast_convert_attributes(zval *ret, HashTable *attributes)
21572178
ht2 = Z_ARR_P(val);
21582179
ZEND_HASH_FOREACH_VAL(ht, val) {
21592180
if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
2181+
zend_ast_convert_to_object(&tmp, Z_ASTVAL_P(val), ce);
21602182
zend_hash_next_index_insert_new(ht2, &tmp);
21612183
} else {
21622184
if (Z_REFCOUNTED_P(val)) {

Zend/zend_compile.c

Lines changed: 67 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1917,50 +1917,6 @@ zend_ast *zend_negate_num_string(zend_ast *ast) /* {{{ */
19171917
}
19181918
/* }}} */
19191919

1920-
void zend_add_attribute(zend_ast *name, zend_ast *value) /* {{{ */
1921-
{
1922-
zval *val, tmp;
1923-
zend_string *key = zend_ast_get_str(name);
1924-
1925-
#if 1 /* SPECIAL_ATTRIBUTE */
1926-
if (ZSTR_LEN(key) >= 2 && ZSTR_VAL(key)[0] == '_' && ZSTR_VAL(key)[1] == '_') {
1927-
zend_error_noreturn(E_COMPILE_ERROR, "Unknown special attribute %s", ZSTR_VAL(key));
1928-
}
1929-
#endif
1930-
if (!CG(attributes)) {
1931-
ALLOC_HASHTABLE(CG(attributes));
1932-
zend_hash_init(CG(attributes), 8, NULL, ZVAL_PTR_DTOR, 0);
1933-
}
1934-
ZVAL_NULL(&tmp);
1935-
val = zend_hash_add(CG(attributes), key, &tmp);
1936-
if (!val) {
1937-
zend_error_noreturn(E_COMPILE_ERROR, "Redeclared attribute %s", ZSTR_VAL(key));
1938-
}
1939-
array_init(val);
1940-
zend_string_release(key);
1941-
}
1942-
/* }}} */
1943-
1944-
zend_ast *zend_add_attribute_value(zend_ast *list_ast, zend_ast *val_ast) /* {{{ */
1945-
{
1946-
zval *list, *val, arr, tmp;
1947-
1948-
if (list_ast->kind == ZEND_AST_ZVAL) {
1949-
list = zend_ast_get_zval(list_ast);
1950-
if (Z_TYPE_P(list) != IS_ARRAY) {
1951-
array_init(&arr);
1952-
zend_hash_next_index_insert_new(Z_ARRVAL(arr), list);
1953-
ZVAL_ARR(list, Z_ARR(arr));
1954-
}
1955-
1956-
val = zend_ast_get_zval(val_ast);
1957-
zend_hash_next_index_insert_new(Z_ARRVAL_P(list), val);
1958-
}
1959-
1960-
return list_ast;
1961-
}
1962-
/* }}} */
1963-
19641920
void zend_verify_namespace(void) /* {{{ */
19651921
{
19661922
if (FC(has_bracketed_namespaces) && !FC(in_namespace)) {
@@ -9326,3 +9282,70 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
93269282
*ast_ptr = zend_ast_create_zval(&result);
93279283
}
93289284
/* }}} */
9285+
9286+
void zend_add_attribute(zend_ast *name, zend_ast *value) /* {{{ */
9287+
{
9288+
zval *val, tmp;
9289+
//zend_string *key = zend_ast_get_str(name);
9290+
9291+
znode class_node;
9292+
9293+
zend_compile_class_ref(&class_node, name, ZEND_FETCH_CLASS_EXCEPTION);
9294+
zend_string *key = Z_STR(class_node.u.constant);
9295+
9296+
if (!CG(attributes)) {
9297+
ALLOC_HASHTABLE(CG(attributes));
9298+
zend_hash_init(CG(attributes), 8, NULL, ZVAL_PTR_DTOR, 0);
9299+
}
9300+
9301+
ZVAL_NULL(&tmp);
9302+
val = zend_hash_add(CG(attributes), key, &tmp);
9303+
9304+
if (!val) {
9305+
zend_error_noreturn(E_COMPILE_ERROR, "Redeclared attribute %s", ZSTR_VAL(key));
9306+
}
9307+
9308+
if (value) {
9309+
if (value->kind == ZEND_AST_ZVAL) {
9310+
zval *zv = zend_ast_get_zval(value);
9311+
9312+
if (Z_TYPE_P(zv) == IS_ARRAY) {
9313+
ZVAL_COPY_VALUE(val, zv);
9314+
} else {
9315+
array_init(val);
9316+
zend_hash_next_index_insert_new(Z_ARRVAL_P(val), zv);
9317+
}
9318+
} else {
9319+
ZVAL_AST(&tmp, zend_ast_copy(value));
9320+
zend_ast_destroy(value);
9321+
array_init(val);
9322+
zend_hash_next_index_insert_new(Z_ARRVAL_P(val), &tmp);
9323+
}
9324+
} else {
9325+
array_init(val);
9326+
}
9327+
9328+
zend_string_release(key);
9329+
}
9330+
/* }}} */
9331+
9332+
zend_ast *zend_add_attribute_value(zend_ast *list_ast, zend_ast *val_ast) /* {{{ */
9333+
{
9334+
zval *list, *val, arr, tmp;
9335+
9336+
if (list_ast->kind == ZEND_AST_ZVAL) {
9337+
list = zend_ast_get_zval(list_ast);
9338+
if (Z_TYPE_P(list) != IS_ARRAY) {
9339+
array_init(&arr);
9340+
zend_hash_next_index_insert_new(Z_ARRVAL(arr), list);
9341+
ZVAL_ARR(list, Z_ARR(arr));
9342+
}
9343+
9344+
val = zend_ast_get_zval(val_ast);
9345+
zend_hash_next_index_insert_new(Z_ARRVAL_P(list), val);
9346+
}
9347+
9348+
return list_ast;
9349+
}
9350+
/* }}} */
9351+

Zend/zend_language_parser.y

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -320,10 +320,10 @@ attribute_values:
320320
;
321321

322322
attribute_list:
323-
namespace_name { zend_add_attribute($1, NULL); }
324-
| namespace_name '(' attribute_values ')' { zend_add_attribute($1, $3); }
325-
| attribute_list ',' namespace_name { zend_add_attribute($3, NULL); }
326-
| attribute_list ',' namespace_name '(' attribute_values ')' { zend_add_attribute($3, $5); }
323+
class_name_reference { zend_add_attribute($1, NULL); }
324+
| class_name_reference '(' attribute_values ')' { zend_add_attribute($1, $3); }
325+
| attribute_list ',' class_name_reference { zend_add_attribute($3, NULL); }
326+
| attribute_list ',' class_name_reference '(' attribute_values ')' { zend_add_attribute($3, $5); }
327327
;
328328

329329
attribute:

ext/reflection/php_reflection.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1642,7 +1642,7 @@ ZEND_METHOD(reflection_function, getAttributes)
16421642
}
16431643
GET_REFLECTION_OBJECT_PTR(fptr);
16441644
if (fptr->type == ZEND_USER_FUNCTION && fptr->op_array.attributes) {
1645-
zend_ast_convert_attributes(return_value, fptr->op_array.attributes);
1645+
zend_ast_convert_attributes(return_value, fptr->op_array.attributes, NULL);
16461646
} else {
16471647
array_init(return_value);
16481648
}
@@ -3645,7 +3645,7 @@ ZEND_METHOD(reflection_class_constant, getAttributes)
36453645
}
36463646
GET_REFLECTION_OBJECT_PTR(ref);
36473647
if (ref->attributes) {
3648-
zend_ast_convert_attributes(return_value, ref->attributes);
3648+
zend_ast_convert_attributes(return_value, ref->attributes, NULL);
36493649
} else {
36503650
array_init(return_value);
36513651
}
@@ -4026,7 +4026,7 @@ ZEND_METHOD(reflection_class, getAttributes)
40264026
}
40274027
GET_REFLECTION_OBJECT_PTR(ce);
40284028
if (ce->type == ZEND_USER_CLASS && ce->info.user.attributes) {
4029-
zend_ast_convert_attributes(return_value, ce->info.user.attributes);
4029+
zend_ast_convert_attributes(return_value, ce->info.user.attributes, NULL);
40304030
} else {
40314031
array_init(return_value);
40324032
}
@@ -5544,7 +5544,7 @@ ZEND_METHOD(reflection_property, getAttributes)
55445544
}
55455545
GET_REFLECTION_OBJECT_PTR(ref);
55465546
if (ref->prop->attributes) {
5547-
zend_ast_convert_attributes(return_value, ref->prop->attributes);
5547+
zend_ast_convert_attributes(return_value, ref->prop->attributes, NULL);
55485548
} else {
55495549
array_init(return_value);
55505550
}

0 commit comments

Comments
 (0)