Hi Etienne,
I took a look into the patch and I don't like it all.
At first, I don't see any consistency there.
Why parent:: does forwarding but self::, static:: and "class names" don't?
At second, it's too complicated.
I would propose more consistent (from my point of view) and simpler patch.
Each call to static method of parent class (it doesn't mater if it was
done using parent:: or something else) assumes forwarding of called context.
Thanks. Dmitry.
Etienne Kneuss wrote:
> Hi,
>
> The patch was made initially by Mike Lively, I adapted it and removed
> forward_static_call
>
> http://patches.colder.ch/Zend/lsb_parent_forwarding_53.patch?markup
> http://patches.colder.ch/Zend/lsb_parent_forwarding_HEAD.patch?markup
>
> They should merge without trouble.
>
> Regards
>
Index: Zend/zend_execute_API.c
===================================================================
RCS file: /repository/ZendEngine2/zend_execute_API.c,v
retrieving revision 1.331.2.20.2.24.2.42
diff -u -p -d -r1.331.2.20.2.24.2.42 zend_execute_API.c
--- Zend/zend_execute_API.c 5 Jun 2008 18:50:29 -0000
1.331.2.20.2.24.2.42
+++ Zend/zend_execute_API.c 8 Jul 2008 11:24:51 -0000
@@ -1041,8 +1041,15 @@ int zend_call_function(zend_fcall_info *
current_this = EG(This);
current_called_scope = EG(called_scope);
- if (calling_scope) {
- EG(called_scope) = calling_scope;
+
+ if (EX(object) &&
+ (EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC) ==
0) {
+ EG(called_scope) = calling_scope = Z_OBJCE_P(EX(object));
+ } else if (calling_scope) {
+ if (!EG(called_scope) ||
+ !instanceof_function(EG(called_scope), calling_scope
TSRMLS_CC)) {
+ EG(called_scope) = calling_scope;
+ }
} else if (EX(function_state).function->type != ZEND_INTERNAL_FUNCTION)
{
EG(called_scope) = NULL;
}
Index: Zend/zend_vm_def.h
===================================================================
RCS file: /repository/ZendEngine2/zend_vm_def.h,v
retrieving revision 1.59.2.29.2.48.2.58
diff -u -p -d -r1.59.2.29.2.48.2.58 zend_vm_def.h
--- Zend/zend_vm_def.h 11 Jun 2008 13:18:39 -0000 1.59.2.29.2.48.2.58
+++ Zend/zend_vm_def.h 8 Jul 2008 11:24:52 -0000
@@ -1980,7 +1980,13 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_ME
EX(fbc) = ce->constructor;
}
- EX(called_scope) = ce;
+ if (EG(called_scope) &&
+ (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0 &&
+ instanceof_function(EG(called_scope), ce TSRMLS_CC)) {
+ EX(called_scope) = EG(called_scope);
+ } else {
+ EX(called_scope) = ce;
+ }
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
Index: Zend/zend_vm_execute.h
===================================================================
RCS file: /repository/ZendEngine2/zend_vm_execute.h,v
retrieving revision 1.62.2.30.2.49.2.58
diff -u -p -d -r1.62.2.30.2.49.2.58 zend_vm_execute.h
--- Zend/zend_vm_execute.h 11 Jun 2008 13:18:39 -0000
1.62.2.30.2.49.2.58
+++ Zend/zend_vm_execute.h 8 Jul 2008 11:24:54 -0000
@@ -2613,7 +2613,13 @@ static int ZEND_FASTCALL ZEND_INIT_STAT
EX(fbc) = ce->constructor;
}
- EX(called_scope) = ce;
+ if (EG(called_scope) &&
+ (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0 &&
+ instanceof_function(EG(called_scope), ce TSRMLS_CC)) {
+ EX(called_scope) = EG(called_scope);
+ } else {
+ EX(called_scope) = ce;
+ }
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
@@ -3186,7 +3192,13 @@ static int ZEND_FASTCALL ZEND_INIT_STAT
EX(fbc) = ce->constructor;
}
- EX(called_scope) = ce;
+ if (EG(called_scope) &&
+ (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0 &&
+ instanceof_function(EG(called_scope), ce TSRMLS_CC)) {
+ EX(called_scope) = EG(called_scope);
+ } else {
+ EX(called_scope) = ce;
+ }
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
@@ -3654,7 +3666,13 @@ static int ZEND_FASTCALL ZEND_INIT_STAT
EX(fbc) = ce->constructor;
}
- EX(called_scope) = ce;
+ if (EG(called_scope) &&
+ (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0 &&
+ instanceof_function(EG(called_scope), ce TSRMLS_CC)) {
+ EX(called_scope) = EG(called_scope);
+ } else {
+ EX(called_scope) = ce;
+ }
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
@@ -3878,7 +3896,13 @@ static int ZEND_FASTCALL ZEND_INIT_STAT
EX(fbc) = ce->constructor;
}
- EX(called_scope) = ce;
+ if (EG(called_scope) &&
+ (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0 &&
+ instanceof_function(EG(called_scope), ce TSRMLS_CC)) {
+ EX(called_scope) = EG(called_scope);
+ } else {
+ EX(called_scope) = ce;
+ }
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
@@ -4314,7 +4338,13 @@ static int ZEND_FASTCALL ZEND_INIT_STAT
EX(fbc) = ce->constructor;
}
- EX(called_scope) = ce;
+ if (EG(called_scope) &&
+ (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0 &&
+ instanceof_function(EG(called_scope), ce TSRMLS_CC)) {
+ EX(called_scope) = EG(called_scope);
+ } else {
+ EX(called_scope) = ce;
+ }
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
@@ -10252,7 +10282,13 @@ static int ZEND_FASTCALL ZEND_INIT_STAT
EX(fbc) = ce->constructor;
}
- EX(called_scope) = ce;
+ if (EG(called_scope) &&
+ (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0 &&
+ instanceof_function(EG(called_scope), ce TSRMLS_CC)) {
+ EX(called_scope) = EG(called_scope);
+ } else {
+ EX(called_scope) = ce;
+ }
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
@@ -12084,7 +12120,13 @@ static int ZEND_FASTCALL ZEND_INIT_STAT
EX(fbc) = ce->constructor;
}
- EX(called_scope) = ce;
+ if (EG(called_scope) &&
+ (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0 &&
+ instanceof_function(EG(called_scope), ce TSRMLS_CC)) {
+ EX(called_scope) = EG(called_scope);
+ } else {
+ EX(called_scope) = ce;
+ }
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
@@ -13886,7 +13928,13 @@ static int ZEND_FASTCALL ZEND_INIT_STAT
EX(fbc) = ce->constructor;
}
- EX(called_scope) = ce;
+ if (EG(called_scope) &&
+ (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0 &&
+ instanceof_function(EG(called_scope), ce TSRMLS_CC)) {
+ EX(called_scope) = EG(called_scope);
+ } else {
+ EX(called_scope) = ce;
+ }
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
@@ -14791,7 +14839,13 @@ static int ZEND_FASTCALL ZEND_INIT_STAT
EX(fbc) = ce->constructor;
}
- EX(called_scope) = ce;
+ if (EG(called_scope) &&
+ (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0 &&
+ instanceof_function(EG(called_scope), ce TSRMLS_CC)) {
+ EX(called_scope) = EG(called_scope);
+ } else {
+ EX(called_scope) = ce;
+ }
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
@@ -16294,7 +16348,13 @@ static int ZEND_FASTCALL ZEND_INIT_STAT
EX(fbc) = ce->constructor;
}
- EX(called_scope) = ce;
+ if (EG(called_scope) &&
+ (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0 &&
+ instanceof_function(EG(called_scope), ce TSRMLS_CC)) {
+ EX(called_scope) = EG(called_scope);
+ } else {
+ EX(called_scope) = ce;
+ }
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
EX(object) = NULL;
Index: Zend/tests/lsb_015.phpt
===================================================================
RCS file: /repository/ZendEngine2/tests/lsb_015.phpt,v
retrieving revision 1.1.2.2
diff -u -p -d -r1.1.2.2 lsb_015.phpt
--- Zend/tests/lsb_015.phpt 29 Sep 2007 07:28:34 -0000 1.1.2.2
+++ Zend/tests/lsb_015.phpt 8 Jul 2008 11:24:54 -0000
@@ -82,11 +82,11 @@ A
via B:
B
B
-A
B
B
B
-A
-A
+B
+B
+B
B
==DONE==
Index: Zend/tests/lsb_021.phpt
===================================================================
RCS file: Zend/tests/lsb_021.phpt
diff -N Zend/tests/lsb_021.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Zend/tests/lsb_021.phpt 8 Jul 2008 11:24:54 -0000
@@ -0,0 +1,105 @@
+--TEST--
+ZE2 Late Static Binding parent:: forwarding while classname doesn't
+--INI--
+error_reporting=0
+--FILE--
+<?php
+class A {
+ public static function test() {
+ echo get_called_class()."\n";
+ }
+ public function test2() {
+ echo get_called_class().(isset($this)?"o":"")."\n";
+ }
+}
+
+class B extends A {
+ public static function testForward() {
+ parent::test();
// C
+ call_user_func("parent::test"); // C
+ call_user_func(array("parent", "test")); // C
+ self::test();
// C
+ call_user_func("self::test"); // C
+ call_user_func(array("self", "test")); // C
+ A::test();
// C
+ call_user_func("A::test"); // C
+ call_user_func(array("A", "test")); // C
+ B::test();
// C
+ call_user_func("B::test"); // C
+ call_user_func(array("B", "test")); // C
+ }
+ public static function testNoForward() {
+ D::test();
// D
+ call_user_func("D::test"); // D
+ call_user_func(array("D", "test")); // D
+ }
+ public function testNoForward2() {
+ $this->test2();
// Co
+ call_user_func(array($this, "test2")); // Co
+ parent::test2();
// Co
+ call_user_func("parent::test2"); // Co
+ call_user_func(array("parent", "test2")); // Co
+ self::test2();
// Co
+ call_user_func("self::test2"); // Co
+ call_user_func(array("self", "test2")); // Co
+ A::test2();
// Co
+ call_user_func("A::test2"); // Co
+ call_user_func(array("A", "test2")); // Co
+ B::test2();
// Co
+ call_user_func("B::test2"); // Co
+ call_user_func(array("B", "test2")); // Co
+ D::test2();
// Co
+ call_user_func("D::test2"); // D
+ call_user_func(array("D", "test2")); // D
+ }
+}
+
+class C extends B {
+
+}
+
+class D extends B {
+}
+
+C::testForward();
+echo "****\n";
+C::testNoForward();
+echo "****\n";
+$x = new C();
+$x->testNoForward2();
+?>
+--EXPECTF--
+C
+C
+C
+C
+C
+C
+C
+C
+C
+C
+C
+C
+****
+D
+D
+D
+****
+Co
+Co
+Co
+Co
+Co
+Co
+Co
+Co
+Co
+Co
+Co
+Co
+Co
+Co
+Co
+D
+D
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php