cvs: ZendEngine2 / zend_compile.c zend_compile.h zend_execute.c zend_execute.h
| From: | Zeev Suraski | Date: | Sun, 14 Dec 2003 16:09:08 +0000 |
| Subject: | cvs: ZendEngine2 / zend_compile.c zend_compile.h zend_execute.c zend_execute.h | ||
| Groups: | php.zend-engine.cvs | ||
| Request: | Send a blank email to php-zend-engine-cvs+get-2115@lists.php.net to get a copy of this message | ||
zeev Sun Dec 14 11:09:08 2003 EDT
Modified files:
/ZendEngine2 zend_compile.c zend_compile.h zend_execute.c
zend_execute.h
Log:
Fix behavior of return-by-reference functions. Remove erroneous warnings,
add E_STRICT warnings in case you return something by reference that you're
not supposed to (anything that's not a variable, or a return-value of a
function that returned by reference).
Index: ZendEngine2/zend_compile.c
diff -u ZendEngine2/zend_compile.c:1.501 ZendEngine2/zend_compile.c:1.502
--- ZendEngine2/zend_compile.c:1.501 Sat Dec 6 14:02:12 2003
+++ ZendEngine2/zend_compile.c Sun Dec 14 11:09:07 2003
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: zend_compile.c,v 1.501 2003/12/06 19:02:12 helly Exp $ */
+/* $Id: zend_compile.c,v 1.502 2003/12/14 16:09:07 zeev Exp $ */
#include "zend_language_parser.h"
#include "zend.h"
@@ -739,7 +739,7 @@
}
}
-zend_bool zend_is_function_or_method_call(znode *variable)
+static inline zend_bool zend_is_function_or_method_call(znode *variable)
{
zend_uint type = variable->u.EA.type;
@@ -1475,10 +1475,6 @@
} else {
zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);
}
-#if 0
- } else if (expr && CG(active_op_array)->return_reference) {
- zend_error(E_COMPILE_ERROR, "Only variables may be returned by reference");
-#endif
}
#ifdef ZTS
@@ -1499,6 +1495,15 @@
opline->op1.op_type = IS_CONST;
INIT_ZVAL(opline->op1.u.constant);
}
+
+ if (do_end_vparse) {
+ if (zend_is_function_or_method_call(expr)) {
+ opline->extended_value = ZEND_RETURNS_FUNCTION;
+ } else {
+ opline->extended_value = 0;
+ }
+ }
+
SET_UNUSED(opline->op2);
}
Index: ZendEngine2/zend_compile.h
diff -u ZendEngine2/zend_compile.h:1.263 ZendEngine2/zend_compile.h:1.264
--- ZendEngine2/zend_compile.h:1.263 Mon Nov 24 13:13:29 2003
+++ ZendEngine2/zend_compile.h Sun Dec 14 11:09:07 2003
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: zend_compile.h,v 1.263 2003/11/24 18:13:29 andi Exp $ */
+/* $Id: zend_compile.h,v 1.264 2003/12/14 16:09:07 zeev Exp $ */
#ifndef ZEND_COMPILE_H
#define ZEND_COMPILE_H
@@ -790,6 +790,9 @@
#define ZEND_RETURN_VAL 0
#define ZEND_RETURN_REF 1
+
+#define ZEND_RETURNS_FUNCTION 1<<0
+
END_EXTERN_C()
#define ZEND_CLONE_FUNC_NAME "__clone"
Index: ZendEngine2/zend_execute.c
diff -u ZendEngine2/zend_execute.c:1.564 ZendEngine2/zend_execute.c:1.565
--- ZendEngine2/zend_execute.c:1.564 Sun Dec 14 07:32:02 2003
+++ ZendEngine2/zend_execute.c Sun Dec 14 11:09:07 2003
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: zend_execute.c,v 1.564 2003/12/14 12:32:02 zeev Exp $ */
+/* $Id: zend_execute.c,v 1.565 2003/12/14 16:09:07 zeev Exp $ */
#define ZEND_INTENSIVE_DEBUGGING 0
@@ -2512,6 +2512,8 @@
should_change_scope = 0;
}
+ EX_T(EX(opline)->result.u.var).var.fcall_returned_reference = 0;
+
if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) {
ALLOC_ZVAL(EX_T(EX(opline)->result.u.var).var.ptr);
INIT_ZVAL(*(EX_T(EX(opline)->result.u.var).var.ptr));
@@ -2561,6 +2563,7 @@
EG(active_op_array) = (zend_op_array *) EX(function_state).function;
zend_execute(EG(active_op_array) TSRMLS_CC);
+ EX_T(EX(opline)->result.u.var).var.fcall_returned_reference =
EG(active_op_array)->return_reference;
if (return_value_used && !EX_T(EX(opline)->result.u.var).var.ptr) {
if (!EG(exception)) {
@@ -2685,20 +2688,28 @@
{
zval *retval_ptr;
zval **retval_ptr_ptr;
-
- if ((EG(active_op_array)->return_reference == ZEND_RETURN_REF) &&
- (EX(opline)->op1.op_type != IS_CONST) &&
- (EX(opline)->op1.op_type != IS_TMP_VAR)) {
-
+
+ if (EG(active_op_array)->return_reference == ZEND_RETURN_REF) {
+ if (EX(opline)->op1.op_type == IS_CONST || EX(opline)->op1.op_type == IS_TMP_VAR) {
+ /* Not supposed to happen, but we'll allow it */
+ zend_error(E_STRICT, "Only variable references should be returned by reference");
+ goto return_by_value;
+ }
+
retval_ptr_ptr = get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_W);
if (!retval_ptr_ptr) {
- zend_error(E_ERROR, "Cannot return overloaded elements or string offsets by
reference");
+ zend_error(E_ERROR, "Cannot return string offsets by reference");
}
if (!(*retval_ptr_ptr)->is_ref
- && EX_T(EX(opline)->op1.u.var).var.ptr_ptr ==
&EX_T(EX(opline)->op1.u.var).var.ptr) {
- zend_error(E_ERROR, "Only variables or references can be returned by reference");
+ /*&& EX_T(EX(opline)->op1.u.var).var.ptr_ptr ==
&EX_T(EX(opline)->op1.u.var).var.ptr*/) {
+ if (EX(opline)->extended_value == ZEND_RETURNS_FUNCTION
+ && !EX_T(EX(opline)->op1.u.var).var.fcall_returned_reference) {
+ zend_error(E_STRICT, "Only variable references should be returned by reference");
+ PZVAL_LOCK(*retval_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */
+ goto return_by_value;
+ }
}
SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);
@@ -2706,6 +2717,7 @@
(*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr);
} else {
+return_by_value:
retval_ptr = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
if (!EG(free_op1)) { /* Not a temp var */
Index: ZendEngine2/zend_execute.h
diff -u ZendEngine2/zend_execute.h:1.59 ZendEngine2/zend_execute.h:1.60
--- ZendEngine2/zend_execute.h:1.59 Sun Dec 14 07:32:02 2003
+++ ZendEngine2/zend_execute.h Sun Dec 14 11:09:07 2003
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: zend_execute.h,v 1.59 2003/12/14 12:32:02 zeev Exp $ */
+/* $Id: zend_execute.h,v 1.60 2003/12/14 16:09:07 zeev Exp $ */
#ifndef ZEND_EXECUTE_H
#define ZEND_EXECUTE_H
@@ -36,6 +36,7 @@
zval *str;
zend_uint offset;
} str_offset;
+ zend_bool fcall_returned_reference;
} var;
zend_class_entry *class_entry;
} temp_variable;