summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZeev Suraski <zeev@php.net>2003-10-09 13:44:44 +0000
committerZeev Suraski <zeev@php.net>2003-10-09 13:44:44 +0000
commit2ab30d71334ea13757aaeb3ada405789c81523d7 (patch)
tree697c4f7133a32bcd372db373014d83e82372dbd2
parent2827b962d9ed47168812a9eb8cfd721a5314fa0a (diff)
downloadphp-git-2ab30d71334ea13757aaeb3ada405789c81523d7.tar.gz
Allow foo::$bar()
-rw-r--r--Zend/zend_compile.c30
-rw-r--r--Zend/zend_execute.c5
-rw-r--r--Zend/zend_language_parser.y7
3 files changed, 28 insertions, 14 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 10dc52ccb4..6df8fc3554 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -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 *));
}
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index a8e20f8cca..3bab0b9cb3 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -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;
}
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index 37b2412c8c..5600e1dff5 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -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);}