Hi, On Fri, Sep 23, 2011 at 14:06, Daniel K. <d...@uw.no> wrote: > When a built-in function is defined with ZEND_SEND_PREFER_REF, PHP will > issue a strict warning if you use an assignment expression as the parameter. > > As an example, current() show this behaviour. > > current() has this arginfo defined: > > ZEND_BEGIN_ARG_INFO(arginfo_current, ZEND_SEND_PREFER_REF) > ZEND_ARG_INFO(ZEND_SEND_PREFER_REF, arg) > ZEND_END_ARG_INFO() > > and a call like: > > <?php > current($foo = array("bar")); > ?> > > Presents you with: > > PHP Strict Standards: Only variables should be passed by reference in > %s on line %d > > > I think it is wrong to warn about this, because, to me, the _PREFER_ > part of ZEND_SEND_PREFER_REF, conveys that we should prefer to pass by > reference, if possible, and not care otherwise. > > The below patch implements the not care part that was missing until now. > > > This is done by having the lexer mark the result variable of the > assignment expression as not passable by reference, and changing the > function zend_do_pass_param() to ignore the marked variables when > considering if a parameter could be passed by reference or not. > > I have run make test, before and after, with no regressions. The only > test affected was the one I sent earlier to specifically test for this bug. > > I am, however, not sure if this is the right approach to solve the > problem, in which case, I hope to at least have put one of you on the > right track to the _real_ solution, and to have made you interested in > fixing it properly.
The patch looks strange to me, why would you only consider stuff like foo($a = 2) ? what about passing any other expressions: foo(array(..)), foo(funcNotReturningARef()) etc... ? To me it makes not much sense to distinguish different non-ref expressions in that regard, they should all be handled the same. Whether we want the actual error on some of our functions like current()/end() etc.. is another question, but that should be fixed at a totally different level. > > The patch is for php-5.3.8 > > > Daniel K. > > diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c > index c325a7e..df30d3d 100644 > --- a/Zend/zend_compile.c > +++ b/Zend/zend_compile.c > @@ -2096,7 +2096,7 @@ void zend_do_pass_param(znode *param, zend_uchar > op, int offset TSRMLS_DC) /* {{ > > if (function_ptr) { > if (ARG_MAY_BE_SENT_BY_REF(function_ptr, (zend_uint) offset)) { > - if (param->op_type & (IS_VAR|IS_CV)) { > + if (param->op_type & (IS_VAR|IS_CV) && > param->u.EA.type != > ZEND_PARSED_EXPR_NO_PASS_BY_REF) { > send_by_reference = 1; > if (op == ZEND_SEND_VAR && > zend_is_function_or_method_call(param)) { > /* Method call */ > diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h > index 15f24df..475f976 100644 > --- a/Zend/zend_compile.h > +++ b/Zend/zend_compile.h > @@ -650,6 +650,7 @@ int zendlex(znode *zendlval TSRMLS_DC); > #define ZEND_PARSED_VARIABLE (1<<4) > #define ZEND_PARSED_REFERENCE_VARIABLE (1<<5) > #define ZEND_PARSED_NEW (1<<6) > +#define ZEND_PARSED_EXPR_NO_PASS_BY_REF (1<<7) > > > /* unset types */ > diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y > index 1753e97..666b9e2 100644 > --- a/Zend/zend_language_parser.y > +++ b/Zend/zend_language_parser.y > @@ -578,7 +578,7 @@ non_empty_for_expr: > > expr_without_variable: > 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 '=' expr { > zend_check_writable_variable(&$1); > zend_do_assign(&$$, &$1, &$3 TSRMLS_CC); $$.u.EA.type = > ZEND_PARSED_EXPR_NO_PASS_BY_REF; } > | 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);} > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > > -- Etienne Kneuss http://www.colder.ch -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php