LTR static member access

This commit is contained in:
Nikita Popov 2014-05-30 22:33:03 +02:00
parent b8b3b355be
commit a8c1595012
4 changed files with 33 additions and 65 deletions

View File

@ -10,7 +10,7 @@ Bug #27669 (PHP 5 didn't support all possibilities for calling static methods dy
}
}
$y[0] = 'hello';
A::$y[0]();
A::{$y[0]}();
?>
===DONE===
--EXPECTF--

View File

@ -703,7 +703,7 @@ void fetch_simple_variable(znode *result, znode *varname, int bp TSRMLS_DC) /* {
}
/* }}} */
void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
void zend_do_fetch_static_member(znode *result, znode *class_name, znode *member_name TSRMLS_DC) /* {{{ */
{
znode class_node;
zend_llist *fetch_list_ptr;
@ -718,65 +718,29 @@ void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC) /*
} else {
zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
}
zend_do_begin_variable_parse(TSRMLS_C);
fetch_list_ptr = zend_stack_top(&CG(bp_stack));
if (result->op_type == IS_CV) {
init_op(&opline TSRMLS_CC);
init_op(&opline TSRMLS_CC);
opline.opcode = ZEND_FETCH_W;
opline.result_type = IS_VAR;
opline.result.var = get_temporary_variable(CG(active_op_array));
opline.op1_type = IS_CONST;
LITERAL_STR(opline.op1, STR_COPY(CG(active_op_array)->vars[EX_VAR_TO_NUM(result->u.op.var)]));
opline.opcode = ZEND_FETCH_W;
opline.result_type = IS_VAR;
opline.result.var = get_temporary_variable(CG(active_op_array));
SET_NODE(opline.op1, member_name);
if (opline.op1_type == IS_CONST) {
GET_POLYMORPHIC_CACHE_SLOT(opline.op1.constant);
if (class_node.op_type == IS_CONST) {
opline.op2_type = IS_CONST;
opline.op2.constant =
zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
} else {
SET_NODE(opline.op2, &class_node);
}
GET_NODE(result,opline.result);
opline.extended_value |= ZEND_FETCH_STATIC_MEMBER;
opline_ptr = &opline;
zend_llist_add_element(fetch_list_ptr, &opline);
} else {
le = fetch_list_ptr->head;
opline_ptr = (zend_op *)le->data;
if (opline_ptr->opcode != ZEND_FETCH_W && opline_ptr->op1_type == IS_CV) {
init_op(&opline TSRMLS_CC);
opline.opcode = ZEND_FETCH_W;
opline.result_type = IS_VAR;
opline.result.var = get_temporary_variable(CG(active_op_array));
opline.op1_type = IS_CONST;
LITERAL_STR(opline.op1, STR_COPY(CG(active_op_array)->vars[EX_VAR_TO_NUM(opline_ptr->op1.var)]));
GET_POLYMORPHIC_CACHE_SLOT(opline.op1.constant);
if (class_node.op_type == IS_CONST) {
opline.op2_type = IS_CONST;
opline.op2.constant =
zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
} else {
SET_NODE(opline.op2, &class_node);
}
opline.extended_value |= ZEND_FETCH_STATIC_MEMBER;
COPY_NODE(opline_ptr->op1, opline.result);
zend_llist_prepend_element(fetch_list_ptr, &opline);
} else {
if (opline_ptr->op1_type == IS_CONST) {
GET_POLYMORPHIC_CACHE_SLOT(opline_ptr->op1.constant);
}
if (class_node.op_type == IS_CONST) {
opline_ptr->op2_type = IS_CONST;
opline_ptr->op2.constant =
zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
} else {
SET_NODE(opline_ptr->op2, &class_node);
}
opline_ptr->extended_value |= ZEND_FETCH_STATIC_MEMBER;
}
}
if (class_node.op_type == IS_CONST) {
opline.op2_type = IS_CONST;
opline.op2.constant =
zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
} else {
SET_NODE(opline.op2, &class_node);
}
GET_NODE(result,opline.result);
opline.extended_value |= ZEND_FETCH_STATIC_MEMBER;
zend_llist_add_element(fetch_list_ptr, &opline);
}
/* }}} */

