Hello,

I made the update anyway as it looked like it wouldn't take much time.

Attached is a updated version of my patch, along with all the tests related to it:
http://patches.colder.ch/Zend/late_static_bindings_take7.patch?markup

--
Etienne Kneuss
http://www.colder.ch

Men never do evil so completely and cheerfully as when they do it from a religious conviction.
-- Pascal

? tests/classes/hooks_byref.phpt
? tests/classes/lsb
Index: Zend/zend_API.c
===================================================================
RCS file: /repository/ZendEngine2/zend_API.c,v
retrieving revision 1.443
diff -u -p -r1.443 zend_API.c
--- Zend/zend_API.c     31 Aug 2007 12:36:00 -0000      1.443
+++ Zend/zend_API.c     16 Sep 2007 16:11:35 -0000
@@ -2860,6 +2860,10 @@ ZEND_API zend_bool zend_is_callable_ex(z
                                                        lcname_len == 
sizeof("parent")-1 &&
                                                        
ZEND_U_EQUAL(Z_TYPE_PP(obj), lcname, lcname_len, "parent", sizeof("parent")-1)) 
{
                                                        ce = 
EG(active_op_array)->scope->parent;
+                                               } else if (EG(active_op_array) 
&& EG(active_op_array)->scope &&
+                                                       lcname_len == 
sizeof("static")-1 &&
+                                                       
ZEND_U_EQUAL(Z_TYPE_PP(obj), lcname, lcname_len, "static", sizeof("static")-1)) 
{
+                                                       ce = 
zend_fetch_class_lsb(EG(active_op_array)->scope TSRMLS_CC);
                                                } else if 
(zend_u_lookup_class(Z_TYPE_PP(obj), Z_UNIVAL_PP(obj), Z_UNILEN_PP(obj), &pce 
TSRMLS_CC) == SUCCESS) {
                                                        ce = *pce;
                                                }
Index: Zend/zend_builtin_functions.c
===================================================================
RCS file: /repository/ZendEngine2/zend_builtin_functions.c,v
retrieving revision 1.352
diff -u -p -r1.352 zend_builtin_functions.c
--- Zend/zend_builtin_functions.c       11 Sep 2007 11:35:46 -0000      1.352
+++ Zend/zend_builtin_functions.c       16 Sep 2007 16:11:38 -0000
@@ -44,6 +44,7 @@ static ZEND_FUNCTION(define);
 static ZEND_FUNCTION(defined);
 static ZEND_FUNCTION(get_class);
 static ZEND_FUNCTION(get_parent_class);
+static ZEND_FUNCTION(get_called_class);
 static ZEND_FUNCTION(method_exists);
 static ZEND_FUNCTION(property_exists);
 static ZEND_FUNCTION(class_exists);
@@ -104,6 +105,7 @@ static zend_function_entry builtin_funct
        ZEND_FE(defined,                        NULL)
        ZEND_FE(get_class,                      NULL)
        ZEND_FE(get_parent_class,       NULL)
+       ZEND_FE(get_called_class,       NULL)
        ZEND_FE(method_exists,          NULL)
        ZEND_FE(property_exists,        NULL)
        ZEND_FE(class_exists,           NULL)
@@ -658,6 +660,30 @@ ZEND_FUNCTION(get_parent_class)
 }
 /* }}} */
 
+/* {{{ proto string get_called_class() U
+   Retrieves the class name that were initially called. @see static:: */
+ZEND_FUNCTION(get_called_class)
+{
+       zend_class_entry *lsb_scope;
+
+       if (ZEND_NUM_ARGS()) {
+               ZEND_WRONG_PARAM_COUNT();
+       }
+       
+       if (!EG(scope)) {
+               RETURN_FALSE;
+       }
+
+       lsb_scope = zend_fetch_class_lsb(EG(scope) TSRMLS_CC);
+
+       if (lsb_scope) {
+               RETURN_TEXTL(lsb_scope->name, lsb_scope->name_length, 1);
+       } else {
+               RETURN_FALSE;
+       }
+}
+/* }}} */
+
 static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass) 
