]> granicus.if.org Git - php/commitdiff
- Allow passing references which are returned from functions and new
authorAndi Gutmans <andi@php.net>
Mon, 27 Nov 2000 18:46:23 +0000 (18:46 +0000)
committerAndi Gutmans <andi@php.net>
Mon, 27 Nov 2000 18:46:23 +0000 (18:46 +0000)
- statements to be passed by reference.

Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute.c

index 047029523a036c697c88c5393452c58a17bbb5a5..c975e5c88ac774893ecd0296ed4b64e301b6db8b 100644 (file)
@@ -916,6 +916,7 @@ void zend_do_pass_param(znode *param, int op, int offset CLS_DC)
        unsigned char *arg_types;
        int original_op=op;
        zend_function **function_ptr_ptr, *function_ptr;
+       int send_by_reference;
 
                                                
        zend_stack_top(&CG(function_call_stack), (void **) &function_ptr_ptr);
@@ -939,20 +940,13 @@ void zend_do_pass_param(znode *param, int op, int offset CLS_DC)
                arg_types = NULL;
        }
 
-       if (op==ZEND_SEND_VAL) {
-               switch (param->op_type) {
-                       case IS_CONST:  /* constants behave like variables when passed to functions,
-                                                        * as far as reference counting is concerned.  Treat them
-                                                        * as if they were variables here.
-                                                        */
-                               break;
-                       case IS_VAR:
-                               op = ZEND_SEND_VAR_NO_REF;
-                               break;
-               }
+       send_by_reference = ARG_SHOULD_BE_SENT_BY_REF(offset, 1, arg_types)?ZEND_ARG_SEND_BY_REF:0;
+
+       if (op == ZEND_SEND_VAL && param->op_type == IS_VAR) {
+                       op = ZEND_SEND_VAR_NO_REF;
        }
-       if (op!=ZEND_SEND_VAR_NO_REF
-               && ARG_SHOULD_BE_SENT_BY_REF(offset, 1, arg_types)) {
+
+       if (op!=ZEND_SEND_VAR_NO_REF && send_by_reference == ZEND_ARG_SEND_BY_REF) {
                /* change to passing by reference */
                switch (param->op_type) {
                        case IS_VAR:
@@ -964,9 +958,11 @@ void zend_do_pass_param(znode *param, int op, int offset CLS_DC)
                }
        }
 
-       if (original_op==ZEND_SEND_VAR) {
+       if (original_op == ZEND_SEND_VAR) {
                switch(op) {
                        case ZEND_SEND_VAR_NO_REF:
+                               zend_do_end_variable_parse(BP_VAR_R, 0 CLS_CC);
+                               break;
                        case ZEND_SEND_VAR:
                                if (function_ptr) {
                                        zend_do_end_variable_parse(BP_VAR_R, 0 CLS_CC);
@@ -981,10 +977,19 @@ void zend_do_pass_param(znode *param, int op, int offset CLS_DC)
        }
 
        opline = get_next_op(CG(active_op_array) CLS_CC);
-       if (function_ptr) {
-               opline->extended_value = ZEND_DO_FCALL;
+
+       if (op == ZEND_SEND_VAR_NO_REF) {
+               if (function_ptr) {
+                       opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND | send_by_reference;
+               } else {
+                       opline->extended_value = 0;
+               }
        } else {
-               opline->extended_value = ZEND_DO_FCALL_BY_NAME;
+               if (function_ptr) {
+                       opline->extended_value = ZEND_DO_FCALL;
+               } else {
+                       opline->extended_value = ZEND_DO_FCALL_BY_NAME;
+               }
        }
        opline->opcode = op;
        opline->op1 = *param;
index b6f87f76281a6d73e8e9e2237e17e609a5cb44c4..b30fde873c53cc388b26d79a7eb1e82bf3b93207 100644 (file)
@@ -597,6 +597,8 @@ int zendlex(znode *zendlval CLS_DC);
 #define ZEND_MEMBER_FUNC_CALL  1<<0
 #define ZEND_CTOR_CALL                 1<<1
 
+#define ZEND_ARG_SEND_BY_REF (1<<0)
+#define ZEND_ARG_COMPILE_TIME_BOUND (1<<1)
 
 #define AI_USE_PTR(ai) \
        if ((ai).ptr_ptr) { \
index eb61393b69d908b416288fdc847ba9ba3c0873fc..a64ba0db7f064457fab21397d9656c76b303c3d1 100644 (file)
@@ -1656,37 +1656,55 @@ do_fcall_common:
                                        zend_ptr_stack_push(&EG(argument_stack), valptr);
                                }
                                NEXT_OPCODE();
-                       case ZEND_SEND_VAR:
                        case ZEND_SEND_VAR_NO_REF:
-                               if (opline->extended_value==ZEND_DO_FCALL_BY_NAME
-                                       && ARG_SHOULD_BE_SENT_BY_REF(opline->op2.u.opline_num, fbc, fbc->common.arg_types)) {
-                                       if (opline->opcode==ZEND_SEND_VAR_NO_REF) {
-                                               zend_error(E_ERROR, "Only variables can be passed by reference");
+                               if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */
+                                       if (!(opline->extended_value & ZEND_ARG_SEND_BY_REF)) {
+                                               goto send_by_var;
                                        }
-                                       goto send_by_ref;
+                               } else if (!ARG_SHOULD_BE_SENT_BY_REF(opline->op2.u.opline_num, fbc, fbc->common.arg_types)) {
+                                       goto send_by_var;
                                }
                                {
                                        zval *varptr;
                                        varptr = get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R);
 
-                                       if (varptr == &EG(uninitialized_zval)) {
-                                               ALLOC_ZVAL(varptr);
-                                               INIT_ZVAL(*varptr);
-                                               varptr->refcount = 0;
-                                       } else if (PZVAL_IS_REF(varptr)) {
-                                               zval *original_var = varptr;
-
-                                               ALLOC_ZVAL(varptr);
-                                               *varptr = *original_var;
-                                               varptr->is_ref = 0;
-                                               varptr->refcount = 0;
-                                               zval_copy_ctor(varptr);
+                                       if (varptr != &EG(uninitialized_zval) && (PZVAL_IS_REF(varptr) || varptr->refcount == 1)) {
+                                               varptr->is_ref = 1;
+                                               varptr->refcount++;
+                                               zend_ptr_stack_push(&EG(argument_stack), varptr);
+                                               NEXT_OPCODE();
                                        }
-                                       varptr->refcount++;
-                                       zend_ptr_stack_push(&EG(argument_stack), varptr);
-                                       FREE_OP(&opline->op1, EG(free_op1));  /* for string offsets */
+                                       zend_error(E_ERROR, "Only variables can be passed by reference");
                                }
                                NEXT_OPCODE();
+                       case ZEND_SEND_VAR:
+                                       if ((opline->extended_value == ZEND_DO_FCALL_BY_NAME)
+                                               && ARG_SHOULD_BE_SENT_BY_REF(opline->op2.u.opline_num, fbc, fbc->common.arg_types)) {
+                                               goto send_by_ref;
+                                       }
+send_by_var:
+                                       {
+                                               zval *varptr;
+                                               varptr = get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R);
+
+                                               if (varptr == &EG(uninitialized_zval)) {
+                                                       ALLOC_ZVAL(varptr);
+                                                       INIT_ZVAL(*varptr);
+                                                       varptr->refcount = 0;
+                                               } else if (PZVAL_IS_REF(varptr)) {
+                                                       zval *original_var = varptr;
+
+                                                       ALLOC_ZVAL(varptr);
+                                                       *varptr = *original_var;
+                                                       varptr->is_ref = 0;
+                                                       varptr->refcount = 0;
+                                                       zval_copy_ctor(varptr);
+                                               }
+                                               varptr->refcount++;
+                                               zend_ptr_stack_push(&EG(argument_stack), varptr);
+                                               FREE_OP(&opline->op1, EG(free_op1));  /* for string offsets */
+                                       }
+                                       NEXT_OPCODE();
 send_by_ref:
                        case ZEND_SEND_REF: {
                                        zval **varptr_ptr;