]> granicus.if.org Git - php/commitdiff
LTR static member access
authorNikita Popov <nikic@php.net>
Fri, 30 May 2014 20:33:03 +0000 (22:33 +0200)
committerNikita Popov <nikic@php.net>
Fri, 30 May 2014 20:33:03 +0000 (22:33 +0200)
Zend/tests/bug27669.phpt
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_language_parser.y

index 4d513e91aa24b90dd4e3475856a1a2c0892bae38..43591a938614a58efe69924084110119be1e9e0b 100644 (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--
index 37649e7bb22f71fcf1d529723dd881584639bb62..b6754d202b1fbfa148f03e8b7a6191578c004dea 100644 (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);
+       }
+       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 {
-               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;
-               }
+               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);
 }
 /* }}} */
 
index 9f17b110d1814f7b6a217d11d5e5d0a718c85a34..bb4142884d7814aeaa817380d66fb60333922d9f 100644 (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);
index 08c3ffe7ebeab5dc55dfec71ad49992fe35b31a6..d22d1c266d04d8609d2a7e775a030b3432ec61c3 100644 (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; }