Skip to content

Commit 511e3db

Browse files
committed
Aligned scope resolution code. Added closure scope and rebind testing.
1 parent 3649c5c commit 511e3db

File tree

4 files changed

+92
-45
lines changed

4 files changed

+92
-45
lines changed

Zend/tests/attributes/013_scope_resolution.phpt renamed to Zend/tests/attributes/013_class_scope.phpt

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Attributes make use of correct scope.
2+
Attributes make use of class scope.
33
--FILE--
44
<?php
55

@@ -25,20 +25,21 @@ print_r($ref->getMethod('bar')->getParameters()[0]->getAttributes()[0]->getArgum
2525

2626
echo "\n";
2727

28-
class C2
28+
trait T1
2929
{
30-
private const FOO = 'foo';
31-
32-
public static function foo()
33-
{
34-
return <<A1(self::class, self::FOO)>> function (<<A1(self::class, self::FOO)>> $p) { };
35-
}
30+
<<A1(self::class, self::FOO)>>
31+
public function foo() { }
3632
}
3733

38-
$ref = new \ReflectionFunction(C2::foo());
39-
print_r($ref->getAttributes()[0]->getArguments());
40-
print_r($ref->getParameters()[0]->getAttributes()[0]->getArguments());
34+
class C2
35+
{
36+
use T1;
37+
38+
private const FOO = 'bar';
39+
}
4140

41+
$ref = new \ReflectionClass(C2::class);
42+
print_r($ref->getMethod('foo')->getAttributes()[0]->getArguments());
4243
echo "\n";
4344

4445
class C3
@@ -56,13 +57,13 @@ class C3
5657
}
5758
}
5859

59-
$obj = C3::foo();
60-
$ref = new \ReflectionObject($obj);
61-
$name = $ref->getMethod('bar')->getAttributes()[0]->getArguments()[0];
60+
$ref = new \ReflectionObject(C3::foo());
6261

63-
print_r($ref->getAttributes()[0]->getArguments());
64-
var_dump($name == get_class($obj));
65-
var_dump($ref->getMethod('bar')->getAttributes()[0]->getArguments()[1]);
62+
$args = $ref->getAttributes()[0]->getArguments();
63+
var_dump($args[0] == $ref->getName(), $args[1]);
64+
65+
$args = $ref->getMethod('bar')->getAttributes()[0]->getArguments();
66+
var_dump($args[0] == $ref->getName(), $args[1]);
6667

6768
?>
6869
--EXPECT--
@@ -95,18 +96,10 @@ Array
9596
Array
9697
(
9798
[0] => C2
98-
[1] => foo
99-
)
100-
Array
101-
(
102-
[0] => C2
103-
[1] => foo
99+
[1] => bar
104100
)
105101

106-
Array
107-
(
108-
[0] => C3
109-
[1] => foo
110-
)
102+
bool(true)
103+
string(3) "bar"
111104
bool(true)
112105
string(3) "bar"
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
--TEST--
2+
Attributes make use of closure scope.
3+
--FILE--
4+
<?php
5+
6+
class Test1
7+
{
8+
private const FOO = 'bar';
9+
}
10+
11+
class C1
12+
{
13+
private const FOO = 'foo';
14+
15+
public static function foo()
16+
{
17+
return <<A1(self::class, self::FOO)>> function (<<A1(self::class, self::FOO)>> $p) { };
18+
}
19+
}
20+
21+
$ref = new \ReflectionFunction(C1::foo());
22+
print_r($ref->getAttributes()[0]->getArguments());
23+
print_r($ref->getParameters()[0]->getAttributes()[0]->getArguments());
24+
25+
echo "\n";
26+
27+
$ref = new \ReflectionFunction(C1::foo()->bindTo(null, Test1::class));
28+
print_r($ref->getAttributes()[0]->getArguments());
29+
print_r($ref->getParameters()[0]->getAttributes()[0]->getArguments());
30+
31+
?>
32+
--EXPECT--
33+
Array
34+
(
35+
[0] => C1
36+
[1] => foo
37+
)
38+
Array
39+
(
40+
[0] => C1
41+
[1] => foo
42+
)
43+
44+
Array
45+
(
46+
[0] => Test1
47+
[1] => bar
48+
)
49+
Array
50+
(
51+
[0] => Test1
52+
[1] => bar
53+
)

