http://3v4l.org/uVNIS

Prior to PHP 5.1 (and the introduction of compiled variables), the
following code would output warnings for the undefined variables in
the order they were used:

echo $x . $y . $z;

However, with the introduction of CVs, we wind up getting the warning
for $y, then $x, and finally $z.  ((Insert "middle-out" reference from
HBO's Silicon Valley, here))  The reason for this, is that ZEND_CONCAT
(and indeed, most binary operations) is implemented as a single inline
function call:

  concat_function(EX_VAR(opline->result.var),
GET_OP1_ZVAL_PTR(BP_VAR_R), GET_OP2_ZVAL_PTR(BP_VAR_R));

When gcc looks at this function call, it treats the execution order
for the arguments as undefined.  In practice (at least on 3v4l.org) it
ends up evaluating the third argument (OP2) first, then the second
argument (OP1), and finally the first argument (result.var).  This is
perfectly legal as far as GCC is concerned since the result of one
function call argument shouldn't have side effects relative to another
argument. I'd like to propose making the order of evaluation defined
by splitting this into separate statements:

  zval *op1 = GET_OP1_ZVAL_PTR(BP_VAR_R);
  zval *op2 = GET_OP2_ZVAL_PTR(BP_VAR_R);
  concat_function(EX_VAR(opline->result.var), op1, op2);

The optimizer should do a proper job of removing the intermediate
assignment while keeping the defined resolution order intact.

God help us if anyone is actually /depending/ on this behavior...

-Sara

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to