Skip to content

Commit 78248be

Browse files
committed
- 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
1 parent 4e1a962 commit 78248be

File tree

5 files changed

+44
-13
lines changed

5 files changed

+44
-13
lines changed

Zend/zend-parser.y

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ statement:
180180
| T_CONTINUE ';' { do_brk_cont(ZEND_CONT, NULL CLS_CC); }
181181
| T_CONTINUE expr ';' { do_brk_cont(ZEND_CONT, &$2 CLS_CC); }
182182
| T_RETURN ';' { do_return(NULL CLS_CC); }
183-
| T_RETURN expr ';' { do_return(&$2 CLS_CC); }
183+
| T_RETURN expr_without_variable ';' { do_return(&$2 CLS_CC); }
184+
| T_RETURN cvar ';' { do_return(&$2 CLS_CC); }
184185
| T_GLOBAL global_var_list
185186
| T_STATIC static_var_list
186187
| T_ECHO echo_expr_list ';'
@@ -387,6 +388,7 @@ expr_without_variable:
387388
T_LIST '(' { do_list_init(CLS_C); } assignment_list ')' '=' expr { do_list_end(&$$, &$7 CLS_CC); }
388389
| cvar '=' expr { do_end_variable_parse(BP_VAR_W, 0 CLS_CC); do_assign(&$$, &$1, &$3 CLS_CC); }
389390
| cvar '=' '&' w_cvar { do_end_variable_parse(BP_VAR_W, 0 CLS_CC); do_assign_ref(&$$, &$1, &$4 CLS_CC); }
391+
| cvar '=' '&' function_call { do_end_variable_parse(BP_VAR_W, 0 CLS_CC); do_assign_ref(&$$, &$1, &$4 CLS_CC); }
390392
| 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);}
391393
| 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); }
392394
| 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:
434436
| expr '?' { do_begin_qm_op(&$1, &$2 CLS_CC); }
435437
expr ':' { do_qm_true(&$4, &$2, &$5 CLS_CC); }
436438
expr { do_qm_false(&$$, &$7, &$2, &$5 CLS_CC); }
437-
| T_STRING '(' { do_extended_fcall_begin(CLS_C); $2.u.opline_num = do_begin_function_call(&$1 CLS_CC); }
438-
function_call_parameter_list
439-
')' { do_end_function_call(&$1, &$$, &$4, 0, $2.u.opline_num CLS_CC); do_extended_fcall_end(CLS_C); }
440-
| r_cvar '(' { do_extended_fcall_begin(CLS_C); do_begin_dynamic_function_call(&$1 CLS_CC); }
441-
function_call_parameter_list
442-
')' { do_end_function_call(&$1, &$$, &$4, 0, 1 CLS_CC); do_extended_fcall_end(CLS_C);}
443-
| T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { do_extended_fcall_begin(CLS_C); do_begin_class_member_function_call(&$1, &$3 CLS_CC); }
444-
function_call_parameter_list
445-
')' { do_end_function_call(&$3, &$$, &$6, 1, 1 CLS_CC); do_extended_fcall_end(CLS_C);}
439+
| function_call { $$ = $1; }
446440
| internal_functions_in_yacc { $$ = $1; }
447441
| T_INT_CAST expr { do_cast(&$$, &$2, IS_LONG CLS_CC); }
448442
| T_DOUBLE_CAST expr { do_cast(&$$, &$2, IS_DOUBLE CLS_CC); }
@@ -459,6 +453,19 @@ expr_without_variable:
459453
;
460454

461455

456+
function_call:
457+
T_STRING '(' { do_extended_fcall_begin(CLS_C); $2.u.opline_num = do_begin_function_call(&$1 CLS_CC); }
458+
function_call_parameter_list
459+
')' { do_end_function_call(&$1, &$$, &$4, 0, $2.u.opline_num CLS_CC); do_extended_fcall_end(CLS_C); }
460+
| r_cvar '(' { do_extended_fcall_begin(CLS_C); do_begin_dynamic_function_call(&$1 CLS_CC); }
461+
function_call_parameter_list
462+
')' { do_end_function_call(&$1, &$$, &$4, 0, 1 CLS_CC); do_extended_fcall_end(CLS_C);}
463+
| T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { do_extended_fcall_begin(CLS_C); do_begin_class_member_function_call(&$1, &$3 CLS_CC); }
464+
function_call_parameter_list
465+
')' { do_end_function_call(&$3, &$$, &$6, 1, 1 CLS_CC); do_extended_fcall_end(CLS_C);}
466+
;
467+
468+
462469
exit_expr:
463470
/* empty */ { $$.op_type = IS_UNUSED; }
464471
| '(' ')' { $$.op_type = IS_UNUSED; }

