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

Reply via email to