]> granicus.if.org Git - php/commitdiff
Allow foo::$bar()
authorZeev Suraski <zeev@php.net>
Thu, 9 Oct 2003 13:44:44 +0000 (13:44 +0000)
committerZeev Suraski <zeev@php.net>
Thu, 9 Oct 2003 13:44:44 +0000 (13:44 +0000)
Zend/zend_compile.c
Zend/zend_execute.c
Zend/zend_language_parser.y

index 10dc52ccb4184e01e77e441ff10ffe8bee04c398..6df8fc35544aeffbd3b2dce77718c17798fdf967 100644 (file)
@@ -1283,19 +1283,27 @@ void zend_do_begin_class_member_function_call(TSRMLS_D)
 {
        unsigned char *ptr = NULL;
        long fetch_const_op_number = get_next_op_number(CG(active_op_array));
-       zend_op *opline = &CG(active_op_array)->opcodes[fetch_const_op_number-1];
-
-       /* a tmp var is leaked here */
-       opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
-       if(opline->op2.op_type == IS_CONST &&
-          (sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == Z_STRLEN(opline->op2.u.constant) &&
-          memcmp(Z_STRVAL(opline->op2.u.constant), ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == 0) {
-               zval_dtor(&opline->op2.u.constant);
-               SET_UNUSED(opline->op2);
-       } else {
-               zend_lowercase_znode_if_const(&opline->op2);
+       zend_op *last_op = &CG(active_op_array)->opcodes[fetch_const_op_number-1];
+
+       if (last_op->opcode == ZEND_FETCH_CONSTANT) { /* regular method call */
+               /* a tmp var is leaked here */
+               last_op->opcode = ZEND_INIT_STATIC_METHOD_CALL;
+               if(last_op->op2.op_type == IS_CONST &&
+                  (sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == Z_STRLEN(last_op->op2.u.constant) &&
+                  memcmp(Z_STRVAL(last_op->op2.u.constant), ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == 0) {
+                       zval_dtor(&last_op->op2.u.constant);
+                       SET_UNUSED(last_op->op2);
+               } else {
+                       zend_lowercase_znode_if_const(&last_op->op2);
+               }
+       } else { /* indirect method call */
+               zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+               opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
+               opline->op1 = last_op->op2;
+               opline->op2 = last_op->result;
        }
 
+
        zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *));
 }
 
index a8e20f8ccaea744849de899e8e29300c11f2dcee..3bab0b9cb3a0f272e8300ac4a2f17451f0fd0107 100644 (file)
@@ -2422,7 +2422,10 @@ int zend_init_static_method_call_handler(ZEND_OPCODE_HANDLER_ARGS)
                        function_name_strlen = EX(opline)->op2.u.constant.value.str.len;
                } else {
                        function_name = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R);
-                       
+
+                       if (Z_TYPE_P(function_name) != IS_STRING) {
+                               zend_error(E_ERROR, "Function name must be a string");
+                       }
                        function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
                        function_name_strlen = function_name->value.str.len;
                }
index 37b2412c8cb093e3689a16b684d6038c944702ca..5600e1dff5058e4c221771f65f4eaeb4cb5754b2 100644 (file)
@@ -592,8 +592,11 @@ function_call:
                                function_call_parameter_list
                                ')' { zend_do_end_function_call(&$1, &$$, &$4, 0, $2.u.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); }
        |       class_constant '(' { zend_do_begin_class_member_function_call(TSRMLS_C); zend_do_extended_fcall_begin(TSRMLS_C); } 
-                                                                                       function_call_parameter_list 
-                                                                                       ')' { zend_do_end_function_call(NULL, &$$, &$4, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
+                       function_call_parameter_list 
+                       ')' { zend_do_end_function_call(NULL, &$$, &$4, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
+       |       static_member '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(TSRMLS_C); zend_do_extended_fcall_begin(TSRMLS_C); } 
+                       function_call_parameter_list 
+                       ')' { zend_do_end_function_call(NULL, &$$, &$4, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
        |       variable_without_objects  '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1 TSRMLS_CC); }
                        function_call_parameter_list ')'
                        { zend_do_end_function_call(&$1, &$$, &$4, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}