Skip to content

Commit d38db15

Browse files
committed
Various adjustments
1 parent 6429474 commit d38db15

23 files changed

+340
-214
lines changed

Zend/Optimizer/optimize_func_calls.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,6 @@ static void zend_try_inline_call(zend_op_array *op_array, zend_op *fcall, zend_o
9797
return;
9898
}
9999

100-
if (fcall->opcode == ZEND_INIT_PARENT_PROPERTY_HOOK_CALL) {
101-
/* Don't inline property hook method */
102-
return;
103-
}
104-
105100
for (i = 0; i < num_args; i++) {
106101
/* Don't inline functions with by-reference arguments. This would require
107102
* correct handling of INDIRECT arguments. */
@@ -181,7 +176,9 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
181176
call_stack[call].func = zend_optimizer_get_called_func(
182177
ctx->script, op_array, opline, &call_stack[call].is_prototype);
183178
call_stack[call].try_inline =
184-
!call_stack[call].is_prototype && opline->opcode != ZEND_NEW;
179+
!call_stack[call].is_prototype
180+
&& opline->opcode != ZEND_NEW
181+
&& opline->opcode != ZEND_INIT_PARENT_PROPERTY_HOOK_CALL;
185182
ZEND_FALLTHROUGH;
186183
case ZEND_INIT_DYNAMIC_CALL:
187184
case ZEND_INIT_USER_CALL:

Zend/Optimizer/zend_optimizer.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -916,7 +916,7 @@ zend_function *zend_optimizer_get_called_func(
916916
}
917917
}
918918
break;
919-
case ZEND_INIT_PARENT_PROPERTY_HOOK_CALL:;
919+
case ZEND_INIT_PARENT_PROPERTY_HOOK_CALL: {
920920
zend_class_entry *scope = op_array->scope;
921921
ZEND_ASSERT(scope != NULL);
922922
if (scope && (scope->ce_flags & ZEND_ACC_LINKED) && scope->parent) {
@@ -931,12 +931,13 @@ zend_function *zend_optimizer_get_called_func(
931931
&& prop_info->hooks) {
932932
zend_function *fbc = prop_info->hooks[hook_kind];
933933
if (fbc) {
934-
*is_prototype = true;
934+
*is_prototype = false;
935935
return fbc;
936936
}
937937
}
938938
}
939939
break;
940+
}
940941
case ZEND_NEW:
941942
{
942943
zend_class_entry *ce = zend_optimizer_get_class_entry_from_op1(
@@ -1474,7 +1475,6 @@ void zend_foreach_op_array(zend_script *script, zend_op_array_func_t func, void
14741475
{
14751476
zval *zv;
14761477
zend_op_array *op_array;
1477-
zend_property_info *property;
14781478

14791479
zend_foreach_op_array_helper(&script->main_op_array, func, context);
14801480

@@ -1495,9 +1495,11 @@ void zend_foreach_op_array(zend_script *script, zend_op_array_func_t func, void
14951495
zend_foreach_op_array_helper(op_array, func, context);
14961496
}
14971497
} ZEND_HASH_FOREACH_END();
1498+
1499+
zend_property_info *property;
14981500
ZEND_HASH_MAP_FOREACH_PTR(&ce->properties_info, property) {
14991501
zend_function **hooks = property->hooks;
1500-
if (hooks) {
1502+
if (property->ce == ce && property->hooks) {
15011503
for (uint32_t i = 0; i < ZEND_PROPERTY_HOOK_COUNT; i++) {
15021504
zend_function *hook = hooks[i];
15031505
if (hook && hook->common.scope == ce) {

Zend/tests/property_hooks/default_on_hooks.phpt

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,6 @@ Backed property may have default value
44
<?php
55

66
class A {
7-
private $prop { get {} set {} }
8-
}
9-
10-
class B extends A {
117
public $prop = 42 {
128
get {
139
echo __METHOD__, "\n";
@@ -20,20 +16,20 @@ class B extends A {
2016
}
2117
}
2218

23-
$b = new B();
24-
var_dump($b);
25-
var_dump($b->prop);
26-
$b->prop = 43;
27-
var_dump($b->prop);
19+
$a = new A();
20+
var_dump($a);
21+
var_dump($a->prop);
22+
$a->prop = 43;
23+
var_dump($a->prop);
2824

2925
?>
3026
--EXPECT--
31-
object(B)#1 (1) {
27+
object(A)#1 (1) {
3228
["prop"]=>
3329
int(42)
3430
}
35-
B::$prop::get
31+
A::$prop::get
3632
int(42)
37-
B::$prop::set
38-
B::$prop::get
33+
A::$prop::set
34+
A::$prop::get
3935
int(43)

Zend/tests/property_hooks/default_on_virtual.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ class Test {
1212

1313
?>
1414
--EXPECTF--
15-
Fatal error: Cannot specify default value for hooked property Test::$prop in %s on line %d
15+
Fatal error: Cannot specify default value for virtual hooked property Test::$prop in %s on line %d

Zend/tests/property_hooks/default_on_virtual_with_inheritance.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Virtual property cannot have default value
44
<?php
55

66
class A {
7-
private $prop;
7+
public $prop { get {} set {} }
88
}
99

1010
class B extends A {
@@ -16,4 +16,4 @@ class B extends A {
1616

1717
?>
1818
--EXPECTF--
19-
Fatal error: Cannot specify default value for hooked property B::$prop in %s on line %d
19+
Fatal error: Cannot specify default value for virtual hooked property B::$prop in %s on line %d

Zend/tests/accessors/final.phpt renamed to Zend/tests/property_hooks/final.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Final accessors
2+
Final hooks
33
--FILE--
44
<?php
55

@@ -17,4 +17,4 @@ class B extends A {
1717

1818
?>
1919
--EXPECTF--
20-
Fatal error: Cannot override final accessor A::$prop::get() in %s on line %d
20+
Fatal error: Cannot override final property hook A::$prop::get() in %s on line %d

Zend/tests/property_hooks/final_prop_final_hook.phpt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ Cannot make hook explicitly final in final property
55

66
class Test {
77
final public $prop {
8-
final get;
9-
final set;
8+
final get => $field;
109
}
1110
}
1211

1312
?>
14-
--EXPECTF--
15-
Fatal error: Hook on final property cannot be explicitly final in %s on line %d
13+
===DONE===
14+
--EXPECT--
15+
===DONE===
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
Property with hook may override default value
3+
--FILE--
4+
<?php
5+
6+
class A {
7+
public $prop = 41;
8+
}
9+
10+
class B extends A {
11+
public $prop = 42 {
12+
get {
13+
return 43;
14+
}
15+
}
16+
}
17+
18+
$b = new B();
19+
var_dump($b);
20+
var_dump($b->prop);
21+
$b->prop = 44;
22+
var_dump($b);
23+
var_dump($b->prop);
24+
25+
?>
26+
--EXPECT--
27+
object(B)#1 (1) {
28+
["prop"]=>
29+
int(42)
30+
}
31+
int(43)
32+
object(B)#1 (1) {
33+
["prop"]=>
34+
int(44)
35+
}
36+
int(43)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
RW on parent get is forbidden
3+
--FILE--
4+
<?php
5+
6+
class A {
7+
public int $prop {
8+
get {
9+
return 41;
10+
}
11+
}
12+
}
13+
14+
class B extends A {
15+
public int $prop {
16+
get {
17+
return ++parent::$prop::get();
18+
}
19+
}
20+
}
21+
22+
$b = new B;
23+
var_dump($b->prop);
24+
25+
?>
26+
--EXPECTF--
27+
Fatal error: Cannot use temporary expression in write context in %s on line %d
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
--TEST--
2+
Extra args to parent hook call
3+
--FILE--
4+
<?php
5+
6+
class A {
7+
public $backed;
8+
public $virtual { get {} set {} }
9+
}
10+
11+
class B extends A {
12+
public $backed {
13+
get {
14+
return parent::$backed::get(42);
15+
}
16+
set {
17+
parent::$backed::set($value, 42);
18+
}
19+
}
20+
public $virtual {
21+
get {
22+
return parent::$virtual::get(42);
23+
}
24+
set {
25+
parent::$virtual::set($value, 42);
26+
}
27+
}
28+
}
29+
30+
$b = new B();
31+
// Calling a parent hook with extra args is ok, because they are user functions.
32+
var_dump($b->virtual = 42);
33+
var_dump($b->virtual);
34+
// Calling the implicit parent hook with extra args is not ok, since it is an internal function.
35+
try {
36+
var_dump($b->backed = 42);
37+
} catch (Error $e) {
38+
echo $e->getMessage(), "\n";
39+
}
40+
try {
41+
var_dump($b->backed);
42+
} catch (Error $e) {
43+
echo $e->getMessage(), "\n";
44+
}
45+
46+
?>
47+
--EXPECT--
48+
int(42)
49+
NULL
50+
set() expects exactly 1 argument, 2 given
51+
get() expects exactly 0 arguments, 1 given

0 commit comments

Comments
 (0)