From 78248be56939433204ff11dbf8f817563cf7755c Mon Sep 17 00:00:00 2001 From: Zeev Suraski Date: Wed, 15 Dec 1999 20:01:45 +0000 Subject: - Implement return by reference: - In function declaration instead of the return statement - In the assignment phase - Implement ability to turn off support for call-time pass by reference --- Zend/zend-parser.y | 27 +++++++++++++++++---------- Zend/zend.h | 5 +++-- Zend/zend_compile.c | 22 ++++++++++++++++++++++ Zend/zend_execute.c | 2 +- Zend/zend_globals.h | 1 + 5 files changed, 44 insertions(+), 13 deletions(-) diff --git a/Zend/zend-parser.y b/Zend/zend-parser.y index da95f04f97..1b543abf2a 100644 --- a/Zend/zend-parser.y +++ b/Zend/zend-parser.y @@ -180,7 +180,8 @@ statement: | T_CONTINUE ';' { do_brk_cont(ZEND_CONT, NULL CLS_CC); } | T_CONTINUE expr ';' { do_brk_cont(ZEND_CONT, &$2 CLS_CC); } | T_RETURN ';' { do_return(NULL CLS_CC); } - | T_RETURN expr ';' { do_return(&$2 CLS_CC); } + | T_RETURN expr_without_variable ';' { do_return(&$2 CLS_CC); } + | T_RETURN cvar ';' { do_return(&$2 CLS_CC); } | T_GLOBAL global_var_list | T_STATIC static_var_list | T_ECHO echo_expr_list ';' @@ -387,6 +388,7 @@ expr_without_variable: T_LIST '(' { do_list_init(CLS_C); } assignment_list ')' '=' expr { do_list_end(&$$, &$7 CLS_CC); } | cvar '=' expr { do_end_variable_parse(BP_VAR_W, 0 CLS_CC); do_assign(&$$, &$1, &$3 CLS_CC); } | cvar '=' '&' w_cvar { do_end_variable_parse(BP_VAR_W, 0 CLS_CC); do_assign_ref(&$$, &$1, &$4 CLS_CC); } + | cvar '=' '&' function_call { do_end_variable_parse(BP_VAR_W, 0 CLS_CC); do_assign_ref(&$$, &$1, &$4 CLS_CC); } | T_NEW class_name { do_extended_fcall_begin(CLS_C); do_begin_new_object(&$1, &$2 CLS_CC); } ctor_arguments { do_end_new_object(&$$, &$2, &$1, &$4 CLS_CC); do_extended_fcall_end(CLS_C);} | cvar T_PLUS_EQUAL expr { do_end_variable_parse(BP_VAR_RW, 0 CLS_CC); do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 CLS_CC); } | cvar T_MINUS_EQUAL expr { do_end_variable_parse(BP_VAR_RW, 0 CLS_CC); do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 CLS_CC); } @@ -434,15 +436,7 @@ expr_without_variable: | expr '?' { do_begin_qm_op(&$1, &$2 CLS_CC); } expr ':' { do_qm_true(&$4, &$2, &$5 CLS_CC); } expr { do_qm_false(&$$, &$7, &$2, &$5 CLS_CC); } - | T_STRING '(' { do_extended_fcall_begin(CLS_C); $2.u.opline_num = do_begin_function_call(&$1 CLS_CC); } - function_call_parameter_list - ')' { do_end_function_call(&$1, &$$, &$4, 0, $2.u.opline_num CLS_CC); do_extended_fcall_end(CLS_C); } - | r_cvar '(' { do_extended_fcall_begin(CLS_C); do_begin_dynamic_function_call(&$1 CLS_CC); } - function_call_parameter_list - ')' { do_end_function_call(&$1, &$$, &$4, 0, 1 CLS_CC); do_extended_fcall_end(CLS_C);} - | T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { do_extended_fcall_begin(CLS_C); do_begin_class_member_function_call(&$1, &$3 CLS_CC); } - function_call_parameter_list - ')' { do_end_function_call(&$3, &$$, &$6, 1, 1 CLS_CC); do_extended_fcall_end(CLS_C);} + | function_call { $$ = $1; } | internal_functions_in_yacc { $$ = $1; } | T_INT_CAST expr { do_cast(&$$, &$2, IS_LONG CLS_CC); } | T_DOUBLE_CAST expr { do_cast(&$$, &$2, IS_DOUBLE CLS_CC); } @@ -459,6 +453,19 @@ expr_without_variable: ; +function_call: + T_STRING '(' { do_extended_fcall_begin(CLS_C); $2.u.opline_num = do_begin_function_call(&$1 CLS_CC); } + function_call_parameter_list + ')' { do_end_function_call(&$1, &$$, &$4, 0, $2.u.opline_num CLS_CC); do_extended_fcall_end(CLS_C); } + | r_cvar '(' { do_extended_fcall_begin(CLS_C); do_begin_dynamic_function_call(&$1 CLS_CC); } + function_call_parameter_list + ')' { do_end_function_call(&$1, &$$, &$4, 0, 1 CLS_CC); do_extended_fcall_end(CLS_C);} + | T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { do_extended_fcall_begin(CLS_C); do_begin_class_member_function_call(&$1, &$3 CLS_CC); } + function_call_parameter_list + ')' { do_end_function_call(&$3, &$$, &$6, 1, 1 CLS_CC); do_extended_fcall_end(CLS_C);} +; + + exit_expr: /* empty */ { $$.op_type = IS_UNUSED; } | '(' ')' { $$.op_type = IS_UNUSED; } diff --git a/Zend/zend.h b/Zend/zend.h index 2129970352..0ef98ee46a 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -187,8 +187,9 @@ typedef struct _zend_utility_functions { typedef struct _zend_utility_values { - unsigned char short_tags; - unsigned char asp_tags; + zend_bool short_tags; + zend_bool asp_tags; + zend_bool allow_call_time_pass_reference; char *import_use_extension; uint import_use_extension_length; } zend_utility_values; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 539bfaa613..879e676406 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -98,6 +98,7 @@ void init_compiler(CLS_D ELS_DC) zend_llist_init(&CG(filenames_list), sizeof(char *), free_filename, 0); CG(short_tags) = ZEND_UV(short_tags); CG(asp_tags) = ZEND_UV(asp_tags); + CG(allow_call_time_pass_reference) = ZEND_UV(allow_call_time_pass_reference); CG(handle_op_arrays) = 1; zend_hash_apply(&module_registry, (int (*)(void *)) module_registry_request_startup); init_resource_list(ELS_C); @@ -857,8 +858,22 @@ void do_pass_param(znode *param, int op, int offset CLS_DC) int original_op=op; zend_function **function_ptr_ptr, *function_ptr; + 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)) { + zend_error(E_COMPILE_WARNING, + "Call-time pass-by-reference has been deprecated - argument passed by value; " + "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. " + "However, future versions may not support this any longer.", + (function_ptr?function_ptr->common.function_name:"[runtime function name]"), + offset+1); + } + if (function_ptr) { arg_types = function_ptr->common.arg_types; } else { @@ -954,6 +969,13 @@ void do_return(znode *expr CLS_DC) { zend_op *opline; + if (expr->op_type==IS_VAR) { + if (CG(active_op_array)->return_reference) { + do_end_variable_parse(BP_VAR_W, 0 CLS_CC); + } else { + do_end_variable_parse(BP_VAR_R, 0 CLS_CC); + } + } #ifdef ZTS zend_stack_apply_with_argument(&CG(switch_cond_stack), (int (*)(void *element, void *)) generate_free_switch_expr, ZEND_STACK_APPLY_TOPDOWN CLS_CC); zend_stack_apply_with_argument(&CG(foreach_copy_stack), (int (*)(void *element, void *)) generate_free_foreach_copy, ZEND_STACK_APPLY_TOPDOWN CLS_CC); diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 9ba08a857c..78982c85c4 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1553,7 +1553,7 @@ do_fcall_common: (opline->op1.op_type != IS_CONST) && (opline->op1.op_type != IS_TMP_VAR)) { - retval_ptr_ptr = get_zval_ptr_ptr(&opline->op1, Ts, BP_VAR_R); + retval_ptr_ptr = get_zval_ptr_ptr(&opline->op1, Ts, BP_VAR_W); if (!PZVAL_IS_REF(*retval_ptr_ptr)) { SEPARATE_ZVAL(retval_ptr_ptr); diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index a55200eaf0..f4b20ee875 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -90,6 +90,7 @@ struct _zend_compiler_globals { zend_bool short_tags; zend_bool asp_tags; + zend_bool allow_call_time_pass_reference; /* For extensions support */ zend_bool extended_info; /* generate extension information for debugger/profiler */ -- cgit v1.2.1