Skip to content

Instantly share code, notes, and snippets.

@moriyoshi
Created August 5, 2009 05:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save moriyoshi/162517 to your computer and use it in GitHub Desktop.
Save moriyoshi/162517 to your computer and use it in GitHub Desktop.
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index a30c2d2..85f27cd 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -677,6 +677,8 @@ void zend_do_assign(znode *result, znode *variable, const znode *value TSRMLS_DC
}
n++;
}
+ } else {
+ zend_check_writable_variable(variable);
}
opline->opcode = ZEND_ASSIGN;
@@ -962,6 +964,9 @@ void zend_check_writable_variable(const znode *variable) /* {{{ */
if (type == ZEND_PARSED_FUNCTION_CALL) {
zend_error(E_COMPILE_ERROR, "Can't use function return value in write context");
}
+ if (variable->op_type == IS_CONST || variable->op_type == IS_TMP_VAR) {
+ zend_error(E_COMPILE_ERROR, "Can't use constant value in write context");
+ }
}
/* }}} */
@@ -2088,47 +2093,52 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) /* {{
zend_stack_top(&CG(function_call_stack), (void **) &function_ptr_ptr);
function_ptr = *function_ptr_ptr;
- if (original_op == ZEND_SEND_REF && !CG(allow_call_time_pass_reference)) {
- if (function_ptr &&
- function_ptr->common.function_name &&
- function_ptr->common.type == ZEND_USER_FUNCTION &&
- !ARG_SHOULD_BE_SENT_BY_REF(function_ptr, (zend_uint) offset)) {
- zend_error(E_DEPRECATED,
- "Call-time pass-by-reference has been deprecated; "
- "If you would like to pass it by reference, modify the declaration of %s(). "
- "If you would like to enable call-time pass-by-reference, you can set "
- "allow_call_time_pass_reference to true in your INI file", function_ptr->common.function_name);
- } else {
- zend_error(E_DEPRECATED, "Call-time pass-by-reference has been deprecated");
+ if (param->op_type & (IS_CONST | IS_TMP_VAR)) {
+ op = ZEND_SEND_VAL;
+ send_by_reference = 0;
+ } else {
+ if (original_op == ZEND_SEND_REF && !CG(allow_call_time_pass_reference)) {
+ if (function_ptr &&
+ function_ptr->common.function_name &&
+ function_ptr->common.type == ZEND_USER_FUNCTION &&
+ !ARG_SHOULD_BE_SENT_BY_REF(function_ptr, (zend_uint) offset)) {
+ zend_error(E_DEPRECATED,
+ "Call-time pass-by-reference has been deprecated; "
+ "If you would like to pass it by reference, modify the declaration of %s(). "
+ "If you would like to enable call-time pass-by-reference, you can set "
+ "allow_call_time_pass_reference to true in your INI file", function_ptr->common.function_name);
+ } else {
+ zend_error(E_DEPRECATED, "Call-time pass-by-reference has been deprecated");
+ }
}
- }
- if (function_ptr) {
- if (ARG_MAY_BE_SENT_BY_REF(function_ptr, (zend_uint) offset)) {
- if (param->op_type & (IS_VAR|IS_CV)) {
- send_by_reference = 1;
- if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) {
- /* Method call */
- op = ZEND_SEND_VAR_NO_REF;
- send_function = ZEND_ARG_SEND_FUNCTION | ZEND_ARG_SEND_SILENT;
+ if (function_ptr) {
+ if (ARG_MAY_BE_SENT_BY_REF(function_ptr, (zend_uint) offset)) {
+ if (param->op_type & (IS_VAR|IS_CV)) {
+ send_by_reference = 1;
+ if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) {
+ /* Method call */
+ op = ZEND_SEND_VAR_NO_REF;
+ send_function = ZEND_ARG_SEND_FUNCTION | ZEND_ARG_SEND_SILENT;
+ }
+ } else {
+ op = ZEND_SEND_VAL;
+ send_by_reference = 0;
}
} else {
- op = ZEND_SEND_VAL;
- send_by_reference = 0;
+ send_by_reference = ARG_SHOULD_BE_SENT_BY_REF(function_ptr, (zend_uint) offset) ? ZEND_ARG_SEND_BY_REF : 0;
}
} else {
- send_by_reference = ARG_SHOULD_BE_SENT_BY_REF(function_ptr, (zend_uint) offset) ? ZEND_ARG_SEND_BY_REF : 0;
+ send_by_reference = 0;
}
- } else {
- send_by_reference = 0;
- }
- if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) {
- /* Method call */
- op = ZEND_SEND_VAR_NO_REF;
- send_function = ZEND_ARG_SEND_FUNCTION;
- } else if (op == ZEND_SEND_VAL && (param->op_type & (IS_VAR|IS_CV))) {
- op = ZEND_SEND_VAR_NO_REF;
+ if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) {
+ /* Method call */
+ op = ZEND_SEND_VAR_NO_REF;
+ send_function = ZEND_ARG_SEND_FUNCTION;
+ } else if (op == ZEND_SEND_VAL && (param->op_type & (IS_VAR|IS_CV))) {
+ op = ZEND_SEND_VAR_NO_REF;
+ }
}
if (op!=ZEND_SEND_VAR_NO_REF && send_by_reference==ZEND_ARG_SEND_BY_REF) {
@@ -2146,6 +2156,7 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) /* {{
if (original_op == ZEND_SEND_VAR) {
switch (op) {
+ case ZEND_SEND_VAL:
case ZEND_SEND_VAR_NO_REF:
zend_do_end_variable_parse(param, BP_VAR_R, 0 TSRMLS_CC);
break;
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index 6ba7852..c01aa6d 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -47,7 +47,7 @@
%}
%pure_parser
-%expect 2
+%expect 20
%left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE
%left ','
@@ -236,7 +236,7 @@ unticked_statement:
| T_CONTINUE ';' { zend_do_brk_cont(ZEND_CONT, NULL TSRMLS_CC); }
| T_CONTINUE expr ';' { zend_do_brk_cont(ZEND_CONT, &$2 TSRMLS_CC); }
| T_RETURN ';' { zend_do_return(NULL, 0 TSRMLS_CC); }
- | T_RETURN expr_without_variable ';' { zend_do_return(&$2, 0 TSRMLS_CC); }
+ | T_RETURN expr_without_variable_and_intrinsics ';' { zend_do_return(&$2, 0 TSRMLS_CC); }
| T_RETURN variable ';' { zend_do_return(&$2, 1 TSRMLS_CC); }
| T_GLOBAL global_var_list ';'
| T_STATIC static_var_list ';'
@@ -248,7 +248,7 @@ unticked_statement:
{ zend_do_foreach_begin(&$1, &$2, &$3, &$4, 1 TSRMLS_CC); }
foreach_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); }
foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); }
- | T_FOREACH '(' expr_without_variable T_AS
+ | T_FOREACH '(' expr_without_variable_and_intrinsics T_AS
{ zend_do_foreach_begin(&$1, &$2, &$3, &$4, 0 TSRMLS_CC); }
variable foreach_optional_arg ')' { zend_check_writable_variable(&$6); zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); }
foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); }
@@ -475,10 +475,10 @@ function_call_parameter_list:
non_empty_function_call_parameter_list:
- expr_without_variable { Z_LVAL($$.u.constant) = 1; zend_do_pass_param(&$1, ZEND_SEND_VAL, Z_LVAL($$.u.constant) TSRMLS_CC); }
+ expr_without_variable_and_intrinsics { Z_LVAL($$.u.constant) = 1; zend_do_pass_param(&$1, ZEND_SEND_VAL, Z_LVAL($$.u.constant) TSRMLS_CC); }
| variable { Z_LVAL($$.u.constant) = 1; zend_do_pass_param(&$1, ZEND_SEND_VAR, Z_LVAL($$.u.constant) TSRMLS_CC); }
| '&' w_variable { Z_LVAL($$.u.constant) = 1; zend_do_pass_param(&$2, ZEND_SEND_REF, Z_LVAL($$.u.constant) TSRMLS_CC); }
- | non_empty_function_call_parameter_list ',' expr_without_variable { Z_LVAL($$.u.constant)=Z_LVAL($1.u.constant)+1; zend_do_pass_param(&$3, ZEND_SEND_VAL, Z_LVAL($$.u.constant) TSRMLS_CC); }
+ | non_empty_function_call_parameter_list ',' expr_without_variable_and_intrinsics { Z_LVAL($$.u.constant)=Z_LVAL($1.u.constant)+1; zend_do_pass_param(&$3, ZEND_SEND_VAL, Z_LVAL($$.u.constant) TSRMLS_CC); }
| non_empty_function_call_parameter_list ',' variable { Z_LVAL($$.u.constant)=Z_LVAL($1.u.constant)+1; zend_do_pass_param(&$3, ZEND_SEND_VAR, Z_LVAL($$.u.constant) TSRMLS_CC); }
| non_empty_function_call_parameter_list ',' '&' w_variable { Z_LVAL($$.u.constant)=Z_LVAL($1.u.constant)+1; zend_do_pass_param(&$4, ZEND_SEND_REF, Z_LVAL($$.u.constant) TSRMLS_CC); }
;
@@ -491,7 +491,7 @@ global_var_list:
global_var:
T_VARIABLE { $$ = $1; }
- | '$' r_variable { $$ = $2; }
+ | '$' variable { zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); $$ = $2; }
| '$' '{' expr '}' { $$ = $3; }
;
@@ -576,13 +576,10 @@ non_empty_for_expr:
| expr { $$ = $1; }
;
-expr_without_variable:
+expr_without_variable_and_intrinsics:
T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' '=' expr { zend_do_list_end(&$$, &$7 TSRMLS_CC); }
| variable '=' expr { zend_check_writable_variable(&$1); zend_do_assign(&$$, &$1, &$3 TSRMLS_CC); }
| variable '=' '&' variable { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$4, BP_VAR_W, 1 TSRMLS_CC); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); }
- | variable '=' '&' T_NEW class_name_reference { zend_error(E_DEPRECATED, "Assigning the return value of new by reference is deprecated"); zend_check_writable_variable(&$1); 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(&$1, BP_VAR_W, 0 TSRMLS_CC); $3.u.EA.type = ZEND_PARSED_NEW; zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); }
- | T_NEW class_name_reference { 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);}
- | T_CLONE expr { zend_do_clone(&$$, &$2 TSRMLS_CC); }
| variable T_PLUS_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 TSRMLS_CC); }
| variable T_MINUS_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 TSRMLS_CC); }
| variable T_MUL_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MUL, &$$, &$1, &$3 TSRMLS_CC); }
@@ -594,10 +591,10 @@ expr_without_variable:
| variable T_XOR_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_XOR, &$$, &$1, &$3 TSRMLS_CC); }
| variable T_SL_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SL, &$$, &$1, &$3 TSRMLS_CC); }
| variable T_SR_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SR, &$$, &$1, &$3 TSRMLS_CC); }
- | rw_variable T_INC { zend_do_post_incdec(&$$, &$1, ZEND_POST_INC TSRMLS_CC); }
- | T_INC rw_variable { zend_do_pre_incdec(&$$, &$2, ZEND_PRE_INC TSRMLS_CC); }
- | rw_variable T_DEC { zend_do_post_incdec(&$$, &$1, ZEND_POST_DEC TSRMLS_CC); }
- | T_DEC rw_variable { zend_do_pre_incdec(&$$, &$2, ZEND_PRE_DEC TSRMLS_CC); }
+ | variable T_INC { zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_check_writable_variable(&$1); zend_do_post_incdec(&$$, &$1, ZEND_POST_INC TSRMLS_CC); }
+ | T_INC variable { zend_do_end_variable_parse(&$2, BP_VAR_RW, 0 TSRMLS_CC); zend_check_writable_variable(&$2); zend_do_pre_incdec(&$$, &$2, ZEND_PRE_INC TSRMLS_CC); }
+ | variable T_DEC { zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_check_writable_variable(&$1); zend_do_post_incdec(&$$, &$1, ZEND_POST_DEC TSRMLS_CC); }
+ | T_DEC variable { zend_do_end_variable_parse(&$2, BP_VAR_RW, 0 TSRMLS_CC); zend_check_writable_variable(&$2); zend_do_pre_incdec(&$$, &$2, ZEND_PRE_DEC TSRMLS_CC); }
| expr T_BOOLEAN_OR { zend_do_boolean_or_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_or_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
| expr T_BOOLEAN_AND { zend_do_boolean_and_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_and_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
| expr T_LOGICAL_OR { zend_do_boolean_or_begin(&$1, &$2 TSRMLS_CC); } expr { zend_do_boolean_or_end(&$$, &$1, &$4, &$2 TSRMLS_CC); }
@@ -627,7 +624,6 @@ expr_without_variable:
| expr '>' expr { zend_do_binary_op(ZEND_IS_SMALLER, &$$, &$3, &$1 TSRMLS_CC); }
| expr T_IS_GREATER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$3, &$1 TSRMLS_CC); }
| expr T_INSTANCEOF class_name_reference { zend_do_instanceof(&$$, &$1, &$3, 0 TSRMLS_CC); }
- | '(' expr ')' { $$ = $2; }
| expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); }
expr ':' { zend_do_qm_true(&$4, &$2, &$5 TSRMLS_CC); }
expr { zend_do_qm_false(&$$, &$7, &$2, &$5 TSRMLS_CC); }
@@ -642,14 +638,20 @@ expr_without_variable:
| T_BOOL_CAST expr { zend_do_cast(&$$, &$2, IS_BOOL TSRMLS_CC); }
| T_UNSET_CAST expr { zend_do_cast(&$$, &$2, IS_NULL TSRMLS_CC); }
| T_EXIT exit_expr { zend_do_exit(&$$, &$2 TSRMLS_CC); }
+ | T_PRINT expr { zend_do_print(&$$, &$2 TSRMLS_CC); }
+;
+
+intrinsics:
+ '(' expr ')' { $$ = $2; }
| '@' { zend_do_begin_silence(&$1 TSRMLS_CC); } expr { zend_do_end_silence(&$1 TSRMLS_CC); $$ = $3; }
| scalar { $$ = $1; }
| T_ARRAY '(' array_pair_list ')' { $$ = $3; }
| '`' backticks_expr '`' { zend_do_shell_exec(&$$, &$2 TSRMLS_CC); }
- | T_PRINT expr { zend_do_print(&$$, &$2 TSRMLS_CC); }
| function is_reference '(' { zend_do_begin_lambda_function_declaration(&$$, &$1, $2.op_type TSRMLS_CC); }
parameter_list ')' lexical_vars '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); $$ = $4; }
-;
+ | T_NEW class_name_reference { 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); $$.u.EA.type = ZEND_PARSED_NEW; }
+ | T_CLONE expr { zend_do_clone(&$$, &$2 TSRMLS_CC); }
+ ;
function:
T_FUNCTION { $$.u.opline_num = CG(zend_lineno); }
@@ -813,26 +815,15 @@ non_empty_static_array_pair_list:
;
expr:
- r_variable { $$ = $1; }
- | expr_without_variable { $$ = $1; }
+ variable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); $$ = $1; }
+ | expr_without_variable_and_intrinsics { $$ = $1; }
;
-
-r_variable:
- variable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); $$ = $1; }
-;
-
-
w_variable:
variable { zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); $$ = $1;
zend_check_writable_variable(&$1); }
;
-rw_variable:
- variable { zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); $$ = $1;
- zend_check_writable_variable(&$1); }
-;
-
variable:
base_variable_with_function_calls T_OBJECT_OPERATOR { zend_do_push_object(&$1 TSRMLS_CC); }
object_property { zend_do_push_object(&$4 TSRMLS_CC); } method_or_not variable_properties
@@ -876,6 +867,7 @@ variable_class_name:
base_variable_with_function_calls:
base_variable { $$ = $1; }
| function_call { zend_do_begin_variable_parse(TSRMLS_C); $$ = $1; $$.u.EA.type = ZEND_PARSED_FUNCTION_CALL; }
+ | intrinsics { zend_do_begin_variable_parse(TSRMLS_C); $$ = $1; }
;
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 34ac304..0b7be97 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -1915,13 +1915,14 @@ ZEND_VM_HANDLER(109, ZEND_FETCH_CLASS, ANY, CONST|TMP|VAR|UNUSED|CV)
}
}
-ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
+ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, ANY, CONST|TMP|VAR|CV)
{
zend_op *opline = EX(opline);
zval *function_name;
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1, free_op2;
+ zend_bool should_free_afterwards = 0;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope));
@@ -1936,33 +1937,59 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
EX(object) = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_R);
- if (EX(object) && Z_TYPE_P(EX(object)) == IS_OBJECT) {
- if (Z_OBJ_HT_P(EX(object))->get_method == NULL) {
- zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ if (EX(object) == NULL) {
+ zend_error_noreturn(E_ERROR, "Method call to a null reference");
+ }
+
+ if (Z_TYPE_P(EX(object)) != IS_OBJECT) {
+ zval *retval = NULL;
+ zval **params[1] = { &EX(object) };
+ zval func_name;
+ ZVAL_STRINGL(&func_name, "__autobox", sizeof("__autobox") - 1, 1);
+ if (IS_OP1_TMP_FREE()) {
+ MAKE_REAL_ZVAL_PTR(*params[0]);
+ }
+ if (FAILURE == call_user_function_ex(CG(function_table), NULL, &func_name, &retval, sizeof(params) / sizeof(*params), params, 1, NULL)) {
+ retval = NULL;
+ }
+ zval_dtor(&func_name);
+ if (IS_OP1_TMP_FREE()) {
+ zval_ptr_dtor(params[0]);
}
- /* First, locate the function. */
- EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
- if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ if (Z_TYPE_P(retval) != IS_OBJECT) {
+ zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
}
-
- EX(called_scope) = Z_OBJCE_P(EX(object));
- } else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+
+ EX(object) = retval;
+ should_free_afterwards = 1;
}
-
+
+ if (Z_OBJ_HT_P(EX(object))->get_method == NULL) {
+ zend_error_noreturn(E_ERROR, "Object does not support method calls");
+ }
+
+ /* First, locate the function. */
+ EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
+ if (!EX(fbc)) {
+ zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ }
+
+ EX(called_scope) = Z_OBJCE_P(EX(object));
+
if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) {
EX(object) = NULL;
} else {
- if (!PZVAL_IS_REF(EX(object))) {
- Z_ADDREF_P(EX(object)); /* For $this pointer */
- } else {
- zval *this_ptr;
- ALLOC_ZVAL(this_ptr);
- INIT_PZVAL_COPY(this_ptr, EX(object));
- zval_copy_ctor(this_ptr);
- EX(object) = this_ptr;
+ if (!should_free_afterwards) {
+ if (!PZVAL_IS_REF(EX(object))) {
+ Z_ADDREF_P(EX(object)); /* For $this pointer */
+ } else {
+ zval *this_ptr;
+ ALLOC_ZVAL(this_ptr);
+ INIT_PZVAL_COPY(this_ptr, EX(object));
+ zval_copy_ctor(this_ptr);
+ EX(object) = this_ptr;
+ }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment