mirror of
https://github.com/php/php-src.git
synced 2026-04-27 10:16:41 +02:00
Allow specifying keys on list() elements
Squashed commit of the following: commit0361dbe356Author: Andrea Faulds <ajf@ajf.me> Date: Fri Mar 25 16:59:20 2016 +0000 UPGRADING and NEWS commitdca9d4a36cAuthor: Andrea Faulds <ajf@ajf.me> Date: Fri Mar 25 16:45:18 2016 +0000 Add tests contributed by @jesseschalken commite557f77eabAuthor: Andrea Faulds <ajf@ajf.me> Date: Fri Mar 25 16:44:51 2016 +0000 Rebuild VM commit70942e4c3cAuthor: Andrea Faulds <ajf@ajf.me> Date: Wed Feb 24 13:12:26 2016 +0000 Add test for evaluation order of nested list() keys commited3592e80cAuthor: Andrea Faulds <ajf@ajf.me> Date: Wed Feb 24 12:42:04 2016 +0000 Add test for evaluation order commit589756cbccAuthor: Andrea Faulds <ajf@ajf.me> Date: Tue Jan 19 17:29:34 2016 +0000 Allow arbitrary expressions for key commit3f622077c3Author: Andrea Faulds <ajf@ajf.me> Date: Tue Jan 19 17:45:10 2016 +0000 Remove compile-time HANDLE_NUMERIC (see bug #63217) commitbab758119aAuthor: Andrea Faulds <ajf@ajf.me> Date: Sun Jan 17 01:20:26 2016 +0000 Handle numeric strings commit14bfe93ddcAuthor: Andrea Faulds <ajf@ajf.me> Date: Sun Jan 17 01:09:36 2016 +0000 Allow trailing comma commitf4c8b2cb30Author: Andrea Faulds <ajf@ajf.me> Date: Sat Jan 16 23:47:11 2016 +0000 Add tests commit0085884a61Author: Andrea Faulds <ajf@ajf.me> Date: Sat Jan 16 22:24:23 2016 +0000 Handle non-integer/string opcodes commite572d2d0adAuthor: Andrea Faulds <ajf@ajf.me> Date: Sat Jan 16 21:10:33 2016 +0000 Disallow mixing keyed and unkeyed list() elements commitcede13ccfeAuthor: Andrea Faulds <ajf@ajf.me> Date: Sun Jan 10 20:46:44 2016 +0000 list() with keys (no foreach or tests)
This commit is contained in:
@@ -12,6 +12,7 @@ PHP NEWS
|
||||
. Added void return type. (Andrea)
|
||||
. Added support for negative string offsets in string offset syntax and
|
||||
various string functions. (Francois)
|
||||
. Added a form of the list() construct where keys can be specified. (Andrea)
|
||||
|
||||
- FTP:
|
||||
. Implemented FR #55651 (Option to ignore the returned FTP PASV address).
|
||||
|
||||
@@ -35,6 +35,8 @@ PHP 7.1 UPGRADE NOTES
|
||||
. String offset access now supports negative references, which will be
|
||||
counted from the end of the string.
|
||||
(RFC: https://wiki.php.net/rfc/negative-string-offsets)
|
||||
. Added a form of the list() construct where keys can be specified.
|
||||
(RFC: https://wiki.php.net/rfc/list_keys)
|
||||
|
||||
========================================
|
||||
3. Changes in SAPI modules
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
--TEST--
|
||||
foreach with list syntax, keyed
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$points = [
|
||||
["x" => 1, "y" => 2],
|
||||
["x" => 2, "y" => 1]
|
||||
];
|
||||
|
||||
foreach ($points as list("x" => $x, "y" => $y)) {
|
||||
var_dump($x, $y);
|
||||
}
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
$invertedPoints = [
|
||||
"x" => [1, 2],
|
||||
"y" => [2, 1]
|
||||
];
|
||||
|
||||
foreach ($invertedPoints as list(0 => $row1, 1 => $row2)) {
|
||||
var_dump($row1, $row2);
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
int(1)
|
||||
int(2)
|
||||
int(2)
|
||||
int(1)
|
||||
|
||||
int(1)
|
||||
int(2)
|
||||
int(2)
|
||||
int(1)
|
||||
@@ -0,0 +1,71 @@
|
||||
--TEST--
|
||||
list() with keys
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$antonyms = [
|
||||
"good" => "bad",
|
||||
"happy" => "sad",
|
||||
];
|
||||
|
||||
list("good" => $good_antonym, "happy" => $happy_antonym) = $antonyms;
|
||||
var_dump($good_antonym, $happy_antonym);
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
$powersOfTwo = [
|
||||
1 => 2,
|
||||
2 => 4,
|
||||
3 => 8
|
||||
];
|
||||
|
||||
list(1 => $two_1, 2 => $two_2, 3 => $two_3) = $powersOfTwo;
|
||||
var_dump($two_1, $two_2, $two_3);
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
$contrivedMixedKeyTypesExample = [
|
||||
7 => "the best PHP version",
|
||||
"elePHPant" => "the cutest mascot"
|
||||
];
|
||||
|
||||
list(7 => $seven, "elePHPant" => $elePHPant) = $contrivedMixedKeyTypesExample;
|
||||
var_dump($seven, $elePHPant);
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
$allTogetherNow = [
|
||||
"antonyms" => $antonyms,
|
||||
"powersOfTwo" => $powersOfTwo,
|
||||
"contrivedMixedKeyTypesExample" => $contrivedMixedKeyTypesExample
|
||||
];
|
||||
|
||||
list(
|
||||
"antonyms" => list("good" => $good_antonym, "happy" => $happy_antonym),
|
||||
"powersOfTwo" => list(1 => $two_1, 2 => $two_2, 3 => $two_3),
|
||||
"contrivedMixedKeyTypesExample" => list(7 => $seven, "elePHPant" => $elePHPant)
|
||||
) = $allTogetherNow;
|
||||
|
||||
var_dump($good_antonym, $happy_antonym);
|
||||
var_dump($two_1, $two_2, $two_3);
|
||||
var_dump($seven, $elePHPant);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(3) "bad"
|
||||
string(3) "sad"
|
||||
|
||||
int(2)
|
||||
int(4)
|
||||
int(8)
|
||||
|
||||
string(20) "the best PHP version"
|
||||
string(17) "the cutest mascot"
|
||||
|
||||
string(3) "bad"
|
||||
string(3) "sad"
|
||||
int(2)
|
||||
int(4)
|
||||
int(8)
|
||||
string(20) "the best PHP version"
|
||||
string(17) "the cutest mascot"
|
||||
@@ -0,0 +1,54 @@
|
||||
--TEST--
|
||||
list() with keys and ArrayAccess
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$antonymObject = new ArrayObject;
|
||||
$antonymObject["good"] = "bad";
|
||||
$antonymObject["happy"] = "sad";
|
||||
|
||||
list("good" => $good, "happy" => $happy) = $antonymObject;
|
||||
var_dump($good, $happy);
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
$stdClassCollection = new SplObjectStorage;
|
||||
$foo = new StdClass;
|
||||
$stdClassCollection[$foo] = "foo";
|
||||
$bar = new StdClass;
|
||||
$stdClassCollection[$bar] = "bar";
|
||||
|
||||
list($foo => $fooStr, $bar => $barStr) = $stdClassCollection;
|
||||
var_dump($fooStr, $barStr);
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
class IndexPrinter implements ArrayAccess
|
||||
{
|
||||
public function offsetGet($offset) {
|
||||
echo "GET ";
|
||||
var_dump($offset);
|
||||
}
|
||||
public function offsetSet($offset, $value) {
|
||||
}
|
||||
public function offsetExists($offset) {
|
||||
}
|
||||
public function offsetUnset($offset) {
|
||||
}
|
||||
}
|
||||
|
||||
$op = new IndexPrinter;
|
||||
list(123 => $x) = $op;
|
||||
// PHP shouldn't convert this to an integer offset, because it's ArrayAccess
|
||||
list("123" => $x) = $op;
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(3) "bad"
|
||||
string(3) "sad"
|
||||
|
||||
string(3) "foo"
|
||||
string(3) "bar"
|
||||
|
||||
GET int(123)
|
||||
GET string(3) "123"
|
||||
@@ -0,0 +1,32 @@
|
||||
--TEST--
|
||||
list() with non-integer-or-string keys
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$results = [
|
||||
0 => 0,
|
||||
1 => 1,
|
||||
"" => ""
|
||||
];
|
||||
|
||||
list(NULL => $NULL, 1.5 => $float, FALSE => $FALSE, TRUE => $TRUE) = $results;
|
||||
var_dump($NULL, $float, $FALSE, $TRUE);
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
list("0" => $zeroString, "1" => $oneString) = $results;
|
||||
var_dump($zeroString, $oneString);
|
||||
|
||||
list(STDIN => $resource) = [];
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
string(0) ""
|
||||
int(1)
|
||||
int(0)
|
||||
int(1)
|
||||
|
||||
int(0)
|
||||
int(1)
|
||||
|
||||
Notice: Resource ID#%d used as offset, casting to integer (%d) in %s on line %d
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
// Observer objects for the Zend/tests/list_keyed_evaluation_order.* tests
|
||||
|
||||
class Stringable
|
||||
{
|
||||
private $name;
|
||||
public function __construct(string $name) {
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function __toString(): string {
|
||||
echo "$this->name evaluated.", PHP_EOL;
|
||||
return $this->name;
|
||||
}
|
||||
}
|
||||
|
||||
class Indexable implements ArrayAccess
|
||||
{
|
||||
private $array;
|
||||
public function __construct(array $array) {
|
||||
$this->array = $array;
|
||||
}
|
||||
|
||||
public function offsetExists($offset): bool {
|
||||
echo "Existence of offset $offset checked for.", PHP_EOL;
|
||||
return isset($this->array[$offset]);
|
||||
}
|
||||
|
||||
public function offsetUnset($offset): void {
|
||||
unset($this->array[$offset]);
|
||||
echo "Offset $offset removed.", PHP_EOL;
|
||||
}
|
||||
|
||||
public function offsetGet($offset) {
|
||||
echo "Offset $offset retrieved.", PHP_EOL;
|
||||
return $this->array[$offset];
|
||||
}
|
||||
|
||||
public function offsetSet($offset, $value): void {
|
||||
$this->array[$offset] = $value;
|
||||
echo "Offset $offset set to $value.", PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
class IndexableRetrievable
|
||||
{
|
||||
private $label;
|
||||
private $indexable;
|
||||
|
||||
public function __construct(string $label, Indexable $indexable) {
|
||||
$this->label = $label;
|
||||
$this->indexable = $indexable;
|
||||
}
|
||||
|
||||
public function getIndexable(): Indexable {
|
||||
echo "Indexable $this->label retrieved.", PHP_EOL;
|
||||
return $this->indexable;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
--TEST--
|
||||
list() with keys, evaluation order
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once "list_keyed_evaluation_order.inc";
|
||||
|
||||
$a = new Stringable("A");
|
||||
$c = new Stringable("C");
|
||||
|
||||
$e = new IndexableRetrievable("E", new Indexable(["A" => "value for offset A", "C" => "value for offset C"]));
|
||||
|
||||
$store = new Indexable([]);
|
||||
|
||||
// list($a => $b, $c => $d) = $e;
|
||||
// Should be evaluated in the order:
|
||||
// 1. Evaluate $e
|
||||
// 2. Evaluate $a
|
||||
// 3. Evaluate $e[$a]
|
||||
// 4. Assign $b from $e[$a]
|
||||
// 5. Evaluate $c
|
||||
// 6. Evaluate $e[$c]
|
||||
// 7. Assign $c from $e[$a]
|
||||
|
||||
list((string)$a => $store["B"], (string)$c => $store["D"]) = $e->getIndexable();
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Indexable E retrieved.
|
||||
A evaluated.
|
||||
Offset A retrieved.
|
||||
Offset B set to value for offset A.
|
||||
C evaluated.
|
||||
Offset C retrieved.
|
||||
Offset D set to value for offset C.
|
||||
@@ -0,0 +1,77 @@
|
||||
--TEST--
|
||||
list() with keys, evaluation order #2
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
// All the following should print 'a' then 'b'
|
||||
|
||||
list($a, $b) = ['a', 'b'];
|
||||
var_dump($a);
|
||||
var_dump($b);
|
||||
|
||||
list(0 => $a, 1 => $b) = ['a', 'b'];
|
||||
var_dump($a);
|
||||
var_dump($b);
|
||||
|
||||
list(1 => $b, 0 => $a) = ['a', 'b'];
|
||||
var_dump($a);
|
||||
var_dump($b);
|
||||
|
||||
$arr = [];
|
||||
list($arr[], $arr[]) = ['a', 'b'];
|
||||
var_dump($arr[0]);
|
||||
var_dump($arr[1]);
|
||||
|
||||
$arr = [];
|
||||
list(0 => $arr[], 1 => $arr[]) = ['a', 'b'];
|
||||
var_dump($arr[0]);
|
||||
var_dump($arr[1]);
|
||||
|
||||
$arr = [];
|
||||
list(1 => $arr[], 0 => $arr[]) = ['b', 'a'];
|
||||
var_dump($arr[0]);
|
||||
var_dump($arr[1]);
|
||||
|
||||
$arr = [];
|
||||
list(list(1 => $arr[], 0 => $arr[])) = [['b', 'a']];
|
||||
var_dump($arr[0]);
|
||||
var_dump($arr[1]);
|
||||
|
||||
$arr = [];
|
||||
list('key1' => $arr[], 'key2' => $arr[]) = ['key2' => 'b', 'key1' => 'a'];
|
||||
var_dump($arr[0]);
|
||||
var_dump($arr[1]);
|
||||
|
||||
// This should print 'foo'
|
||||
$a = 0;
|
||||
list($a => $a) = ['foo', 'bar'];
|
||||
var_dump($a);
|
||||
|
||||
// This should print 'bar' then 'foo'
|
||||
$a = 0;
|
||||
$b = 1;
|
||||
list($b => $a, $a => $c) = ['bar' => 'foo', 1 => 'bar'];
|
||||
var_dump($a);
|
||||
var_dump($c);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(1) "a"
|
||||
string(1) "b"
|
||||
string(1) "a"
|
||||
string(1) "b"
|
||||
string(1) "a"
|
||||
string(1) "b"
|
||||
string(1) "a"
|
||||
string(1) "b"
|
||||
string(1) "a"
|
||||
string(1) "b"
|
||||
string(1) "a"
|
||||
string(1) "b"
|
||||
string(1) "a"
|
||||
string(1) "b"
|
||||
string(1) "a"
|
||||
string(1) "b"
|
||||
string(3) "foo"
|
||||
string(3) "bar"
|
||||
string(3) "foo"
|
||||
@@ -0,0 +1,24 @@
|
||||
--TEST--
|
||||
list() with keys, evaluation order #3
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$i = 0;
|
||||
$a = [
|
||||
0 => [
|
||||
'b' => 'bar',
|
||||
'a' => 'foo',
|
||||
],
|
||||
1 => 'a',
|
||||
3 => 'b',
|
||||
];
|
||||
list($a[$i++] => $a[$i++], $a[$i++] => $a[$i++]) = $a[$i++];
|
||||
var_dump($i); // should be 5
|
||||
var_dump($a[2]); // should be 'foo'
|
||||
var_dump($a[4]); // should be 'bar'
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
int(5)
|
||||
string(3) "foo"
|
||||
string(3) "bar"
|
||||
@@ -0,0 +1,77 @@
|
||||
--TEST--
|
||||
list() with keys, evaluation order: nested
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once "list_keyed_evaluation_order.inc";
|
||||
|
||||
$a = new Stringable("A");
|
||||
$c = new Stringable("C");
|
||||
$f = new Stringable("F");
|
||||
$g = new Stringable("G");
|
||||
$i = new Stringable("I");
|
||||
|
||||
$k = new IndexableRetrievable("K", new Indexable([
|
||||
"A" => "offset value for A",
|
||||
"C" => new Indexable([
|
||||
0 => "offset value for 0",
|
||||
1 => "offset value for 1"
|
||||
]),
|
||||
"F" => new Indexable([
|
||||
"G" => "offset value for G",
|
||||
"I" => "offset value for I"
|
||||
])
|
||||
]));
|
||||
|
||||
$store = new Indexable([]);
|
||||
|
||||
// list($a => $b, $c => list($d, $e), $f => list($g => $h, $i => $j)) = $k;
|
||||
// Should be evaluated in the order:
|
||||
// 1. Evaluate $k
|
||||
// 2. Evaluate $a
|
||||
// 3. Evaluate $k[$a]
|
||||
// 4. Assign $b from $k[$a]
|
||||
// 5. Evaluate $c
|
||||
// 6. Evaluate $k[$c]
|
||||
// 7. Evaluate $k[$c][0]
|
||||
// 8. Assign $d from $k[$c][0]
|
||||
// 9. Evaluate $k[$c][1]
|
||||
// 10. Assign $e from $k[$c][1]
|
||||
// 11. Evaluate $f
|
||||
// 12. Evaluate $k[$f]
|
||||
// 13. Evaluate $g
|
||||
// 14. Evaluate $k[$f][$g]
|
||||
// 15. Assign $h from $k[$f][$g]
|
||||
// 16. Evaluate $i
|
||||
// 17. Evaluate $k[$f][$i]
|
||||
// 18. Assign $j from $k[$f][$i]
|
||||
|
||||
list(
|
||||
(string)$a => $store["B"],
|
||||
(string)$c => list($store["D"], $store["E"]),
|
||||
(string)$f => list(
|
||||
(string)$g => $store["H"],
|
||||
(string)$i => $store["J"]
|
||||
)
|
||||
) = $k->getIndexable();
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Indexable K retrieved.
|
||||
A evaluated.
|
||||
Offset A retrieved.
|
||||
Offset B set to offset value for A.
|
||||
C evaluated.
|
||||
Offset C retrieved.
|
||||
Offset 0 retrieved.
|
||||
Offset D set to offset value for 0.
|
||||
Offset 1 retrieved.
|
||||
Offset E set to offset value for 1.
|
||||
F evaluated.
|
||||
Offset F retrieved.
|
||||
G evaluated.
|
||||
Offset G retrieved.
|
||||
Offset H set to offset value for G.
|
||||
I evaluated.
|
||||
Offset I retrieved.
|
||||
Offset J set to offset value for I.
|
||||
@@ -0,0 +1,30 @@
|
||||
--TEST--
|
||||
list() with constant keys
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$arr = [
|
||||
1 => "one",
|
||||
2 => "two",
|
||||
3 => "three"
|
||||
];
|
||||
|
||||
const COMPILE_TIME_RESOLVABLE = 1;
|
||||
|
||||
define('PROBABLY_NOT_COMPILE_TIME_RESOLVABLE', file_get_contents("data:text/plain,2"));
|
||||
|
||||
$probablyNotCompileTimeResolvable3 = cos(0) * 3;
|
||||
|
||||
list(
|
||||
COMPILE_TIME_RESOLVABLE => $one,
|
||||
PROBABLY_NOT_COMPILE_TIME_RESOLVABLE => $two,
|
||||
$probablyNotCompileTimeResolvable3 => $three
|
||||
) = $arr;
|
||||
|
||||
var_dump($one, $two, $three);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
string(3) "one"
|
||||
string(3) "two"
|
||||
string(5) "three"
|
||||
@@ -0,0 +1,38 @@
|
||||
--TEST--
|
||||
list() with keys and a trailing comma
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$antonyms = [
|
||||
"good" => "bad",
|
||||
"happy" => "sad",
|
||||
];
|
||||
|
||||
list(
|
||||
"good" => $good,
|
||||
"happy" => $happy
|
||||
) = $antonyms;
|
||||
|
||||
var_dump($good, $happy);
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
$antonyms = [
|
||||
"good" => "bad",
|
||||
"happy" => "sad",
|
||||
];
|
||||
|
||||
list(
|
||||
"good" => $good,
|
||||
"happy" => $happy,
|
||||
) = $antonyms;
|
||||
|
||||
var_dump($good, $happy);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(3) "bad"
|
||||
string(3) "sad"
|
||||
|
||||
string(3) "bad"
|
||||
string(3) "sad"
|
||||
@@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
list() with undefined keys
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$contrivedMixedKeyTypesExample = [
|
||||
7 => "the best PHP version",
|
||||
"elePHPant" => "the cutest mascot"
|
||||
];
|
||||
|
||||
list(5 => $five, "duke" => $duke) = $contrivedMixedKeyTypesExample;
|
||||
|
||||
var_dump($five, $duke);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
|
||||
Notice: Undefined offset: 5 in %s on line %d
|
||||
|
||||
Notice: Undefined index: duke in %s on line %d
|
||||
NULL
|
||||
NULL
|
||||
@@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
list() with both keyed and unkeyed elements
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$contrivedKeyedAndUnkeyedArrayExample = [
|
||||
0,
|
||||
1 => 1,
|
||||
"foo" => "bar"
|
||||
];
|
||||
|
||||
list($zero, 1 => $one, "foo" => $foo) = $contrivedKeyedAndUnkeyedArrayExample;
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Parse error: syntax error, unexpected %s in %s on line %d
|
||||
@@ -0,0 +1,34 @@
|
||||
--TEST--
|
||||
list() with nested unkeyed and keyed list()
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$points = [
|
||||
["x" => 1, "y" => 2],
|
||||
["x" => 2, "y" => 1]
|
||||
];
|
||||
|
||||
list(list("x" => $x1, "y" => $y1), list("x" => $x2, "y" => $y2)) = $points;
|
||||
var_dump($x1, $y1, $x2, $y2);
|
||||
|
||||
echo PHP_EOL;
|
||||
|
||||
$invertedPoints = [
|
||||
"x" => [1, 2],
|
||||
"y" => [2, 1]
|
||||
];
|
||||
|
||||
list("x" => list($x1, $x2), "y" => list($y1, $y2)) = $invertedPoints;
|
||||
var_dump($x1, $y1, $x2, $y2);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
int(1)
|
||||
int(2)
|
||||
int(2)
|
||||
int(1)
|
||||
|
||||
int(1)
|
||||
int(2)
|
||||
int(2)
|
||||
int(1)
|
||||
+35
-2
@@ -2709,9 +2709,8 @@ void zend_compile_static_prop(znode *result, zend_ast *ast, uint32_t type, int d
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_node) /* {{{ */
|
||||
static void zend_compile_unkeyed_list_assign(zend_ast_list *list, znode *expr_node) /* {{{ */
|
||||
{
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
uint32_t i;
|
||||
zend_bool has_elems = 0;
|
||||
|
||||
@@ -2738,6 +2737,40 @@ static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_n
|
||||
if (!has_elems) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use empty list");
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void zend_compile_keyed_list_assign(zend_ast_list *list, znode *expr_node) /* {{{ */
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < list->children; ++i) {
|
||||
zend_ast *pair_ast = list->child[i];
|
||||
zend_ast *var_ast = pair_ast->child[0];
|
||||
zend_ast *key_ast = pair_ast->child[1];
|
||||
znode fetch_result, dim_node;
|
||||
|
||||
zend_compile_expr(&dim_node, key_ast);
|
||||
|
||||
if (expr_node->op_type == IS_CONST) {
|
||||
Z_TRY_ADDREF(expr_node->u.constant);
|
||||
}
|
||||
|
||||
zend_emit_op(&fetch_result, ZEND_FETCH_LIST, expr_node, &dim_node);
|
||||
zend_emit_assign_znode(var_ast, &fetch_result);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_node) /* {{{ */
|
||||
{
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
|
||||
if (list->children > 0 && list->child[0] != NULL && list->child[0]->kind == ZEND_AST_ARRAY_ELEM) {
|
||||
zend_compile_keyed_list_assign(list, expr_node);
|
||||
} else {
|
||||
zend_compile_unkeyed_list_assign(list, expr_node);
|
||||
}
|
||||
|
||||
*result = *expr_node;
|
||||
}
|
||||
|
||||
@@ -241,7 +241,8 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
|
||||
%type <ast> exit_expr scalar backticks_expr lexical_var function_call member_name property_name
|
||||
%type <ast> variable_class_name dereferencable_scalar constant dereferencable
|
||||
%type <ast> callable_expr callable_variable static_member new_variable
|
||||
%type <ast> assignment_list_element array_pair encaps_var encaps_var_offset isset_variables
|
||||
%type <ast> unkeyed_assignment_list_element keyed_assignment_list_element array_pair
|
||||
%type <ast> encaps_var encaps_var_offset isset_variables
|
||||
%type <ast> top_statement_list use_declarations const_list inner_statement_list if_stmt
|
||||
%type <ast> alt_if_stmt for_exprs switch_case_list global_var_list static_var_list
|
||||
%type <ast> echo_expr_list unset_variables catch_list parameter_list class_statement_list
|
||||
@@ -250,7 +251,8 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
|
||||
%type <ast> class_const_list class_const_decl name_list trait_adaptations method_body non_empty_for_exprs
|
||||
%type <ast> ctor_arguments alt_if_stmt_without_else trait_adaptation_list lexical_vars
|
||||
%type <ast> lexical_var_list encaps_list array_pair_list non_empty_array_pair_list
|
||||
%type <ast> assignment_list isset_variable type return_type
|
||||
%type <ast> assignment_list unkeyed_assignment_list keyed_assignment_list
|
||||
%type <ast> isset_variable type return_type
|
||||
%type <ast> identifier
|
||||
|
||||
%type <num> returns_ref function is_reference is_variadic variable_modifiers
|
||||
@@ -1170,18 +1172,39 @@ property_name:
|
||||
;
|
||||
|
||||
assignment_list:
|
||||
assignment_list ',' assignment_list_element
|
||||
unkeyed_assignment_list
|
||||
{ $$ = $1; }
|
||||
| keyed_assignment_list possible_comma
|
||||
{ $$ = $1; }
|
||||
;
|
||||
|
||||
unkeyed_assignment_list:
|
||||
unkeyed_assignment_list ',' unkeyed_assignment_list_element
|
||||
{ $$ = zend_ast_list_add($1, $3); }
|
||||
| assignment_list_element
|
||||
| unkeyed_assignment_list_element
|
||||
{ $$ = zend_ast_create_list(1, ZEND_AST_LIST, $1); }
|
||||
;
|
||||
|
||||
assignment_list_element:
|
||||
unkeyed_assignment_list_element:
|
||||
variable { $$ = $1; }
|
||||
| T_LIST '(' assignment_list ')' { $$ = $3; }
|
||||
| /* empty */ { $$ = NULL; }
|
||||
;
|
||||
|
||||
keyed_assignment_list:
|
||||
keyed_assignment_list ',' keyed_assignment_list_element
|
||||
{ $$ = zend_ast_list_add($1, $3); }
|
||||
| keyed_assignment_list_element
|
||||
{ $$ = zend_ast_create_list(1, ZEND_AST_LIST, $1); }
|
||||
;
|
||||
|
||||
keyed_assignment_list_element:
|
||||
expr T_DOUBLE_ARROW variable
|
||||
{ $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $3, $1); }
|
||||
| expr T_DOUBLE_ARROW T_LIST '(' assignment_list ')'
|
||||
{ $$ = zend_ast_create(ZEND_AST_ARRAY_ELEM, $5, $1); }
|
||||
;
|
||||
|
||||
|
||||
array_pair_list:
|
||||
/* empty */ { $$ = zend_ast_create_list(0, ZEND_AST_ARRAY); }
|
||||
|
||||
+58
-7
@@ -2062,30 +2062,80 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV)
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(98, ZEND_FETCH_LIST, CONST|TMPVAR|CV, CONST)
|
||||
ZEND_VM_HANDLER(98, ZEND_FETCH_LIST, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1;
|
||||
zend_free_op free_op2;
|
||||
zval *container;
|
||||
zval *offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
|
||||
|
||||
SAVE_OPLINE();
|
||||
container = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
|
||||
|
||||
ZEND_VM_C_LABEL(try_fetch_list):
|
||||
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
||||
zval *value = zend_hash_index_find(Z_ARRVAL_P(container), Z_LVAL_P(EX_CONSTANT(opline->op2)));
|
||||
zval *value;
|
||||
zend_string *str;
|
||||
zend_ulong hval;
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE,"Undefined offset: " ZEND_ULONG_FMT, Z_LVAL_P(EX_CONSTANT(opline->op2)));
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
ZEND_VM_C_LABEL(assign_again_list):
|
||||
if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
||||
hval = Z_LVAL_P(offset);
|
||||
ZEND_VM_C_LABEL(num_index_list):
|
||||
value = zend_hash_index_find(Z_ARRVAL_P(container), hval);
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE, "Undefined offset: " ZEND_ULONG_FMT, hval);
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
|
||||
str = Z_STR_P(offset);
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
||||
ZEND_VM_C_GOTO(num_index_list);
|
||||
}
|
||||
|
||||
ZEND_VM_C_LABEL(str_index_list):
|
||||
value = zend_hash_find(Z_ARRVAL_P(container), str);
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(str));
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
}
|
||||
if (UNEXPECTED(str != Z_STR_P(offset))) {
|
||||
zend_string_release(str);
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
|
||||
offset = Z_REFVAL_P(offset);
|
||||
ZEND_VM_C_GOTO(assign_again_list);
|
||||
} else if (Z_TYPE_P(offset) == IS_NULL) {
|
||||
str = ZSTR_EMPTY_ALLOC();
|
||||
ZEND_VM_C_GOTO(str_index_list);
|
||||
} else if (Z_TYPE_P(offset) == IS_DOUBLE) {
|
||||
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
||||
ZEND_VM_C_GOTO(num_index_list);
|
||||
} else if (Z_TYPE_P(offset) == IS_FALSE) {
|
||||
hval = 0;
|
||||
ZEND_VM_C_GOTO(num_index_list);
|
||||
} else if (Z_TYPE_P(offset) == IS_TRUE) {
|
||||
hval = 1;
|
||||
ZEND_VM_C_GOTO(num_index_list);
|
||||
} else if (Z_TYPE_P(offset) == IS_RESOURCE) {
|
||||
zend_error(E_NOTICE, "Resource ID#%pd used as offset, casting to integer (%pd)", Z_RES_HANDLE_P(offset), Z_RES_HANDLE_P(offset));
|
||||
hval = Z_RES_HANDLE_P(offset);
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
zend_error(E_WARNING, "Illegal offset type");
|
||||
}
|
||||
} else if (OP1_TYPE != IS_CONST &&
|
||||
UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
|
||||
EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) {
|
||||
zval *result = EX_VAR(opline->result.var);
|
||||
zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, EX_CONSTANT(opline->op2), BP_VAR_R, result);
|
||||
zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, offset, BP_VAR_R, result);
|
||||
|
||||
if (retval) {
|
||||
if (result != retval) {
|
||||
@@ -2103,6 +2153,7 @@ ZEND_VM_C_LABEL(try_fetch_list):
|
||||
}
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
}
|
||||
FREE_OP2();
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
|
||||
+753
-30
@@ -5746,26 +5746,76 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_CONST_CONST_HA
|
||||
{
|
||||
USE_OPLINE
|
||||
|
||||
|
||||
zval *container;
|
||||
zval *offset = EX_CONSTANT(opline->op2);
|
||||
|
||||
SAVE_OPLINE();
|
||||
container = EX_CONSTANT(opline->op1);
|
||||
|
||||
try_fetch_list:
|
||||
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
||||
zval *value = zend_hash_index_find(Z_ARRVAL_P(container), Z_LVAL_P(EX_CONSTANT(opline->op2)));
|
||||
zval *value;
|
||||
zend_string *str;
|
||||
zend_ulong hval;
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE,"Undefined offset: " ZEND_ULONG_FMT, Z_LVAL_P(EX_CONSTANT(opline->op2)));
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
assign_again_list:
|
||||
if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
||||
hval = Z_LVAL_P(offset);
|
||||
num_index_list:
|
||||
value = zend_hash_index_find(Z_ARRVAL_P(container), hval);
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE, "Undefined offset: " ZEND_ULONG_FMT, hval);
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
|
||||
str = Z_STR_P(offset);
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
||||
goto num_index_list;
|
||||
}
|
||||
|
||||
str_index_list:
|
||||
value = zend_hash_find(Z_ARRVAL_P(container), str);
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(str));
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
}
|
||||
if (UNEXPECTED(str != Z_STR_P(offset))) {
|
||||
zend_string_release(str);
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
|
||||
offset = Z_REFVAL_P(offset);
|
||||
goto assign_again_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_NULL) {
|
||||
str = ZSTR_EMPTY_ALLOC();
|
||||
goto str_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_DOUBLE) {
|
||||
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_FALSE) {
|
||||
hval = 0;
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_TRUE) {
|
||||
hval = 1;
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_RESOURCE) {
|
||||
zend_error(E_NOTICE, "Resource ID#%pd used as offset, casting to integer (%pd)", Z_RES_HANDLE_P(offset), Z_RES_HANDLE_P(offset));
|
||||
hval = Z_RES_HANDLE_P(offset);
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
zend_error(E_WARNING, "Illegal offset type");
|
||||
}
|
||||
} else if (IS_CONST != IS_CONST &&
|
||||
UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
|
||||
EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) {
|
||||
zval *result = EX_VAR(opline->result.var);
|
||||
zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, EX_CONSTANT(opline->op2), BP_VAR_R, result);
|
||||
zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, offset, BP_VAR_R, result);
|
||||
|
||||
if (retval) {
|
||||
if (result != retval) {
|
||||
@@ -5783,6 +5833,7 @@ try_fetch_list:
|
||||
}
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
}
|
||||
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
@@ -9499,6 +9550,101 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_
|
||||
}
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
|
||||
|
||||
zval *container;
|
||||
zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
||||
|
||||
SAVE_OPLINE();
|
||||
container = EX_CONSTANT(opline->op1);
|
||||
|
||||
try_fetch_list:
|
||||
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
||||
zval *value;
|
||||
zend_string *str;
|
||||
zend_ulong hval;
|
||||
|
||||
assign_again_list:
|
||||
if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
||||
hval = Z_LVAL_P(offset);
|
||||
num_index_list:
|
||||
value = zend_hash_index_find(Z_ARRVAL_P(container), hval);
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE, "Undefined offset: " ZEND_ULONG_FMT, hval);
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
|
||||
str = Z_STR_P(offset);
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
||||
goto num_index_list;
|
||||
}
|
||||
|
||||
str_index_list:
|
||||
value = zend_hash_find(Z_ARRVAL_P(container), str);
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(str));
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
}
|
||||
if (UNEXPECTED(str != Z_STR_P(offset))) {
|
||||
zend_string_release(str);
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
|
||||
offset = Z_REFVAL_P(offset);
|
||||
goto assign_again_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_NULL) {
|
||||
str = ZSTR_EMPTY_ALLOC();
|
||||
goto str_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_DOUBLE) {
|
||||
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_FALSE) {
|
||||
hval = 0;
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_TRUE) {
|
||||
hval = 1;
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_RESOURCE) {
|
||||
zend_error(E_NOTICE, "Resource ID#%pd used as offset, casting to integer (%pd)", Z_RES_HANDLE_P(offset), Z_RES_HANDLE_P(offset));
|
||||
hval = Z_RES_HANDLE_P(offset);
|
||||
} else {
|
||||
zend_error(E_WARNING, "Illegal offset type");
|
||||
}
|
||||
} else if (IS_CONST != IS_CONST &&
|
||||
UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
|
||||
EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) {
|
||||
zval *result = EX_VAR(opline->result.var);
|
||||
zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, offset, BP_VAR_R, result);
|
||||
|
||||
if (retval) {
|
||||
if (result != retval) {
|
||||
ZVAL_COPY(result, retval);
|
||||
}
|
||||
} else {
|
||||
ZVAL_NULL(result);
|
||||
}
|
||||
} else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_TYPE_P(container) == IS_REFERENCE) {
|
||||
container = Z_REFVAL_P(container);
|
||||
goto try_fetch_list;
|
||||
} else {
|
||||
if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
|
||||
GET_OP1_UNDEF_CV(container, BP_VAR_R);
|
||||
}
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
}
|
||||
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@@ -11310,6 +11456,101 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_
|
||||
}
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
|
||||
zend_free_op free_op2;
|
||||
zval *container;
|
||||
zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
||||
|
||||
SAVE_OPLINE();
|
||||
container = EX_CONSTANT(opline->op1);
|
||||
|
||||
try_fetch_list:
|
||||
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
||||
zval *value;
|
||||
zend_string *str;
|
||||
zend_ulong hval;
|
||||
|
||||
assign_again_list:
|
||||
if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
||||
hval = Z_LVAL_P(offset);
|
||||
num_index_list:
|
||||
value = zend_hash_index_find(Z_ARRVAL_P(container), hval);
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE, "Undefined offset: " ZEND_ULONG_FMT, hval);
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
|
||||
str = Z_STR_P(offset);
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
||||
goto num_index_list;
|
||||
}
|
||||
|
||||
str_index_list:
|
||||
value = zend_hash_find(Z_ARRVAL_P(container), str);
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(str));
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
}
|
||||
if (UNEXPECTED(str != Z_STR_P(offset))) {
|
||||
zend_string_release(str);
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
|
||||
offset = Z_REFVAL_P(offset);
|
||||
goto assign_again_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_NULL) {
|
||||
str = ZSTR_EMPTY_ALLOC();
|
||||
goto str_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_DOUBLE) {
|
||||
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_FALSE) {
|
||||
hval = 0;
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_TRUE) {
|
||||
hval = 1;
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_RESOURCE) {
|
||||
zend_error(E_NOTICE, "Resource ID#%pd used as offset, casting to integer (%pd)", Z_RES_HANDLE_P(offset), Z_RES_HANDLE_P(offset));
|
||||
hval = Z_RES_HANDLE_P(offset);
|
||||
} else {
|
||||
zend_error(E_WARNING, "Illegal offset type");
|
||||
}
|
||||
} else if (IS_CONST != IS_CONST &&
|
||||
UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
|
||||
EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) {
|
||||
zval *result = EX_VAR(opline->result.var);
|
||||
zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, offset, BP_VAR_R, result);
|
||||
|
||||
if (retval) {
|
||||
if (result != retval) {
|
||||
ZVAL_COPY(result, retval);
|
||||
}
|
||||
} else {
|
||||
ZVAL_NULL(result);
|
||||
}
|
||||
} else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_TYPE_P(container) == IS_REFERENCE) {
|
||||
container = Z_REFVAL_P(container);
|
||||
goto try_fetch_list;
|
||||
} else {
|
||||
if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
|
||||
GET_OP1_UNDEF_CV(container, BP_VAR_R);
|
||||
}
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
}
|
||||
zval_ptr_dtor_nogc(free_op2);
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@@ -37859,26 +38100,76 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_CV_CONST_HANDL
|
||||
{
|
||||
USE_OPLINE
|
||||
|
||||
|
||||
zval *container;
|
||||
zval *offset = EX_CONSTANT(opline->op2);
|
||||
|
||||
SAVE_OPLINE();
|
||||
container = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
|
||||
|
||||
try_fetch_list:
|
||||
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
||||
zval *value = zend_hash_index_find(Z_ARRVAL_P(container), Z_LVAL_P(EX_CONSTANT(opline->op2)));
|
||||
zval *value;
|
||||
zend_string *str;
|
||||
zend_ulong hval;
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE,"Undefined offset: " ZEND_ULONG_FMT, Z_LVAL_P(EX_CONSTANT(opline->op2)));
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
assign_again_list:
|
||||
if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
||||
hval = Z_LVAL_P(offset);
|
||||
num_index_list:
|
||||
value = zend_hash_index_find(Z_ARRVAL_P(container), hval);
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE, "Undefined offset: " ZEND_ULONG_FMT, hval);
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
|
||||
str = Z_STR_P(offset);
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
||||
goto num_index_list;
|
||||
}
|
||||
|
||||
str_index_list:
|
||||
value = zend_hash_find(Z_ARRVAL_P(container), str);
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(str));
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
}
|
||||
if (UNEXPECTED(str != Z_STR_P(offset))) {
|
||||
zend_string_release(str);
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
|
||||
offset = Z_REFVAL_P(offset);
|
||||
goto assign_again_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_NULL) {
|
||||
str = ZSTR_EMPTY_ALLOC();
|
||||
goto str_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_DOUBLE) {
|
||||
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_FALSE) {
|
||||
hval = 0;
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_TRUE) {
|
||||
hval = 1;
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_RESOURCE) {
|
||||
zend_error(E_NOTICE, "Resource ID#%pd used as offset, casting to integer (%pd)", Z_RES_HANDLE_P(offset), Z_RES_HANDLE_P(offset));
|
||||
hval = Z_RES_HANDLE_P(offset);
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
zend_error(E_WARNING, "Illegal offset type");
|
||||
}
|
||||
} else if (IS_CV != IS_CONST &&
|
||||
UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
|
||||
EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) {
|
||||
zval *result = EX_VAR(opline->result.var);
|
||||
zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, EX_CONSTANT(opline->op2), BP_VAR_R, result);
|
||||
zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, offset, BP_VAR_R, result);
|
||||
|
||||
if (retval) {
|
||||
if (result != retval) {
|
||||
@@ -37896,6 +38187,7 @@ try_fetch_list:
|
||||
}
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
}
|
||||
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
@@ -44238,6 +44530,101 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HAN
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
|
||||
|
||||
zval *container;
|
||||
zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
||||
|
||||
SAVE_OPLINE();
|
||||
container = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
|
||||
|
||||
try_fetch_list:
|
||||
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
||||
zval *value;
|
||||
zend_string *str;
|
||||
zend_ulong hval;
|
||||
|
||||
assign_again_list:
|
||||
if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
||||
hval = Z_LVAL_P(offset);
|
||||
num_index_list:
|
||||
value = zend_hash_index_find(Z_ARRVAL_P(container), hval);
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE, "Undefined offset: " ZEND_ULONG_FMT, hval);
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
|
||||
str = Z_STR_P(offset);
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
||||
goto num_index_list;
|
||||
}
|
||||
|
||||
str_index_list:
|
||||
value = zend_hash_find(Z_ARRVAL_P(container), str);
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(str));
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
}
|
||||
if (UNEXPECTED(str != Z_STR_P(offset))) {
|
||||
zend_string_release(str);
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
|
||||
offset = Z_REFVAL_P(offset);
|
||||
goto assign_again_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_NULL) {
|
||||
str = ZSTR_EMPTY_ALLOC();
|
||||
goto str_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_DOUBLE) {
|
||||
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_FALSE) {
|
||||
hval = 0;
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_TRUE) {
|
||||
hval = 1;
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_RESOURCE) {
|
||||
zend_error(E_NOTICE, "Resource ID#%pd used as offset, casting to integer (%pd)", Z_RES_HANDLE_P(offset), Z_RES_HANDLE_P(offset));
|
||||
hval = Z_RES_HANDLE_P(offset);
|
||||
} else {
|
||||
zend_error(E_WARNING, "Illegal offset type");
|
||||
}
|
||||
} else if (IS_CV != IS_CONST &&
|
||||
UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
|
||||
EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) {
|
||||
zval *result = EX_VAR(opline->result.var);
|
||||
zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, offset, BP_VAR_R, result);
|
||||
|
||||
if (retval) {
|
||||
if (result != retval) {
|
||||
ZVAL_COPY(result, retval);
|
||||
}
|
||||
} else {
|
||||
ZVAL_NULL(result);
|
||||
}
|
||||
} else if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(container) == IS_REFERENCE) {
|
||||
container = Z_REFVAL_P(container);
|
||||
goto try_fetch_list;
|
||||
} else {
|
||||
if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
|
||||
GET_OP1_UNDEF_CV(container, BP_VAR_R);
|
||||
}
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
}
|
||||
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@@ -47793,6 +48180,101 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
|
||||
zend_free_op free_op2;
|
||||
zval *container;
|
||||
zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
||||
|
||||
SAVE_OPLINE();
|
||||
container = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
|
||||
|
||||
try_fetch_list:
|
||||
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
||||
zval *value;
|
||||
zend_string *str;
|
||||
zend_ulong hval;
|
||||
|
||||
assign_again_list:
|
||||
if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
||||
hval = Z_LVAL_P(offset);
|
||||
num_index_list:
|
||||
value = zend_hash_index_find(Z_ARRVAL_P(container), hval);
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE, "Undefined offset: " ZEND_ULONG_FMT, hval);
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
|
||||
str = Z_STR_P(offset);
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
||||
goto num_index_list;
|
||||
}
|
||||
|
||||
str_index_list:
|
||||
value = zend_hash_find(Z_ARRVAL_P(container), str);
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(str));
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
}
|
||||
if (UNEXPECTED(str != Z_STR_P(offset))) {
|
||||
zend_string_release(str);
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
|
||||
offset = Z_REFVAL_P(offset);
|
||||
goto assign_again_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_NULL) {
|
||||
str = ZSTR_EMPTY_ALLOC();
|
||||
goto str_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_DOUBLE) {
|
||||
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_FALSE) {
|
||||
hval = 0;
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_TRUE) {
|
||||
hval = 1;
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_RESOURCE) {
|
||||
zend_error(E_NOTICE, "Resource ID#%pd used as offset, casting to integer (%pd)", Z_RES_HANDLE_P(offset), Z_RES_HANDLE_P(offset));
|
||||
hval = Z_RES_HANDLE_P(offset);
|
||||
} else {
|
||||
zend_error(E_WARNING, "Illegal offset type");
|
||||
}
|
||||
} else if (IS_CV != IS_CONST &&
|
||||
UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
|
||||
EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) {
|
||||
zval *result = EX_VAR(opline->result.var);
|
||||
zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, offset, BP_VAR_R, result);
|
||||
|
||||
if (retval) {
|
||||
if (result != retval) {
|
||||
ZVAL_COPY(result, retval);
|
||||
}
|
||||
} else {
|
||||
ZVAL_NULL(result);
|
||||
}
|
||||
} else if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(container) == IS_REFERENCE) {
|
||||
container = Z_REFVAL_P(container);
|
||||
goto try_fetch_list;
|
||||
} else {
|
||||
if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
|
||||
GET_OP1_UNDEF_CV(container, BP_VAR_R);
|
||||
}
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
}
|
||||
zval_ptr_dtor_nogc(free_op2);
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@@ -51010,26 +51492,76 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_TMPVAR_CONST_H
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1;
|
||||
|
||||
zval *container;
|
||||
zval *offset = EX_CONSTANT(opline->op2);
|
||||
|
||||
SAVE_OPLINE();
|
||||
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
||||
|
||||
try_fetch_list:
|
||||
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
||||
zval *value = zend_hash_index_find(Z_ARRVAL_P(container), Z_LVAL_P(EX_CONSTANT(opline->op2)));
|
||||
zval *value;
|
||||
zend_string *str;
|
||||
zend_ulong hval;
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE,"Undefined offset: " ZEND_ULONG_FMT, Z_LVAL_P(EX_CONSTANT(opline->op2)));
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
assign_again_list:
|
||||
if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
||||
hval = Z_LVAL_P(offset);
|
||||
num_index_list:
|
||||
value = zend_hash_index_find(Z_ARRVAL_P(container), hval);
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE, "Undefined offset: " ZEND_ULONG_FMT, hval);
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
|
||||
str = Z_STR_P(offset);
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
||||
goto num_index_list;
|
||||
}
|
||||
|
||||
str_index_list:
|
||||
value = zend_hash_find(Z_ARRVAL_P(container), str);
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(str));
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
}
|
||||
if (UNEXPECTED(str != Z_STR_P(offset))) {
|
||||
zend_string_release(str);
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
|
||||
offset = Z_REFVAL_P(offset);
|
||||
goto assign_again_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_NULL) {
|
||||
str = ZSTR_EMPTY_ALLOC();
|
||||
goto str_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_DOUBLE) {
|
||||
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_FALSE) {
|
||||
hval = 0;
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_TRUE) {
|
||||
hval = 1;
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_RESOURCE) {
|
||||
zend_error(E_NOTICE, "Resource ID#%pd used as offset, casting to integer (%pd)", Z_RES_HANDLE_P(offset), Z_RES_HANDLE_P(offset));
|
||||
hval = Z_RES_HANDLE_P(offset);
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
zend_error(E_WARNING, "Illegal offset type");
|
||||
}
|
||||
} else if ((IS_TMP_VAR|IS_VAR) != IS_CONST &&
|
||||
UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
|
||||
EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) {
|
||||
zval *result = EX_VAR(opline->result.var);
|
||||
zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, EX_CONSTANT(opline->op2), BP_VAR_R, result);
|
||||
zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, offset, BP_VAR_R, result);
|
||||
|
||||
if (retval) {
|
||||
if (result != retval) {
|
||||
@@ -51047,6 +51579,7 @@ try_fetch_list:
|
||||
}
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
}
|
||||
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
@@ -53295,6 +53828,101 @@ fetch_obj_is_no_object:
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1;
|
||||
|
||||
zval *container;
|
||||
zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
||||
|
||||
SAVE_OPLINE();
|
||||
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
||||
|
||||
try_fetch_list:
|
||||
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
||||
zval *value;
|
||||
zend_string *str;
|
||||
zend_ulong hval;
|
||||
|
||||
assign_again_list:
|
||||
if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
||||
hval = Z_LVAL_P(offset);
|
||||
num_index_list:
|
||||
value = zend_hash_index_find(Z_ARRVAL_P(container), hval);
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE, "Undefined offset: " ZEND_ULONG_FMT, hval);
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
|
||||
str = Z_STR_P(offset);
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
||||
goto num_index_list;
|
||||
}
|
||||
|
||||
str_index_list:
|
||||
value = zend_hash_find(Z_ARRVAL_P(container), str);
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(str));
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
}
|
||||
if (UNEXPECTED(str != Z_STR_P(offset))) {
|
||||
zend_string_release(str);
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
|
||||
offset = Z_REFVAL_P(offset);
|
||||
goto assign_again_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_NULL) {
|
||||
str = ZSTR_EMPTY_ALLOC();
|
||||
goto str_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_DOUBLE) {
|
||||
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_FALSE) {
|
||||
hval = 0;
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_TRUE) {
|
||||
hval = 1;
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_RESOURCE) {
|
||||
zend_error(E_NOTICE, "Resource ID#%pd used as offset, casting to integer (%pd)", Z_RES_HANDLE_P(offset), Z_RES_HANDLE_P(offset));
|
||||
hval = Z_RES_HANDLE_P(offset);
|
||||
} else {
|
||||
zend_error(E_WARNING, "Illegal offset type");
|
||||
}
|
||||
} else if ((IS_TMP_VAR|IS_VAR) != IS_CONST &&
|
||||
UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
|
||||
EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) {
|
||||
zval *result = EX_VAR(opline->result.var);
|
||||
zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, offset, BP_VAR_R, result);
|
||||
|
||||
if (retval) {
|
||||
if (result != retval) {
|
||||
ZVAL_COPY(result, retval);
|
||||
}
|
||||
} else {
|
||||
ZVAL_NULL(result);
|
||||
}
|
||||
} else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(container) == IS_REFERENCE) {
|
||||
container = Z_REFVAL_P(container);
|
||||
goto try_fetch_list;
|
||||
} else {
|
||||
if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
|
||||
GET_OP1_UNDEF_CV(container, BP_VAR_R);
|
||||
}
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
}
|
||||
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@@ -54444,6 +55072,101 @@ fetch_obj_is_no_object:
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zend_free_op free_op1;
|
||||
zend_free_op free_op2;
|
||||
zval *container;
|
||||
zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
||||
|
||||
SAVE_OPLINE();
|
||||
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
||||
|
||||
try_fetch_list:
|
||||
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
||||
zval *value;
|
||||
zend_string *str;
|
||||
zend_ulong hval;
|
||||
|
||||
assign_again_list:
|
||||
if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
||||
hval = Z_LVAL_P(offset);
|
||||
num_index_list:
|
||||
value = zend_hash_index_find(Z_ARRVAL_P(container), hval);
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE, "Undefined offset: " ZEND_ULONG_FMT, hval);
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
|
||||
str = Z_STR_P(offset);
|
||||
|
||||
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
||||
goto num_index_list;
|
||||
}
|
||||
|
||||
str_index_list:
|
||||
value = zend_hash_find(Z_ARRVAL_P(container), str);
|
||||
|
||||
if (UNEXPECTED(value == NULL)) {
|
||||
zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(str));
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
} else {
|
||||
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
||||
}
|
||||
if (UNEXPECTED(str != Z_STR_P(offset))) {
|
||||
zend_string_release(str);
|
||||
}
|
||||
} else if (EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
|
||||
offset = Z_REFVAL_P(offset);
|
||||
goto assign_again_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_NULL) {
|
||||
str = ZSTR_EMPTY_ALLOC();
|
||||
goto str_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_DOUBLE) {
|
||||
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_FALSE) {
|
||||
hval = 0;
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_TRUE) {
|
||||
hval = 1;
|
||||
goto num_index_list;
|
||||
} else if (Z_TYPE_P(offset) == IS_RESOURCE) {
|
||||
zend_error(E_NOTICE, "Resource ID#%pd used as offset, casting to integer (%pd)", Z_RES_HANDLE_P(offset), Z_RES_HANDLE_P(offset));
|
||||
hval = Z_RES_HANDLE_P(offset);
|
||||
} else {
|
||||
zend_error(E_WARNING, "Illegal offset type");
|
||||
}
|
||||
} else if ((IS_TMP_VAR|IS_VAR) != IS_CONST &&
|
||||
UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
|
||||
EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) {
|
||||
zval *result = EX_VAR(opline->result.var);
|
||||
zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, offset, BP_VAR_R, result);
|
||||
|
||||
if (retval) {
|
||||
if (result != retval) {
|
||||
ZVAL_COPY(result, retval);
|
||||
}
|
||||
} else {
|
||||
ZVAL_NULL(result);
|
||||
}
|
||||
} else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(container) == IS_REFERENCE) {
|
||||
container = Z_REFVAL_P(container);
|
||||
goto try_fetch_list;
|
||||
} else {
|
||||
if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
|
||||
GET_OP1_UNDEF_CV(container, BP_VAR_R);
|
||||
}
|
||||
ZVAL_NULL(EX_VAR(opline->result.var));
|
||||
}
|
||||
zval_ptr_dtor_nogc(free_op2);
|
||||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
|
||||
}
|
||||
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
@@ -57495,30 +58218,30 @@ void zend_init_opcodes_handlers(void)
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER,
|
||||
ZEND_FETCH_LIST_SPEC_CONST_CONST_HANDLER,
|
||||
ZEND_FETCH_LIST_SPEC_CONST_TMPVAR_HANDLER,
|
||||
ZEND_FETCH_LIST_SPEC_CONST_TMPVAR_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_FETCH_LIST_SPEC_CONST_CV_HANDLER,
|
||||
ZEND_FETCH_LIST_SPEC_TMPVAR_CONST_HANDLER,
|
||||
ZEND_FETCH_LIST_SPEC_TMPVAR_TMPVAR_HANDLER,
|
||||
ZEND_FETCH_LIST_SPEC_TMPVAR_TMPVAR_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_FETCH_LIST_SPEC_TMPVAR_CV_HANDLER,
|
||||
ZEND_FETCH_LIST_SPEC_TMPVAR_CONST_HANDLER,
|
||||
ZEND_FETCH_LIST_SPEC_TMPVAR_TMPVAR_HANDLER,
|
||||
ZEND_FETCH_LIST_SPEC_TMPVAR_TMPVAR_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_FETCH_LIST_SPEC_TMPVAR_CV_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_FETCH_LIST_SPEC_CV_CONST_HANDLER,
|
||||
ZEND_FETCH_LIST_SPEC_CV_TMPVAR_HANDLER,
|
||||
ZEND_FETCH_LIST_SPEC_CV_TMPVAR_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_FETCH_LIST_SPEC_CV_CV_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
|
||||
@@ -307,7 +307,7 @@ static uint32_t zend_vm_opcodes_flags[184] = {
|
||||
0x00010107,
|
||||
0x00000701,
|
||||
0x00000751,
|
||||
0x00000307,
|
||||
0x00000707,
|
||||
0x06000301,
|
||||
0x00000000,
|
||||
0x00000000,
|
||||
|
||||
Reference in New Issue
Block a user