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