Zend/zend.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,9 @@ typedef struct _zend_utility_functions {
187187

188188

189189
typedef struct _zend_utility_values {
190-
unsigned char short_tags;
191-
unsigned char asp_tags;
190+
zend_bool short_tags;
191+
zend_bool asp_tags;
192+
zend_bool allow_call_time_pass_reference;
192193
char *import_use_extension;
193194
uint import_use_extension_length;
194195
} zend_utility_values;

Zend/zend_compile.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ void init_compiler(CLS_D ELS_DC)
9898
zend_llist_init(&CG(filenames_list), sizeof(char *), free_filename, 0);
9999
CG(short_tags) = ZEND_UV(short_tags);
100100
CG(asp_tags) = ZEND_UV(asp_tags);
101+
CG(allow_call_time_pass_reference) = ZEND_UV(allow_call_time_pass_reference);
101102
CG(handle_op_arrays) = 1;
102103
zend_hash_apply(&module_registry, (int (*)(void *)) module_registry_request_startup);
103104
init_resource_list(ELS_C);
@@ -857,8 +858,22 @@ void do_pass_param(znode *param, int op, int offset CLS_DC)
857858
int original_op=op;
858859
zend_function **function_ptr_ptr, *function_ptr;
859860

861+
860862
zend_stack_top(&CG(function_call_stack), (void **) &function_ptr_ptr);
861863
function_ptr = *function_ptr_ptr;
864+
865+
if (original_op==ZEND_SEND_REF
866+
&& !CG(allow_call_time_pass_reference)) {
867+
zend_error(E_COMPILE_WARNING,
868+
"Call-time pass-by-reference has been deprecated - argument passed by value; "
869+
"If you would like to pass it by reference, modify the declaration of %s(). "
870+
"If you would like to enable call-time pass-by-reference, you can set"
871+
"allow_call_time_pass_reference to true in your INI file. "
872+
"However, future versions may not support this any longer.",
873+
(function_ptr?function_ptr->common.function_name:"[runtime function name]"),
874+
offset+1);
875+
}
876+
862877
if (function_ptr) {
863878
arg_types = function_ptr->common.arg_types;
864879
} else {
@@ -954,6 +969,13 @@ void do_return(znode *expr CLS_DC)
954969
{
955970
zend_op *opline;
956971

972+
if (expr->op_type==IS_VAR) {
973+
if (CG(active_op_array)->return_reference) {
974+
do_end_variable_parse(BP_VAR_W, 0 CLS_CC);
975+
} else {
976+
do_end_variable_parse(BP_VAR_R, 0 CLS_CC);
977+
}
978+
}
957979
#ifdef ZTS
958980
zend_stack_apply_with_argument(&CG(switch_cond_stack), (int (*)(void *element, void *)) generate_free_switch_expr, ZEND_STACK_APPLY_TOPDOWN CLS_CC);
959981
zend_stack_apply_with_argument(&CG(foreach_copy_stack), (int (*)(void *element, void *)) generate_free_foreach_copy, ZEND_STACK_APPLY_TOPDOWN CLS_CC);

Zend/zend_execute.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1553,7 +1553,7 @@ binary_assign_op_addr: {
15531553
(opline->op1.op_type != IS_CONST) &&
15541554
(opline->op1.op_type != IS_TMP_VAR)) {
15551555

1556-
retval_ptr_ptr = get_zval_ptr_ptr(&opline->op1, Ts, BP_VAR_R);
1556+
retval_ptr_ptr = get_zval_ptr_ptr(&opline->op1, Ts, BP_VAR_W);
15571557

15581558
if (!PZVAL_IS_REF(*retval_ptr_ptr)) {
15591559
SEPARATE_ZVAL(retval_ptr_ptr);

Zend/zend_globals.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ struct _zend_compiler_globals {
9090

9191
zend_bool short_tags;
9292
zend_bool asp_tags;
93+
zend_bool allow_call_time_pass_reference;
9394

9495
/* For extensions support */
9596
zend_bool extended_info; /* generate extension information for debugger/profiler */

0 commit comments

Comments
 (0)