/* {{{ */
 {
        zval **obj, **class_name;
Index: Zend/zend_compile.c
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.c,v
retrieving revision 1.767
diff -u -p -r1.767 zend_compile.c
--- Zend/zend_compile.c 5 Sep 2007 07:24:52 -0000       1.767
+++ Zend/zend_compile.c 16 Sep 2007 16:11:47 -0000
@@ -1701,6 +1701,7 @@ void zend_do_fetch_class(znode *result, 
                fetch_type = 
zend_get_class_fetch_type(Z_TYPE(class_name->u.constant), 
Z_UNIVAL(class_name->u.constant), Z_UNILEN(class_name->u.constant));
                switch (fetch_type) {
                        case ZEND_FETCH_CLASS_SELF:
+                       case ZEND_FETCH_CLASS_LATE:
                        case ZEND_FETCH_CLASS_PARENT:
                                SET_UNUSED(opline->op2);
                                opline->extended_value = fetch_type;
@@ -3178,7 +3179,9 @@ void zend_do_begin_class_declaration(zno
 
        if ((lcname_len == sizeof("self")-1 &&
             ZEND_U_EQUAL(Z_TYPE(class_name->u.constant), lcname, lcname_len, 
"self", sizeof("self")-1)) ||
-           (lcname_len == sizeof("parent")-1 &&
+           (lcname_len == sizeof("static")-1 &&
+            ZEND_U_EQUAL(Z_TYPE(class_name->u.constant), lcname, lcname_len, 
"static", sizeof("static")-1)) ||
+               (lcname_len == sizeof("parent")-1 &&
             ZEND_U_EQUAL(Z_TYPE(class_name->u.constant), lcname, lcname_len, 
"parent", sizeof("parent")-1))) {
                efree(lcname.v);
                zend_error(E_COMPILE_ERROR, "Cannot use '%R' as class name as 
it is reserved", Z_TYPE(class_name->u.constant), 
Z_UNIVAL(class_name->u.constant));
@@ -3214,6 +3217,9 @@ void zend_do_begin_class_declaration(zno
 
        if (parent_class_name && parent_class_name->op_type != IS_UNUSED) {
                switch (parent_class_name->u.EA.type) {
+                       case ZEND_FETCH_CLASS_LATE:
+                               zend_error(E_COMPILE_ERROR, "Cannot use 
'static' as class name as it is reserved");
+                               break;
                        case ZEND_FETCH_CLASS_SELF:
                                zend_error(E_COMPILE_ERROR, "Cannot use 'self' 
as class name as it is reserved");
                                break;
@@ -3326,6 +3332,9 @@ void zend_do_implements_interface(znode 
 
        zend_do_fetch_class(&interface_node, interface_name TSRMLS_CC);
        switch (interface_node.u.EA.type) {
+               case ZEND_FETCH_CLASS_LATE:
+                       zend_error(E_COMPILE_ERROR, "Cannot use 'static' as 
interface name as it is reserved");
+                       break;
                case ZEND_FETCH_CLASS_SELF:
                        zend_error(E_COMPILE_ERROR, "Cannot use 'self' as 
interface name as it is reserved");
                        break;
@@ -4873,6 +4882,9 @@ int zend_get_class_fetch_type(zend_uchar
        if ((class_name_len == sizeof("self")-1) &&
            ZEND_U_EQUAL(type, class_name, class_name_len, "self", 
sizeof("self")-1)) {
                return ZEND_FETCH_CLASS_SELF;
+       } else if ((class_name_len == sizeof("static")-1) &&
+           ZEND_U_EQUAL(type, class_name, class_name_len, "static", 
sizeof("static")-1)) {
+               return ZEND_FETCH_CLASS_LATE;
        } else if ((class_name_len == sizeof("parent")-1) &&
            ZEND_U_EQUAL(type, class_name, class_name_len, "parent", 
sizeof("parent")-1)) {
                return ZEND_FETCH_CLASS_PARENT;
Index: Zend/zend_compile.h
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.h,v
retrieving revision 1.364
diff -u -p -r1.364 zend_compile.h
--- Zend/zend_compile.h 24 Aug 2007 13:50:52 -0000      1.364
+++ Zend/zend_compile.h 16 Sep 2007 16:11:50 -0000
@@ -308,6 +308,8 @@ struct _zend_execute_data {
        HashTable *symbol_table;
        struct _zend_execute_data *prev_execute_data;
        zval *old_error_reporting;
+       int lsb_push_number;
+       int lsb_break;
 };
 
 #define EX(element) execute_data.element
@@ -632,6 +634,7 @@ int zendlex(znode *zendlval TSRMLS_DC);
 #define ZEND_FETCH_CLASS_GLOBAL                4
 #define ZEND_FETCH_CLASS_AUTO          5
 #define ZEND_FETCH_CLASS_INTERFACE     6
+#define ZEND_FETCH_CLASS_LATE          7
 #define ZEND_FETCH_CLASS_FLAGS        0xF0
 #define ZEND_FETCH_CLASS_NO_NORMALIZE 0x10
 #define ZEND_FETCH_CLASS_RT_NS_CHECK  0x20
Index: Zend/zend_constants.c
===================================================================
RCS file: /repository/ZendEngine2/zend_constants.c,v
retrieving revision 1.100
diff -u -p -r1.100 zend_constants.c
--- Zend/zend_constants.c       11 Sep 2007 11:23:12 -0000      1.100
+++ Zend/zend_constants.c       16 Sep 2007 16:11:52 -0000
@@ -382,6 +382,15 @@ ZEND_API int zend_u_get_constant_ex(zend
                                ce = scope->parent;
                        }
                        efree(lcname.v);
+               } else if (lcname_len == sizeof("static")-1 &&
+                   ZEND_U_EQUAL(type, lcname, lcname_len, "static", 
sizeof("static")-1)) {
+                       if (scope) {
+                           ce = zend_fetch_class_lsb(scope TSRMLS_CC);
+                       } else {
+                               zend_error(E_ERROR, "Cannot access static:: 
when no class scope is active");
+                               retval = 0;
+                       }
+                       efree(lcname.v);
                } else {
                        /* Check for namespace constant */
                        zstr nsname;
Index: Zend/zend_execute.h
===================================================================
RCS file: /repository/ZendEngine2/zend_execute.h,v
retrieving revision 1.109
diff -u -p -r1.109 zend_execute.h
--- Zend/zend_execute.h 11 Sep 2007 11:23:12 -0000      1.109
+++ Zend/zend_execute.h 16 Sep 2007 16:11:52 -0000
@@ -194,6 +194,7 @@ ZEND_API void zend_unset_timeout(TSRMLS_
 ZEND_API void zend_timeout(int dummy);
 ZEND_API zend_class_entry *zend_fetch_class(char *class_name, uint 
class_name_len, int fetch_type TSRMLS_DC);
 ZEND_API zend_class_entry *zend_u_fetch_class(zend_uchar type, zstr 
class_name, uint class_name_len, int fetch_type TSRMLS_DC);
+ZEND_API zend_class_entry *zend_fetch_class_lsb(zend_class_entry *scope 
TSRMLS_DC);
 void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC);
 
 #ifdef ZEND_WIN32
Index: Zend/zend_execute_API.c
===================================================================
RCS file: /repository/ZendEngine2/zend_execute_API.c,v
retrieving revision 1.415
diff -u -p -r1.415 zend_execute_API.c
--- Zend/zend_execute_API.c     11 Sep 2007 11:23:12 -0000      1.415
+++ Zend/zend_execute_API.c     16 Sep 2007 16:11:56 -0000
@@ -159,7 +159,11 @@ void init_executor(TSRMLS_D) /* {{{ */
        EG(in_autoload) = NULL;
        EG(autoload_func) = NULL;
 
+       EG(last_fetched_class) = NULL;
+       zend_ptr_stack_init(&EG(class_call_stack));
+
        zend_ptr_stack_init(&EG(argument_stack));
+
        zend_ptr_stack_push(&EG(argument_stack), (void *) NULL);
 
        zend_u_hash_init(&EG(symbol_table), 50, NULL, ZVAL_PTR_DTOR, 0, 
UG(unicode));
@@ -307,6 +311,8 @@ void shutdown_executor(TSRMLS_D) /* {{{ 
                }
                zend_hash_apply(EG(class_table), (apply_func_t) 
zend_cleanup_class_data TSRMLS_CC);
 
+               zend_ptr_stack_destroy(&EG(class_call_stack));
+
                zend_ptr_stack_destroy(&EG(argument_stack));
 
                /* Destroy all op arrays */
@@ -1026,6 +1032,8 @@ int zend_call_function(zend_fcall_info *
        current_scope = EG(scope);
        EG(scope) = calling_scope;
 
+       EG(last_fetched_class) = calling_scope;
+
        current_this = EG(This);
 
        if (fci->object_pp) {
@@ -1077,7 +1085,11 @@ int zend_call_function(zend_fcall_info *
                EG(return_value_ptr_ptr) = fci->retval_ptr_ptr;
                EG(active_op_array) = (zend_op_array *) 
EX(function_state).function;
                original_opline_ptr = EG(opline_ptr);
+
+               zend_ptr_stack_push(&EG(class_call_stack), calling_scope);
                zend_execute(EG(active_op_array) TSRMLS_CC);
+               zend_ptr_stack_pop(&EG(class_call_stack));
+
                if (!fci->symbol_table) {
                        zend_hash_destroy(EG(active_symbol_table));
                        FREE_HASHTABLE(EG(active_symbol_table));
@@ -1654,6 +1666,19 @@ void zend_unset_timeout(TSRMLS_D) /* {{{
 }
 /* }}} */
 
+ZEND_API zend_class_entry *zend_fetch_class_lsb(zend_class_entry *scope 
TSRMLS_DC) /* {{{ */
+{
+       zend_class_entry *last_scope = 
EG(class_call_stack).elements[EG(class_call_stack).top-1];
+       
+       if (last_scope == NULL || instanceof_function(last_scope, scope 
TSRMLS_CC) != 1) {
+               return scope;
+       } else {
+               return last_scope;
+       }
+
+}
+/* }}} */
+
 ZEND_API zend_class_entry *zend_u_fetch_class(zend_uchar type, zstr 
class_name, uint class_name_len, int fetch_type TSRMLS_DC) /* {{{ */
 {
        zend_class_entry **pce;
@@ -1666,10 +1691,18 @@ ZEND_API zend_class_entry *zend_u_fetch_
 
 check_fetch_type:
        switch (fetch_type) {
+               case ZEND_FETCH_CLASS_LATE:
+                       if (!EG(scope)) {
+                               zend_error(E_ERROR, "Cannot access static:: 
when no class scope is active");
+                       }
+                       zend_class_entry *lsb_scope = 
zend_fetch_class_lsb(EG(scope) TSRMLS_CC);
+                       EG(last_fetched_class) = lsb_scope;
+                       return lsb_scope;
                case ZEND_FETCH_CLASS_SELF:
                        if (!EG(scope)) {
                                zend_error(E_ERROR, "Cannot access self:: when 
no class scope is active");
                        }
+                       EG(last_fetched_class) = EG(scope);
                        return EG(scope);
                case ZEND_FETCH_CLASS_PARENT:
                        if (!EG(scope)) {
@@ -1678,6 +1711,7 @@ check_fetch_type:
                        if (!EG(scope)->parent) {
                                zend_error(E_ERROR, "Cannot access parent:: 
when current class scope has no parent");
                        }
+                       EG(last_fetched_class) = EG(scope)->parent;
                        return EG(scope)->parent;
                case ZEND_FETCH_CLASS_AUTO: {
                                if (do_normalize) {
@@ -1724,6 +1758,7 @@ check_fetch_type:
                                if (lcname.v != class_name.v) {
                                        efree(lcname.v);
                                }
+                               EG(last_fetched_class) = *pce;
                                return *pce;
                        }
                }
@@ -1733,6 +1768,7 @@ check_fetch_type:
                                if (lcname.v != class_name.v) {
                                        efree(lcname.v);
                                }
+                               EG(last_fetched_class) = *pce;
                                return *pce;
                        }
                        if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) {
@@ -1744,11 +1780,13 @@ check_fetch_type:
                if (lcname.v != class_name.v) {
                        efree(lcname.v);
                }
+               EG(last_fetched_class) = NULL;
                return NULL;
        } else {
                if (lcname.v != class_name.v) {
                        efree(lcname.v);
                }
+               EG(last_fetched_class) = *pce;
                return *pce;
        }
 }
Index: Zend/zend_globals.h
===================================================================
RCS file: /repository/ZendEngine2/zend_globals.h,v
retrieving revision 1.168
diff -u -p -r1.168 zend_globals.h
--- Zend/zend_globals.h 12 Jul 2007 09:23:48 -0000      1.168
+++ Zend/zend_globals.h 16 Sep 2007 16:11:57 -0000
@@ -160,6 +160,9 @@ struct _zend_executor_globals {
        zend_function_state *function_state_ptr;
        zend_ptr_stack arg_types_stack;
 
+       zend_ptr_stack    class_call_stack;
+       zend_class_entry *last_fetched_class;
+
        /* symbol table cache */
        HashTable *symtable_cache[SYMTABLE_CACHE_SIZE];
        HashTable **symtable_cache_limit;
Index: Zend/zend_language_parser.y
===================================================================
RCS file: /repository/ZendEngine2/zend_language_parser.y,v
retrieving revision 1.189
diff -u -p -r1.189 zend_language_parser.y
--- Zend/zend_language_parser.y 24 Aug 2007 13:50:52 -0000      1.189
+++ Zend/zend_language_parser.y 16 Sep 2007 16:12:01 -0000
@@ -672,6 +672,7 @@ fully_qualified_class_name:
                T_STRING { $$ = $1; }
        |       T_PAAMAYIM_NEKUDOTAYIM T_STRING { 
zend_do_build_namespace_name(&$$, NULL, &$2 TSRMLS_CC); }
        |       fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING { 
zend_do_build_namespace_name(&$$, &$1, &$3 TSRMLS_CC); }
+       |       T_STATIC { znode tmp; tmp.op_type = IS_CONST; 
ZVAL_STRINGL(&tmp.u.constant, "static", sizeof("static")-1, 1);  
INIT_PZVAL(&tmp.u.constant); $$ = tmp; }
 ;
 
 
Index: Zend/zend_vm_def.h
===================================================================
RCS file: /repository/ZendEngine2/zend_vm_def.h,v
retrieving revision 1.182
diff -u -p -r1.182 zend_vm_def.h
--- Zend/zend_vm_def.h  11 Sep 2007 11:23:12 -0000      1.182
+++ Zend/zend_vm_def.h  16 Sep 2007 16:12:09 -0000
@@ -1754,6 +1754,10 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CA
                        zend_error_noreturn(E_ERROR, "Object does not support 
method calls");
                }
 
+               if (Z_OBJCE_P(EX(object))) {
+                       EG(last_fetched_class) = Z_OBJCE_P(EX(object));
+               }
+
                /* First, locate the function. */
                EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), 
function_name_strval, function_name_strlen TSRMLS_CC);
                if (!EX(fbc)) {
@@ -2637,6 +2641,11 @@ ZEND_VM_HANDLER(68, ZEND_NEW, ANY, ANY)
                EX(object) = object_zval;
                EX(fbc) = constructor;
 
+               if (constructor->common.fn_flags && constructor->type == 
ZEND_USER_FUNCTION) {
+                       /* Affect the lsb_push_number of the next execute data 
*/
+                       EG(current_execute_data)->lsb_break = 1;
+               }
+
                ZEND_VM_NEXT_OPCODE();
        }
 }
Index: Zend/zend_vm_execute.h
===================================================================
RCS file: /repository/ZendEngine2/zend_vm_execute.h,v
retrieving revision 1.186
diff -u -p -r1.186 zend_vm_execute.h
--- Zend/zend_vm_execute.h      11 Sep 2007 11:23:12 -0000      1.186
+++ Zend/zend_vm_execute.h      16 Sep 2007 16:13:04 -0000
@@ -82,6 +82,27 @@ ZEND_API void execute(zend_op_array *op_
        EX(function_state).function_symbol_table = NULL;
 #endif
 
+       execute_data.lsb_push_number = 0;
+       execute_data.lsb_break = 0;
+
+       if (EX(prev_execute_data) && EX(prev_execute_data)->lsb_break) {
+                       /* Detect that last execute_data triggered a break */
+                       zend_ptr_stack_push(&EG(class_call_stack), NULL);
+                       execute_data.lsb_push_number++;
+                       EX(prev_execute_data)->lsb_break = 0;
+       }
+
+       if (EG(last_fetched_class) == 
EX(function_state).function->common.scope) { 
+               /* No fallback */
+               zend_ptr_stack_push(&EG(class_call_stack), NULL);
+               zend_ptr_stack_push(&EG(class_call_stack), EG(scope));
+               execute_data.lsb_push_number += 2;
+       } else if (EX(function_state).function->common.scope != NULL) {
+               /* we are executing a method, static or not check scope */
+               zend_ptr_stack_push(&EG(class_call_stack), 
EG(last_fetched_class));
+               execute_data.lsb_push_number += 1;
+       }
+
        while (1) {
 #ifdef ZEND_WIN32
                if (EG(timed_out)) {
@@ -90,6 +111,12 @@ ZEND_API void execute(zend_op_array *op_
 #endif
 
                if (EX(opline)->handler(&execute_data TSRMLS_CC) > 0) {
+                       if (execute_data.lsb_push_number) {
+                               /* clean block separation(s) */
+                               while(--execute_data.lsb_push_number >= 0) {
+                                       
zend_ptr_stack_pop(&EG(class_call_stack));
+                               }
+                       }
       return;
                }
 
@@ -437,6 +464,11 @@ static int ZEND_NEW_SPEC_HANDLER(ZEND_OP
                EX(object) = object_zval;
                EX(fbc) = constructor;
 
+               if (constructor->common.fn_flags && constructor->type == 
ZEND_USER_FUNCTION) {
+                       /* Affect the lsb_push_number of the next execute data 
*/
+                       EG(current_execute_data)->lsb_break = 1;
+               }
+
                ZEND_VM_NEXT_OPCODE();
        }
 }
@@ -5784,6 +5816,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TM
                        zend_error_noreturn(E_ERROR, "Object does not support 
method calls");
                }
 
+               if (Z_OBJCE_P(EX(object))) {
+                       EG(last_fetched_class) = Z_OBJCE_P(EX(object));
+               }
+
                /* First, locate the function. */
                EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), 
function_name_strval, function_name_strlen TSRMLS_CC);
                if (!EX(fbc)) {
@@ -6233,6 +6269,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TM
                        zend_error_noreturn(E_ERROR, "Object does not support 
method calls");
                }
 
+               if (Z_OBJCE_P(EX(object))) {
+                       EG(last_fetched_class) = Z_OBJCE_P(EX(object));
+               }
+
                /* First, locate the function. */
                EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), 
function_name_strval, function_name_strlen TSRMLS_CC);
                if (!EX(fbc)) {
@@ -6684,6 +6724,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TM
                        zend_error_noreturn(E_ERROR, "Object does not support 
method calls");
                }
 
+               if (Z_OBJCE_P(EX(object))) {
+                       EG(last_fetched_class) = Z_OBJCE_P(EX(object));
+               }
+
                /* First, locate the function. */
                EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), 
function_name_strval, function_name_strlen TSRMLS_CC);
                if (!EX(fbc)) {
@@ -7228,6 +7272,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TM
                        zend_error_noreturn(E_ERROR, "Object does not support 
method calls");
                }
 
+               if (Z_OBJCE_P(EX(object))) {
+                       EG(last_fetched_class) = Z_OBJCE_P(EX(object));
+               }
+
                /* First, locate the function. */
                EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), 
function_name_strval, function_name_strlen TSRMLS_CC);
                if (!EX(fbc)) {
@@ -9980,6 +10028,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VA
                        zend_error_noreturn(E_ERROR, "Object does not support 
method calls");
                }
 
+               if (Z_OBJCE_P(EX(object))) {
+                       EG(last_fetched_class) = Z_OBJCE_P(EX(object));
+               }
+
                /* First, locate the function. */
                EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), 
function_name_strval, function_name_strlen TSRMLS_CC);
                if (!EX(fbc)) {
@@ -11677,6 +11729,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VA
                        zend_error_noreturn(E_ERROR, "Object does not support 
method calls");
                }
 
+               if (Z_OBJCE_P(EX(object))) {
+                       EG(last_fetched_class) = Z_OBJCE_P(EX(object));
+               }
+
                /* First, locate the function. */
                EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), 
function_name_strval, function_name_strlen TSRMLS_CC);
                if (!EX(fbc)) {
@@ -13347,6 +13403,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VA
                        zend_error_noreturn(E_ERROR, "Object does not support 
method calls");
                }
 
+               if (Z_OBJCE_P(EX(object))) {
+                       EG(last_fetched_class) = Z_OBJCE_P(EX(object));
+               }
+
                /* First, locate the function. */
                EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), 
function_name_strval, function_name_strlen TSRMLS_CC);
                if (!EX(fbc)) {
@@ -15536,6 +15596,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VA
                        zend_error_noreturn(E_ERROR, "Object does not support 
method calls");
                }
 
+               if (Z_OBJCE_P(EX(object))) {
+                       EG(last_fetched_class) = Z_OBJCE_P(EX(object));
+               }
+
                /* First, locate the function. */
                EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), 
function_name_strval, function_name_strlen TSRMLS_CC);
                if (!EX(fbc)) {
@@ -16835,6 +16899,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UN
                        zend_error_noreturn(E_ERROR, "Object does not support 
method calls");
                }
 
+               if (Z_OBJCE_P(EX(object))) {
+                       EG(last_fetched_class) = Z_OBJCE_P(EX(object));
+               }
+
                /* First, locate the function. */
                EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), 
function_name_strval, function_name_strlen TSRMLS_CC);
                if (!EX(fbc)) {
@@ -17918,6 +17986,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UN
                        zend_error_noreturn(E_ERROR, "Object does not support 
method calls");
                }
 
+               if (Z_OBJCE_P(EX(object))) {
+                       EG(last_fetched_class) = Z_OBJCE_P(EX(object));
+               }
+
                /* First, locate the function. */
                EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), 
function_name_strval, function_name_strlen TSRMLS_CC);
                if (!EX(fbc)) {
@@ -18935,6 +19007,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UN
                        zend_error_noreturn(E_ERROR, "Object does not support 
method calls");
                }
 
+               if (Z_OBJCE_P(EX(object))) {
+                       EG(last_fetched_class) = Z_OBJCE_P(EX(object));
+               }
+
                /* First, locate the function. */
                EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), 
function_name_strval, function_name_strlen TSRMLS_CC);
                if (!EX(fbc)) {
@@ -20217,6 +20293,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UN
                        zend_error_noreturn(E_ERROR, "Object does not support 
method calls");
                }
 
+               if (Z_OBJCE_P(EX(object))) {
+                       EG(last_fetched_class) = Z_OBJCE_P(EX(object));
+               }
+
                /* First, locate the function. */
                EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), 
function_name_strval, function_name_strlen TSRMLS_CC);
                if (!EX(fbc)) {
@@ -22987,6 +23067,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV
                        zend_error_noreturn(E_ERROR, "Object does not support 
method calls");
                }
 
+               if (Z_OBJCE_P(EX(object))) {
+                       EG(last_fetched_class) = Z_OBJCE_P(EX(object));
+               }
+
                /* First, locate the function. */
                EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), 
function_name_strval, function_name_strlen TSRMLS_CC);
                if (!EX(fbc)) {
@@ -24522,6 +24606,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV
                        zend_error_noreturn(E_ERROR, "Object does not support 
method calls");
                }
 
+               if (Z_OBJCE_P(EX(object))) {
+                       EG(last_fetched_class) = Z_OBJCE_P(EX(object));
+               }
+
                /* First, locate the function. */
                EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), 
function_name_strval, function_name_strlen TSRMLS_CC);
                if (!EX(fbc)) {
@@ -26096,6 +26184,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV
                        zend_error_noreturn(E_ERROR, "Object does not support 
method calls");
                }
 
+               if (Z_OBJCE_P(EX(object))) {
+                       EG(last_fetched_class) = Z_OBJCE_P(EX(object));
+               }
+
                /* First, locate the function. */
                EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), 
function_name_strval, function_name_strlen TSRMLS_CC);
                if (!EX(fbc)) {
@@ -28101,6 +28193,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV
                        zend_error_noreturn(E_ERROR, "Object does not support 
method calls");
                }
 
+               if (Z_OBJCE_P(EX(object))) {
+                       EG(last_fetched_class) = Z_OBJCE_P(EX(object));
+               }
+
                /* First, locate the function. */
                EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), 
function_name_strval, function_name_strlen TSRMLS_CC);
                if (!EX(fbc)) {
Index: Zend/zend_vm_execute.skl
===================================================================
RCS file: /repository/ZendEngine2/zend_vm_execute.skl,v
retrieving revision 1.7
diff -u -p -r1.7 zend_vm_execute.skl
--- Zend/zend_vm_execute.skl    21 Jul 2007 00:34:41 -0000      1.7
+++ Zend/zend_vm_execute.skl    16 Sep 2007 16:13:04 -0000
@@ -53,6 +53,27 @@ ZEND_API void {%EXECUTOR_NAME%}(zend_op_
        EX(function_state).function_symbol_table = NULL;
 #endif
 
+       execute_data.lsb_push_number = 0;
+       execute_data.lsb_break = 0;
+
+       if (EX(prev_execute_data) && EX(prev_execute_data)->lsb_break) {
+                       /* Detect that last execute_data triggered a break */
+                       zend_ptr_stack_push(&EG(class_call_stack), NULL);
+                       execute_data.lsb_push_number++;
+                       EX(prev_execute_data)->lsb_break = 0;
+       }
+
+       if (EG(last_fetched_class) == 
EX(function_state).function->common.scope) { 
+               /* No fallback */
+               zend_ptr_stack_push(&EG(class_call_stack), NULL);
+               zend_ptr_stack_push(&EG(class_call_stack), EG(scope));
+               execute_data.lsb_push_number += 2;
+       } else if (EX(function_state).function->common.scope != NULL) {
+               /* we are executing a method, static or not check scope */
+               zend_ptr_stack_push(&EG(class_call_stack), 
EG(last_fetched_class));
+               execute_data.lsb_push_number += 1;
+       }
+
        while (1) {
     {%ZEND_VM_CONTINUE_LABEL%}
 #ifdef ZEND_WIN32
@@ -62,6 +83,12 @@ ZEND_API void {%EXECUTOR_NAME%}(zend_op_
 #endif
 
                {%ZEND_VM_DISPATCH%} {
+                       if (execute_data.lsb_push_number) {
+                               /* clean block separation(s) */
+                               while(--execute_data.lsb_push_number >= 0) {
+                                       
zend_ptr_stack_pop(&EG(class_call_stack));
+                               }
+                       }
       {%INTERNAL_EXECUTOR%}
                }
 
Index: tests/classes/late_static_binding_001.phpt
===================================================================
RCS file: tests/classes/late_static_binding_001.phpt
diff -N tests/classes/late_static_binding_001.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/classes/late_static_binding_001.phpt  16 Sep 2007 16:13:05 -0000
@@ -0,0 +1,61 @@
+--TEST--
+ZE2 Late Static Binding in a static function
+--FILE--
+<?php
+
+class TestClass {
+   protected static $staticVar = 'TestClassStatic';
+   const CLASS_CONST = 'TestClassConst';
+
+   protected static function staticFunction() {
+       return 'TestClassFunction';
+   }
+   
+   public static function testStaticVar() {
+       return static::$staticVar;
+   }
+
+   public static function testClassConst() {
+       return static::CLASS_CONST;
+   }
+
+   public static function testStaticFunction() {
+       return static::staticFunction();
+   }
+}
+
+class ChildClass1 extends TestClass {
+   protected static $staticVar = 'ChildClassStatic';
+   const CLASS_CONST = 'ChildClassConst';
+
+   protected static function staticFunction() {
+       return 'ChildClassFunction';
+   }
+}
+
+class ChildClass2 extends TestClass {}
+
+echo TestClass::testStaticVar() . "\n";
+echo TestClass::testClassConst() . "\n";
+echo TestClass::testStaticFunction() . "\n";
+
+echo ChildClass1::testStaticVar() . "\n";
+echo ChildClass1::testClassConst() . "\n";
+echo ChildClass1::testStaticFunction() . "\n";
+
+echo ChildClass2::testStaticVar() . "\n";
+echo ChildClass2::testClassConst() . "\n";
+echo ChildClass2::testStaticFunction() . "\n";
+?>
+==DONE==
+--EXPECTF--
+TestClassStatic
+TestClassConst
+TestClassFunction
+ChildClassStatic
+ChildClassConst
+ChildClassFunction
+TestClassStatic
+TestClassConst
+TestClassFunction
+==DONE==
Index: tests/classes/late_static_binding_002.phpt
===================================================================
RCS file: tests/classes/late_static_binding_002.phpt
diff -N tests/classes/late_static_binding_002.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/classes/late_static_binding_002.phpt  16 Sep 2007 16:13:05 -0000
@@ -0,0 +1,65 @@
+--TEST--
+ZE2 Late Static Binding with instances
+--FILE--
+<?php
+
+class TestClass {
+   protected static $staticVar = 'TestClassStatic';
+   const CLASS_CONST = 'TestClassConst';
+
+   protected static function staticFunction() {
+       return 'TestClassFunction';
+   }
+   
+   public function testStaticVar() {
+       return static::$staticVar;
+   }
+
+   public function testClassConst() {
+       return static::CLASS_CONST;
+   }
+
+   public function testStaticFunction() {
+       return static::staticFunction();
+   }
+}
+
+class ChildClass1 extends TestClass {
+   protected static $staticVar = 'ChildClassStatic';
+   const CLASS_CONST = 'ChildClassConst';
+
+   protected static function staticFunction() {
+       return 'ChildClassFunction';
+   }
+}
+
+class ChildClass2 extends TestClass {}
+
+$testClass = new TestClass();
+$childClass1 = new ChildClass1();
+$childClass2 = new ChildClass2();
+
+echo $testClass->testStaticVar() . "\n";
+echo $testClass->testClassConst() . "\n";
+echo $testClass->testStaticFunction() . "\n";
+
+echo $childClass1->testStaticVar() . "\n";
+echo $childClass1->testClassConst() . "\n";
+echo $childClass1->testStaticFunction() . "\n";
+
+echo $childClass2->testStaticVar() . "\n";
+echo $childClass2->testClassConst() . "\n";
+echo $childClass2->testStaticFunction() . "\n";
+?>
+==DONE==
+--EXPECTF--
+TestClassStatic
+TestClassConst
+TestClassFunction
+ChildClassStatic
+ChildClassConst
+ChildClassFunction
+TestClassStatic
+TestClassConst
+TestClassFunction
+==DONE==
Index: tests/classes/late_static_binding_003.phpt
===================================================================
RCS file: tests/classes/late_static_binding_003.phpt
diff -N tests/classes/late_static_binding_003.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/classes/late_static_binding_003.phpt  16 Sep 2007 16:13:05 -0000
@@ -0,0 +1,68 @@
+--TEST--
+ZE2 Late Static Binding with dynamic method names
+--FILE--
+<?php
+
+class TestClass {
+   protected static $staticVar = 'TestClassStatic';
+   const CLASS_CONST = 'TestClassConst';
+
+   protected static function staticFunction() {
+       return 'TestClassFunction';
+   }
+   
+   public function testStaticVar() {
+       return static::$staticVar;
+   }
+
+   public function testClassConst() {
+       return static::CLASS_CONST;
+   }
+
+   public function testStaticFunction() {
+       return static::staticFunction();
+   }
+}
+
+class ChildClass1 extends TestClass {
+   protected static $staticVar = 'ChildClassStatic';
+   const CLASS_CONST = 'ChildClassConst';
+
+   protected static function staticFunction() {
+       return 'ChildClassFunction';
+   }
+}
+
+class ChildClass2 extends TestClass {}
+
+$testClass = new TestClass();
+$childClass1 = new ChildClass1();
+$childClass2 = new ChildClass2();
+$func1 = 'testStaticVar';
+$func2 = 'testClassConst';
+$func3 = 'testStaticFunction';
+
+echo $testClass->$func1() . "\n";
+echo $testClass->$func2() . "\n";
+echo $testClass->$func3() . "\n";
+
+echo $childClass1->$func1() . "\n";
+echo $childClass1->$func2() . "\n";
+echo $childClass1->$func3() . "\n";
+
+echo $childClass2->$func1() . "\n";
+echo $childClass2->$func2() . "\n";
+echo $childClass2->$func3() . "\n";
+?>
+==DONE==
+--EXPECTF--
+TestClassStatic
+TestClassConst
+TestClassFunction
+ChildClassStatic
+ChildClassConst
+ChildClassFunction
+TestClassStatic
+TestClassConst
+TestClassFunction
+==DONE==
Index: tests/classes/late_static_binding_004.phpt
===================================================================
RCS file: tests/classes/late_static_binding_004.phpt
diff -N tests/classes/late_static_binding_004.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/classes/late_static_binding_004.phpt  16 Sep 2007 16:13:05 -0000
@@ -0,0 +1,95 @@
+--TEST--
+ZE2 Late Static Binding with dynamic function calls 
+--FILE--
+<?php
+
+class TestClass {
+   protected static $staticVar = 'TestClassStatic';
+   const CLASS_CONST = 'TestClassConst';
+
+   protected static function staticFunction() {
+       return 'TestClassFunction';
+   }
+   public static function staticTestStaticVar() {
+       return static::$staticVar;
+   }
+
+   public static function staticTestClassConst() {
+       return static::CLASS_CONST;
+   }
+
+   public static function staticTestStaticFunction() {
+       return static::staticFunction();
+   }
+   
+   public function testStaticVar() {
+       return static::$staticVar;
+   }
+
+   public function testClassConst() {
+       return static::CLASS_CONST;
+   }
+
+   public function testStaticFunction() {
+       return static::staticFunction();
+   }
+}
+
+class ChildClass1 extends TestClass {
+   protected static $staticVar = 'ChildClassStatic';
+   const CLASS_CONST = 'ChildClassConst';
+
+   protected static function staticFunction() {
+       return 'ChildClassFunction';
+   }
+}
+
+class ChildClass2 extends TestClass {}
+
+$testClass = new TestClass();
+$childClass1 = new ChildClass1();
+$childClass2 = new ChildClass2();
+
+
+echo call_user_func(array($testClass, 'testStaticVar')) . "\n";
+echo call_user_func(array($testClass, 'testClassConst')) . "\n";
+echo call_user_func(array($testClass, 'testStaticFunction')) . "\n";
+echo call_user_func(array('TestClass', 'staticTestStaticVar')) . "\n";
+echo call_user_func(array('TestClass', 'staticTestClassConst')) . "\n";
+echo call_user_func(array('TestClass', 'staticTestStaticFunction')) . "\n";
+
+echo call_user_func(array($childClass1, 'testStaticVar')) . "\n";
+echo call_user_func(array($childClass1, 'testClassConst')) . "\n";
+echo call_user_func(array($childClass1, 'testStaticFunction')) . "\n";
+echo call_user_func(array('ChildClass1', 'staticTestStaticVar')) . "\n";
+echo call_user_func(array('ChildClass1', 'staticTestClassConst')) . "\n";
+echo call_user_func(array('ChildClass1', 'staticTestStaticFunction')) . "\n";
+
+echo call_user_func(array($childClass2, 'testStaticVar')) . "\n";
+echo call_user_func(array($childClass2, 'testClassConst')) . "\n";
+echo call_user_func(array($childClass2, 'testStaticFunction')) . "\n";
+echo call_user_func(array('ChildClass2', 'staticTestStaticVar')) . "\n";
+echo call_user_func(array('ChildClass2', 'staticTestClassConst')) . "\n";
+echo call_user_func(array('ChildClass2', 'staticTestStaticFunction')) . "\n";
+?>
+==DONE==
+--EXPECTF--
+TestClassStatic
+TestClassConst
+TestClassFunction
+TestClassStatic
+TestClassConst
+TestClassFunction
+ChildClassStatic
+ChildClassConst
+ChildClassFunction
+ChildClassStatic
+ChildClassConst
+ChildClassFunction
+TestClassStatic
+TestClassConst
+TestClassFunction
+TestClassStatic
+TestClassConst
+TestClassFunction
+==DONE==
Index: tests/classes/late_static_binding_005.phpt
===================================================================
RCS file: tests/classes/late_static_binding_005.phpt
diff -N tests/classes/late_static_binding_005.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/classes/late_static_binding_005.phpt  16 Sep 2007 16:13:05 -0000
@@ -0,0 +1,92 @@
+--TEST--
+ZE2 Late Static Binding with exceptions 
+--FILE--
+<?php
+function foo() {
+    B::throwException();
+}
+class C {
+    public static function bla() {
+        B::throwException();
+    }
+    public static function getException() {
+        return new Exception();
+         
+    }
+}
+class A {
+
+    public static function throwException_after() {
+        C::bla();
+    }
+    public static function throwException() {
+        throw C::getException();
+    }
+    public static function test() {
+        static::who();
+    }
+    public static function who() {
+        echo "A\n";
+    }
+
+    public static function mycatch() {
+        try {
+            static::who();
+            B::throwException_after();
+        } catch(Exception $e) {
+            static::who();
+            A::test();
+            static::who();
+            B::test();
+            static::who();
+
+            self::simpleCatch();
+            static::who();
+        }
+    }
+
+    public static function simpleCatch() {
+        try {
+            static::who();
+            throw new Exception();
+        } catch (Exception $e) {
+            static::who();
+        }
+    }
+}
+
+class B extends A {
+    public static function who() {
+        echo "B\n";
+    }
+
+}
+
+echo "via A:\n";
+A::myCatch();
+echo "via B:\n";
+B::myCatch();
+?>
+==DONE==
+--EXPECTF--
+via A:
+A
+A
+A
+A
+B
+A
+A
+A
+A
+via B:
+B
+B
+A
+B
+B
+B
+A
+A
+B
+==DONE==
Index: tests/classes/late_static_binding_006.phpt
===================================================================
RCS file: tests/classes/late_static_binding_006.phpt
diff -N tests/classes/late_static_binding_006.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/classes/late_static_binding_006.phpt  16 Sep 2007 16:13:05 -0000
@@ -0,0 +1,36 @@
+--TEST--
+ZE2 Late Static Binding within constructors
+--FILE--
+<?php
+
+class TestChild extends TestParent {
+    public function __construct() {
+        static::who();
+    }
+
+    public function test() {
+        $o = new TestParent();
+    }
+
+    public static function who() {
+        echo __CLASS__."\n";
+    }
+}
+
+class TestParent {
+    public function __construct() {
+        static::who();
+    }
+
+    public static function who() {
+        echo __CLASS__."\n";
+    }
+}
+$o = new TestChild;
+$o->test();
+?>
+==DONE==
+--EXPECTF--
+TestChild
+TestParent
+==DONE==
Index: tests/classes/late_static_binding_007.phpt
===================================================================
RCS file: tests/classes/late_static_binding_007.phpt
diff -N tests/classes/late_static_binding_007.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/classes/late_static_binding_007.phpt  16 Sep 2007 16:13:05 -0000
@@ -0,0 +1,41 @@
+--TEST--
+ZE2 Late Static Binding within hooks/magic methods
+--FILE--
+<?php
+
+class TestChild extends TestParent {
+
+    public static function who() {
+        echo __CLASS__."\n";
+    }
+}
+
+class TestParent {
+
+    public function __get($var) {
+        static::who();
+    }
+
+    public function __set($var, $val) {
+        static::who();
+    }
+
+    public function __call($name, $args) {
+        static::who();
+    }
+
+    public static function who() {
+        echo __CLASS__."\n";
+    }
+}
+$o = new TestChild;
+$o->test();
+$o->a = "b";
+echo $o->a;
+?>
+==DONE==
+--EXPECTF--
+TestChild
+TestChild
+TestChild
+==DONE==
Index: tests/classes/late_static_binding_008.phpt
===================================================================
RCS file: tests/classes/late_static_binding_008.phpt
diff -N tests/classes/late_static_binding_008.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/classes/late_static_binding_008.phpt  16 Sep 2007 16:13:05 -0000
@@ -0,0 +1,45 @@
+--TEST--
+ZE2 Late Static Binding with get_called_class()
+--FILE--
+<?php
+
+class TestChild extends TestParent {
+}
+
+class TestParent {
+
+    public function __get($var) {
+        echo get_called_class()."\n";
+    }
+
+    public function __set($var, $val) {
+        echo get_called_class()."\n";
+    }
+
+    public function __call($name, $args) {
+        echo get_called_class()."\n";
+    }
+
+    public static function test() {
+        echo get_called_class()."\n";
+    }
+}
+$o = new TestChild;
+$o->test();
+$o->a = "b";
+echo $o->a;
+
+TestParent::test();
+TestChild::test();
+
+var_dump(get_called_class());
+?>
+==DONE==
+--EXPECTF--
+TestChild
+TestChild
+TestChild
+TestParent
+TestChild
+bool(false)
+==DONE==
Index: tests/classes/late_static_binding_009.phpt
===================================================================
RCS file: tests/classes/late_static_binding_009.phpt
diff -N tests/classes/late_static_binding_009.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/classes/late_static_binding_009.phpt  16 Sep 2007 16:13:05 -0000
@@ -0,0 +1,49 @@
+--TEST--
+ZE2 Late Static Binding with scope paths
+--FILE--
+<?php
+
+class A {
+
+    public static function test1() {
+        C::test1();
+    }
+    public static function test2() {
+        echo get_called_class()."\n";
+    }
+}
+
+class B extends A {
+    public static function test1() {
+        A::test1();
+    }
+    public static function test2() {
+        C::test2();
+    }
+}
+
+class C extends A {
+
+    public static function test1() {
+        echo get_called_class()."\n";
+    }
+
+    public static function test2() {
+        A::test2();
+    }
+}
+
+//   A
+//  / \
+// B   C
+
+// code path 2: B -> C -> A
+B::test2();
+// code path 1: B -> A -> C
+B::test1();
+?>
+==DONE==
+--EXPECTF--
+A
+C
+==DONE==
Index: tests/classes/late_static_binding_010.phpt
===================================================================
RCS file: tests/classes/late_static_binding_010.phpt
diff -N tests/classes/late_static_binding_010.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/classes/late_static_binding_010.phpt  16 Sep 2007 16:13:05 -0000
@@ -0,0 +1,25 @@
+--TEST--
+ZE2 Late Static Binding with dynamic constant access
+--FILE--
+<?php
+
+class A{
+    const C = 'A';
+    public static function foo() {
+        var_dump(defined('static::D'));
+        var_dump(constant('static::D'));
+    }
+}
+
+class B extends A {
+    const C = 'B';
+    const D = 'B';
+}
+
+B::foo();
+?>
+==DONE==
+--EXPECTF--
+bool(true)
+string(1) "B"
+==DONE==
Index: tests/classes/late_static_binding_011.phpt
===================================================================
RCS file: tests/classes/late_static_binding_011.phpt
diff -N tests/classes/late_static_binding_011.phpt
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/classes/late_static_binding_011.phpt  16 Sep 2007 16:13:05 -0000
@@ -0,0 +1,33 @@
+--TEST--
+ZE2 Late Static Binding callbacks
+--FILE--
+<?php
+
+class A{
+    public static function foo() {
+        var_dump(is_callable(array('static', 'who')));
+        var_dump(is_callable('static::who'));
+        call_user_func(array('static', 'who'));
+        call_user_func('static::who');
+    }
+    
+    public static function who() {
+        echo __CLASS__."\n";
+    }
+}
+
+class B extends A {
+    public static function who() {
+        echo __CLASS__."\n";
+    }
+}
+
+B::foo();
+?>
+==DONE==
+--EXPECTF--
+bool(true)
+bool(true)
+B
+B
+==DONE==

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to