Zend/zend_compile.c

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,10 +1046,6 @@ ZEND_API void function_add_ref(zend_function *function) /* {{{ */
10461046
ZEND_MAP_PTR_INIT(op_array->run_time_cache, zend_arena_alloc(&CG(arena), sizeof(void*)));
10471047
ZEND_MAP_PTR_SET(op_array->run_time_cache, NULL);
10481048
}
1049-
1050-
if (op_array->attributes) {
1051-
GC_ADDREF(op_array->attributes);
1052-
}
10531049
}
10541050

10551051
if (function->common.function_name) {
@@ -6371,15 +6367,7 @@ void zend_compile_func_decl(znode *result, zend_ast *ast, zend_bool toplevel) /*
63716367
if (decl->doc_comment) {
63726368
op_array->doc_comment = zend_string_copy(decl->doc_comment);
63736369
}
6374-
if (decl->child[4]) {
6375-
int target = ZEND_ATTRIBUTE_TARGET_FUNCTION;
63766370

6377-
if (is_method) {
6378-
target = ZEND_ATTRIBUTE_TARGET_METHOD;
6379-
}
6380-
op_array->attributes = create_attribute_array();
6381-
zend_compile_attributes(op_array->attributes, decl->child[4], 0, target);
6382-
}
63836371
if (decl->kind == ZEND_AST_CLOSURE || decl->kind == ZEND_AST_ARROW_FUNC) {
63846372
op_array->fn_flags |= ZEND_ACC_CLOSURE;
63856373
}
@@ -6399,6 +6387,17 @@ void zend_compile_func_decl(znode *result, zend_ast *ast, zend_bool toplevel) /*
63996387

64006388
CG(active_op_array) = op_array;
64016389

6390+
if (decl->child[4]) {
6391+
int target = ZEND_ATTRIBUTE_TARGET_FUNCTION;
6392+
6393+
if (is_method) {
6394+
target = ZEND_ATTRIBUTE_TARGET_METHOD;
6395+
}
6396+
6397+
op_array->attributes = create_attribute_array();
6398+
zend_compile_attributes(op_array->attributes, decl->child[4], 0, target);
6399+
}
6400+
64026401
/* Do not leak the class scope into free standing functions, even if they are dynamically
64036402
* defined inside a class method. This is necessary for correct handling of magic constants.
64046403
* For example __CLASS__ should always be "" inside a free standing function. */
@@ -6824,10 +6823,6 @@ void zend_compile_class_decl(znode *result, zend_ast *ast, zend_bool toplevel) /
68246823
if (decl->doc_comment) {
68256824
ce->info.user.doc_comment = zend_string_copy(decl->doc_comment);
68266825
}
6827-
if (decl->child[4]) {
6828-
ce->attributes = create_attribute_array();
6829-
zend_compile_attributes(ce->attributes, decl->child[4], 0, ZEND_ATTRIBUTE_TARGET_CLASS);
6830-
}
68316826

68326827
if (UNEXPECTED((decl->flags & ZEND_ACC_ANON_CLASS))) {
68336828
/* Serialization is not supported for anonymous classes */
@@ -6842,6 +6837,11 @@ void zend_compile_class_decl(znode *result, zend_ast *ast, zend_bool toplevel) /
68426837

68436838
CG(active_class_entry) = ce;
68446839

6840+
if (decl->child[4]) {
6841+
ce->attributes = create_attribute_array();
6842+
zend_compile_attributes(ce->attributes, decl->child[4], 0, ZEND_ATTRIBUTE_TARGET_CLASS);
6843+
}
6844+
68456845
if (implements_ast) {
68466846
zend_compile_implements(implements_ast);
68476847
}

ext/reflection/php_reflection.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6411,8 +6411,9 @@ ZEND_METHOD(ReflectionAttribute, getName)
64116411
static zend_always_inline int import_attribute_value(zval *ret, zval *val, zend_class_entry *scope) /* {{{ */
64126412
{
64136413
ZVAL_COPY_OR_DUP(ret, val);
6414+
64146415
if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
6415-
if (FAILURE == zval_update_constant_ex(ret, scope)) {
6416+
if (SUCCESS != zval_update_constant_ex(ret, scope)) {
64166417
zval_ptr_dtor(ret);
64176418
return FAILURE;
64186419
}

0 commit comments

Comments
 (0)