On Wed, 2006-03-01 at 17:37 +0300, Dmitry Stogov wrote: > 1) I would very like to see some real example where "static" is necessary? > > 2) "static" is really bad name. I suggest "caller", Marcus thought about > "class". > > 3) I COMPLETELY DISAGREE TO ADD RUNTIME DATA INTO > zend_function/zend_op_array. > We can try to store "caller_scope" in execute_data. > > Thanks. Dmitry. >
Rewrote the patch to use execute_data to store caller_scope. I have not renamed any functions or keywords (still using static::) as I did not see any consensus on that yet. Please review the implementation of caller_scope and I can take care of the naming issues when names are decided on. patch attached and also available at http://test.ft11.net/_mlively/late-static-binding.patch It would be nice if the patch in PAT could be changed to reference this new version if the appropriate people have time.
diff -Naur php-src/tests/classes/caller_001.phpt php-new/tests/classes/caller_001.phpt --- php-src/tests/classes/caller_001.phpt 1969-12-31 16:00:00.000000000 -0800 +++ php-new/tests/classes/caller_001.phpt 2006-03-06 11:43:51.000000000 -0800 @@ -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== diff -Naur php-src/tests/classes/caller_002.phpt php-new/tests/classes/caller_002.phpt --- php-src/tests/classes/caller_002.phpt 1969-12-31 16:00:00.000000000 -0800 +++ php-new/tests/classes/caller_002.phpt 2006-03-06 11:43:51.000000000 -0800 @@ -0,0 +1,66 @@ +--TEST-- +ZE2 Late Static Binding in an instance function +--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== diff -Naur php-src/tests/classes/caller_003.phpt php-new/tests/classes/caller_003.phpt --- php-src/tests/classes/caller_003.phpt 1969-12-31 16:00:00.000000000 -0800 +++ php-new/tests/classes/caller_003.phpt 2006-03-06 11:43:51.000000000 -0800 @@ -0,0 +1,24 @@ +--TEST-- +ZE2 creating a new class with 'static' +--FILE-- +<?php + +class TestClass { + public static function createInstance() { + return new static(); + } +} + +class ChildClass extends TestClass {} + +$testClass = TestClass::createInstance(); +$childClass = ChildClass::createInstance(); + +echo get_class($testClass) . "\n"; +echo get_class($childClass) . "\n"; +?> +==DONE== +--EXPECTF-- +TestClass +ChildClass +==DONE== diff -Naur php-src/tests/classes/caller_004.phpt php-new/tests/classes/caller_004.phpt --- php-src/tests/classes/caller_004.phpt 1969-12-31 16:00:00.000000000 -0800 +++ php-new/tests/classes/caller_004.phpt 2006-03-06 11:43:51.000000000 -0800 @@ -0,0 +1,21 @@ +--TEST-- +ZE2 testing get_caller_class() +--FILE-- +<?php + +class TestClass { + public static function getClassName() { + return get_caller_class(); + } +} + +class ChildClass extends TestClass {} + +echo TestClass::getClassName() . "\n"; +echo ChildClass::getClassName() . "\n"; +?> +==DONE== +--EXPECTF-- +TestClass +ChildClass +==DONE== diff -Naur php-src/tests/classes/caller_005.phpt php-new/tests/classes/caller_005.phpt --- php-src/tests/classes/caller_005.phpt 1969-12-31 16:00:00.000000000 -0800 +++ php-new/tests/classes/caller_005.phpt 2006-03-06 11:43:51.000000000 -0800 @@ -0,0 +1,51 @@ +--TEST-- +ZE2 stacking static callers +--FILE-- +<?php + +class TestA { + public static function test() { + echo get_class(new static()) . "\n"; + TestB::test(); + echo get_class(new static()) . "\n"; + TestC::test(); + echo get_class(new static()) . "\n"; + TestBB::test(); + echo get_class(new static()) . "\n"; + } +} + +class TestB { + public static function test() { + echo get_class(new static()) . "\n"; + TestC::test(); + echo get_class(new static()) . "\n"; + } +} + +class TestC { + public static function test() { + echo get_class(new static()) . "\n"; + } +} + +class TestBB extends TestB { +} + +TestA::test(); + +?> +==DONE== +--EXPECTF-- +TestA +TestB +TestC +TestB +TestA +TestC +TestA +TestBB +TestC +TestBB +TestA +==DONE== diff -Naur php-src/tests/classes/caller_006.phpt php-new/tests/classes/caller_006.phpt --- php-src/tests/classes/caller_006.phpt 1969-12-31 16:00:00.000000000 -0800 +++ php-new/tests/classes/caller_006.phpt 2006-03-06 11:43:51.000000000 -0800 @@ -0,0 +1,12 @@ +--TEST-- +ZE2 ensuring extending 'static' is not allowed +--FILE-- +<?php + +class Foo extends static { +} + +?> +==DONE== +--EXPECTF-- +Fatal error: Cannot use 'static' as class name as it is reserved in %s on line %d diff -Naur php-src/tests/classes/caller_007.phpt php-new/tests/classes/caller_007.phpt --- php-src/tests/classes/caller_007.phpt 1969-12-31 16:00:00.000000000 -0800 +++ php-new/tests/classes/caller_007.phpt 2006-03-06 11:43:51.000000000 -0800 @@ -0,0 +1,12 @@ +--TEST-- +ZE2 ensuring implementing 'static' is not allowed +--FILE-- +<?php + +class Foo implements static { +} + +?> +==DONE== +--EXPECTF-- +Fatal error: Cannot use 'static' as interface name as it is reserved in %s on line %d diff -Naur php-src/tests/classes/caller_008.phpt php-new/tests/classes/caller_008.phpt --- php-src/tests/classes/caller_008.phpt 1969-12-31 16:00:00.000000000 -0800 +++ php-new/tests/classes/caller_008.phpt 2006-03-08 10:26:41.000000000 -0800 @@ -0,0 +1,38 @@ +--TEST-- +ZE2 using static:: in functions called by non execute() calls and constructors. +--FILE-- +<?php + +class Foo { + protected static $className = 'Foo'; + public static function bar() { + echo static::$className . "::bar\n"; + } + public function __construct() { + echo static::$className . "::__construct\n"; + } + public function __destruct() { + echo static::$className . "::__destruct\n"; + } +} + +class FooChild extends Foo { + protected static $className = 'FooChild'; +} + +register_shutdown_function(array('Foo', 'bar')); +register_shutdown_function(array('FooChild', 'bar')); + +$foo = new Foo(); +$fooChild = new FooChild(); +unset($foo); +unset($fooChild); + +?> +--EXPECTF-- +Foo::__construct +FooChild::__construct +Foo::__destruct +FooChild::__destruct +Foo::bar +FooChild::bar diff -Naur php-src/ZendEngine2/zend_builtin_functions.c php-new/ZendEngine2/zend_builtin_functions.c --- php-src/ZendEngine2/zend_builtin_functions.c 2006-03-07 00:33:46.000000000 -0800 +++ php-new/ZendEngine2/zend_builtin_functions.c 2006-03-06 11:43:51.000000000 -0800 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_builtin_functions.c,v 1.310 2006/03/07 08:33:46 andrei Exp $ */ +/* $Id: zend_builtin_functions.c,v 1.307 2006/03/03 10:09:35 dmitry Exp $ */ #include "zend.h" #include "zend_API.h" @@ -41,6 +41,7 @@ static ZEND_FUNCTION(define); static ZEND_FUNCTION(defined); static ZEND_FUNCTION(get_class); +static ZEND_FUNCTION(get_caller_class); static ZEND_FUNCTION(get_parent_class); static ZEND_FUNCTION(method_exists); static ZEND_FUNCTION(property_exists); @@ -101,6 +102,7 @@ ZEND_FE(define, NULL) ZEND_FE(defined, NULL) ZEND_FE(get_class, NULL) + ZEND_FE(get_caller_class, NULL) ZEND_FE(get_parent_class, NULL) ZEND_FE(method_exists, NULL) ZEND_FE(property_exists, NULL) @@ -592,6 +594,26 @@ } /* }}} */ +/* {{{ proto string get_caller_class() U + Retrieves the class that was used to call a static function */ +ZEND_FUNCTION(get_caller_class) +{ + zend_execute_data *ptr; + if (!ZEND_NUM_ARGS()) { + ptr = EG(current_execute_data); + ptr = ptr->prev_execute_data; + if (ptr && ptr->caller_scope) { + RETURN_TEXTL(ptr->caller_scope->name, + ptr->caller_scope->name_length, 1); + } else { + zend_error(E_ERROR, "get_caller_class() called from outside a class"); + } + } else { + ZEND_WRONG_PARAM_COUNT(); + } +} +/* }}} */ + /* {{{ proto string get_parent_class([mixed object]) U Retrieves the parent class name for object or class or current scope. */ diff -Naur php-src/ZendEngine2/zend_compile.c php-new/ZendEngine2/zend_compile.c --- php-src/ZendEngine2/zend_compile.c 2006-03-07 00:43:21.000000000 -0800 +++ php-new/ZendEngine2/zend_compile.c 2006-03-06 11:43:51.000000000 -0800 @@ -1514,6 +1514,7 @@ switch (fetch_type) { case ZEND_FETCH_CLASS_SELF: case ZEND_FETCH_CLASS_PARENT: + case ZEND_FETCH_CLASS_STATIC: SET_UNUSED(opline->op2); opline->extended_value = fetch_type; zval_dtor(&class_name->u.constant); @@ -2857,6 +2858,9 @@ case ZEND_FETCH_CLASS_PARENT: zend_error(E_COMPILE_ERROR, "Cannot use 'parent' as class name as it is reserved"); break; + case ZEND_FETCH_CLASS_STATIC: + zend_error(E_COMPILE_ERROR, "Cannot use 'static' as class name as it is reserved"); + break; default: break; } @@ -2966,6 +2970,9 @@ case ZEND_FETCH_CLASS_PARENT: zend_error(E_COMPILE_ERROR, "Cannot use 'parent' as interface name as it is reserved"); break; + case ZEND_FETCH_CLASS_STATIC: + zend_error(E_COMPILE_ERROR, "Cannot use 'static' as interface name as it is reserved"); + break; default: if (CG(active_op_array)->last > 0) { opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1]; @@ -4285,6 +4292,9 @@ } 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; + } 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_STATIC; } else { return ZEND_FETCH_CLASS_DEFAULT; } diff -Naur php-src/ZendEngine2/zend_compile.h php-new/ZendEngine2/zend_compile.h --- php-src/ZendEngine2/zend_compile.h 2006-03-07 00:43:21.000000000 -0800 +++ php-new/ZendEngine2/zend_compile.h 2006-03-06 11:43:51.000000000 -0800 @@ -291,6 +292,7 @@ struct _zend_op *opline; zend_function_state function_state; zend_function *fbc; /* Function Being Called */ + zend_class_entry *caller_scope; /* Scope of the calling class */ zend_op_array *op_array; zval *object; union _temp_variable *Ts; @@ -602,6 +603,7 @@ #define ZEND_FETCH_CLASS_GLOBAL 4 #define ZEND_FETCH_CLASS_AUTO 5 #define ZEND_FETCH_CLASS_INTERFACE 6 +#define ZEND_FETCH_CLASS_STATIC 7 #define ZEND_FETCH_CLASS_NO_AUTOLOAD 0x80 /* variable parsing type (compile-time) */ diff -Naur php-src/ZendEngine2/zend_execute_API.c php-new/ZendEngine2/zend_execute_API.c --- php-src/ZendEngine2/zend_execute_API.c 2006-03-03 15:20:29.000000000 -0800 +++ php-new/ZendEngine2/zend_execute_API.c 2006-03-08 10:20:30.000000000 -0800 @@ -714,6 +714,16 @@ found = (*ce != NULL?SUCCESS:FAILURE); fci->object_pp = EG(This)?&EG(This):NULL; EX(object) = EG(This); + } else if (EG(current_execute_data) && EG(current_execute_data)->prev_execute_data && + Z_UNILEN_PP(fci->object_pp) == sizeof("static")-1 && + ZEND_U_EQUAL(Z_TYPE_PP(fci->object_pp), Z_UNIVAL_PP(fci->object_pp), Z_UNILEN_PP(fci->object_pp), "static", sizeof("static")-1)) { + + if (!EG(current_execute_data)->prev_execute_data->caller_scope) { + zend_error(E_ERROR, "Cannot access static:: when no called scope is active"); + } + ce = &(EG(current_execute_data)->prev_execute_data->caller_scope); + found = (*ce != NULL?SUCCESS:FAILURE); + fci->object_pp = EG(This)?&EG(This):NULL; } else { zend_class_entry *scope; scope = EG(active_op_array) ? EG(active_op_array)->scope : NULL; @@ -782,6 +792,9 @@ } else if (calling_scope && clen == sizeof("parent") - 1 && ZEND_U_EQUAL(Z_TYPE_P(fci->function_name), lcname, clen, "parent", sizeof("parent")-1)) { ce_child = EG(active_op_array) && EG(active_op_array)->scope ? EG(scope)->parent : NULL; + } else if (calling_scope && clen == sizeof("static") - 1 && + ZEND_U_EQUAL(Z_TYPE_P(fci->function_name), lcname, clen, "static", sizeof("static")-1)) { + ce_child = EG(current_execute_data) && EG(current_execute_data)->prev_execute_data && EG(current_execute_data)->prev_execute_data->caller_scope ? EG(current_execute_data)->prev_execute_data->caller_scope : NULL; } else if (zend_u_lookup_class(Z_TYPE_P(fci->function_name), Z_UNIVAL_P(fci->function_name), clen, &pce TSRMLS_CC) == SUCCESS) { ce_child = *pce; } @@ -870,6 +883,7 @@ fci->object_pp = fci_cache->object_pp; EX(object) = fci->object_pp ? *fci->object_pp : NULL; } + EX(caller_scope) = calling_scope; if (EX(function_state).function->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) { if (EX(function_state).function->common.fn_flags & ZEND_ACC_ABSTRACT) { @@ -1530,6 +1544,11 @@ zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent"); } return EG(scope)->parent; + case ZEND_FETCH_CLASS_STATIC: + if (!EG(current_execute_data)->prev_execute_data || !EG(current_execute_data)->prev_execute_data->caller_scope) { + zend_error(E_ERROR, "Cannot access static:: when no called scope is active"); + } + return EG(current_execute_data)->prev_execute_data->caller_scope; case ZEND_FETCH_CLASS_AUTO: { fetch_type = zend_get_class_fetch_type(type, class_name, class_name_len); if (fetch_type!=ZEND_FETCH_CLASS_DEFAULT) { diff -Naur php-src/ZendEngine2/zend_language_parser.y php-new/ZendEngine2/zend_language_parser.y --- php-src/ZendEngine2/zend_language_parser.y 2006-03-07 00:43:21.000000000 -0800 +++ php-new/ZendEngine2/zend_language_parser.y 2006-03-06 11:43:51.000000000 -0800 @@ -642,10 +642,12 @@ fully_qualified_class_name: T_STRING { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); } + | T_STATIC { znode static_string; static_string.op_type = IS_CONST; static_string.u.constant.type = IS_STRING; static_string.u.constant.value.str.val = (char *)estrndup("static", 6); static_string.u.constant.value.str.len = 6; zend_do_fetch_class(&$$, &static_string TSRMLS_CC); } ; class_name_reference: T_STRING { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); } + | T_STATIC { znode static_string; static_string.op_type = IS_CONST; static_string.u.constant.type = IS_STRING; static_string.u.constant.value.str.val = (char *)estrndup("static", 6); static_string.u.constant.value.str.len = 6; zend_do_fetch_class(&$$, &static_string TSRMLS_CC); } | dynamic_class_name_reference { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_fetch_class(&$$, &$1 TSRMLS_CC); } ; diff -Naur php-src/ZendEngine2/zend_vm_def.h php-new/ZendEngine2/zend_vm_def.h --- php-src/ZendEngine2/zend_vm_def.h 2006-03-01 08:14:37.000000000 -0800 +++ php-new/ZendEngine2/zend_vm_def.h 2006-03-08 10:29:36.000000000 -0800 @@ -1660,6 +1660,8 @@ zstr function_name_strval; int function_name_strlen; zend_free_op free_op1, free_op2; + zend_object *zobj; + /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; @@ -1675,6 +1677,7 @@ function_name_strlen = Z_UNILEN_P(function_name); EX(object) = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_R); + zobj = zend_objects_get_address(EX(object) TSRMLS_CC); if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) { if (Z_OBJ_HT_P(EX(object))->get_method == NULL) { @@ -1686,6 +1689,8 @@ if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(caller_scope) = zobj->ce; } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } @@ -1750,6 +1755,8 @@ EX(fbc) = ce->constructor; } + EX(caller_scope) = ce; + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -2438,6 +2445,7 @@ zend_op *opline = EX(opline); zval *object_zval; zend_function *constructor; + zend_object *zobj; if (EX_T(opline->op1.u.var).class_entry->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) { char *class_type; @@ -2474,6 +2482,9 @@ EX(object) = object_zval; EX(fbc) = constructor; + zobj = zend_objects_get_address(EX(object) TSRMLS_CC); + EX(caller_scope) = zobj->ce; + ZEND_VM_NEXT_OPCODE(); } } diff -Naur php-src/ZendEngine2/zend_vm_execute.skl php-new/ZendEngine2/zend_vm_execute.skl --- php-src/ZendEngine2/zend_vm_execute.skl 2006-02-21 00:00:39.000000000 -0800 +++ php-new/ZendEngine2/zend_vm_execute.skl 2006-03-06 11:43:52.000000000 -0800 @@ -13,6 +13,7 @@ /* Initialize execute_data */ EX(fbc) = NULL; + EX(caller_scope) = NULL; EX(object) = NULL; EX(old_error_reporting) = NULL; if (op_array->T < TEMP_VAR_STACK_LIMIT) { diff -Naur php-src/ZendEngine2/zend_vm_execute.h php-new/ZendEngine2/zend_vm_execute.h --- php-src/ZendEngine2/zend_vm_execute.h 2006-03-03 08:47:55.000000000 -0800 +++ php-new/ZendEngine2/zend_vm_execute.h 2006-03-08 10:29:50.000000000 -0800 @@ -42,6 +42,7 @@ /* Initialize execute_data */ EX(fbc) = NULL; + EX(caller_scope) = NULL; EX(object) = NULL; EX(old_error_reporting) = NULL; if (op_array->T < TEMP_VAR_STACK_LIMIT) { @@ -400,6 +401,7 @@ zend_op *opline = EX(opline); zval *object_zval; zend_function *constructor; + zend_object *zobj; if (EX_T(opline->op1.u.var).class_entry->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) { char *class_type; @@ -436,6 +438,9 @@ EX(object) = object_zval; EX(fbc) = constructor; + zobj = zend_objects_get_address(EX(object) TSRMLS_CC); + EX(caller_scope) = zobj->ce; + ZEND_VM_NEXT_OPCODE(); } } @@ -684,6 +689,8 @@ EX(fbc) = ce->constructor; } + EX(caller_scope) = ce; + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -871,6 +878,8 @@ EX(fbc) = ce->constructor; } + EX(caller_scope) = ce; + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -995,6 +1004,8 @@ EX(fbc) = ce->constructor; } + EX(caller_scope) = ce; + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -1118,6 +1129,8 @@ EX(fbc) = ce->constructor; } + EX(caller_scope) = ce; + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -1199,6 +1212,8 @@ EX(fbc) = ce->constructor; } + EX(caller_scope) = ce; + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { EX(object) = NULL; } else { @@ -5046,6 +5061,8 @@ zstr function_name_strval; int function_name_strlen; zend_free_op free_op1; + zend_object *zobj; + /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; @@ -5061,6 +5078,7 @@ function_name_strlen = Z_UNILEN_P(function_name); EX(object) = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + zobj = zend_objects_get_address(EX(object) TSRMLS_CC); if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) { if (Z_OBJ_HT_P(EX(object))->get_method == NULL) { @@ -5072,6 +5090,8 @@ if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(caller_scope) = zobj->ce; } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } @@ -5480,6 +5500,8 @@ zstr function_name_strval; int function_name_strlen; zend_free_op free_op1, free_op2; + zend_object *zobj; + /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; @@ -5495,6 +5517,7 @@ function_name_strlen = Z_UNILEN_P(function_name); EX(object) = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + zobj = zend_objects_get_address(EX(object) TSRMLS_CC); if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) { if (Z_OBJ_HT_P(EX(object))->get_method == NULL) { @@ -5506,6 +5529,8 @@ if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(caller_scope) = zobj->ce; } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } @@ -5916,6 +5941,8 @@ zstr function_name_strval; int function_name_strlen; zend_free_op free_op1, free_op2; + zend_object *zobj; + /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; @@ -5931,6 +5958,7 @@ function_name_strlen = Z_UNILEN_P(function_name); EX(object) = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + zobj = zend_objects_get_address(EX(object) TSRMLS_CC); if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) { if (Z_OBJ_HT_P(EX(object))->get_method == NULL) { @@ -5942,6 +5970,8 @@ if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(caller_scope) = zobj->ce; } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } @@ -6433,6 +6463,8 @@ zstr function_name_strval; int function_name_strlen; zend_free_op free_op1; + zend_object *zobj; + /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; @@ -6448,6 +6480,7 @@ function_name_strlen = Z_UNILEN_P(function_name); EX(object) = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + zobj = zend_objects_get_address(EX(object) TSRMLS_CC); if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) { if (Z_OBJ_HT_P(EX(object))->get_method == NULL) { @@ -6459,6 +6492,8 @@ if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(caller_scope) = zobj->ce; } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } @@ -8992,6 +9027,8 @@ zstr function_name_strval; int function_name_strlen; zend_free_op free_op1; + zend_object *zobj; + /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; @@ -9007,6 +9044,7 @@ function_name_strlen = Z_UNILEN_P(function_name); EX(object) = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + zobj = zend_objects_get_address(EX(object) TSRMLS_CC); if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) { if (Z_OBJ_HT_P(EX(object))->get_method == NULL) { @@ -9018,6 +9056,8 @@ if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(caller_scope) = zobj->ce; } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } @@ -10473,6 +10513,8 @@ zstr function_name_strval; int function_name_strlen; zend_free_op free_op1, free_op2; + zend_object *zobj; + /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; @@ -10488,6 +10530,7 @@ function_name_strlen = Z_UNILEN_P(function_name); EX(object) = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + zobj = zend_objects_get_address(EX(object) TSRMLS_CC); if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) { if (Z_OBJ_HT_P(EX(object))->get_method == NULL) { @@ -10499,6 +10542,8 @@ if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(caller_scope) = zobj->ce; } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } @@ -11994,6 +12039,8 @@ zstr function_name_strval; int function_name_strlen; zend_free_op free_op1, free_op2; + zend_object *zobj; + /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; @@ -12009,6 +12056,7 @@ function_name_strlen = Z_UNILEN_P(function_name); EX(object) = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + zobj = zend_objects_get_address(EX(object) TSRMLS_CC); if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) { if (Z_OBJ_HT_P(EX(object))->get_method == NULL) { @@ -12020,6 +12068,8 @@ if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(caller_scope) = zobj->ce; } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } @@ -13920,6 +13970,8 @@ zstr function_name_strval; int function_name_strlen; zend_free_op free_op1; + zend_object *zobj; + /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; @@ -13935,6 +13987,7 @@ function_name_strlen = Z_UNILEN_P(function_name); EX(object) = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); + zobj = zend_objects_get_address(EX(object) TSRMLS_CC); if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) { if (Z_OBJ_HT_P(EX(object))->get_method == NULL) { @@ -13946,6 +13999,8 @@ if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(caller_scope) = zobj->ce; } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } @@ -15121,6 +15176,8 @@ zstr function_name_strval; int function_name_strlen; + zend_object *zobj; + /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; @@ -15136,6 +15193,7 @@ function_name_strlen = Z_UNILEN_P(function_name); EX(object) = _get_obj_zval_ptr_unused(TSRMLS_C); + zobj = zend_objects_get_address(EX(object) TSRMLS_CC); if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) { if (Z_OBJ_HT_P(EX(object))->get_method == NULL) { @@ -15147,6 +15205,8 @@ if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(caller_scope) = zobj->ce; } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } @@ -16257,6 +16317,8 @@ zstr function_name_strval; int function_name_strlen; zend_free_op free_op2; + zend_object *zobj; + /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; @@ -16272,6 +16334,7 @@ function_name_strlen = Z_UNILEN_P(function_name); EX(object) = _get_obj_zval_ptr_unused(TSRMLS_C); + zobj = zend_objects_get_address(EX(object) TSRMLS_CC); if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) { if (Z_OBJ_HT_P(EX(object))->get_method == NULL) { @@ -16283,6 +16346,8 @@ if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(caller_scope) = zobj->ce; } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } @@ -17351,6 +17416,8 @@ zstr function_name_strval; int function_name_strlen; zend_free_op free_op2; + zend_object *zobj; + /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; @@ -17366,6 +17433,7 @@ function_name_strlen = Z_UNILEN_P(function_name); EX(object) = _get_obj_zval_ptr_unused(TSRMLS_C); + zobj = zend_objects_get_address(EX(object) TSRMLS_CC); if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) { if (Z_OBJ_HT_P(EX(object))->get_method == NULL) { @@ -17377,6 +17445,8 @@ if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(caller_scope) = zobj->ce; } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } @@ -18810,6 +18880,8 @@ zstr function_name_strval; int function_name_strlen; + zend_object *zobj; + /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; @@ -18825,6 +18897,7 @@ function_name_strlen = Z_UNILEN_P(function_name); EX(object) = _get_obj_zval_ptr_unused(TSRMLS_C); + zobj = zend_objects_get_address(EX(object) TSRMLS_CC); if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) { if (Z_OBJ_HT_P(EX(object))->get_method == NULL) { @@ -18836,6 +18909,8 @@ if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(caller_scope) = zobj->ce; } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } @@ -21474,6 +21549,8 @@ zstr function_name_strval; int function_name_strlen; + zend_object *zobj; + /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; @@ -21489,6 +21566,7 @@ function_name_strlen = Z_UNILEN_P(function_name); EX(object) = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC); + zobj = zend_objects_get_address(EX(object) TSRMLS_CC); if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) { if (Z_OBJ_HT_P(EX(object))->get_method == NULL) { @@ -21500,6 +21578,8 @@ if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(caller_scope) = zobj->ce; } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } @@ -22947,6 +23027,8 @@ zstr function_name_strval; int function_name_strlen; zend_free_op free_op2; + zend_object *zobj; + /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; @@ -22962,6 +23044,7 @@ function_name_strlen = Z_UNILEN_P(function_name); EX(object) = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC); + zobj = zend_objects_get_address(EX(object) TSRMLS_CC); if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) { if (Z_OBJ_HT_P(EX(object))->get_method == NULL) { @@ -22973,6 +23056,8 @@ if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(caller_scope) = zobj->ce; } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } @@ -24459,6 +24544,8 @@ zstr function_name_strval; int function_name_strlen; zend_free_op free_op2; + zend_object *zobj; + /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; @@ -24474,6 +24561,7 @@ function_name_strlen = Z_UNILEN_P(function_name); EX(object) = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC); + zobj = zend_objects_get_address(EX(object) TSRMLS_CC); if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) { if (Z_OBJ_HT_P(EX(object))->get_method == NULL) { @@ -24485,6 +24573,8 @@ if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(caller_scope) = zobj->ce; } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } @@ -26375,6 +26465,8 @@ zstr function_name_strval; int function_name_strlen; + zend_object *zobj; + /* FIXME: type is default */ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING; @@ -26390,6 +26482,7 @@ function_name_strlen = Z_UNILEN_P(function_name); EX(object) = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC); + zobj = zend_objects_get_address(EX(object) TSRMLS_CC); if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) { if (Z_OBJ_HT_P(EX(object))->get_method == NULL) { @@ -26401,6 +26494,8 @@ if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(caller_scope) = zobj->ce; } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); }
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php