mirror of
https://github.com/php/php-src.git
synced 2026-04-30 03:33:17 +02:00
f182309e87
Instead of looping, use straight-line code with the following layout: 1. Try to apply the base operation on the dereferenced operands. 2. Try overloaded object operations. 3. Try to convert operands to number, else error out. 4. Apply the base operation on the converted operands. This makes the code easier to reason about and fixes some edge-case bugs: 1. We should only try invoking operator overloading once prior to type conversion. Previously it was invoked both before and after type conversion. 2. We should not modify any values if an exception is thrown. Previously we sometimes modified the LHS of a compound assignment operator. 3. If conversion of the first operand fails, we no longer try to convert the second operand. I think the previous behavior here was fine as well, but this still seems a more typical. This will also make some followup changes I have in mind simpler.
252 lines
3.6 KiB
PHP
252 lines
3.6 KiB
PHP
--TEST--
|
|
Behavior of failing compound assignment
|
|
--INI--
|
|
opcache.optimization_level=0
|
|
--FILE--
|
|
<?php
|
|
|
|
try {
|
|
$a = 1;
|
|
$a %= 0;
|
|
} catch (Error $e) { var_dump($a); }
|
|
|
|
try {
|
|
$a = 1;
|
|
$a >>= -1;
|
|
} catch (Error $e) { var_dump($a); }
|
|
|
|
try {
|
|
$a = 1;
|
|
$a <<= -1;
|
|
} catch (Error $e) { var_dump($a); }
|
|
|
|
set_error_handler(function($type, $msg) { throw new Exception($msg); });
|
|
|
|
try {
|
|
$a = [];
|
|
$a .= "foo";
|
|
} catch (Throwable $e) { var_dump($a); }
|
|
|
|
try {
|
|
$a = "foo";
|
|
$a .= [];
|
|
} catch (Throwable $e) { var_dump($a); }
|
|
|
|
$x = new stdClass;
|
|
try { $x += 1; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = 1;
|
|
try { $x += new stdClass; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = "foo";
|
|
try { $x += new stdClass; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = new stdClass;
|
|
try { $x -= 1; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = 1;
|
|
try { $x -= new stdClass; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = "foo";
|
|
try { $x -= new stdClass; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = new stdClass;
|
|
try { $x *= 1; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = 1;
|
|
try { $x *= new stdClass; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = "foo";
|
|
try { $x *= new stdClass; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = new stdClass;
|
|
try { $x /= 1; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = 1;
|
|
try { $x /= new stdClass; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = "foo";
|
|
try { $x /= new stdClass; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = new stdClass;
|
|
try { $x %= 1; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = 1;
|
|
try { $x %= new stdClass; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = "foo";
|
|
try { $x %= new stdClass; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = new stdClass;
|
|
try { $x **= 1; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = 1;
|
|
try { $x **= new stdClass; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = "foo";
|
|
try { $x **= new stdClass; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = new stdClass;
|
|
try { $x ^= 1; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = 1;
|
|
try { $x ^= new stdClass; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = "foo";
|
|
try { $x ^= new stdClass; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = new stdClass;
|
|
try { $x &= 1; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = 1;
|
|
try { $x &= new stdClass; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = "foo";
|
|
try { $x &= new stdClass; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = new stdClass;
|
|
try { $x |= 1; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = 1;
|
|
try { $x |= new stdClass; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = "foo";
|
|
try { $x |= new stdClass; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = new stdClass;
|
|
try { $x <<= 1; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = 1;
|
|
try { $x <<= new stdClass; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = "foo";
|
|
try { $x <<= new stdClass; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = new stdClass;
|
|
try { $x >>= 1; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = 1;
|
|
try { $x >>= new stdClass; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
$x = "foo";
|
|
try { $x >>= new stdClass; }
|
|
catch (Exception $e) {}
|
|
var_dump($x);
|
|
|
|
?>
|
|
--EXPECTF--
|
|
int(1)
|
|
int(1)
|
|
int(1)
|
|
array(0) {
|
|
}
|
|
string(3) "foo"
|
|
object(stdClass)#%d (0) {
|
|
}
|
|
int(1)
|
|
string(3) "foo"
|
|
object(stdClass)#%d (0) {
|
|
}
|
|
int(1)
|
|
string(3) "foo"
|
|
object(stdClass)#%d (0) {
|
|
}
|
|
int(1)
|
|
string(3) "foo"
|
|
object(stdClass)#%d (0) {
|
|
}
|
|
int(1)
|
|
string(3) "foo"
|
|
object(stdClass)#%d (0) {
|
|
}
|
|
int(1)
|
|
string(3) "foo"
|
|
object(stdClass)#%d (0) {
|
|
}
|
|
int(1)
|
|
string(3) "foo"
|
|
object(stdClass)#%d (0) {
|
|
}
|
|
int(1)
|
|
string(3) "foo"
|
|
object(stdClass)#%d (0) {
|
|
}
|
|
int(1)
|
|
string(3) "foo"
|
|
object(stdClass)#%d (0) {
|
|
}
|
|
int(1)
|
|
string(3) "foo"
|
|
object(stdClass)#%d (0) {
|
|
}
|
|
int(1)
|
|
string(3) "foo"
|
|
object(stdClass)#%d (0) {
|
|
}
|
|
int(1)
|
|
string(3) "foo"
|