1--TEST--
2Exceptions thrown in operand cleaning must cause leak of return value
3--FILE--
4<?php
5
6try {
7    var_dump(new class {
8        function __toString() { return "a"; }
9        function __destruct() { throw new Exception; }
10    } . "foo");
11} catch (Exception $e) { print "caught Exception 1\n"; }
12
13try {
14    var_dump([0] + [new class {
15        function __destruct() { throw new Exception; }
16    }]);
17} catch (Exception $e) { print "caught Exception 2\n"; }
18
19try {
20    $foo = [0];
21    var_dump($foo += [new class {
22        function __destruct() { throw new Exception; }
23    }]);
24} catch (Exception $e) { print "caught Exception 3\n"; }
25
26try {
27    $foo = (object)["foo" => [0]];
28    var_dump($foo->foo += [new class {
29        function __destruct() { throw new Exception; }
30    }]);
31} catch (Exception $e) { print "caught Exception 4\n"; }
32
33try {
34    $foo = new class {
35        function __get($x) { return [0]; }
36        function __set($x, $y) {}
37    };
38    var_dump($foo->foo += [new class {
39        function __destruct() { throw new Exception; }
40    }]);
41} catch (Exception $e) { print "caught Exception 5\n"; }
42
43try {
44    $foo = new class {
45        public $bar = [0];
46        function &__get($x) { return $this->bar; }
47    };
48    var_dump($foo->foo += [new class {
49        function __destruct() { throw new Exception; }
50    }]);
51} catch (Exception $e) { print "caught Exception 6\n"; }
52
53try {
54    $foo = new class implements ArrayAccess {
55        function offsetGet($x): mixed { return [0]; }
56        function offsetSet($x, $y): void {}
57        function offsetExists($x): bool { return true; }
58        function offsetUnset($x): void {}
59    };
60    var_dump($foo[0] += [new class {
61        function __destruct() { throw new Exception; }
62    }]);
63} catch (Exception $e) { print "caught Exception 7\n"; }
64
65try {
66    $foo = new class implements ArrayAccess {
67        public $foo = [0];
68        function &offsetGet($x): bool { return $this->foo; }
69        function offsetSet($x, $y): void {}
70        function offsetExists($x): bool { return true; }
71        function offsetUnset($x): void {}
72    };
73    var_dump($foo[0] += [new class {
74        function __destruct() { throw new Exception; }
75    }]);
76} catch (Exception $e) { print "caught Exception 8\n"; }
77
78try {
79    var_dump((function() { return new class {
80        public $foo;
81        function __construct() { $this->foo = new stdClass; }
82        function __destruct() { throw new Exception; }
83    }; })()->foo++);
84} catch (Exception $e) { print "caught Exception 9\n"; }
85
86try {
87    var_dump((function() { return new class {
88        function __get($x) { return new stdClass; }
89        function __set($x, $y) {}
90        function __destruct() { throw new Exception; }
91    }; })()->foo++);
92} catch (Exception $e) { print "caught Exception 10\n"; }
93
94try {
95    var_dump((function() { return new class {
96        public $bar;
97        function __construct() { $this->bar = new stdClass; }
98        function &__get($x) { return $this->bar; }
99        function __destruct() { throw new Exception; }
100    }; })()->foo++);
101} catch (Exception $e) { print "caught Exception 11\n"; }
102
103try {
104    var_dump(++(function() { return new class {
105        function __construct() { $this->foo = new stdClass; }
106        function __destruct() { throw new Exception; }
107    }; })()->foo);
108} catch (Exception $e) { print "caught Exception 12\n"; }
109
110try {
111    var_dump(++(function() { return new class {
112        function __get($x) { return new stdClass; }
113        function __set($x, $y) {}
114        function __destruct() { throw new Exception; }
115    }; })()->foo);
116} catch (Exception $e) { print "caught Exception 13\n"; }
117
118try {
119    var_dump(++(function() { return new class {
120        public $bar;
121        function __construct() { $this->bar = new stdClass; }
122        function &__get($x) { return $this->bar; }
123        function __destruct() { throw new Exception; }
124    }; })()->foo);
125} catch (Exception $e) { print "caught Exception 14\n"; }
126
127try {
128    var_dump((function() { return new class implements ArrayAccess {
129        function offsetGet($x): mixed { return [new stdClass]; }
130        function offsetSet($x, $y): void {}
131        function offsetExists($x): bool { return true; }
132        function offsetUnset($x): void {}
133        function __destruct() { throw new Exception; }
134    }; })()[0]++);
135} catch (Exception $e) { print "caught Exception 15\n"; }
136
137try {
138    var_dump(++(function() { return new class implements ArrayAccess {
139        function offsetGet($x): mixed { return [new stdClass]; }
140        function offsetSet($x, $y): void {}
141        function offsetExists($x): bool { return true; }
142        function offsetUnset($x): void {}
143        function __destruct() { throw new Exception; }
144    }; })()[0]);
145} catch (Exception $e) { print "caught Exception 16\n"; }
146
147try {
148    var_dump((new class {
149        public $foo;
150        function __construct() { $this->foo = new stdClass; }
151        function __destruct() { throw new Exception; }
152    })->foo);
153} catch (Exception $e) { print "caught Exception 17\n"; }
154
155try {
156    var_dump((new class {
157        function __get($x) { return new stdClass; }
158        function __set($x, $y) {}
159        function __destruct() { throw new Exception; }
160    })->foo);
161} catch (Exception $e) { print "caught Exception 18\n"; }
162
163try {
164    var_dump((new class implements ArrayAccess {
165        function offsetGet($x): mixed { return [new stdClass]; }
166        function offsetSet($x, $y): void {}
167        function offsetExists($x): bool { return true; }
168        function offsetUnset($x): void {}
169        function __destruct() { throw new Exception; }
170    })[0]);
171} catch (Exception $e) { print "caught Exception 19\n"; }
172
173try {
174    var_dump(isset((new class {
175        public $foo;
176        function __construct() { $this->foo = new stdClass; }
177        function __destruct() { throw new Exception; }
178    })->foo->bar));
179} catch (Exception $e) { print "caught Exception 20\n"; }
180
181try {
182    var_dump(isset((new class {
183        function __get($x) { return new stdClass; }
184        function __set($x, $y) {}
185        function __destruct() { throw new Exception; }
186    })->foo->bar));
187} catch (Exception $e) { print "caught Exception 21\n"; }
188
189try {
190    var_dump(isset((new class implements ArrayAccess {
191        function offsetGet($x): mixed { return [new stdClass]; }
192        function offsetSet($x, $y): void {}
193        function offsetExists($x): bool { return true; }
194        function offsetUnset($x): void {}
195        function __destruct() { throw new Exception; }
196    })[0]->bar));
197} catch (Exception $e) { print "caught Exception 22\n"; }
198
199try {
200    $foo = new class {
201        function __destruct() { throw new Exception; }
202    };
203    var_dump($foo = new stdClass);
204} catch (Exception $e) { print "caught Exception 23\n"; }
205
206try {
207    $foo = [new class {
208        function __destruct() { throw new Exception; }
209    }];
210    var_dump($foo[0] = new stdClass);
211} catch (Exception $e) { print "caught Exception 24\n"; }
212
213try {
214    $foo = (object) ["foo" => new class {
215        function __destruct() { throw new Exception; }
216    }];
217    var_dump($foo->foo = new stdClass);
218} catch (Exception $e) { print "caught Exception 25\n"; }
219
220try {
221    $foo = new class {
222        function __get($x) {}
223        function __set($x, $y) { throw new Exception; }
224    };
225    var_dump($foo->foo = new stdClass);
226} catch (Exception $e) { print "caught Exception 26\n"; }
227
228try {
229    $foo = new class implements ArrayAccess {
230        function offsetGet($x): mixed {}
231        function offsetSet($x, $y): void { throw new Exception; }
232        function offsetExists($x): bool { return true; }
233        function offsetUnset($x): void {}
234    };
235    var_dump($foo[0] = new stdClass);
236} catch (Exception $e) { print "caught Exception 27\n"; }
237
238try {
239    $foo = new class {
240        function __destruct() { throw new Exception; }
241    };
242    $bar = new stdClass;
243    var_dump($foo = &$bar);
244} catch (Exception $e) { print "caught Exception 28\n"; }
245
246try {
247    $f = function() {
248        return new class {
249            function __toString() { return "a"; }
250            function __destruct() { throw new Exception; }
251        };
252    };
253    var_dump("{$f()}foo");
254} catch (Exception $e) { print "caught Exception 29\n"; }
255
256try {
257    $f = function() {
258        return new class {
259            function __toString() { return "a"; }
260            function __destruct() { throw new Exception; }
261        };
262    };
263    var_dump("bar{$f()}foo");
264} catch (Exception $e) { print "caught Exception 30\n"; }
265
266try {
267    var_dump((string) new class {
268        function __toString() { $x = "Z"; return ++$x; }
269        function __destruct() { throw new Exception; }
270    });
271} catch (Exception $e) { print "caught Exception 31\n"; }
272
273try {
274    var_dump(clone (new class {
275        function __clone() { throw new Exception; }
276    }));
277} catch (Exception $e) { print "caught Exception 32\n"; }
278
279?>
280--EXPECTF--
281caught Exception 1
282caught Exception 2
283caught Exception 3
284caught Exception 4
285caught Exception 5
286
287Deprecated: Creation of dynamic property class@anonymous::$foo is deprecated in %s on line %d
288caught Exception 6
289caught Exception 7
290caught Exception 8
291caught Exception 9
292caught Exception 10
293
294Deprecated: Creation of dynamic property class@anonymous::$foo is deprecated in %s on line %d
295caught Exception 11
296
297Deprecated: Creation of dynamic property class@anonymous::$foo is deprecated in %s on line %d
298caught Exception 12
299caught Exception 13
300
301Deprecated: Creation of dynamic property class@anonymous::$foo is deprecated in %s on line %d
302caught Exception 14
303
304Notice: Indirect modification of overloaded element of ArrayAccess@anonymous has no effect in %s on line %d
305caught Exception 15
306
307Notice: Indirect modification of overloaded element of ArrayAccess@anonymous has no effect in %s on line %d
308caught Exception 16
309caught Exception 17
310caught Exception 18
311caught Exception 19
312caught Exception 20
313caught Exception 21
314caught Exception 22
315caught Exception 23
316caught Exception 24
317caught Exception 25
318caught Exception 26
319caught Exception 27
320caught Exception 28
321caught Exception 29
322caught Exception 30
323caught Exception 31
324caught Exception 32
325