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