View File

@ -464,7 +464,7 @@ void zend_do_fetch_global_variable(znode *varname, const znode *static_assignmen
void fetch_array_begin(znode *result, znode *varname, znode *first_dim TSRMLS_DC);
void fetch_array_dim(znode *result, znode *parent, znode *dim TSRMLS_DC);
void fetch_string_offset(znode *result, znode *parent, znode *offset TSRMLS_DC);
void zend_do_fetch_static_member(znode *result, znode *class_znode TSRMLS_DC);
void zend_do_fetch_static_member(znode *result, znode *class_name, znode *member_name TSRMLS_DC);
void zend_do_print(znode *result, znode *arg TSRMLS_DC);
void zend_do_echo(znode *arg TSRMLS_DC);
typedef int (*unary_op_type)(zval *, zval * TSRMLS_DC);

View File

@ -898,13 +898,13 @@ function_call:
function_call_parameter_list { zend_do_end_function_call(&$2, &$$, 0, $3.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
| class_name T_PAAMAYIM_NEKUDOTAYIM variable_name { $$.u.op.opline_num = zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
function_call_parameter_list { zend_do_end_function_call($4.u.op.opline_num?NULL:&$3, &$$, $4.u.op.opline_num, $4.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
| class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
| class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable { fetch_simple_variable_ex(&$$, &$3, 0, ZEND_FETCH_R TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$$ TSRMLS_CC); }
function_call_parameter_list { zend_do_end_function_call(NULL, &$$, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
| variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_name { zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
function_call_parameter_list { zend_do_end_function_call(NULL, &$$, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
| variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
| variable_class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable { fetch_simple_variable_ex(&$$, &$3, 0, ZEND_FETCH_R TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$$ TSRMLS_CC); }
function_call_parameter_list { zend_do_end_function_call(NULL, &$$, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
| variable_without_objects { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1, 0 TSRMLS_CC); }
| directly_callable_variable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1, 0 TSRMLS_CC); }
function_call_parameter_list { zend_do_end_function_call(&$1, &$$, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
;
@ -1086,7 +1086,6 @@ variable:
object_property { zend_do_push_object(&$4 TSRMLS_CC); } method_or_not
{ zend_do_pop_object(&$$ TSRMLS_CC); $$.EA = $6.EA; }
| reference_variable { $$ = $1; $$.EA = ZEND_PARSED_VARIABLE; }
| static_member { $$ = $1; $$.EA = ZEND_PARSED_STATIC_MEMBER; }
| array_function_dereference { $$ = $1; }
| function_call { zend_do_begin_variable_parse(TSRMLS_C); $$ = $1; $$.EA = ZEND_PARSED_FUNCTION_CALL; }
;
@ -1116,8 +1115,8 @@ variable_without_objects:
;
static_member:
class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { $$ = $3; zend_do_fetch_static_member(&$$, &$1 TSRMLS_CC); }
| variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { $$ = $3; zend_do_fetch_static_member(&$$, &$1 TSRMLS_CC); }
class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable { zend_do_fetch_static_member(&$$, &$1, &$3 TSRMLS_CC); }
| variable_class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable { zend_do_fetch_static_member(&$$, &$1, &$3 TSRMLS_CC); }
;
@ -1131,12 +1130,17 @@ array_function_dereference:
'[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$4 TSRMLS_CC); }
;
reference_variable:
directly_callable_variable:
reference_variable '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); }
| reference_variable '{' expr '}' { fetch_string_offset(&$$, &$1, &$3 TSRMLS_CC); }
| simple_variable { zend_do_begin_variable_parse(TSRMLS_C); fetch_simple_variable(&$$, &$1, 1 TSRMLS_CC); }
;
reference_variable:
directly_callable_variable { $$ = $1; }
| static_member { $$ = $1; }
;
simple_variable:
T_VARIABLE { $$ = $1; }
| '$' '{' expr '}' { $$ = $3; }