mirror of
https://github.com/php/php-src.git
synced 2026-04-25 00:48:25 +02:00
- Support instantiation of nested class. The following script now should
- work:
-<?php
- class foo
- {
- function bar()
- {
- print "bar() in class bar\n";
- }
-
- class barbara
- {
- function bar()
- {
- print "bar() in class foo::barbara\n";
- }
- }
- }
-
- $obj = new foo();
- $obj->bar();
-
- $obj = new foo::barbara();
- $obj->bar();
-
This commit is contained in:
+9
-9
@@ -914,6 +914,7 @@ void do_fetch_class(znode *result, znode *class_entry, znode *class_name TSRMLS_
|
||||
} else {
|
||||
SET_UNUSED(opline->op1);
|
||||
}
|
||||
zend_str_tolower(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len);
|
||||
opline->op2 = *class_name;
|
||||
opline->result.u.var = get_temporary_variable(CG(active_op_array));
|
||||
opline->result.op_type = IS_CONST; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */
|
||||
@@ -948,12 +949,14 @@ void zend_do_end_function_call(znode *function_name, znode *result, znode *argum
|
||||
{
|
||||
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
|
||||
if (function_name->op_type==IS_CONST && !is_method && !is_dynamic_fcall) {
|
||||
if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) {
|
||||
opline->opcode = ZEND_DO_FCALL;
|
||||
opline->op1 = *function_name;
|
||||
} else {
|
||||
opline->opcode = ZEND_DO_FCALL_BY_NAME;
|
||||
SET_UNUSED(opline->op1);
|
||||
}
|
||||
opline->op1 = *function_name;
|
||||
|
||||
opline->result.u.var = get_temporary_variable(CG(active_op_array));
|
||||
opline->result.op_type = IS_VAR;
|
||||
*result = opline->result;
|
||||
@@ -1824,7 +1827,7 @@ void zend_do_pop_object(znode *object TSRMLS_DC)
|
||||
}
|
||||
|
||||
|
||||
void zend_do_begin_new_object(znode *new_token, znode *class_name TSRMLS_DC)
|
||||
void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC)
|
||||
{
|
||||
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
unsigned char *ptr = NULL;
|
||||
@@ -1832,7 +1835,7 @@ void zend_do_begin_new_object(znode *new_token, znode *class_name TSRMLS_DC)
|
||||
opline->opcode = ZEND_NEW;
|
||||
opline->result.op_type = IS_VAR;
|
||||
opline->result.u.var = get_temporary_variable(CG(active_op_array));
|
||||
opline->op1 = *class_name;
|
||||
opline->op1 = *class_type;
|
||||
SET_UNUSED(opline->op2);
|
||||
|
||||
new_token->u.opline_num = get_next_op_number(CG(active_op_array));
|
||||
@@ -1851,14 +1854,11 @@ void zend_do_begin_new_object(znode *new_token, znode *class_name TSRMLS_DC)
|
||||
}
|
||||
|
||||
|
||||
void zend_do_end_new_object(znode *result, znode *class_name, znode *new_token, znode *argument_list TSRMLS_DC)
|
||||
void zend_do_end_new_object(znode *result, znode *new_token, znode *argument_list TSRMLS_DC)
|
||||
{
|
||||
znode ctor_result;
|
||||
|
||||
if (class_name->op_type == IS_CONST) {
|
||||
zval_copy_ctor(&class_name->u.constant);
|
||||
}
|
||||
zend_do_end_function_call(class_name, &ctor_result, argument_list, 1, 0 TSRMLS_CC);
|
||||
zend_do_end_function_call(NULL, &ctor_result, argument_list, 1, 0 TSRMLS_CC);
|
||||
zend_do_free(&ctor_result TSRMLS_CC);
|
||||
|
||||
CG(active_op_array)->opcodes[new_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
|
||||
|
||||
+2
-2
@@ -313,8 +313,8 @@ void zend_do_push_object(znode *object TSRMLS_DC);
|
||||
void zend_do_pop_object(znode *object TSRMLS_DC);
|
||||
|
||||
|
||||
void zend_do_begin_new_object(znode *new_token, znode *class_name TSRMLS_DC);
|
||||
void zend_do_end_new_object(znode *result, znode *class_name, znode *new_token, znode *argument_list TSRMLS_DC);
|
||||
void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC);
|
||||
void zend_do_end_new_object(znode *result, znode *new_token, znode *argument_list TSRMLS_DC);
|
||||
|
||||
void zend_do_fetch_constant(znode *result, znode *constant_name, int mode TSRMLS_DC);
|
||||
|
||||
|
||||
+20
-18
@@ -1487,9 +1487,24 @@ binary_assign_op_addr: {
|
||||
case ZEND_FETCH_CLASS:
|
||||
{
|
||||
if (EX(opline)->op1.op_type == IS_UNUSED) {
|
||||
if (zend_hash_find(EG(class_table), EX(opline)->op2.u.constant.value.str.val, EX(opline)->op2.u.constant.value.str.len+1, &EX(Ts)[EX(opline)->result.u.var].EA.class_entry) == FAILURE) {
|
||||
zend_error(E_ERROR, "Class '%s' not found", EX(opline)->op2.u.constant.value.str.val);
|
||||
zval tmp;
|
||||
zval *class_name = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R);
|
||||
|
||||
if (class_name->type != IS_STRING) {
|
||||
tmp = *class_name;
|
||||
zval_copy_ctor(&tmp);
|
||||
convert_to_string(&tmp);
|
||||
class_name = &tmp;
|
||||
zend_str_tolower(tmp.value.str.val, tmp.value.str.len);
|
||||
}
|
||||
|
||||
if (zend_hash_find(EG(class_table), class_name->value.str.val, class_name->value.str.len+1, &EX(Ts)[EX(opline)->result.u.var].EA.class_entry) == FAILURE) {
|
||||
zend_error(E_ERROR, "Class '%s' not found", class_name->value.str.val);
|
||||
}
|
||||
if (class_name == &tmp) {
|
||||
zval_dtor(&tmp);
|
||||
}
|
||||
FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2));
|
||||
} else {
|
||||
if (zend_hash_find(&EX(Ts)[EX(opline)->op1.u.var].EA.class_entry->class_table, EX(opline)->op2.u.constant.value.str.val, EX(opline)->op2.u.constant.value.str.len+1, &EX(Ts)[EX(opline)->result.u.var].EA.class_entry) == FAILURE) {
|
||||
zend_error(E_ERROR, "Class '%s' not found", EX(opline)->op2.u.constant.value.str.val);
|
||||
@@ -2015,26 +2030,13 @@ send_by_ref:
|
||||
case ZEND_SWITCH_FREE:
|
||||
zend_switch_free(EX(opline), EX(Ts) TSRMLS_CC);
|
||||
NEXT_OPCODE();
|
||||
case ZEND_NEW: {
|
||||
zval *tmp = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
|
||||
zval class_name;
|
||||
zend_class_entry *ce;
|
||||
|
||||
class_name = *tmp;
|
||||
zval_copy_ctor(&class_name);
|
||||
convert_to_string(&class_name);
|
||||
zend_str_tolower(class_name.value.str.val, class_name.value.str.len);
|
||||
|
||||
if (zend_hash_find(EG(class_table), class_name.value.str.val, class_name.value.str.len+1, (void **) &ce)==FAILURE) {
|
||||
zend_error(E_ERROR, "Cannot instantiate non-existent class: %s", class_name.value.str.val);
|
||||
}
|
||||
case ZEND_NEW:
|
||||
{
|
||||
EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr = &EX(Ts)[EX(opline)->result.u.var].var.ptr;
|
||||
ALLOC_ZVAL(EX(Ts)[EX(opline)->result.u.var].var.ptr);
|
||||
object_init_ex(EX(Ts)[EX(opline)->result.u.var].var.ptr, ce);
|
||||
object_init_ex(EX(Ts)[EX(opline)->result.u.var].var.ptr, EX(Ts)[EX(opline)->op1.u.var].EA.class_entry);
|
||||
EX(Ts)[EX(opline)->result.u.var].var.ptr->refcount=1;
|
||||
EX(Ts)[EX(opline)->result.u.var].var.ptr->is_ref=1;
|
||||
zval_dtor(&class_name);
|
||||
FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1));
|
||||
}
|
||||
NEXT_OPCODE();
|
||||
case ZEND_FETCH_CONSTANT:
|
||||
|
||||
@@ -429,8 +429,8 @@ expr_without_variable:
|
||||
| cvar '=' expr { zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign(&$$, &$1, &$3 TSRMLS_CC); }
|
||||
| cvar '=' '&' w_cvar { zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); }
|
||||
| cvar '=' '&' function_call { zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); }
|
||||
| cvar '=' '&' T_NEW static_or_variable_string { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$5, &$4, &$7 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); }
|
||||
| T_NEW static_or_variable_string { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$2, &$1, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
|
||||
| cvar '=' '&' T_NEW parse_class_entry { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$4, &$7 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); }
|
||||
| T_NEW parse_class_entry { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
|
||||
| cvar T_PLUS_EQUAL expr { zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 TSRMLS_CC); }
|
||||
| cvar T_MINUS_EQUAL expr { zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 TSRMLS_CC); }
|
||||
| cvar T_MUL_EQUAL expr { zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MUL, &$$, &$1, &$3 TSRMLS_CC); }
|
||||
@@ -509,7 +509,8 @@ function_call:
|
||||
|
||||
parse_class_entry:
|
||||
parse_class_entry T_PAAMAYIM_NEKUDOTAYIM T_STRING { do_fetch_class(&$$, &$1, &$3 TSRMLS_CC); }
|
||||
| T_STRING { do_fetch_class(&$$, NULL, &$1 TSRMLS_CC); }
|
||||
| static_or_variable_string { /* Using static_or_variable_string and not T_STRING because NEW supported $var */
|
||||
do_fetch_class(&$$, NULL, &$1 TSRMLS_CC); }
|
||||
;
|
||||
|
||||
static_or_variable_string:
|
||||
|
||||
Reference in New Issue
Block a user