Coverage Report

Created: 2026-06-02 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/php-src/Zend/zend_ast.c
Line
Count
Source
1
/*
2
   +----------------------------------------------------------------------+
3
   | Zend Engine                                                          |
4
   +----------------------------------------------------------------------+
5
   | Copyright © Zend Technologies Ltd., a subsidiary company of          |
6
   |     Perforce Software, Inc., and Contributors.                       |
7
   +----------------------------------------------------------------------+
8
   | This source file is subject to the Modified BSD License that is      |
9
   | bundled with this package in the file LICENSE, and is available      |
10
   | through the World Wide Web at <https://www.php.net/license/>.        |
11
   |                                                                      |
12
   | SPDX-License-Identifier: BSD-3-Clause                                |
13
   +----------------------------------------------------------------------+
14
   | Authors: Bob Weinand <bwoebi@php.net>                                |
15
   |          Dmitry Stogov <dmitry@php.net>                              |
16
   +----------------------------------------------------------------------+
17
*/
18
19
#include "zend_ast.h"
20
#include "zend_API.h"
21
#include "zend_operators.h"
22
#include "zend_language_parser.h"
23
#include "zend_smart_str.h"
24
#include "zend_exceptions.h"
25
#include "zend_closures.h"
26
#include "zend_constants.h"
27
#include "zend_enum.h"
28
29
ZEND_API zend_ast_process_t zend_ast_process = NULL;
30
31
9.64M
static inline void *zend_ast_alloc(size_t size) {
32
9.64M
  return zend_arena_alloc(&CG(ast_arena), size);
33
9.64M
}
34
35
139k
static inline void *zend_ast_realloc(const void *old, size_t old_size, size_t new_size) {
36
139k
  void *new = zend_ast_alloc(new_size);
37
139k
  memcpy(new, old, old_size);
38
139k
  return new;
39
139k
}
40
41
1.61M
static inline size_t zend_ast_list_size(uint32_t children) {
42
1.61M
  return sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * children;
43
1.61M
}
44
45
47.3k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_znode(const znode *node) {
46
47.3k
  zend_ast_znode *ast;
47
48
47.3k
  ast = zend_ast_alloc(sizeof(zend_ast_znode));
49
47.3k
  ast->kind = ZEND_AST_ZNODE;
50
47.3k
  ast->attr = 0;
51
47.3k
  ast->lineno = CG(zend_lineno);
52
47.3k
  ast->node = *node;
53
47.3k
  return (zend_ast *) ast;
54
47.3k
}
55
56
4.88k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_fcc(zend_ast *args) {
57
4.88k
  zend_ast_fcc *ast;
58
59
4.88k
  ast = zend_ast_alloc(sizeof(zend_ast_fcc));
60
4.88k
  ast->kind = ZEND_AST_CALLABLE_CONVERT;
61
4.88k
  ast->attr = 0;
62
4.88k
  ast->lineno = CG(zend_lineno);
63
4.88k
  ast->args = args;
64
4.88k
  ZEND_MAP_PTR_INIT(ast->fptr, NULL);
65
66
4.88k
  return (zend_ast *) ast;
67
4.88k
}
68
69
3.67M
static zend_always_inline zend_ast * zend_ast_create_zval_int(const zval *zv, uint32_t attr, uint32_t lineno) {
70
3.67M
  zend_ast_zval *ast;
71
72
3.67M
  ast = zend_ast_alloc(sizeof(zend_ast_zval));
73
3.67M
  ast->kind = ZEND_AST_ZVAL;
74
3.67M
  ast->attr = attr;
75
3.67M
  ZVAL_COPY_VALUE(&ast->val, zv);
76
3.67M
  Z_LINENO(ast->val) = lineno;
77
3.67M
  return (zend_ast *) ast;
78
3.67M
}
79
80
3.30M
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_with_lineno(const zval *zv, uint32_t lineno) {
81
3.30M
  return zend_ast_create_zval_int(zv, 0, lineno);
82
3.30M
}
83
84
1.03k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_ex(const zval *zv, zend_ast_attr attr) {
85
1.03k
  return zend_ast_create_zval_int(zv, attr, CG(zend_lineno));
86
1.03k
}
87
88
286k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval(const zval *zv) {
89
286k
  return zend_ast_create_zval_int(zv, 0, CG(zend_lineno));
90
286k
}
91
92
25.6k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_str(zend_string *str) {
93
25.6k
  zval zv;
94
25.6k
  ZVAL_STR(&zv, str);
95
25.6k
  return zend_ast_create_zval_int(&zv, 0, CG(zend_lineno));
96
25.6k
}
97
98
56.4k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_long(zend_long lval) {
99
56.4k
  zval zv;
100
56.4k
  ZVAL_LONG(&zv, lval);
101
56.4k
  return zend_ast_create_zval_int(&zv, 0, CG(zend_lineno));
102
56.4k
}
103
104
22.2k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_constant(zend_string *name, zend_ast_attr attr) {
105
22.2k
  zend_ast_zval *ast;
106
107
22.2k
  ast = zend_ast_alloc(sizeof(zend_ast_zval));
108
22.2k
  ast->kind = ZEND_AST_CONSTANT;
109
22.2k
  ast->attr = attr;
110
22.2k
  ZVAL_STR(&ast->val, name);
111
22.2k
  Z_LINENO(ast->val) = CG(zend_lineno);
112
22.2k
  return (zend_ast *) ast;
113
22.2k
}
114
115
143
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_op_array(zend_op_array *op_array) {
116
143
  zend_ast_op_array *ast;
117
118
143
  ast = zend_ast_alloc(sizeof(zend_ast_op_array));
119
143
  ast->kind = ZEND_AST_OP_ARRAY;
120
143
  ast->attr = 0;
121
143
  ast->lineno = CG(zend_lineno);
122
143
  ast->op_array = op_array;
123
124
143
  return (zend_ast *) ast;
125
143
}
126
127
34.3k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_class_const_or_name(zend_ast *class_name, zend_ast *name) {
128
34.3k
  zend_string *name_str = zend_ast_get_str(name);
129
34.3k
  if (zend_string_equals_ci(name_str, ZSTR_KNOWN(ZEND_STR_CLASS))) {
130
7.44k
    zend_string_release(name_str);
131
7.44k
    return zend_ast_create(ZEND_AST_CLASS_NAME, class_name);
132
26.9k
  } else {
133
26.9k
    return zend_ast_create(ZEND_AST_CLASS_CONST, class_name, name);
134
26.9k
  }
135
34.3k
}
136
137
ZEND_API zend_ast *zend_ast_create_decl(
138
  zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment,
139
  zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2, zend_ast *child3, zend_ast *child4
140
136k
) {
141
136k
  zend_ast_decl *ast;
142
143
136k
  ast = zend_ast_alloc(sizeof(zend_ast_decl));
144
136k
  ast->kind = kind;
145
136k
  ast->attr = 0;
146
136k
  ast->start_lineno = start_lineno;
147
136k
  ast->end_lineno = CG(zend_lineno);
148
136k
  ast->flags = flags;
149
136k
  ast->doc_comment = doc_comment;
150
136k
  ast->name = name;
151
136k
  ast->child[0] = child0;
152
136k
  ast->child[1] = child1;
153
136k
  ast->child[2] = child2;
154
136k
  ast->child[3] = child3;
155
136k
  ast->child[4] = child4;
156
157
136k
  return (zend_ast *) ast;
158
136k
}
159
160
370k
static bool zend_ast_is_placeholder_arg(zend_ast *arg) {
161
370k
  return arg->kind == ZEND_AST_PLACEHOLDER_ARG
162
366k
    || (arg->kind == ZEND_AST_NAMED_ARG
163
10.6k
        && arg->child[1]->kind == ZEND_AST_PLACEHOLDER_ARG);
164
370k
}
165
166
#if ZEND_AST_SPEC
167
28.0k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_0(zend_ast_kind kind) {
168
28.0k
  zend_ast *ast;
169
170
28.0k
  ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 0);
171
28.0k
  ast = zend_ast_alloc(zend_ast_size(0));
172
28.0k
  ast->kind = kind;
173
28.0k
  ast->attr = 0;
174
28.0k
  ast->lineno = CG(zend_lineno);
175
176
28.0k
  return ast;
177
28.0k
}
178
179
2.15M
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_1(zend_ast_kind kind, zend_ast *child) {
180
2.15M
  zend_ast *ast;
181
2.15M
  uint32_t lineno;
182
183
2.15M
  ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 1);
184
2.15M
  ast = zend_ast_alloc(zend_ast_size(1));
185
2.15M
  ast->kind = kind;
186
2.15M
  ast->attr = 0;
187
2.15M
  ast->child[0] = child;
188
2.15M
  if (child) {
189
2.14M
    lineno = zend_ast_get_lineno(child);
190
2.14M
  } else {
191
2.90k
    lineno = CG(zend_lineno);
192
2.90k
  }
193
2.15M
  ast->lineno = lineno;
194
195
2.15M
  return ast;
196
2.15M
}
197
198
1.80M
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_2(zend_ast_kind kind, zend_ast *child1, zend_ast *child2) {
199
1.80M
  zend_ast *ast;
200
1.80M
  uint32_t lineno;
201
202
1.80M
  ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 2);
203
1.80M
  ast = zend_ast_alloc(zend_ast_size(2));
204
1.80M
  ast->kind = kind;
205
1.80M
  ast->attr = 0;
206
1.80M
  ast->child[0] = child1;
207
1.80M
  ast->child[1] = child2;
208
1.80M
  if (child1) {
209
1.79M
    lineno = zend_ast_get_lineno(child1);
210
1.79M
  } else if (child2) {
211
5.86k
    lineno = zend_ast_get_lineno(child2);
212
5.86k
  } else {
213
2.35k
    lineno = CG(zend_lineno);
214
2.35k
  }
215
1.80M
  ast->lineno = lineno;
216
217
1.80M
  return ast;
218
1.80M
}
219
220
171k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_3(zend_ast_kind kind, zend_ast *child1, zend_ast *child2, zend_ast *child3) {
221
171k
  zend_ast *ast;
222
171k
  uint32_t lineno;
223
224
171k
  ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 3);
225
171k
  ast = zend_ast_alloc(zend_ast_size(3));
226
171k
  ast->kind = kind;
227
171k
  ast->attr = 0;
228
171k
  ast->child[0] = child1;
229
171k
  ast->child[1] = child2;
230
171k
  ast->child[2] = child3;
231
171k
  if (child1) {
232
157k
    lineno = zend_ast_get_lineno(child1);
233
157k
  } else if (child2) {
234
13.7k
    lineno = zend_ast_get_lineno(child2);
235
13.7k
  } else if (child3) {
236
0
    lineno = zend_ast_get_lineno(child3);
237
0
  } else {
238
0
    lineno = CG(zend_lineno);
239
0
  }
240
171k
  ast->lineno = lineno;
241
242
171k
  return ast;
243
171k
}
244
245
81.4k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_4(zend_ast_kind kind, zend_ast *child1, zend_ast *child2, zend_ast *child3, zend_ast *child4) {
246
81.4k
  zend_ast *ast;
247
81.4k
  uint32_t lineno;
248
249
81.4k
  ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 4);
250
81.4k
  ast = zend_ast_alloc(zend_ast_size(4));
251
81.4k
  ast->kind = kind;
252
81.4k
  ast->attr = 0;
253
81.4k
  ast->child[0] = child1;
254
81.4k
  ast->child[1] = child2;
255
81.4k
  ast->child[2] = child3;
256
81.4k
  ast->child[3] = child4;
257
81.4k
  if (child1) {
258
77.8k
    lineno = zend_ast_get_lineno(child1);
259
77.8k
  } else if (child2) {
260
1.66k
    lineno = zend_ast_get_lineno(child2);
261
1.97k
  } else if (child3) {
262
509
    lineno = zend_ast_get_lineno(child3);
263
1.47k
  } else if (child4) {
264
1.33k
    lineno = zend_ast_get_lineno(child4);
265
1.33k
  } else {
266
138
    lineno = CG(zend_lineno);
267
138
  }
268
81.4k
  ast->lineno = lineno;
269
270
81.4k
  return ast;
271
81.4k
}
272
273
0
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_5(zend_ast_kind kind, zend_ast *child1, zend_ast *child2, zend_ast *child3, zend_ast *child4, zend_ast *child5) {
274
0
  zend_ast *ast;
275
0
  uint32_t lineno;
276
277
0
  ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 5);
278
0
  ast = zend_ast_alloc(zend_ast_size(5));
279
0
  ast->kind = kind;
280
0
  ast->attr = 0;
281
0
  ast->child[0] = child1;
282
0
  ast->child[1] = child2;
283
0
  ast->child[2] = child3;
284
0
  ast->child[3] = child4;
285
0
  ast->child[4] = child5;
286
0
  if (child1) {
287
0
    lineno = zend_ast_get_lineno(child1);
288
0
  } else if (child2) {
289
0
    lineno = zend_ast_get_lineno(child2);
290
0
  } else if (child3) {
291
0
    lineno = zend_ast_get_lineno(child3);
292
0
  } else if (child4) {
293
0
    lineno = zend_ast_get_lineno(child4);
294
0
  } else if (child5) {
295
0
    lineno = zend_ast_get_lineno(child5);
296
0
  } else {
297
0
    lineno = CG(zend_lineno);
298
0
  }
299
0
  ast->lineno = lineno;
300
301
0
  return ast;
302
0
}
303
304
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_va(
305
51.3k
    zend_ast_kind kind, zend_ast_attr attr, va_list *va) {
306
51.3k
  uint32_t lineno = (uint32_t)-1;
307
51.3k
  uint32_t children = kind >> ZEND_AST_NUM_CHILDREN_SHIFT;
308
51.3k
  zend_ast *ast = zend_ast_alloc(zend_ast_size(children));
309
51.3k
  ast->kind = kind;
310
51.3k
  ast->attr = attr;
311
359k
  for (uint32_t i = 0; i < children; i++) {
312
308k
    ast->child[i] = va_arg(*va, zend_ast *);
313
308k
    if (lineno == (uint32_t)-1 && ast->child[i]) {
314
51.3k
      lineno = zend_ast_get_lineno(ast->child[i]);
315
51.3k
    }
316
308k
  }
317
51.3k
  if (lineno == (uint32_t)-1) {
318
0
    lineno = CG(zend_lineno);
319
0
  }
320
51.3k
  ast->lineno = lineno;
321
51.3k
  return ast;
322
51.3k
}
323
324
1.43k
ZEND_API zend_ast * zend_ast_create_n(unsigned kind, ...) {
325
1.43k
  va_list va;
326
1.43k
  va_start(va, kind);
327
1.43k
  zend_ast *ast = zend_ast_create_va(kind, 0, &va);
328
1.43k
  va_end(va);
329
1.43k
  return ast;
330
1.43k
}
331
332
ZEND_API zend_ast * zend_ast_create_ex_n(
333
49.9k
    zend_ast_kind kind, unsigned attr, ...) {
334
49.9k
  va_list va;
335
49.9k
  va_start(va, attr);
336
49.9k
  zend_ast *ast = zend_ast_create_va(kind, attr, &va);
337
49.9k
  va_end(va);
338
49.9k
  return ast;
339
49.9k
}
340
341
556k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_0(zend_ast_kind kind) {
342
556k
  zend_ast *ast;
343
556k
  zend_ast_list *list;
344
345
556k
  ast = zend_ast_alloc(zend_ast_list_size(4));
346
556k
  list = (zend_ast_list *) ast;
347
556k
  list->kind = kind;
348
556k
  list->attr = 0;
349
556k
  list->lineno = CG(zend_lineno);
350
556k
  list->children = 0;
351
352
556k
  return ast;
353
556k
}
354
355
728k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_1(zend_ast_kind kind, zend_ast *child) {
356
728k
  zend_ast *ast;
357
728k
  zend_ast_list *list;
358
728k
  uint32_t lineno;
359
360
728k
  ast = zend_ast_alloc(zend_ast_list_size(4));
361
728k
  list = (zend_ast_list *) ast;
362
728k
  list->kind = kind;
363
728k
  list->attr = 0;
364
728k
  list->children = 1;
365
728k
  list->child[0] = child;
366
728k
  if (child) {
367
710k
    lineno = zend_ast_get_lineno(child);
368
710k
    if (lineno > CG(zend_lineno)) {
369
170
      lineno = CG(zend_lineno);
370
170
    }
371
710k
  } else {
372
17.9k
    lineno = CG(zend_lineno);
373
17.9k
  }
374
728k
  list->lineno = lineno;
375
376
728k
  return ast;
377
728k
}
378
379
43.2k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_2(zend_ast_kind kind, zend_ast *child1, zend_ast *child2) {
380
43.2k
  zend_ast *ast;
381
43.2k
  zend_ast_list *list;
382
43.2k
  uint32_t lineno;
383
384
43.2k
  ast = zend_ast_alloc(zend_ast_list_size(4));
385
43.2k
  list = (zend_ast_list *) ast;
386
43.2k
  list->kind = kind;
387
43.2k
  list->attr = 0;
388
43.2k
  list->children = 2;
389
43.2k
  list->child[0] = child1;
390
43.2k
  list->child[1] = child2;
391
43.2k
  if (child1) {
392
43.2k
    lineno = zend_ast_get_lineno(child1);
393
43.2k
    if (lineno > CG(zend_lineno)) {
394
0
      lineno = CG(zend_lineno);
395
0
    }
396
43.2k
  } else if (child2) {
397
0
    lineno = zend_ast_get_lineno(child2);
398
0
    if (lineno > CG(zend_lineno)) {
399
0
      lineno = CG(zend_lineno);
400
0
    }
401
0
  } else {
402
0
    list->children = 0;
403
0
    lineno = CG(zend_lineno);
404
0
  }
405
43.2k
  list->lineno = lineno;
406
407
43.2k
  return ast;
408
43.2k
}
409
410
81.8k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_arg_list_0(zend_ast_kind kind) {
411
81.8k
  return zend_ast_create_list(0, kind);
412
81.8k
}
413
414
251k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_arg_list_1(zend_ast_kind kind, zend_ast *arg) {
415
251k
  zend_ast *list = zend_ast_create_list(1, kind, arg);
416
417
251k
  if (zend_ast_is_placeholder_arg(arg)) {
418
4.41k
    return zend_ast_create_fcc(list);
419
4.41k
  }
420
421
247k
  return list;
422
251k
}
423
424
559
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_arg_list_2(zend_ast_kind kind, zend_ast *arg1, zend_ast *arg2) {
425
559
  zend_ast *list = zend_ast_create_list(2, kind, arg1, arg2);
426
427
559
  if (zend_ast_is_placeholder_arg(arg1) || zend_ast_is_placeholder_arg(arg2)) {
428
111
    return zend_ast_create_fcc(list);
429
111
  }
430
431
448
  return list;
432
559
}
433
#else
434
static zend_ast *zend_ast_create_from_va_list(zend_ast_kind kind, zend_ast_attr attr, va_list va) {
435
  uint32_t i, children = kind >> ZEND_AST_NUM_CHILDREN_SHIFT;
436
  zend_ast *ast;
437
438
  ast = zend_ast_alloc(zend_ast_size(children));
439
  ast->kind = kind;
440
  ast->attr = attr;
441
  ast->lineno = (uint32_t) -1;
442
443
  for (i = 0; i < children; ++i) {
444
    ast->child[i] = va_arg(va, zend_ast *);
445
    if (ast->child[i] != NULL) {
446
      uint32_t lineno = zend_ast_get_lineno(ast->child[i]);
447
      if (lineno < ast->lineno) {
448
        ast->lineno = lineno;
449
      }
450
    }
451
  }
452
453
  if (ast->lineno == UINT_MAX) {
454
    ast->lineno = CG(zend_lineno);
455
  }
456
457
  return ast;
458
}
459
460
ZEND_API zend_ast *zend_ast_create_ex(zend_ast_kind kind, zend_ast_attr attr, ...) {
461
  va_list va;
462
  zend_ast *ast;
463
464
  va_start(va, attr);
465
  ast = zend_ast_create_from_va_list(kind, attr, va);
466
  va_end(va);
467
468
  return ast;
469
}
470
471
ZEND_API zend_ast *zend_ast_create(zend_ast_kind kind, ...) {
472
  va_list va;
473
  zend_ast *ast;
474
475
  va_start(va, kind);
476
  ast = zend_ast_create_from_va_list(kind, 0, va);
477
  va_end(va);
478
479
  return ast;
480
}
481
482
ZEND_API zend_ast *zend_ast_create_list(uint32_t init_children, zend_ast_kind kind, ...) {
483
  zend_ast *ast;
484
  zend_ast_list *list;
485
486
  ast = zend_ast_alloc(zend_ast_list_size(4));
487
  list = (zend_ast_list *) ast;
488
  list->kind = kind;
489
  list->attr = 0;
490
  list->lineno = CG(zend_lineno);
491
  list->children = 0;
492
493
  {
494
    va_list va;
495
    uint32_t i;
496
    va_start(va, kind);
497
    for (i = 0; i < init_children; ++i) {
498
      zend_ast *child = va_arg(va, zend_ast *);
499
      ast = zend_ast_list_add(ast, child);
500
      if (child != NULL) {
501
        uint32_t lineno = zend_ast_get_lineno(child);
502
        if (lineno < ast->lineno) {
503
          ast->lineno = lineno;
504
        }
505
      }
506
    }
507
    va_end(va);
508
  }
509
510
  return ast;
511
}
512
513
ZEND_API zend_ast *zend_ast_create_arg_list(uint32_t init_children, zend_ast_kind kind, ...) {
514
  zend_ast *ast;
515
  zend_ast_list *list;
516
  bool has_placeholders = false;
517
518
  ast = zend_ast_alloc(zend_ast_list_size(4));
519
  list = (zend_ast_list *) ast;
520
  list->kind = kind;
521
  list->attr = 0;
522
  list->lineno = CG(zend_lineno);
523
  list->children = 0;
524
525
  {
526
    va_list va;
527
    uint32_t i;
528
    va_start(va, kind);
529
    for (i = 0; i < init_children; ++i) {
530
      zend_ast *child = va_arg(va, zend_ast *);
531
      ast = zend_ast_list_add(ast, child);
532
      uint32_t lineno = zend_ast_get_lineno(child);
533
      if (lineno < ast->lineno) {
534
        ast->lineno = lineno;
535
      }
536
      has_placeholders = has_placeholders || zend_ast_is_placeholder_arg(child);
537
    }
538
    va_end(va);
539
  }
540
541
  if (has_placeholders) {
542
    return zend_ast_create_fcc(list);
543
  }
544
545
  return ast;
546
}
547
#endif
548
549
91.3k
zend_ast *zend_ast_create_concat_op(zend_ast *op0, zend_ast *op1) {
550
91.3k
  if (op0->kind == ZEND_AST_ZVAL && op1->kind == ZEND_AST_ZVAL) {
551
21.3k
    zval *zv0 = zend_ast_get_zval(op0);
552
21.3k
    zval *zv1 = zend_ast_get_zval(op1);
553
21.3k
    if (!zend_binary_op_produces_error(ZEND_CONCAT, zv0, zv1) &&
554
21.3k
        concat_function(zv0, zv0, zv1) == SUCCESS) {
555
21.3k
      zval_ptr_dtor_nogc(zv1);
556
21.3k
      return zend_ast_create_zval(zv0);
557
21.3k
    }
558
21.3k
  }
559
70.0k
  return zend_ast_create_binary_op(ZEND_CONCAT, op0, op1);
560
91.3k
}
561
562
1.03M
static inline bool is_power_of_two(uint32_t n) {
563
1.03M
  return ((n != 0) && (n == (n & (~n + 1))));
564
1.03M
}
565
566
1.90M
ZEND_ATTRIBUTE_NODISCARD ZEND_API zend_ast * ZEND_FASTCALL zend_ast_list_add(zend_ast *ast, zend_ast *op) {
567
1.90M
  zend_ast_list *list = zend_ast_get_list(ast);
568
1.90M
  if (list->children >= 4 && is_power_of_two(list->children)) {
569
139k
      list = zend_ast_realloc(list,
570
139k
      zend_ast_list_size(list->children), zend_ast_list_size(list->children * 2));
571
139k
  }
572
1.90M
  list->child[list->children++] = op;
573
1.90M
  return (zend_ast *) list;
574
1.90M
}
575
576
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_arg_list_add(zend_ast *list, zend_ast *arg)
577
118k
{
578
118k
  if (list->kind == ZEND_AST_CALLABLE_CONVERT) {
579
544
    zend_ast_fcc *fcc_ast = (zend_ast_fcc*)list;
580
544
    fcc_ast->args = zend_ast_list_add(fcc_ast->args, arg);
581
544
    return (zend_ast*)fcc_ast;
582
544
  }
583
584
118k
  ZEND_ASSERT(list->kind == ZEND_AST_ARG_LIST);
585
586
118k
  if (zend_ast_is_placeholder_arg(arg)) {
587
365
    return zend_ast_create_fcc(zend_ast_list_add(list, arg));
588
365
  }
589
590
117k
  return zend_ast_list_add(list, arg);
591
118k
}
592
593
static zend_result zend_ast_add_array_element(const zval *result, zval *offset, zval *expr)
594
487
{
595
487
  if (Z_TYPE_P(offset) == IS_UNDEF) {
596
117
    if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), expr)) {
597
5
      zend_throw_error(NULL,
598
5
        "Cannot add element to the array as the next element is already occupied");
599
5
      return FAILURE;
600
5
    }
601
112
    return SUCCESS;
602
117
  }
603
604
370
  if (array_set_zval_key(Z_ARRVAL_P(result), offset, expr) == FAILURE) {
605
8
    return FAILURE;
606
8
  }
607
608
362
  zval_ptr_dtor_nogc(offset);
609
362
  zval_ptr_dtor_nogc(expr);
610
362
  return SUCCESS;
611
370
}
612
613
23
static zend_result zend_ast_add_unpacked_element(const zval *result, const zval *expr) {
614
23
  if (EXPECTED(Z_TYPE_P(expr) == IS_ARRAY)) {
615
18
    const HashTable *ht = Z_ARRVAL_P(expr);
616
18
    zval *val;
617
18
    zend_string *key;
618
619
104
    ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) {
620
104
      if (key) {
621
0
        zend_hash_update(Z_ARRVAL_P(result), key, val);
622
43
      } else {
623
43
        if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), val)) {
624
8
          zend_throw_error(NULL,
625
8
            "Cannot add element to the array as the next element is already occupied");
626
8
          return FAILURE;
627
8
        }
628
43
      }
629
35
      Z_TRY_ADDREF_P(val);
630
35
    } ZEND_HASH_FOREACH_END();
631
10
    return SUCCESS;
632
18
  }
633
634
5
  zend_throw_error(NULL, "Only arrays can be unpacked in constant expression");
635
5
  return FAILURE;
636
23
}
637
638
static zend_class_entry *zend_ast_fetch_class(zend_ast *ast, zend_class_entry *scope)
639
552
{
640
552
  return zend_fetch_class_with_scope(zend_ast_get_str(ast), (ast->attr >> ZEND_CONST_EXPR_NEW_FETCH_TYPE_SHIFT) | ZEND_FETCH_CLASS_EXCEPTION, scope);
641
552
}
642
643
static zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
644
  zval *result,
645
  zend_ast *ast,
646
  zend_class_entry *scope,
647
  bool *short_circuited_ptr,
648
  zend_ast_evaluate_ctx *ctx
649
);
650
651
ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_ex(
652
  zval *result,
653
  zend_ast *ast,
654
  zend_class_entry *scope,
655
  bool *short_circuited_ptr,
656
  zend_ast_evaluate_ctx *ctx
657
10.4k
) {
658
10.4k
  zend_string *previous_filename;
659
10.4k
  zend_long previous_lineno;
660
10.4k
  if (scope) {
661
7.04k
    previous_filename = EG(filename_override);
662
7.04k
    previous_lineno = EG(lineno_override);
663
7.04k
    EG(filename_override) = scope->info.user.filename;
664
7.04k
    EG(lineno_override) = zend_ast_get_lineno(ast);
665
7.04k
  }
666
10.4k
  zend_result r = zend_ast_evaluate_inner(result, ast, scope, short_circuited_ptr, ctx);
667
10.4k
  if (scope) {
668
7.03k
    EG(filename_override) = previous_filename;
669
7.03k
    EG(lineno_override) = previous_lineno;
670
7.03k
  }
671
10.4k
  return r;
672
10.4k
}
673
674
static zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
675
  zval *result,
676
  zend_ast *ast,
677
  zend_class_entry *scope,
678
  bool *short_circuited_ptr,
679
  zend_ast_evaluate_ctx *ctx
680
10.4k
) {
681
10.4k
  zval op1, op2;
682
10.4k
  zend_result ret = SUCCESS;
683
10.4k
  bool short_circuited;
684
10.4k
  *short_circuited_ptr = false;
685
686
10.4k
  switch (ast->kind) {
687
467
    case ZEND_AST_BINARY_OP:
688
467
      if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
689
43
        ret = FAILURE;
690
424
      } else if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
691
18
        zval_ptr_dtor_nogc(&op1);
692
18
        ret = FAILURE;
693
406
      } else {
694
406
        binary_op_type op = get_binary_op(ast->attr);
695
406
        op(result, &op1, &op2);
696
406
        zval_ptr_dtor_nogc(&op1);
697
406
        zval_ptr_dtor_nogc(&op2);
698
406
        ret = EG(exception) ? FAILURE : SUCCESS;
699
406
      }
700
467
      break;
701
21
    case ZEND_AST_GREATER:
702
30
    case ZEND_AST_GREATER_EQUAL:
703
30
      if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
704
0
        ret = FAILURE;
705
30
      } else if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
706
5
        zval_ptr_dtor_nogc(&op1);
707
5
        ret = FAILURE;
708
25
      } else {
709
        /* op1 > op2 is the same as op2 < op1 */
710
25
        binary_op_type op = ast->kind == ZEND_AST_GREATER
711
25
          ? is_smaller_function : is_smaller_or_equal_function;
712
25
        op(result, &op2, &op1);
713
25
        zval_ptr_dtor_nogc(&op1);
714
25
        zval_ptr_dtor_nogc(&op2);
715
25
        ret = EG(exception) ? FAILURE : SUCCESS;
716
25
      }
717
30
      break;
718
22
    case ZEND_AST_UNARY_OP:
719
22
      if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
720
3
        ret = FAILURE;
721
19
      } else {
722
19
        unary_op_type op = get_unary_op(ast->attr);
723
19
        ret = op(result, &op1);
724
19
        zval_ptr_dtor_nogc(&op1);
725
19
      }
726
22
      break;
727
3.70k
    case ZEND_AST_ZVAL:
728
3.70k
    {
729
3.70k
      zval *zv = zend_ast_get_zval(ast);
730
731
3.70k
      ZVAL_COPY(result, zv);
732
3.70k
      break;
733
21
    }
734
957
    case ZEND_AST_CONSTANT:
735
957
    {
736
957
      zend_string *name = zend_ast_get_constant_name(ast);
737
957
      zval *zv = zend_get_constant_ex(name, scope, ast->attr);
738
739
957
      if (UNEXPECTED(zv == NULL)) {
740
148
        ZVAL_UNDEF(result);
741
148
        return FAILURE;
742
148
      }
743
809
      ZVAL_COPY_OR_DUP(result, zv);
744
809
      break;
745
957
    }
746
20
    case ZEND_AST_CONSTANT_CLASS:
747
20
      if (scope) {
748
20
        ZVAL_STR_COPY(result, scope->name);
749
20
      } else {
750
0
        ZVAL_EMPTY_STRING(result);
751
0
      }
752
20
      break;
753
69
    case ZEND_AST_CLASS_NAME:
754
69
      if (!scope) {
755
5
        zend_throw_error(NULL, "Cannot use \"self\" when no class scope is active");
756
5
        return FAILURE;
757
5
      }
758
64
      if (ast->attr == ZEND_FETCH_CLASS_SELF) {
759
64
        ZVAL_STR_COPY(result, scope->name);
760
64
      } else if (ast->attr == ZEND_FETCH_CLASS_PARENT) {
761
0
        if (!scope->parent) {
762
0
          zend_throw_error(NULL,
763
0
            "Cannot use \"parent\" when current class scope has no parent");
764
0
          return FAILURE;
765
0
        }
766
0
        ZVAL_STR_COPY(result, scope->parent->name);
767
0
      } else {
768
0
        ZEND_ASSERT(0 && "Should have errored during compilation");
769
0
      }
770
64
      break;
771
64
    case ZEND_AST_AND:
772
31
      if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
773
0
        ret = FAILURE;
774
0
        break;
775
0
      }
776
31
      if (zend_is_true(&op1)) {
777
22
        if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
778
5
          zval_ptr_dtor_nogc(&op1);
779
5
          ret = FAILURE;
780
5
          break;
781
5
        }
782
17
        ZVAL_BOOL(result, zend_is_true(&op2));
783
17
        zval_ptr_dtor_nogc(&op2);
784
17
      } else {
785
9
        ZVAL_FALSE(result);
786
9
      }
787
26
      zval_ptr_dtor_nogc(&op1);
788
26
      break;
789
114
    case ZEND_AST_CAST:
790
114
      if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
791
3
        ret = FAILURE;
792
3
        break;
793
3
      }
794
111
      if (ast->attr == Z_TYPE(op1)) {
795
0
        ZVAL_COPY_VALUE(result, &op1);
796
111
      } else {
797
111
        switch (ast->attr) {
798
8
          case _IS_BOOL:
799
8
            ZVAL_BOOL(result, zend_is_true(&op1));
800
8
            break;
801
21
          case IS_LONG:
802
21
            ZVAL_LONG(result, zval_get_long_func(&op1, false));
803
21
            break;
804
5
          case IS_DOUBLE:
805
5
            ZVAL_DOUBLE(result, zval_get_double_func(&op1));
806
5
            break;
807
18
          case IS_STRING:
808
18
            ZVAL_STR(result, zval_get_string_func(&op1));
809
18
            break;
810
44
          case IS_ARRAY:
811
44
            zend_cast_zval_to_array(result, &op1, IS_VAR);
812
44
            break;
813
15
          case IS_OBJECT:
814
15
            zend_cast_zval_to_object(result, &op1, IS_VAR);
815
15
            break;
816
0
          default: ZEND_UNREACHABLE();
817
111
        }
818
111
        zval_ptr_dtor_nogc(&op1);
819
111
        if (UNEXPECTED(EG(exception))) {
820
0
          ret = FAILURE;
821
0
        }
822
111
      }
823
111
      break;
824
111
    case ZEND_AST_OR:
825
20
      if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
826
2
        ret = FAILURE;
827
2
        break;
828
2
      }
829
18
      if (zend_is_true(&op1)) {
830
9
        ZVAL_TRUE(result);
831
9
      } else {
832
9
        if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
833
0
          zval_ptr_dtor_nogc(&op1);
834
0
          ret = FAILURE;
835
0
          break;
836
0
        }
837
9
        ZVAL_BOOL(result, zend_is_true(&op2));
838
9
        zval_ptr_dtor_nogc(&op2);
839
9
      }
840
18
      zval_ptr_dtor_nogc(&op1);
841
18
      break;
842
62
    case ZEND_AST_CONDITIONAL:
843
62
      if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
844
0
        ret = FAILURE;
845
0
        break;
846
0
      }
847
62
      if (zend_is_true(&op1)) {
848
44
        if (!ast->child[1]) {
849
17
          *result = op1;
850
27
        } else {
851
27
          if (UNEXPECTED(zend_ast_evaluate_ex(result, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
852
3
            zval_ptr_dtor_nogc(&op1);
853
3
            ret = FAILURE;
854
3
            break;
855
3
          }
856
24
          zval_ptr_dtor_nogc(&op1);
857
24
        }
858
44
      } else {
859
18
        if (UNEXPECTED(zend_ast_evaluate_ex(result, ast->child[2], scope, &short_circuited, ctx) != SUCCESS)) {
860
0
          zval_ptr_dtor_nogc(&op1);
861
0
          ret = FAILURE;
862
0
          break;
863
0
        }
864
18
        zval_ptr_dtor_nogc(&op1);
865
18
      }
866
59
      break;
867
64
    case ZEND_AST_COALESCE:
868
64
      if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
869
0
        ret = FAILURE;
870
0
        break;
871
0
      }
872
64
      if (Z_TYPE(op1) > IS_NULL) {
873
0
        *result = op1;
874
64
      } else {
875
64
        if (UNEXPECTED(zend_ast_evaluate_ex(result, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
876
0
          zval_ptr_dtor_nogc(&op1);
877
0
          ret = FAILURE;
878
0
          break;
879
0
        }
880
64
        zval_ptr_dtor_nogc(&op1);
881
64
      }
882
64
      break;
883
64
    case ZEND_AST_UNARY_PLUS:
884
23
      if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
885
0
        ret = FAILURE;
886
23
      } else {
887
23
        ZVAL_LONG(&op1, 0);
888
23
        ret = add_function(result, &op1, &op2);
889
23
        zval_ptr_dtor_nogc(&op2);
890
23
      }
891
23
      break;
892
19
    case ZEND_AST_UNARY_MINUS:
893
19
      if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
894
6
        ret = FAILURE;
895
13
      } else {
896
13
        ZVAL_LONG(&op1, -1);
897
13
        ret = mul_function(result, &op1, &op2);
898
13
        zval_ptr_dtor_nogc(&op2);
899
13
      }
900
19
      break;
901
499
    case ZEND_AST_ARRAY:
902
499
      {
903
499
        uint32_t i;
904
499
        zend_ast_list *list = zend_ast_get_list(ast);
905
906
499
        if (!list->children) {
907
0
          ZVAL_EMPTY_ARRAY(result);
908
0
          break;
909
0
        }
910
499
        array_init(result);
911
983
        for (i = 0; i < list->children; i++) {
912
630
          zend_ast *elem = list->child[i];
913
630
          if (elem->kind == ZEND_AST_UNPACK) {
914
45
            if (UNEXPECTED(zend_ast_evaluate_ex(&op1, elem->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
915
22
              zval_ptr_dtor_nogc(result);
916
22
              return FAILURE;
917
22
            }
918
23
            if (UNEXPECTED(zend_ast_add_unpacked_element(result, &op1) != SUCCESS)) {
919
13
              zval_ptr_dtor_nogc(&op1);
920
13
              zval_ptr_dtor_nogc(result);
921
13
              return FAILURE;
922
13
            }
923
10
            zval_ptr_dtor_nogc(&op1);
924
10
            continue;
925
23
          }
926
585
          if (elem->child[1]) {
927
428
            if (UNEXPECTED(zend_ast_evaluate_ex(&op1, elem->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
928
33
              zval_ptr_dtor_nogc(result);
929
33
              return FAILURE;
930
33
            }
931
428
          } else {
932
157
            ZVAL_UNDEF(&op1);
933
157
          }
934
552
          if (UNEXPECTED(zend_ast_evaluate_ex(&op2, elem->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
935
65
            zval_ptr_dtor_nogc(&op1);
936
65
            zval_ptr_dtor_nogc(result);
937
65
            return FAILURE;
938
65
          }
939
487
          if (UNEXPECTED(zend_ast_add_array_element(result, &op1, &op2) != SUCCESS)) {
940
13
            zval_ptr_dtor_nogc(&op1);
941
13
            zval_ptr_dtor_nogc(&op2);
942
13
            zval_ptr_dtor_nogc(result);
943
13
            return FAILURE;
944
13
          }
945
487
        }
946
499
      }
947
353
      break;
948
353
    case ZEND_AST_DIM:
949
282
      if (ast->child[1] == NULL) {
950
0
        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
951
0
      }
952
953
282
      if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
954
1
        ret = FAILURE;
955
1
        break;
956
1
      }
957
281
      if (short_circuited) {
958
7
        *short_circuited_ptr = true;
959
7
        ZVAL_NULL(result);
960
7
        return SUCCESS;
961
7
      }
962
963
      // DIM on objects is disallowed because it allows executing arbitrary expressions
964
274
      if (Z_TYPE(op1) == IS_OBJECT) {
965
5
        zval_ptr_dtor_nogc(&op1);
966
5
        zend_throw_error(NULL, "Cannot use [] on objects in constant expression");
967
5
        ret = FAILURE;
968
5
        break;
969
5
      }
970
971
269
      if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
972
3
        zval_ptr_dtor_nogc(&op1);
973
3
        ret = FAILURE;
974
3
        break;
975
3
      }
976
977
266
      zend_fetch_dimension_const(result, &op1, &op2, (ast->attr & ZEND_DIM_IS) ? BP_VAR_IS : BP_VAR_R);
978
979
266
      zval_ptr_dtor_nogc(&op1);
980
266
      zval_ptr_dtor_nogc(&op2);
981
266
      if (UNEXPECTED(EG(exception))) {
982
4
        return FAILURE;
983
4
      }
984
985
262
      break;
986
1.57k
    case ZEND_AST_CONST_ENUM_INIT:
987
1.57k
    {
988
      // Preloading will attempt to resolve constants but objects can't be stored in shm
989
      // Aborting here to store the const AST instead
990
1.57k
      if (CG(in_compilation)) {
991
0
        return FAILURE;
992
0
      }
993
994
1.57k
      zend_ast *class_name_ast = ast->child[0];
995
1.57k
      zend_string *class_name = zend_ast_get_str(class_name_ast);
996
997
1.57k
      zend_ast *case_id_ast = ast->child[1];
998
1.57k
      int case_id = (int)Z_LVAL_P(zend_ast_get_zval(case_id_ast));
999
1000
1.57k
      zend_ast *case_name_ast = ast->child[2];
1001
1.57k
      zend_string *case_name = zend_ast_get_str(case_name_ast);
1002
1003
1.57k
      zend_ast *case_value_ast = ast->child[3];
1004
1005
1.57k
      zval case_value_zv;
1006
1.57k
      ZVAL_UNDEF(&case_value_zv);
1007
1.57k
      if (case_value_ast != NULL) {
1008
725
        if (UNEXPECTED(zend_ast_evaluate_ex(&case_value_zv, case_value_ast, scope, &short_circuited, ctx) != SUCCESS)) {
1009
10
          return FAILURE;
1010
10
        }
1011
725
      }
1012
1013
1.56k
      zend_class_entry *ce = zend_lookup_class(class_name);
1014
1.56k
      zend_enum_new(result, ce, case_id, case_name, case_value_ast != NULL ? &case_value_zv : NULL);
1015
1.56k
      zval_ptr_dtor_nogc(&case_value_zv);
1016
1.56k
      break;
1017
1.57k
    }
1018
1.47k
    case ZEND_AST_CLASS_CONST:
1019
1.47k
    {
1020
1.47k
      zend_string *class_name = zend_ast_get_str(ast->child[0]);
1021
1.47k
      if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
1022
6
        return FAILURE;
1023
6
      }
1024
1.46k
      if (UNEXPECTED(Z_TYPE(op2) != IS_STRING)) {
1025
3
        zend_invalid_class_constant_type_error(Z_TYPE(op2));
1026
3
        zval_ptr_dtor_nogc(&op2);
1027
3
        return FAILURE;
1028
3
      }
1029
1.46k
      zend_string *const_name = Z_STR(op2);
1030
1031
1.46k
      zend_string *previous_filename;
1032
1.46k
      zend_long previous_lineno;
1033
1.46k
      if (scope) {
1034
1.31k
        previous_filename = EG(filename_override);
1035
1.31k
        previous_lineno = EG(lineno_override);
1036
1.31k
        EG(filename_override) = scope->info.user.filename;
1037
1.31k
        EG(lineno_override) = zend_ast_get_lineno(ast);
1038
1.31k
      }
1039
1.46k
      zval *zv = zend_get_class_constant_ex(class_name, const_name, scope, ast->attr);
1040
1.46k
      if (scope) {
1041
1.30k
        EG(filename_override) = previous_filename;
1042
1.30k
        EG(lineno_override) = previous_lineno;
1043
1.30k
      }
1044
1045
1.46k
      if (UNEXPECTED(zv == NULL)) {
1046
162
        ZVAL_UNDEF(result);
1047
162
        zval_ptr_dtor_nogc(&op2);
1048
162
        return FAILURE;
1049
162
      }
1050
1.30k
      ZVAL_COPY_OR_DUP(result, zv);
1051
1.30k
      zval_ptr_dtor_nogc(&op2);
1052
1.30k
      break;
1053
1.46k
    }
1054
471
    case ZEND_AST_NEW:
1055
471
    {
1056
471
      zend_class_entry *ce = zend_ast_fetch_class(ast->child[0], scope);
1057
471
      if (!ce) {
1058
20
        return FAILURE;
1059
20
      }
1060
1061
451
      if (object_init_ex(result, ce) != SUCCESS) {
1062
0
        return FAILURE;
1063
0
      }
1064
1065
      /* Even if there is no constructor, the object can have cause side-effects in various ways (__toString(), __get(), __isset(), etc). */
1066
451
      ctx->had_side_effects = true;
1067
1068
451
      zend_ast_list *args_ast = zend_ast_get_list(ast->child[1]);
1069
451
      if (args_ast->attr) {
1070
        /* Has named arguments. */
1071
76
        HashTable *args = zend_new_array(args_ast->children);
1072
149
        for (uint32_t i = 0; i < args_ast->children; i++) {
1073
76
          zend_ast *arg_ast = args_ast->child[i];
1074
76
          zend_string *name = NULL;
1075
76
          zval arg;
1076
76
          if (arg_ast->kind == ZEND_AST_NAMED_ARG) {
1077
76
            name = zend_ast_get_str(arg_ast->child[0]);
1078
76
            arg_ast = arg_ast->child[1];
1079
76
          }
1080
76
          if (zend_ast_evaluate_ex(&arg, arg_ast, scope, &short_circuited, ctx) == FAILURE) {
1081
3
            zend_array_destroy(args);
1082
3
            zval_ptr_dtor(result);
1083
3
            return FAILURE;
1084
3
          }
1085
73
          if (name) {
1086
73
            if (!zend_hash_add(args, name, &arg)) {
1087
0
              zend_throw_error(NULL,
1088
0
                "Named parameter $%s overwrites previous argument",
1089
0
                ZSTR_VAL(name));
1090
0
              zend_array_destroy(args);
1091
0
              zval_ptr_dtor(result);
1092
0
              return FAILURE;
1093
0
            }
1094
73
          } else {
1095
0
            zend_hash_next_index_insert(args, &arg);
1096
0
          }
1097
73
        }
1098
1099
73
        zend_function *ctor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result));
1100
73
        if (ctor) {
1101
70
          zend_call_known_function(
1102
70
            ctor, Z_OBJ_P(result), Z_OBJCE_P(result), NULL, 0, NULL, args);
1103
70
        }
1104
1105
73
        zend_array_destroy(args);
1106
375
      } else {
1107
375
        ALLOCA_FLAG(use_heap)
1108
375
        zval *args = do_alloca(sizeof(zval) * args_ast->children, use_heap);
1109
553
        for (uint32_t i = 0; i < args_ast->children; i++) {
1110
189
          if (zend_ast_evaluate_ex(&args[i], args_ast->child[i], scope, &short_circuited, ctx) == FAILURE) {
1111
11
            for (uint32_t j = 0; j < i; j++) {
1112
0
              zval_ptr_dtor(&args[j]);
1113
0
            }
1114
11
            free_alloca(args, use_heap);
1115
11
            zval_ptr_dtor(result);
1116
11
            return FAILURE;
1117
11
          }
1118
189
        }
1119
1120
364
        zend_function *ctor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result));
1121
364
        if (ctor) {
1122
211
          zend_call_known_instance_method(
1123
211
            ctor, Z_OBJ_P(result), NULL, args_ast->children, args);
1124
211
        }
1125
1126
542
        for (uint32_t i = 0; i < args_ast->children; i++) {
1127
178
          zval_ptr_dtor(&args[i]);
1128
178
        }
1129
364
        free_alloca(args, use_heap);
1130
364
      }
1131
1132
437
      if (EG(exception)) {
1133
5
        zend_object_store_ctor_failed(Z_OBJ_P(result));
1134
5
        zval_ptr_dtor(result);
1135
5
        return FAILURE;
1136
5
      }
1137
432
      return SUCCESS;
1138
437
    }
1139
105
    case ZEND_AST_CALL:
1140
186
    case ZEND_AST_STATIC_CALL:
1141
186
    {
1142
186
      zend_function *fptr;
1143
186
      zend_class_entry *called_scope = NULL;
1144
1145
186
      zend_ast *args_ast = zend_ast_call_get_args(ast);
1146
186
      ZEND_ASSERT(args_ast->kind == ZEND_AST_CALLABLE_CONVERT);
1147
1148
186
      zend_ast_fcc *fcc_ast = (zend_ast_fcc*)args_ast;
1149
1150
186
      zend_ast_list *args = zend_ast_get_list(fcc_ast->args);
1151
186
      ZEND_ASSERT(args->children > 0);
1152
186
      if (args->children != 1 || args->child[0]->attr != ZEND_PLACEHOLDER_VARIADIC) {
1153
        /* TODO: PFAs */
1154
0
        zend_error_noreturn(E_COMPILE_ERROR, "Constant expression contains invalid operations");
1155
0
      }
1156
1157
186
      switch (ast->kind) {
1158
105
        case ZEND_AST_CALL: {
1159
105
          fptr = ZEND_MAP_PTR_GET(fcc_ast->fptr);
1160
1161
105
          if (!fptr) {
1162
100
            zend_string *function_name = zend_ast_get_str(ast->child[0]);
1163
100
            zend_string *function_name_lc = zend_string_tolower(function_name);
1164
100
            fptr = zend_fetch_function(function_name_lc);
1165
100
            if (!fptr && ast->child[0]->attr != ZEND_NAME_FQ) {
1166
21
              const char *backslash = zend_memrchr(ZSTR_VAL(function_name_lc), '\\', ZSTR_LEN(function_name_lc));
1167
21
              if (backslash) {
1168
17
                fptr = zend_fetch_function_str(backslash + 1, ZSTR_LEN(function_name_lc) - (backslash - ZSTR_VAL(function_name_lc) + 1));
1169
17
              }
1170
21
            }
1171
100
            zend_string_release(function_name_lc);
1172
100
            if (!fptr) {
1173
13
              zend_throw_error(NULL, "Call to undefined function %s()", ZSTR_VAL(function_name));
1174
13
              return FAILURE;
1175
13
            }
1176
1177
87
            ZEND_MAP_PTR_SET(fcc_ast->fptr, fptr);
1178
87
          }
1179
1180
92
          break;
1181
105
        }
1182
92
        case ZEND_AST_STATIC_CALL: {
1183
81
          zend_class_entry *ce = zend_ast_fetch_class(ast->child[0], scope);
1184
81
          if (!ce) {
1185
4
            return FAILURE;
1186
4
          }
1187
77
          called_scope = ce;
1188
1189
77
          fptr = ZEND_MAP_PTR_GET(fcc_ast->fptr);
1190
1191
77
          if (!fptr) {
1192
77
            zend_string *method_name = zend_ast_get_str(ast->child[1]);
1193
77
            if (ce->get_static_method) {
1194
0
              fptr = ce->get_static_method(ce, method_name);
1195
77
            } else {
1196
77
              fptr = zend_hash_find_ptr_lc(&ce->function_table, method_name);
1197
77
              if (fptr) {
1198
66
                if (!zend_check_method_accessible(fptr, scope)) {
1199
10
                  if (ce->__callstatic) {
1200
0
                    zend_throw_error(NULL, "Creating a callable for the magic __callStatic() method is not supported in constant expressions");
1201
10
                  } else {
1202
10
                    zend_bad_method_call(fptr, method_name, scope);
1203
10
                  }
1204
1205
10
                  return FAILURE;
1206
10
                }
1207
66
              } else {
1208
11
                if (ce->__callstatic) {
1209
5
                  zend_throw_error(NULL, "Creating a callable for the magic __callStatic() method is not supported in constant expressions");
1210
6
                } else {
1211
6
                  zend_undefined_method(ce, method_name);
1212
6
                }
1213
1214
11
                return FAILURE;
1215
11
              }
1216
77
            }
1217
1218
56
            if (!(fptr->common.fn_flags & ZEND_ACC_STATIC)) {
1219
5
              zend_non_static_method_call(fptr);
1220
1221
5
              return FAILURE;
1222
5
            }
1223
51
            if ((fptr->common.fn_flags & ZEND_ACC_ABSTRACT)) {
1224
6
              zend_abstract_method_call(fptr);
1225
1226
6
              return FAILURE;
1227
45
            } else if (fptr->common.scope->ce_flags & ZEND_ACC_TRAIT) {
1228
5
              zend_error(E_DEPRECATED,
1229
5
                "Calling static trait method %s::%s is deprecated, "
1230
5
                "it should only be called on a class using the trait",
1231
5
                ZSTR_VAL(fptr->common.scope->name), ZSTR_VAL(fptr->common.function_name));
1232
5
              if (EG(exception)) {
1233
0
                return FAILURE;
1234
0
              }
1235
5
            }
1236
1237
45
            ZEND_MAP_PTR_SET(fcc_ast->fptr, fptr);
1238
45
          }
1239
1240
45
          break;
1241
77
        }
1242
45
        default: ZEND_UNREACHABLE();
1243
186
      }
1244
1245
137
      zend_create_fake_closure(result, fptr, fptr->common.scope, called_scope, NULL);
1246
1247
137
      return SUCCESS;
1248
186
    }
1249
66
    case ZEND_AST_OP_ARRAY:
1250
66
    {
1251
      // Preloading will attempt to resolve constants but objects can't be stored in shm
1252
      // Aborting here to store the const AST instead
1253
66
      if (CG(in_compilation)) {
1254
0
        return FAILURE;
1255
0
      }
1256
1257
66
      zend_function *func = (zend_function *)zend_ast_get_op_array(ast)->op_array;
1258
1259
66
      zend_create_closure(result, func, scope, scope, NULL);
1260
66
      return SUCCESS;
1261
66
    }
1262
163
    case ZEND_AST_PROP:
1263
305
    case ZEND_AST_NULLSAFE_PROP:
1264
305
    {
1265
305
      if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
1266
4
        return FAILURE;
1267
4
      }
1268
301
      if (short_circuited) {
1269
7
        *short_circuited_ptr = true;
1270
7
        ZVAL_NULL(result);
1271
7
        return SUCCESS;
1272
7
      }
1273
294
      if (ast->kind == ZEND_AST_NULLSAFE_PROP && Z_TYPE(op1) == IS_NULL) {
1274
51
        *short_circuited_ptr = true;
1275
51
        ZVAL_NULL(result);
1276
51
        return SUCCESS;
1277
51
      }
1278
1279
243
      if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
1280
4
        zval_ptr_dtor_nogc(&op1);
1281
4
        return FAILURE;
1282
4
      }
1283
1284
239
      if (!try_convert_to_string(&op2)) {
1285
4
        zval_ptr_dtor_nogc(&op1);
1286
4
        zval_ptr_dtor_nogc(&op2);
1287
4
        return FAILURE;
1288
4
      }
1289
1290
235
      if (Z_TYPE(op1) != IS_OBJECT) {
1291
37
        zend_wrong_property_read(&op1, &op2);
1292
1293
37
        zval_ptr_dtor_nogc(&op1);
1294
37
        zval_ptr_dtor_nogc(&op2);
1295
1296
37
        ZVAL_NULL(result);
1297
37
        return SUCCESS;
1298
37
      }
1299
1300
198
      zend_object *zobj = Z_OBJ(op1);
1301
198
      if (!(zobj->ce->ce_flags & ZEND_ACC_ENUM)) {
1302
23
        zend_throw_error(NULL, "Fetching properties on non-enums in constant expressions is not allowed");
1303
23
        zval_ptr_dtor_nogc(&op1);
1304
23
        zval_ptr_dtor_nogc(&op2);
1305
23
        return FAILURE;
1306
23
      }
1307
1308
175
      zend_string *name = Z_STR(op2);
1309
175
      zval *property_result = zend_read_property_ex(scope, zobj, name, 0, result);
1310
175
      if (EG(exception)) {
1311
0
        zval_ptr_dtor_nogc(&op1);
1312
0
        zval_ptr_dtor_nogc(&op2);
1313
0
        return FAILURE;
1314
0
      }
1315
1316
175
      if (result != property_result) {
1317
175
        ZVAL_COPY(result, property_result);
1318
175
      }
1319
175
      zval_ptr_dtor_nogc(&op1);
1320
175
      zval_ptr_dtor_nogc(&op2);
1321
175
      return SUCCESS;
1322
175
    }
1323
0
    default:
1324
0
      zend_throw_error(NULL, "Unsupported constant expression");
1325
0
      ret = FAILURE;
1326
10.4k
  }
1327
8.92k
  return ret;
1328
10.4k
}
1329
1330
ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope)
1331
0
{
1332
0
  zend_ast_evaluate_ctx ctx = {0};
1333
0
  bool short_circuited;
1334
0
  return zend_ast_evaluate_ex(result, ast, scope, &short_circuited, &ctx);
1335
0
}
1336
1337
static size_t ZEND_FASTCALL zend_ast_tree_size(zend_ast *ast)
1338
168k
{
1339
168k
  size_t size;
1340
1341
168k
  if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) {
1342
118k
    size = sizeof(zend_ast_zval);
1343
118k
  } else if (ast->kind == ZEND_AST_OP_ARRAY) {
1344
143
    size = sizeof(zend_ast_op_array);
1345
50.2k
  } else if (ast->kind == ZEND_AST_CALLABLE_CONVERT) {
1346
489
    zend_ast *args_ast = ((zend_ast_fcc*)ast)->args;
1347
489
    size = sizeof(zend_ast_fcc) + zend_ast_tree_size(args_ast);
1348
49.7k
  } else if (zend_ast_is_list(ast)) {
1349
2.83k
    uint32_t i;
1350
2.83k
    const zend_ast_list *list = zend_ast_get_list(ast);
1351
1352
2.83k
    size = zend_ast_list_size(list->children);
1353
5.01k
    for (i = 0; i < list->children; i++) {
1354
2.18k
      if (list->child[i]) {
1355
2.18k
        size += zend_ast_tree_size(list->child[i]);
1356
2.18k
      }
1357
2.18k
    }
1358
46.9k
  } else if (zend_ast_is_decl(ast)) {
1359
    /* Not implemented. */
1360
0
    ZEND_UNREACHABLE();
1361
46.9k
  } else {
1362
46.9k
    uint32_t i, children = zend_ast_get_num_children(ast);
1363
1364
46.9k
    size = zend_ast_size(children);
1365
193k
    for (i = 0; i < children; i++) {
1366
146k
      if (ast->child[i]) {
1367
118k
        size += zend_ast_tree_size(ast->child[i]);
1368
118k
      }
1369
146k
    }
1370
46.9k
  }
1371
168k
  return size;
1372
168k
}
1373
1374
static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf)
1375
168k
{
1376
168k
  if (ast->kind == ZEND_AST_ZVAL) {
1377
96.5k
    zend_ast_zval *new = (zend_ast_zval*)buf;
1378
96.5k
    new->kind = ZEND_AST_ZVAL;
1379
96.5k
    new->attr = ast->attr;
1380
96.5k
    ZVAL_COPY(&new->val, zend_ast_get_zval(ast));
1381
96.5k
    Z_LINENO(new->val) = zend_ast_get_lineno(ast);
1382
96.5k
    buf = (void*)((char*)buf + sizeof(zend_ast_zval));
1383
96.5k
  } else if (ast->kind == ZEND_AST_CONSTANT) {
1384
22.0k
    zend_ast_zval *new = (zend_ast_zval*)buf;
1385
22.0k
    new->kind = ZEND_AST_CONSTANT;
1386
22.0k
    new->attr = ast->attr;
1387
22.0k
    ZVAL_STR_COPY(&new->val, zend_ast_get_constant_name(ast));
1388
22.0k
    Z_LINENO(new->val) = zend_ast_get_lineno(ast);
1389
22.0k
    buf = (void*)((char*)buf + sizeof(zend_ast_zval));
1390
50.3k
  } else if (zend_ast_is_list(ast)) {
1391
2.83k
    const zend_ast_list *list = zend_ast_get_list(ast);
1392
2.83k
    zend_ast_list *new = (zend_ast_list*)buf;
1393
2.83k
    uint32_t i;
1394
2.83k
    new->kind = list->kind;
1395
2.83k
    new->attr = list->attr;
1396
2.83k
    new->children = list->children;
1397
2.83k
    new->lineno = list->lineno;
1398
2.83k
    buf = (void*)((char*)buf + zend_ast_list_size(list->children));
1399
5.01k
    for (i = 0; i < list->children; i++) {
1400
2.18k
      if (list->child[i]) {
1401
2.18k
        new->child[i] = (zend_ast*)buf;
1402
2.18k
        buf = zend_ast_tree_copy(list->child[i], buf);
1403
2.18k
      } else {
1404
0
        new->child[i] = NULL;
1405
0
      }
1406
2.18k
    }
1407
47.5k
  } else if (ast->kind == ZEND_AST_OP_ARRAY) {
1408
143
    const zend_ast_op_array *old = zend_ast_get_op_array(ast);
1409
143
    zend_ast_op_array *new = (zend_ast_op_array*)buf;
1410
143
    new->kind = old->kind;
1411
143
    new->attr = old->attr;
1412
143
    new->lineno = old->lineno;
1413
143
    new->op_array = old->op_array;
1414
143
    function_add_ref((zend_function *)new->op_array);
1415
143
    buf = (void*)((char*)buf + sizeof(zend_ast_op_array));
1416
47.4k
  } else if (ast->kind == ZEND_AST_CALLABLE_CONVERT) {
1417
489
    const zend_ast_fcc *old = (zend_ast_fcc*)ast;
1418
489
    zend_ast_fcc *new = (zend_ast_fcc*)buf;
1419
489
    new->kind = old->kind;
1420
489
    new->attr = old->attr;
1421
489
    new->lineno = old->lineno;
1422
489
    ZEND_MAP_PTR_INIT(new->fptr, ZEND_MAP_PTR(old->fptr));
1423
489
    buf = (void*)((char*)buf + sizeof(zend_ast_fcc));
1424
489
    new->args = buf;
1425
489
    buf = zend_ast_tree_copy(old->args, buf);
1426
46.9k
  } else if (zend_ast_is_decl(ast)) {
1427
    /* Not implemented. */
1428
0
    ZEND_UNREACHABLE();
1429
46.9k
  } else {
1430
46.9k
    uint32_t i, children = zend_ast_get_num_children(ast);
1431
46.9k
    zend_ast *new = (zend_ast*)buf;
1432
46.9k
    new->kind = ast->kind;
1433
46.9k
    new->attr = ast->attr;
1434
46.9k
    new->lineno = ast->lineno;
1435
46.9k
    buf = (void*)((char*)buf + zend_ast_size(children));
1436
193k
    for (i = 0; i < children; i++) {
1437
146k
      if (ast->child[i]) {
1438
118k
        new->child[i] = (zend_ast*)buf;
1439
118k
        buf = zend_ast_tree_copy(ast->child[i], buf);
1440
118k
      } else {
1441
28.4k
        new->child[i] = NULL;
1442
28.4k
      }
1443
146k
    }
1444
46.9k
  }
1445
168k
  return buf;
1446
168k
}
1447
1448
ZEND_API zend_ast_ref * ZEND_FASTCALL zend_ast_copy(zend_ast *ast)
1449
47.8k
{
1450
47.8k
  size_t tree_size;
1451
47.8k
  zend_ast_ref *ref;
1452
1453
47.8k
  ZEND_ASSERT(ast != NULL);
1454
47.8k
  tree_size = zend_ast_tree_size(ast) + sizeof(zend_ast_ref);
1455
47.8k
  ref = emalloc(tree_size);
1456
47.8k
  zend_ast_tree_copy(ast, GC_AST(ref));
1457
47.8k
  GC_SET_REFCOUNT(ref, 1);
1458
47.8k
  GC_TYPE_INFO(ref) = GC_CONSTANT_AST;
1459
47.8k
  return ref;
1460
47.8k
}
1461
1462
ZEND_API void ZEND_FASTCALL zend_ast_destroy(zend_ast *ast)
1463
5.08M
{
1464
10.1M
tail_call:
1465
10.1M
  if (!ast) {
1466
1.37M
    return;
1467
1.37M
  }
1468
1469
8.80M
  if (EXPECTED(ast->kind >= ZEND_AST_VAR)) {
1470
4.08M
    uint32_t i, children = zend_ast_get_num_children(ast);
1471
1472
6.62M
    for (i = 1; i < children; i++) {
1473
2.54M
      zend_ast_destroy(ast->child[i]);
1474
2.54M
    }
1475
4.08M
    ast = ast->child[0];
1476
4.08M
    goto tail_call;
1477
4.72M
  } else if (EXPECTED(ast->kind == ZEND_AST_ZVAL)) {
1478
3.37M
    zval_ptr_dtor_nogc(zend_ast_get_zval(ast));
1479
3.37M
  } else if (EXPECTED(zend_ast_is_list(ast))) {
1480
1.15M
    const zend_ast_list *list = zend_ast_get_list(ast);
1481
1.15M
    if (list->children) {
1482
887k
      uint32_t i;
1483
1484
2.45M
      for (i = 1; i < list->children; i++) {
1485
1.56M
        zend_ast_destroy(list->child[i]);
1486
1.56M
      }
1487
887k
      ast = list->child[0];
1488
887k
      goto tail_call;
1489
887k
    }
1490
1.15M
  } else if (EXPECTED(ast->kind == ZEND_AST_CONSTANT)) {
1491
41.0k
    zend_string_release_ex(zend_ast_get_constant_name(ast), 0);
1492
150k
  } else if (EXPECTED(ast->kind == ZEND_AST_OP_ARRAY)) {
1493
213
    destroy_op_array(zend_ast_get_op_array(ast)->op_array);
1494
150k
  } else if (EXPECTED(zend_ast_is_decl(ast))) {
1495
119k
    const zend_ast_decl *decl = (const zend_ast_decl *) ast;
1496
1497
119k
    if (decl->name) {
1498
90.0k
        zend_string_release_ex(decl->name, 0);
1499
90.0k
    }
1500
119k
    if (decl->doc_comment) {
1501
397
      zend_string_release_ex(decl->doc_comment, 0);
1502
397
    }
1503
119k
    zend_ast_destroy(decl->child[0]);
1504
119k
    zend_ast_destroy(decl->child[1]);
1505
119k
    zend_ast_destroy(decl->child[2]);
1506
119k
    zend_ast_destroy(decl->child[3]);
1507
119k
    ast = decl->child[4];
1508
119k
    goto tail_call;
1509
119k
  } else if (EXPECTED(ast->kind == ZEND_AST_CALLABLE_CONVERT)) {
1510
4.81k
    zend_ast_fcc *fcc_ast = (zend_ast_fcc*) ast;
1511
1512
4.81k
    ast = fcc_ast->args;
1513
4.81k
    goto tail_call;
1514
4.81k
  }
1515
8.80M
}
1516
1517
ZEND_API void ZEND_FASTCALL zend_ast_ref_destroy(zend_ast_ref *ast)
1518
42.1k
{
1519
42.1k
  zend_ast_destroy(GC_AST(ast));
1520
42.1k
  efree(ast);
1521
42.1k
}
1522
1523
92.8k
ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn, void *context) {
1524
92.8k
  if (zend_ast_is_list(ast)) {
1525
7.34k
    zend_ast_list *list = zend_ast_get_list(ast);
1526
7.34k
    uint32_t i;
1527
15.9k
    for (i = 0; i < list->children; ++i) {
1528
8.61k
      fn(&list->child[i], context);
1529
8.61k
    }
1530
85.5k
  } else if (zend_ast_is_decl(ast)) {
1531
    /* Not implemented. */
1532
0
    ZEND_UNREACHABLE();
1533
85.5k
  } else {
1534
85.5k
    uint32_t i, children = zend_ast_get_num_children(ast);
1535
278k
    for (i = 0; i < children; ++i) {
1536
193k
      fn(&ast->child[i], context);
1537
193k
    }
1538
85.5k
  }
1539
92.8k
}
1540
1541
/*
1542
 * Operator Precedence
1543
 * ====================
1544
 * priority  associativity  operators
1545
 * ----------------------------------
1546
 *   10     left            include, include_once, eval, require, require_once
1547
 *   20     left            ,
1548
 *   30     left            or
1549
 *   40     left            xor
1550
 *   50     left            and
1551
 *   60     right           print
1552
 *   70     right           yield
1553
 *   80     right           =>
1554
 *   85     right           yield from
1555
 *   90     right           = += -= *= /= .= %= &= |= ^= <<= >>= **=
1556
 *  100     left            ? :
1557
 *  110     right           ??
1558
 *  120     left            ||
1559
 *  130     left            &&
1560
 *  140     left            |
1561
 *  150     left            ^
1562
 *  160     left            &
1563
 *  170     non-associative == != === !==
1564
 *  180     non-associative < <= > >= <=>
1565
 *  185     left            .
1566
 *  190     left            << >>
1567
 *  200     left            + -
1568
 *  210     left            * / %
1569
 *  220     right           !
1570
 *  230     non-associative instanceof
1571
 *  240     right           + - ++ -- ~ (type) @
1572
 *  250     right           **
1573
 *  260     left            [
1574
 *  270     non-associative clone new
1575
 */
1576
1577
static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int priority, int indent);
1578
1579
static ZEND_COLD void zend_ast_export_str(smart_str *str, const zend_string *s)
1580
36.6k
{
1581
36.6k
  size_t i;
1582
1583
1.34M
  for (i = 0; i < ZSTR_LEN(s); i++) {
1584
1.30M
    unsigned char c = ZSTR_VAL(s)[i];
1585
1.30M
    if (c == '\'' || c == '\\') {
1586
15.3k
      smart_str_appendc(str, '\\');
1587
15.3k
      smart_str_appendc(str, c);
1588
1.28M
    } else {
1589
1.28M
      smart_str_appendc(str, c);
1590
1.28M
    }
1591
1.30M
  }
1592
36.6k
}
1593
1594
static ZEND_COLD void zend_ast_export_qstr(smart_str *str, char quote, const zend_string *s)
1595
56.9k
{
1596
56.9k
  size_t i;
1597
1598
1.20M
  for (i = 0; i < ZSTR_LEN(s); i++) {
1599
1.15M
    unsigned char c = ZSTR_VAL(s)[i];
1600
1.15M
    if (c < ' ') {
1601
515k
      switch (c) {
1602
20.3k
        case '\n':
1603
20.3k
          smart_str_appends(str, "\\n");
1604
20.3k
          break;
1605
17.5k
        case '\r':
1606
17.5k
          smart_str_appends(str, "\\r");
1607
17.5k
          break;
1608
7.26k
        case '\t':
1609
7.26k
          smart_str_appends(str, "\\t");
1610
7.26k
          break;
1611
3.30k
        case '\f':
1612
3.30k
          smart_str_appends(str, "\\f");
1613
3.30k
          break;
1614
12.9k
        case '\v':
1615
12.9k
          smart_str_appends(str, "\\v");
1616
12.9k
          break;
1617
#ifdef ZEND_WIN32
1618
        case VK_ESCAPE:
1619
#else
1620
11.0k
        case '\e':
1621
11.0k
#endif
1622
11.0k
          smart_str_appends(str, "\\e");
1623
11.0k
          break;
1624
443k
        default:
1625
443k
          smart_str_appends(str, "\\0");
1626
443k
          smart_str_appendc(str, '0' + (c / 8));
1627
443k
          smart_str_appendc(str, '0' + (c % 8));
1628
443k
          break;
1629
515k
      }
1630
636k
    } else {
1631
636k
      if (c == quote || c == '$' || c == '\\') {
1632
61.1k
        smart_str_appendc(str, '\\');
1633
61.1k
      }
1634
636k
      smart_str_appendc(str, c);
1635
636k
    }
1636
1.15M
  }
1637
56.9k
}
1638
1639
static ZEND_COLD void zend_ast_export_indent(smart_str *str, int indent)
1640
158k
{
1641
1.12M
  while (indent > 0) {
1642
961k
    smart_str_appends(str, "    ");
1643
961k
    indent--;
1644
961k
  }
1645
158k
}
1646
1647
static ZEND_COLD void zend_ast_export_name(smart_str *str, zend_ast *ast, int priority, int indent)
1648
46.1k
{
1649
46.1k
  if (ast->kind == ZEND_AST_ZVAL) {
1650
39.6k
    const zval *zv = zend_ast_get_zval(ast);
1651
1652
39.6k
    if (Z_TYPE_P(zv) == IS_STRING) {
1653
36.7k
      smart_str_append(str, Z_STR_P(zv));
1654
36.7k
      return;
1655
36.7k
    }
1656
39.6k
  }
1657
9.38k
  zend_ast_export_ex(str, ast, priority, indent);
1658
9.38k
}
1659
1660
static ZEND_COLD void zend_ast_export_ns_name(smart_str *str, zend_ast *ast, int priority, int indent)
1661
907k
{
1662
907k
  if (ast->kind == ZEND_AST_ZVAL) {
1663
902k
    const zval *zv = zend_ast_get_zval(ast);
1664
1665
902k
    if (Z_TYPE_P(zv) == IS_STRING) {
1666
902k
        if (ast->attr == ZEND_NAME_FQ) {
1667
87.3k
        smart_str_appendc(str, '\\');
1668
815k
        } else if (ast->attr == ZEND_NAME_RELATIVE) {
1669
937
        smart_str_appends(str, "namespace\\");
1670
937
        }
1671
902k
      smart_str_append(str, Z_STR_P(zv));
1672
902k
      return;
1673
902k
    }
1674
902k
  }
1675
5.07k
  zend_ast_export_ex(str, ast, priority, indent);
1676
5.07k
}
1677
1678
static ZEND_COLD bool zend_ast_valid_var_char(char ch)
1679
34.7k
{
1680
34.7k
  unsigned char c = (unsigned char)ch;
1681
1682
34.7k
  if (c != '_' && c < 127 &&
1683
32.8k
      (c < '0' || c > '9') &&
1684
30.8k
      (c < 'A' || c > 'Z') &&
1685
30.3k
      (c < 'a' || c > 'z')) {
1686
29.5k
    return false;
1687
29.5k
  }
1688
5.21k
  return true;
1689
34.7k
}
1690
1691
static ZEND_COLD bool zend_ast_valid_var_name(const char *s, size_t len)
1692
101k
{
1693
101k
  unsigned char c;
1694
101k
  size_t i;
1695
1696
101k
  if (len == 0) {
1697
1.54k
    return false;
1698
1.54k
  }
1699
99.6k
  c = (unsigned char)s[0];
1700
99.6k
  if (c != '_' && c < 127 &&
1701
84.9k
      (c < 'A' || c > 'Z') &&
1702
69.7k
      (c < 'a' || c > 'z')) {
1703
1.46k
    return false;
1704
1.46k
  }
1705
327k
  for (i = 1; i < len; i++) {
1706
230k
    c = (unsigned char)s[i];
1707
230k
    if (c != '_' && c < 127 &&
1708
167k
        (c < '0' || c > '9') &&
1709
163k
        (c < 'A' || c > 'Z') &&
1710
135k
        (c < 'a' || c > 'z')) {
1711
1.01k
      return false;
1712
1.01k
    }
1713
230k
  }
1714
97.2k
  return true;
1715
98.2k
}
1716
1717
static ZEND_COLD bool zend_ast_var_needs_braces(char ch)
1718
35.0k
{
1719
35.0k
  return ch == '[' || zend_ast_valid_var_char(ch);
1720
35.0k
}
1721
1722
static ZEND_COLD void zend_ast_export_var(smart_str *str, zend_ast *ast, int indent)
1723
107k
{
1724
107k
  if (ast->kind == ZEND_AST_ZVAL) {
1725
104k
    zval *zv = zend_ast_get_zval(ast);
1726
104k
    if (Z_TYPE_P(zv) == IS_STRING &&
1727
101k
        zend_ast_valid_var_name(Z_STRVAL_P(zv), Z_STRLEN_P(zv))) {
1728
97.2k
      smart_str_append(str, Z_STR_P(zv));
1729
97.2k
      return;
1730
97.2k
    }
1731
104k
  } else if (ast->kind == ZEND_AST_VAR) {
1732
2.10k
    zend_ast_export_ex(str, ast, 0, indent);
1733
2.10k
    return;
1734
2.10k
  }
1735
8.60k
  smart_str_appendc(str, '{');
1736
8.60k
  zend_ast_export_name(str, ast, 0, indent);
1737
8.60k
  smart_str_appendc(str, '}');
1738
8.60k
}
1739
1740
/* Use zend_ast_export_list() unless fewer than `list->children` children should
1741
 * be exported. */
1742
static ZEND_COLD void zend_ast_export_list_ex(smart_str *str, const zend_ast_list *list, bool separator, int priority, int indent, uint32_t children)
1743
533k
{
1744
533k
  ZEND_ASSERT(children <= list->children);
1745
533k
  uint32_t i = 0;
1746
1747
1.27M
  while (i < children) {
1748
743k
    if (i != 0 && separator) {
1749
238k
      smart_str_appends(str, ", ");
1750
238k
    }
1751
743k
    zend_ast_export_ex(str, list->child[i], priority, indent);
1752
743k
    i++;
1753
743k
  }
1754
533k
}
1755
1756
static ZEND_COLD void zend_ast_export_list(smart_str *str, const zend_ast_list *list, bool separator, int priority, int indent)
1757
533k
{
1758
533k
  zend_ast_export_list_ex(str, list, separator, priority, indent, list->children);
1759
533k
}
1760
1761
static ZEND_COLD void zend_ast_export_encaps_list(smart_str *str, char quote, const zend_ast_list *list, int indent)
1762
5.27k
{
1763
5.27k
  uint32_t i = 0;
1764
5.27k
  zend_ast *ast;
1765
1766
116k
  while (i < list->children) {
1767
111k
    ast = list->child[i];
1768
111k
    if (ast->kind == ZEND_AST_ZVAL) {
1769
54.1k
      const zval *zv = zend_ast_get_zval(ast);
1770
1771
54.1k
      ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
1772
54.1k
      zend_ast_export_qstr(str, quote, Z_STR_P(zv));
1773
57.4k
    } else if (ast->kind == ZEND_AST_VAR &&
1774
39.7k
               ast->child[0]->kind == ZEND_AST_ZVAL &&
1775
38.4k
               (i + 1 == list->children ||
1776
37.6k
                list->child[i + 1]->kind != ZEND_AST_ZVAL ||
1777
35.0k
                !zend_ast_var_needs_braces(
1778
35.0k
                    *Z_STRVAL_P(
1779
35.0k
                        zend_ast_get_zval(list->child[i + 1]))))) {
1780
32.9k
      zend_ast_export_ex(str, ast, 0, indent);
1781
32.9k
    } else {
1782
24.4k
      smart_str_appendc(str, '{');
1783
24.4k
      zend_ast_export_ex(str, ast, 0, indent);
1784
24.4k
      smart_str_appendc(str, '}');
1785
24.4k
    }
1786
111k
    i++;
1787
111k
  }
1788
5.27k
}
1789
1790
static ZEND_COLD void zend_ast_export_name_list_ex(smart_str *str, const zend_ast_list *list, int indent, const char *separator)
1791
2.52k
{
1792
2.52k
  uint32_t i = 0;
1793
1794
6.35k
  while (i < list->children) {
1795
3.83k
    if (i != 0) {
1796
1.30k
      smart_str_appends(str, separator);
1797
1.30k
    }
1798
3.83k
    zend_ast_export_name(str, list->child[i], 0, indent);
1799
3.83k
    i++;
1800
3.83k
  }
1801
2.52k
}
1802
1803
2.17k
#define zend_ast_export_name_list(s, l, i) zend_ast_export_name_list_ex(s, l, i, ", ")
1804
352
#define zend_ast_export_catch_name_list(s, l, i) zend_ast_export_name_list_ex(s, l, i, "|")
1805
1806
static ZEND_COLD void zend_ast_export_var_list(smart_str *str, const zend_ast_list *list, int indent)
1807
866
{
1808
866
  uint32_t i = 0;
1809
1810
3.86k
  while (i < list->children) {
1811
2.99k
    if (i != 0) {
1812
2.12k
      smart_str_appends(str, ", ");
1813
2.12k
    }
1814
2.99k
    if (list->child[i]->attr & ZEND_BIND_REF) {
1815
2.20k
      smart_str_appendc(str, '&');
1816
2.20k
    }
1817
2.99k
    smart_str_appendc(str, '$');
1818
2.99k
    zend_ast_export_name(str, list->child[i], 20, indent);
1819
2.99k
    i++;
1820
2.99k
  }
1821
866
}
1822
1823
static ZEND_COLD void zend_ast_export_stmt(smart_str *str, zend_ast *ast, int indent)
1824
151k
{
1825
151k
  if (!ast) {
1826
8.77k
    return;
1827
8.77k
  }
1828
1829
143k
  if (ast->kind == ZEND_AST_STMT_LIST ||
1830
101k
      ast->kind == ZEND_AST_TRAIT_ADAPTATIONS) {
1831
41.9k
    const zend_ast_list *list = (const zend_ast_list*)ast;
1832
41.9k
    uint32_t i = 0;
1833
1834
145k
    while (i < list->children) {
1835
103k
      ast = list->child[i];
1836
103k
      zend_ast_export_stmt(str, ast, indent);
1837
103k
      i++;
1838
103k
    }
1839
101k
  } else {
1840
101k
    zend_ast_export_indent(str, indent);
1841
101k
    zend_ast_export_ex(str, ast, 0, indent);
1842
101k
    switch (ast->kind) {
1843
1.29k
      case ZEND_AST_LABEL:
1844
7.21k
      case ZEND_AST_IF:
1845
7.50k
      case ZEND_AST_SWITCH:
1846
7.97k
      case ZEND_AST_WHILE:
1847
8.67k
      case ZEND_AST_TRY:
1848
11.8k
      case ZEND_AST_FOR:
1849
12.7k
      case ZEND_AST_FOREACH:
1850
14.0k
      case ZEND_AST_FUNC_DECL:
1851
15.2k
      case ZEND_AST_METHOD:
1852
21.3k
      case ZEND_AST_CLASS:
1853
22.2k
      case ZEND_AST_USE_TRAIT:
1854
22.2k
      case ZEND_AST_NAMESPACE:
1855
22.7k
      case ZEND_AST_DECLARE:
1856
22.7k
        break;
1857
3.04k
      case ZEND_AST_PROP_GROUP: {
1858
3.04k
        const zend_ast *first_prop = zend_ast_get_list(ast->child[1])->child[0];
1859
3.04k
        const zend_ast *hook_list = first_prop->child[3];
1860
3.04k
        if (hook_list == NULL) {
1861
1.81k
          smart_str_appendc(str, ';');
1862
1.81k
        }
1863
3.04k
        break;
1864
22.2k
      }
1865
75.3k
      default:
1866
75.3k
        smart_str_appendc(str, ';');
1867
75.3k
        break;
1868
101k
    }
1869
101k
    smart_str_appendc(str, '\n');
1870
101k
  }
1871
143k
}
1872
1873
static ZEND_COLD void zend_ast_export_if_stmt(smart_str *str, const zend_ast_list *list, int indent)
1874
5.92k
{
1875
5.92k
  uint32_t i;
1876
5.92k
  zend_ast *ast;
1877
1878
6.52k
tail_call:
1879
6.52k
  i = 0;
1880
23.3k
  while (i < list->children) {
1881
17.4k
    ast = list->child[i];
1882
17.4k
    ZEND_ASSERT(ast->kind == ZEND_AST_IF_ELEM);
1883
17.4k
    if (ast->child[0]) {
1884
13.5k
      if (i == 0) {
1885
6.52k
        smart_str_appends(str, "if (");
1886
6.97k
      } else {
1887
6.97k
        zend_ast_export_indent(str, indent);
1888
6.97k
        smart_str_appends(str, "} elseif (");
1889
6.97k
      }
1890
13.5k
      zend_ast_export_ex(str, ast->child[0], 0, indent);
1891
13.5k
      smart_str_appends(str, ") {\n");
1892
13.5k
      zend_ast_export_stmt(str, ast->child[1], indent + 1);
1893
13.5k
    } else {
1894
3.95k
      zend_ast_export_indent(str, indent);
1895
3.95k
      smart_str_appends(str, "} else ");
1896
3.95k
      if (ast->child[1] && ast->child[1]->kind == ZEND_AST_IF) {
1897
607
        list = (const zend_ast_list*)ast->child[1];
1898
607
        goto tail_call;
1899
3.35k
      } else {
1900
3.35k
        smart_str_appends(str, "{\n");
1901
3.35k
        zend_ast_export_stmt(str, ast->child[1], indent + 1);
1902
3.35k
      }
1903
3.95k
    }
1904
16.8k
    i++;
1905
16.8k
  }
1906
5.92k
  zend_ast_export_indent(str, indent);
1907
5.92k
  smart_str_appendc(str, '}');
1908
5.92k
}
1909
1910
static ZEND_COLD void zend_ast_export_zval(smart_str *str, const zval *zv, int priority, int indent)
1911
424k
{
1912
424k
  ZVAL_DEREF(zv);
1913
424k
  switch (Z_TYPE_P(zv)) {
1914
1
    case IS_NULL:
1915
1
      smart_str_appends(str, "null");
1916
1
      break;
1917
68
    case IS_FALSE:
1918
68
      smart_str_appends(str, "false");
1919
68
      break;
1920
0
    case IS_TRUE:
1921
0
      smart_str_appends(str, "true");
1922
0
      break;
1923
197k
    case IS_LONG:
1924
197k
      smart_str_append_long(str, Z_LVAL_P(zv));
1925
197k
      break;
1926
189k
    case IS_DOUBLE:
1927
189k
      smart_str_append_double(
1928
189k
        str, Z_DVAL_P(zv), (int) EG(precision), /* zero_fraction */ true);
1929
189k
      break;
1930
36.6k
    case IS_STRING:
1931
36.6k
      smart_str_appendc(str, '\'');
1932
36.6k
      zend_ast_export_str(str, Z_STR_P(zv));
1933
36.6k
      smart_str_appendc(str, '\'');
1934
36.6k
      break;
1935
93
    case IS_ARRAY: {
1936
93
      zend_long idx;
1937
93
      zend_string *key;
1938
93
      zval *val;
1939
93
      bool first = true;
1940
93
      smart_str_appendc(str, '[');
1941
435
      ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(zv), idx, key, val) {
1942
435
        if (first) {
1943
88
          first = false;
1944
88
        } else {
1945
83
          smart_str_appends(str, ", ");
1946
83
        }
1947
435
        if (key) {
1948
0
          smart_str_appendc(str, '\'');
1949
0
          zend_ast_export_str(str, key);
1950
0
          smart_str_appends(str, "' => ");
1951
171
        } else {
1952
171
          smart_str_append_long(str, idx);
1953
171
          smart_str_appends(str, " => ");
1954
171
        }
1955
435
        zend_ast_export_zval(str, val, 0, indent);
1956
435
      } ZEND_HASH_FOREACH_END();
1957
93
      smart_str_appendc(str, ']');
1958
93
      break;
1959
0
    }
1960
0
    case IS_CONSTANT_AST:
1961
0
      zend_ast_export_ex(str, Z_ASTVAL_P(zv), priority, indent);
1962
0
      break;
1963
0
    default: ZEND_UNREACHABLE();
1964
424k
  }
1965
424k
}
1966
1967
7.84k
static ZEND_COLD void zend_ast_export_class_no_header(smart_str *str, const zend_ast_decl *decl, int indent) {
1968
7.84k
  if (decl->child[0]) {
1969
747
    smart_str_appends(str, " extends ");
1970
747
    zend_ast_export_ns_name(str, decl->child[0], 0, indent);
1971
747
  }
1972
7.84k
  if (decl->child[1]) {
1973
1.10k
    smart_str_appends(str, " implements ");
1974
1.10k
    zend_ast_export_ex(str, decl->child[1], 0, indent);
1975
1.10k
  }
1976
7.84k
  smart_str_appends(str, " {\n");
1977
7.84k
  zend_ast_export_stmt(str, decl->child[2], indent + 1);
1978
7.84k
  zend_ast_export_indent(str, indent);
1979
7.84k
  smart_str_appendc(str, '}');
1980
7.84k
}
1981
1982
4.09k
static ZEND_COLD void zend_ast_export_attribute_group(smart_str *str, zend_ast *ast, int indent) {
1983
4.09k
  const zend_ast_list *list = zend_ast_get_list(ast);
1984
8.84k
  for (uint32_t i = 0; i < list->children; i++) {
1985
4.75k
    const zend_ast *attr = list->child[i];
1986
1987
4.75k
    if (i) {
1988
651
      smart_str_appends(str, ", ");
1989
651
    }
1990
4.75k
    zend_ast_export_ns_name(str, attr->child[0], 0, indent);
1991
1992
4.75k
    if (attr->child[1]) {
1993
998
      smart_str_appendc(str, '(');
1994
998
      zend_ast_export_ex(str, attr->child[1], 0, indent);
1995
998
      smart_str_appendc(str, ')');
1996
998
    }
1997
4.75k
  }
1998
4.09k
}
1999
2000
2.89k
static ZEND_COLD void zend_ast_export_attributes(smart_str *str, zend_ast *ast, int indent, bool newlines) {
2001
2.89k
  const zend_ast_list *list = zend_ast_get_list(ast);
2002
2.89k
  uint32_t i;
2003
2004
6.99k
  for (i = 0; i < list->children; i++) {
2005
4.09k
    smart_str_appends(str, "#[");
2006
4.09k
    zend_ast_export_attribute_group(str, list->child[i], indent);
2007
4.09k
    smart_str_appendc(str, ']');
2008
2009
4.09k
    if (newlines) {
2010
2.69k
      smart_str_appendc(str, '\n');
2011
2.69k
      zend_ast_export_indent(str, indent);
2012
2.69k
    } else {
2013
1.40k
      smart_str_appendc(str, ' ');
2014
1.40k
    }
2015
4.09k
  }
2016
2.89k
}
2017
2018
44.6k
static ZEND_COLD void zend_ast_export_visibility(smart_str *str, uint32_t flags, zend_modifier_target target) {
2019
44.6k
  if (flags & ZEND_ACC_PUBLIC) {
2020
3.61k
    smart_str_appends(str, "public ");
2021
41.0k
  } else if (flags & ZEND_ACC_PROTECTED) {
2022
203
    smart_str_appends(str, "protected ");
2023
40.8k
  } else if (flags & ZEND_ACC_PRIVATE) {
2024
620
    smart_str_appends(str, "private ");
2025
620
  }
2026
2027
44.6k
  if (target == ZEND_MODIFIER_TARGET_PROPERTY || target == ZEND_MODIFIER_TARGET_CPP) {
2028
15.4k
    if (flags & ZEND_ACC_PRIVATE_SET) {
2029
1.03k
      smart_str_appends(str, "private(set) ");
2030
14.4k
    } else if (flags & ZEND_ACC_PROTECTED_SET) {
2031
45
      smart_str_appends(str, "protected(set) ");
2032
14.3k
    } else if (flags & ZEND_ACC_PUBLIC_SET) {
2033
582
      smart_str_appends(str, "public(set) ");
2034
582
    }
2035
15.4k
  }
2036
44.6k
}
2037
2038
11.6k
static ZEND_COLD void zend_ast_export_type(smart_str *str, zend_ast *ast, int indent) {
2039
11.6k
  if (ast->kind == ZEND_AST_TYPE_UNION) {
2040
1.00k
    const zend_ast_list *list = zend_ast_get_list(ast);
2041
3.75k
    for (uint32_t i = 0; i < list->children; i++) {
2042
2.75k
      if (i != 0) {
2043
1.75k
        smart_str_appendc(str, '|');
2044
1.75k
      }
2045
2.75k
      zend_ast_export_type(str, list->child[i], indent);
2046
2.75k
    }
2047
1.00k
    return;
2048
1.00k
  }
2049
10.6k
  if (ast->kind == ZEND_AST_TYPE_INTERSECTION) {
2050
395
    const zend_ast_list *list = zend_ast_get_list(ast);
2051
1.44k
    for (uint32_t i = 0; i < list->children; i++) {
2052
1.04k
      if (i != 0) {
2053
654
        smart_str_appendc(str, '&');
2054
654
      }
2055
1.04k
      zend_ast_export_type(str, list->child[i], indent);
2056
1.04k
    }
2057
395
    return;
2058
395
  }
2059
10.2k
  if (ast->attr & ZEND_TYPE_NULLABLE) {
2060
1.09k
    smart_str_appendc(str, '?');
2061
1.09k
  }
2062
10.2k
  zend_ast_export_ns_name(str, ast, 0, indent);
2063
10.2k
}
2064
2065
static ZEND_COLD void zend_ast_export_hook_list(smart_str *str, const zend_ast_list *hook_list, int indent)
2066
1.27k
{
2067
1.27k
  smart_str_appends(str, " {");
2068
1.27k
  smart_str_appendc(str, '\n');
2069
1.27k
  indent++;
2070
1.27k
  zend_ast_export_indent(str, indent);
2071
2072
5.23k
  for (uint32_t i = 0; i < hook_list->children; i++) {
2073
3.96k
    const zend_ast_decl *hook = (const zend_ast_decl *)hook_list->child[i];
2074
3.96k
    zend_ast_export_visibility(str, hook->flags, ZEND_MODIFIER_TARGET_PROPERTY);
2075
3.96k
    if (hook->flags & ZEND_ACC_FINAL) {
2076
894
      smart_str_appends(str, "final ");
2077
894
    }
2078
3.96k
    smart_str_append(str, hook->name);
2079
3.96k
    zend_ast *body = hook->child[2];
2080
3.96k
    if (body == NULL) {
2081
1.59k
      smart_str_appendc(str, ';');
2082
2.36k
    } else if (body->kind == ZEND_AST_PROPERTY_HOOK_SHORT_BODY) {
2083
1.04k
      smart_str_appends(str, " => ");
2084
1.04k
      zend_ast_export_ex(str, body->child[0], 0, indent);
2085
1.04k
      smart_str_appendc(str, ';');
2086
1.32k
    } else {
2087
1.32k
      smart_str_appends(str, " {\n");
2088
1.32k
      zend_ast_export_stmt(str, body, indent + 1);
2089
1.32k
      zend_ast_export_indent(str, indent);
2090
1.32k
      smart_str_appendc(str, '}');
2091
1.32k
    }
2092
3.96k
    if (i < (hook_list->children - 1)) {
2093
2.78k
      smart_str_appendc(str, '\n');
2094
2.78k
      zend_ast_export_indent(str, indent);
2095
2.78k
    }
2096
3.96k
  }
2097
1.27k
  smart_str_appendc(str, '\n');
2098
1.27k
  indent--;
2099
1.27k
  zend_ast_export_indent(str, indent);
2100
1.27k
  smart_str_appendc(str, '}');
2101
1.27k
}
2102
2103
532k
#define BINARY_OP(_op, _p, _pl, _pr) do { \
2104
532k
    op = _op; \
2105
532k
    p = _p; \
2106
532k
    pl = _pl; \
2107
532k
    pr = _pr; \
2108
532k
    goto binary_op; \
2109
532k
  } while (0)
2110
2111
275k
#define PREFIX_OP(_op, _p, _pl) do { \
2112
275k
    op = _op; \
2113
275k
    p = _p; \
2114
275k
    pl = _pl; \
2115
275k
    goto prefix_op; \
2116
275k
  } while (0)
2117
2118
8.04k
#define FUNC_OP(_op) do { \
2119
8.04k
    op = _op; \
2120
8.04k
    goto func_op; \
2121
8.04k
  } while (0)
2122
2123
1.03k
#define POSTFIX_OP(_op, _p, _pl) do { \
2124
1.03k
    op = _op; \
2125
1.03k
    p = _p; \
2126
1.03k
    pl = _pl; \
2127
1.03k
    goto postfix_op; \
2128
1.03k
  } while (0)
2129
2130
30.1k
#define APPEND_NODE_1(_op) do { \
2131
30.1k
    op = _op; \
2132
30.1k
    goto append_node_1; \
2133
30.1k
  } while (0)
2134
2135
23.8k
#define APPEND_STR(_op) do { \
2136
23.8k
    op = _op; \
2137
23.8k
    goto append_str; \
2138
23.8k
  } while (0)
2139
2140
1.32k
#define APPEND_DEFAULT_VALUE(n) do { \
2141
1.32k
    p = n; \
2142
1.32k
    goto append_default_value; \
2143
1.32k
  } while (0)
2144
2145
static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int priority, int indent)
2146
2.93M
{
2147
2.93M
  const zend_ast_decl *decl;
2148
2.93M
  int p, pl, pr;
2149
2.93M
  const char *op;
2150
2151
3.14M
tail_call:
2152
3.14M
  if (!ast) {
2153
30.0k
    return;
2154
30.0k
  }
2155
3.11M
  switch (ast->kind) {
2156
    /* special nodes */
2157
424k
    case ZEND_AST_ZVAL:
2158
424k
      zend_ast_export_zval(str, zend_ast_get_zval(ast), priority, indent);
2159
424k
      break;
2160
219
    case ZEND_AST_CONSTANT: {
2161
219
      zend_string *name = zend_ast_get_constant_name(ast);
2162
219
      smart_str_append(str, name);
2163
219
      break;
2164
0
    }
2165
6
    case ZEND_AST_OP_ARRAY:
2166
6
      smart_str_appends(str, "Closure(");
2167
6
      smart_str_append(str, zend_ast_get_op_array(ast)->op_array->function_name);
2168
6
      smart_str_appendc(str, ')');
2169
6
      break;
2170
0
    case ZEND_AST_CONSTANT_CLASS:
2171
0
      smart_str_appendl(str, "__CLASS__", sizeof("__CLASS__")-1);
2172
0
      break;
2173
0
    case ZEND_AST_ZNODE:
2174
      /* This AST kind is only used for temporary nodes during compilation */
2175
0
      ZEND_UNREACHABLE();
2176
0
      break;
2177
2178
    /* declaration nodes */
2179
1.27k
    case ZEND_AST_FUNC_DECL:
2180
14.6k
    case ZEND_AST_CLOSURE:
2181
27.5k
    case ZEND_AST_ARROW_FUNC:
2182
28.6k
    case ZEND_AST_METHOD:
2183
28.6k
      decl = (const zend_ast_decl *) ast;
2184
28.6k
      if (decl->kind == ZEND_AST_ARROW_FUNC && (decl->attr & ZEND_PARENTHESIZED_ARROW_FUNC)) {
2185
76
        smart_str_appendc(str, '(');
2186
76
      }
2187
28.6k
      if (decl->child[4]) {
2188
1.19k
        bool newlines = !(ast->kind == ZEND_AST_CLOSURE || ast->kind == ZEND_AST_ARROW_FUNC);
2189
1.19k
        zend_ast_export_attributes(str, decl->child[4], indent, newlines);
2190
1.19k
      }
2191
2192
28.6k
      zend_ast_export_visibility(str, decl->flags, ZEND_MODIFIER_TARGET_METHOD);
2193
2194
28.6k
      if (decl->flags & ZEND_ACC_STATIC) {
2195
603
        smart_str_appends(str, "static ");
2196
603
      }
2197
28.6k
      if (decl->flags & ZEND_ACC_ABSTRACT) {
2198
380
        smart_str_appends(str, "abstract ");
2199
380
      }
2200
28.6k
      if (decl->flags & ZEND_ACC_FINAL) {
2201
97
        smart_str_appends(str, "final ");
2202
97
      }
2203
28.6k
      if (decl->kind == ZEND_AST_ARROW_FUNC) {
2204
12.8k
        smart_str_appends(str, "fn");
2205
15.7k
      } else {
2206
15.7k
        smart_str_appends(str, "function ");
2207
15.7k
      }
2208
28.6k
      if (decl->flags & ZEND_ACC_RETURN_REFERENCE) {
2209
575
        smart_str_appendc(str, '&');
2210
575
      }
2211
28.6k
      if (ast->kind != ZEND_AST_CLOSURE && ast->kind != ZEND_AST_ARROW_FUNC) {
2212
2.41k
        smart_str_append(str, decl->name);
2213
2.41k
      }
2214
28.6k
      smart_str_appendc(str, '(');
2215
28.6k
      zend_ast_export_ex(str, decl->child[0], 0, indent);
2216
28.6k
      smart_str_appendc(str, ')');
2217
28.6k
      zend_ast_export_ex(str, decl->child[1], 0, indent);
2218
28.6k
      if (decl->child[3]) {
2219
1.40k
        smart_str_appends(str, ": ");
2220
1.40k
        zend_ast_export_type(str, decl->child[3], indent);
2221
1.40k
      }
2222
28.6k
      if (decl->child[2]) {
2223
27.6k
        if (decl->kind == ZEND_AST_ARROW_FUNC) {
2224
12.8k
          zend_ast *body = decl->child[2];
2225
12.8k
          if (body->kind == ZEND_AST_RETURN) {
2226
0
            body = body->child[0];
2227
0
          }
2228
12.8k
          smart_str_appends(str, " => ");
2229
12.8k
          zend_ast_export_ex(str, body, 0, indent);
2230
12.8k
          if (decl->attr & ZEND_PARENTHESIZED_ARROW_FUNC) {
2231
76
            smart_str_appendc(str, ')');
2232
76
          }
2233
12.8k
          break;
2234
12.8k
        }
2235
2236
14.8k
        smart_str_appends(str, " {\n");
2237
14.8k
        zend_ast_export_stmt(str, decl->child[2], indent + 1);
2238
14.8k
        zend_ast_export_indent(str, indent);
2239
14.8k
        smart_str_appendc(str, '}');
2240
14.8k
        if (ast->kind != ZEND_AST_CLOSURE) {
2241
1.47k
          smart_str_appendc(str, '\n');
2242
1.47k
        }
2243
14.8k
      } else {
2244
944
        smart_str_appends(str, ";\n");
2245
944
      }
2246
15.7k
      break;
2247
15.7k
    case ZEND_AST_CLASS:
2248
6.10k
      decl = (const zend_ast_decl *) ast;
2249
6.10k
      if (decl->child[3]) {
2250
1.05k
        zend_ast_export_attributes(str, decl->child[3], indent, true);
2251
1.05k
      }
2252
6.10k
      if (decl->flags & ZEND_ACC_INTERFACE) {
2253
1.56k
        smart_str_appends(str, "interface ");
2254
4.53k
      } else if (decl->flags & ZEND_ACC_TRAIT) {
2255
299
        smart_str_appends(str, "trait ");
2256
4.23k
      } else if (decl->flags & ZEND_ACC_ENUM) {
2257
802
        smart_str_appends(str, "enum ");
2258
3.43k
      } else {
2259
3.43k
        if (decl->flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) {
2260
456
          smart_str_appends(str, "abstract ");
2261
456
        }
2262
3.43k
        if (decl->flags & ZEND_ACC_FINAL) {
2263
173
          smart_str_appends(str, "final ");
2264
173
        }
2265
3.43k
        if (decl->flags & ZEND_ACC_READONLY_CLASS) {
2266
88
          smart_str_appends(str, "readonly ");
2267
88
        }
2268
3.43k
        smart_str_appends(str, "class ");
2269
3.43k
      }
2270
6.10k
      smart_str_append(str, decl->name);
2271
6.10k
      if (decl->flags & ZEND_ACC_ENUM && decl->child[4]) {
2272
308
        smart_str_appends(str, ": ");
2273
308
        zend_ast_export_type(str, decl->child[4], indent);
2274
308
      }
2275
6.10k
      zend_ast_export_class_no_header(str, decl, indent);
2276
6.10k
      smart_str_appendc(str, '\n');
2277
6.10k
      break;
2278
2279
    /* list nodes */
2280
490k
    case ZEND_AST_ARG_LIST:
2281
495k
    case ZEND_AST_EXPR_LIST:
2282
524k
    case ZEND_AST_PARAM_LIST:
2283
528k
simple_list:
2284
528k
      zend_ast_export_list(str, zend_ast_get_list(ast), true, 20, indent);
2285
528k
      break;
2286
3.25k
    case ZEND_AST_ARRAY:
2287
3.25k
      smart_str_appendc(str, '[');
2288
3.25k
      zend_ast_export_list(str, zend_ast_get_list(ast), true, 20, indent);
2289
3.25k
      smart_str_appendc(str, ']');
2290
3.25k
      break;
2291
4.69k
    case ZEND_AST_ENCAPS_LIST:
2292
4.69k
      smart_str_appendc(str, '"');
2293
4.69k
      zend_ast_export_encaps_list(str, '"', zend_ast_get_list(ast), indent);
2294
4.69k
      smart_str_appendc(str, '"');
2295
4.69k
      break;
2296
0
    case ZEND_AST_STMT_LIST:
2297
316
    case ZEND_AST_TRAIT_ADAPTATIONS:
2298
316
      zend_ast_export_stmt(str, ast, indent);
2299
316
      break;
2300
5.92k
    case ZEND_AST_IF:
2301
5.92k
      zend_ast_export_if_stmt(str, zend_ast_get_list(ast), indent);
2302
5.92k
      break;
2303
295
    case ZEND_AST_SWITCH_LIST:
2304
993
    case ZEND_AST_CATCH_LIST:
2305
1.31k
    case ZEND_AST_MATCH_ARM_LIST:
2306
1.31k
      zend_ast_export_list(str, zend_ast_get_list(ast), false, 0, indent);
2307
1.31k
      break;
2308
866
    case ZEND_AST_CLOSURE_USES:
2309
866
      smart_str_appends(str, " use(");
2310
866
      zend_ast_export_var_list(str, zend_ast_get_list(ast), indent);
2311
866
      smart_str_appendc(str, ')');
2312
866
      break;
2313
3.04k
    case ZEND_AST_PROP_GROUP: {
2314
3.04k
      zend_ast *type_ast = ast->child[0];
2315
3.04k
      zend_ast *prop_ast = ast->child[1];
2316
2317
3.04k
      if (ast->child[2]) {
2318
101
        zend_ast_export_attributes(str, ast->child[2], indent, true);
2319
101
      }
2320
2321
3.04k
      zend_ast_export_visibility(str, ast->attr, ZEND_MODIFIER_TARGET_PROPERTY);
2322
2323
3.04k
      if (ast->attr & ZEND_ACC_STATIC) {
2324
512
        smart_str_appends(str, "static ");
2325
512
      }
2326
3.04k
      if (ast->attr & ZEND_ACC_READONLY) {
2327
75
        smart_str_appends(str, "readonly ");
2328
75
      }
2329
2330
3.04k
      if (type_ast) {
2331
1.15k
        zend_ast_export_type(str, type_ast, indent);
2332
1.15k
        smart_str_appendc(str, ' ');
2333
1.15k
      }
2334
2335
3.04k
      ast = prop_ast;
2336
3.04k
      goto simple_list;
2337
993
    }
2338
2339
0
    case ZEND_AST_CONST_DECL: {
2340
0
      zend_ast_list *ast_list = zend_ast_get_list(ast);
2341
      /* Attributes are stored at the end of the list if present. */
2342
0
      if (ast_list->child[ast_list->children - 1]->kind == ZEND_AST_ATTRIBUTE_LIST) {
2343
0
        zend_ast_export_attributes(
2344
0
          str,
2345
0
          ast_list->child[ast_list->children - 1],
2346
0
          indent,
2347
0
          true
2348
0
        );
2349
        /* So that the list printing doesn't try to print the attributes,
2350
         * use zend_ast_export_list_ex() to override the number of children
2351
         * to print. */
2352
0
        smart_str_appends(str, "const ");
2353
0
        zend_ast_export_list_ex(str, ast_list, true, 20, indent, ast_list->children - 1);
2354
0
        break;
2355
0
      }
2356
0
      smart_str_appends(str, "const ");
2357
0
      goto simple_list;
2358
0
    }
2359
522
    case ZEND_AST_CLASS_CONST_GROUP:
2360
522
      if (ast->child[1]) {
2361
42
        zend_ast_export_attributes(str, ast->child[1], indent, true);
2362
42
      }
2363
2364
522
      zend_ast_export_visibility(str, ast->attr, ZEND_MODIFIER_TARGET_CONSTANT);
2365
522
      smart_str_appends(str, "const ");
2366
522
      if (ast->child[2]) {
2367
341
        zend_ast_export_type(str, ast->child[2], indent);
2368
341
        smart_str_appendc(str, ' ');
2369
341
      }
2370
2371
522
      ast = ast->child[0];
2372
2373
522
      goto simple_list;
2374
2.17k
    case ZEND_AST_NAME_LIST:
2375
2.17k
      zend_ast_export_name_list(str, zend_ast_get_list(ast), indent);
2376
2.17k
      break;
2377
0
    case ZEND_AST_USE:
2378
0
      smart_str_appends(str, "use ");
2379
0
      if (ast->attr == T_FUNCTION) {
2380
0
        smart_str_appends(str, "function ");
2381
0
      } else if (ast->attr == T_CONST) {
2382
0
        smart_str_appends(str, "const ");
2383
0
      }
2384
0
      goto simple_list;
2385
2386
    /* 0 child nodes */
2387
23.0k
    case ZEND_AST_MAGIC_CONST:
2388
23.0k
      switch (ast->attr) {
2389
4
        case T_LINE:     APPEND_STR("__LINE__");
2390
8
        case T_FILE:     APPEND_STR("__FILE__");
2391
0
        case T_DIR:      APPEND_STR("__DIR__");
2392
22.3k
        case T_TRAIT_C:  APPEND_STR("__TRAIT__");
2393
664
        case T_METHOD_C: APPEND_STR("__METHOD__");
2394
4
        case T_FUNC_C:   APPEND_STR("__FUNCTION__");
2395
4
        case T_PROPERTY_C: APPEND_STR("__PROPERTY__");
2396
6
        case T_NS_C:     APPEND_STR("__NAMESPACE__");
2397
8
        case T_CLASS_C:  APPEND_STR("__CLASS__");
2398
0
        default: ZEND_UNREACHABLE();
2399
23.0k
      }
2400
0
      break;
2401
534
    case ZEND_AST_TYPE:
2402
534
      switch (ast->attr & ~ZEND_TYPE_NULLABLE) {
2403
102
        case IS_ARRAY:    APPEND_STR("array");
2404
5
        case IS_CALLABLE: APPEND_STR("callable");
2405
427
        case IS_STATIC:   APPEND_STR("static");
2406
0
        case IS_MIXED:    APPEND_STR("mixed");
2407
0
        default: ZEND_UNREACHABLE();
2408
534
      }
2409
0
      break;
2410
247
    case ZEND_AST_PLACEHOLDER_ARG:
2411
247
      if (ast->attr == ZEND_PLACEHOLDER_VARIADIC) {
2412
147
        APPEND_STR("...");
2413
147
      } else  {
2414
100
        APPEND_STR("?");
2415
100
      }
2416
0
      break;
2417
2418
    /* 1 child node */
2419
87.7k
    case ZEND_AST_VAR:
2420
87.7k
      smart_str_appendc(str, '$');
2421
87.7k
      zend_ast_export_var(str, ast->child[0], indent);
2422
87.7k
      break;
2423
400k
    case ZEND_AST_CONST:
2424
400k
      zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2425
400k
      break;
2426
1.01k
    case ZEND_AST_UNPACK:
2427
1.01k
      smart_str_appends(str, "...");
2428
1.01k
      ast = ast->child[0];
2429
1.01k
      goto tail_call;
2430
59.3k
    case ZEND_AST_UNARY_PLUS:  PREFIX_OP("+", 240, 241);
2431
48.4k
    case ZEND_AST_UNARY_MINUS: PREFIX_OP("-", 240, 241);
2432
2.91k
    case ZEND_AST_CAST:
2433
2.91k
      switch (ast->attr) {
2434
1.03k
        case IS_NULL:      PREFIX_OP("(unset)",  240, 241);
2435
197
        case _IS_BOOL:     PREFIX_OP("(bool)",   240, 241);
2436
85
        case IS_LONG:      PREFIX_OP("(int)",    240, 241);
2437
209
        case IS_DOUBLE:    PREFIX_OP("(float)", 240, 241);
2438
814
        case IS_STRING:    PREFIX_OP("(string)", 240, 241);
2439
518
        case IS_ARRAY:     PREFIX_OP("(array)",  240, 241);
2440
54
        case IS_OBJECT:    PREFIX_OP("(object)", 240, 241);
2441
0
        default: ZEND_UNREACHABLE();
2442
2.91k
      }
2443
0
      break;
2444
877
    case ZEND_AST_CAST_VOID:
2445
877
      PREFIX_OP("(void)", 240, 241);
2446
0
      break;
2447
441
    case ZEND_AST_EMPTY:
2448
441
      FUNC_OP("empty");
2449
5.89k
    case ZEND_AST_ISSET:
2450
5.89k
      FUNC_OP("isset");
2451
30.3k
    case ZEND_AST_SILENCE:
2452
30.3k
      PREFIX_OP("@", 240, 241);
2453
3.39k
    case ZEND_AST_SHELL_EXEC:
2454
3.39k
      smart_str_appendc(str, '`');
2455
3.39k
      if (ast->child[0]->kind == ZEND_AST_ENCAPS_LIST) {
2456
576
        zend_ast_export_encaps_list(str, '`', zend_ast_get_list(ast->child[0]), indent);
2457
2.82k
      } else {
2458
2.82k
        zval *zv;
2459
2.82k
        ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_ZVAL);
2460
2.82k
        zv = zend_ast_get_zval(ast->child[0]);
2461
2.82k
        ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
2462
2.82k
        zend_ast_export_qstr(str, '`', Z_STR_P(zv));
2463
2.82k
      }
2464
3.39k
      smart_str_appendc(str, '`');
2465
3.39k
      break;
2466
134
    case ZEND_AST_PRINT:
2467
134
      PREFIX_OP("print ", 60, 61);
2468
1.68k
    case ZEND_AST_INCLUDE_OR_EVAL:
2469
1.68k
      switch (ast->attr) {
2470
304
        case ZEND_INCLUDE_ONCE: FUNC_OP("include_once");
2471
454
        case ZEND_INCLUDE:      FUNC_OP("include");
2472
358
        case ZEND_REQUIRE_ONCE: FUNC_OP("require_once");
2473
325
        case ZEND_REQUIRE:      FUNC_OP("require");
2474
242
        case ZEND_EVAL:         FUNC_OP("eval");
2475
0
        default: ZEND_UNREACHABLE();
2476
1.68k
      }
2477
0
      break;
2478
132k
    case ZEND_AST_UNARY_OP:
2479
132k
      switch (ast->attr) {
2480
72.2k
        case ZEND_BW_NOT:   PREFIX_OP("~", 240, 241);
2481
60.1k
        case ZEND_BOOL_NOT: PREFIX_OP("!", 240, 241);
2482
0
        default: ZEND_UNREACHABLE();
2483
132k
      }
2484
0
      break;
2485
205
    case ZEND_AST_PRE_INC:
2486
205
      PREFIX_OP("++", 240, 241);
2487
156
    case ZEND_AST_PRE_DEC:
2488
156
      PREFIX_OP("--", 240, 241);
2489
956
    case ZEND_AST_POST_INC:
2490
956
      POSTFIX_OP("++", 240, 241);
2491
80
    case ZEND_AST_POST_DEC:
2492
80
      POSTFIX_OP("--", 240, 241);
2493
2494
392
    case ZEND_AST_GLOBAL:
2495
392
      APPEND_NODE_1("global");
2496
22
    case ZEND_AST_UNSET:
2497
22
      FUNC_OP("unset");
2498
435
    case ZEND_AST_RETURN:
2499
435
      APPEND_NODE_1("return");
2500
1.29k
    case ZEND_AST_LABEL:
2501
1.29k
      zend_ast_export_name(str, ast->child[0], 0, indent);
2502
1.29k
      smart_str_appendc(str, ':');
2503
1.29k
      break;
2504
534
    case ZEND_AST_REF:
2505
534
      smart_str_appendc(str, '&');
2506
534
      ast = ast->child[0];
2507
534
      goto tail_call;
2508
0
    case ZEND_AST_HALT_COMPILER:
2509
0
      APPEND_STR("__HALT_COMPILER()");
2510
28.4k
    case ZEND_AST_ECHO:
2511
28.4k
      APPEND_NODE_1("echo");
2512
79
    case ZEND_AST_THROW:
2513
79
      APPEND_NODE_1("throw");
2514
185
    case ZEND_AST_GOTO:
2515
185
      smart_str_appends(str, "goto ");
2516
185
      zend_ast_export_name(str, ast->child[0], 0, indent);
2517
185
      break;
2518
126
    case ZEND_AST_BREAK:
2519
126
      APPEND_NODE_1("break");
2520
729
    case ZEND_AST_CONTINUE:
2521
729
      APPEND_NODE_1("continue");
2522
2523
    /* 2 child nodes */
2524
4.60k
    case ZEND_AST_DIM:
2525
4.60k
      zend_ast_export_ex(str, ast->child[0], 260, indent);
2526
4.60k
      smart_str_appendc(str, '[');
2527
4.60k
      if (ast->child[1]) {
2528
4.32k
        zend_ast_export_ex(str, ast->child[1], 0, indent);
2529
4.32k
      }
2530
4.60k
      smart_str_appendc(str, ']');
2531
4.60k
      break;
2532
7.50k
    case ZEND_AST_PROP:
2533
17.7k
    case ZEND_AST_NULLSAFE_PROP:
2534
17.7k
      zend_ast_export_ex(str, ast->child[0], 0, indent);
2535
17.7k
      smart_str_appends(str, ast->kind == ZEND_AST_NULLSAFE_PROP ? "?->" : "->");
2536
17.7k
      zend_ast_export_var(str, ast->child[1], indent);
2537
17.7k
      break;
2538
1.41k
    case ZEND_AST_STATIC_PROP:
2539
1.41k
      zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2540
1.41k
      smart_str_appends(str, "::$");
2541
1.41k
      zend_ast_export_var(str, ast->child[1], indent);
2542
1.41k
      break;
2543
487k
    case ZEND_AST_CALL: {
2544
487k
      zend_ast *left = ast->child[0];
2545
487k
      if (left->kind == ZEND_AST_ARROW_FUNC || left->kind == ZEND_AST_CLOSURE) {
2546
209
        smart_str_appendc(str, '(');
2547
209
        zend_ast_export_ns_name(str, left, 0, indent);
2548
209
        smart_str_appendc(str, ')');
2549
486k
      } else {
2550
486k
        zend_ast_export_ns_name(str, left, 0, indent);
2551
486k
      }
2552
487k
      smart_str_appendc(str, '(');
2553
487k
      zend_ast_export_ex(str, ast->child[1], 0, indent);
2554
487k
      smart_str_appendc(str, ')');
2555
487k
      break;
2556
7.50k
    }
2557
247
    case ZEND_AST_CALLABLE_CONVERT: {
2558
247
      zend_ast_fcc *fcc_ast = (zend_ast_fcc*)ast;
2559
247
      ast = fcc_ast->args;
2560
247
      goto simple_list;
2561
7.50k
    }
2562
1.43k
    case ZEND_AST_CLASS_CONST:
2563
1.43k
      zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2564
1.43k
      smart_str_appends(str, "::");
2565
1.43k
      zend_ast_export_name(str, ast->child[1], 0, indent);
2566
1.43k
      break;
2567
198
    case ZEND_AST_CLASS_NAME:
2568
198
      if (ast->child[0] == NULL) {
2569
        /* The const expr representation stores the fetch type instead. */
2570
0
        switch (ast->attr) {
2571
0
          case ZEND_FETCH_CLASS_SELF:
2572
0
            smart_str_append(str, ZSTR_KNOWN(ZEND_STR_SELF));
2573
0
            break;
2574
0
          case ZEND_FETCH_CLASS_PARENT:
2575
0
            smart_str_append(str, ZSTR_KNOWN(ZEND_STR_PARENT));
2576
0
            break;
2577
0
          default: ZEND_UNREACHABLE();
2578
0
        }
2579
198
      } else {
2580
198
        zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2581
198
      }
2582
198
      smart_str_appends(str, "::class");
2583
198
      break;
2584
8.47k
    case ZEND_AST_ASSIGN:            BINARY_OP(" = ",   90, 91, 90);
2585
235
    case ZEND_AST_ASSIGN_REF:        BINARY_OP(" =& ",  90, 91, 90);
2586
5.27k
    case ZEND_AST_ASSIGN_OP:
2587
5.27k
      switch (ast->attr) {
2588
15
        case ZEND_ADD:    BINARY_OP(" += ",  90, 91, 90);
2589
140
        case ZEND_SUB:    BINARY_OP(" -= ",  90, 91, 90);
2590
4.11k
        case ZEND_MUL:    BINARY_OP(" *= ",  90, 91, 90);
2591
0
        case ZEND_DIV:    BINARY_OP(" /= ",  90, 91, 90);
2592
15
        case ZEND_MOD:    BINARY_OP(" %= ",  90, 91, 90);
2593
0
        case ZEND_SL:     BINARY_OP(" <<= ", 90, 91, 90);
2594
0
        case ZEND_SR:     BINARY_OP(" >>= ", 90, 91, 90);
2595
335
        case ZEND_CONCAT: BINARY_OP(" .= ",  90, 91, 90);
2596
35
        case ZEND_BW_OR:  BINARY_OP(" |= ",  90, 91, 90);
2597
13
        case ZEND_BW_AND: BINARY_OP(" &= ",  90, 91, 90);
2598
596
        case ZEND_BW_XOR: BINARY_OP(" ^= ",  90, 91, 90);
2599
3
        case ZEND_POW:    BINARY_OP(" **= ", 90, 91, 90);
2600
0
        default: ZEND_UNREACHABLE();
2601
5.27k
      }
2602
0
      break;
2603
564
    case ZEND_AST_ASSIGN_COALESCE: BINARY_OP(" \?\?= ", 90, 91, 90);
2604
503k
    case ZEND_AST_BINARY_OP:
2605
503k
      switch (ast->attr) {
2606
15.2k
        case ZEND_ADD:                 BINARY_OP(" + ",   200, 200, 201);
2607
110k
        case ZEND_SUB:                 BINARY_OP(" - ",   200, 200, 201);
2608
97.2k
        case ZEND_MUL:                 BINARY_OP(" * ",   210, 210, 211);
2609
37.0k
        case ZEND_DIV:                 BINARY_OP(" / ",   210, 210, 211);
2610
3.93k
        case ZEND_MOD:                 BINARY_OP(" % ",   210, 210, 211);
2611
371
        case ZEND_SL:                  BINARY_OP(" << ",  190, 190, 191);
2612
174
        case ZEND_SR:                  BINARY_OP(" >> ",  190, 190, 191);
2613
70.7k
        case ZEND_CONCAT:              BINARY_OP(" . ",   185, 185, 186);
2614
35.7k
        case ZEND_BW_OR:               BINARY_OP(" | ",   140, 140, 141);
2615
126k
        case ZEND_BW_AND:              BINARY_OP(" & ",   160, 160, 161);
2616
834
        case ZEND_BW_XOR:              BINARY_OP(" ^ ",   150, 150, 151);
2617
515
        case ZEND_IS_IDENTICAL:        BINARY_OP(" === ", 170, 171, 171);
2618
474
        case ZEND_IS_NOT_IDENTICAL:    BINARY_OP(" !== ", 170, 171, 171);
2619
883
        case ZEND_IS_EQUAL:            BINARY_OP(" == ",  170, 171, 171);
2620
246
        case ZEND_IS_NOT_EQUAL:        BINARY_OP(" != ",  170, 171, 171);
2621
1.23k
        case ZEND_IS_SMALLER:          BINARY_OP(" < ",   180, 181, 181);
2622
179
        case ZEND_IS_SMALLER_OR_EQUAL: BINARY_OP(" <= ",  180, 181, 181);
2623
565
        case ZEND_POW:                 BINARY_OP(" ** ",  250, 251, 250);
2624
375
        case ZEND_BOOL_XOR:            BINARY_OP(" xor ",  40,  40,  41);
2625
417
        case ZEND_SPACESHIP:           BINARY_OP(" <=> ", 180, 181, 181);
2626
0
        default: ZEND_UNREACHABLE();
2627
503k
      }
2628
0
      break;
2629
4.16k
    case ZEND_AST_GREATER:                 BINARY_OP(" > ",   180, 181, 181);
2630
782
    case ZEND_AST_GREATER_EQUAL:           BINARY_OP(" >= ",  180, 181, 181);
2631
7.03k
    case ZEND_AST_AND:                     BINARY_OP(" && ",  130, 130, 131);
2632
866
    case ZEND_AST_OR:                      BINARY_OP(" || ",  120, 120, 121);
2633
371
    case ZEND_AST_PIPE:                    BINARY_OP(" |> ",  183, 183, 184);
2634
4.71k
    case ZEND_AST_ARRAY_ELEM:
2635
4.71k
      if (ast->child[1]) {
2636
472
        zend_ast_export_ex(str, ast->child[1], 80, indent);
2637
472
        smart_str_appends(str, " => ");
2638
472
      }
2639
4.71k
      if (ast->attr)
2640
908
        smart_str_appendc(str, '&');
2641
4.71k
      zend_ast_export_ex(str, ast->child[0], 80, indent);
2642
4.71k
      break;
2643
2.46k
    case ZEND_AST_NEW:
2644
2.46k
      smart_str_appends(str, "new ");
2645
2.46k
      if (ast->child[0]->kind == ZEND_AST_CLASS) {
2646
1.74k
        const zend_ast_decl *decl = (const zend_ast_decl *) ast->child[0];
2647
1.74k
        if (decl->child[3]) {
2648
18
          zend_ast_export_attributes(str, decl->child[3], indent, false);
2649
18
        }
2650
1.74k
        smart_str_appends(str, "class");
2651
1.74k
        if (!zend_ast_is_list(ast->child[1])
2652
1.66k
            || zend_ast_get_list(ast->child[1])->children) {
2653
659
          smart_str_appendc(str, '(');
2654
659
          zend_ast_export_ex(str, ast->child[1], 0, indent);
2655
659
          smart_str_appendc(str, ')');
2656
659
        }
2657
1.74k
        zend_ast_export_class_no_header(str, decl, indent);
2658
1.74k
      } else {
2659
714
        zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2660
714
        smart_str_appendc(str, '(');
2661
714
        zend_ast_export_ex(str, ast->child[1], 0, indent);
2662
714
        smart_str_appendc(str, ')');
2663
714
      }
2664
2.46k
      break;
2665
105
    case ZEND_AST_INSTANCEOF:
2666
105
      zend_ast_export_ex(str, ast->child[0], 0, indent);
2667
105
      smart_str_appends(str, " instanceof ");
2668
105
      zend_ast_export_ns_name(str, ast->child[1], 0, indent);
2669
105
      break;
2670
6.14k
    case ZEND_AST_YIELD:
2671
6.14k
      if (priority > 70) smart_str_appendc(str, '(');
2672
6.14k
      smart_str_appends(str, "yield ");
2673
6.14k
      if (ast->child[0]) {
2674
5.98k
        if (ast->child[1]) {
2675
823
          zend_ast_export_ex(str, ast->child[1], 70, indent);
2676
823
          smart_str_appends(str, " => ");
2677
823
        }
2678
5.98k
        zend_ast_export_ex(str, ast->child[0], 70, indent);
2679
5.98k
      }
2680
6.14k
      if (priority > 70) smart_str_appendc(str, ')');
2681
6.14k
      break;
2682
342
    case ZEND_AST_YIELD_FROM:
2683
342
      PREFIX_OP("yield from ", 85, 86);
2684
993
    case ZEND_AST_COALESCE: BINARY_OP(" ?? ", 110, 111, 110);
2685
214
    case ZEND_AST_STATIC:
2686
214
      smart_str_appends(str, "static $");
2687
214
      zend_ast_export_name(str, ast->child[0], 0, indent);
2688
214
      APPEND_DEFAULT_VALUE(1);
2689
472
    case ZEND_AST_WHILE:
2690
472
      smart_str_appends(str, "while (");
2691
472
      zend_ast_export_ex(str, ast->child[0], 0, indent);
2692
472
      smart_str_appends(str, ") {\n");
2693
472
      zend_ast_export_stmt(str, ast->child[1], indent + 1);
2694
472
      zend_ast_export_indent(str, indent);
2695
472
      smart_str_appendc(str, '}');
2696
472
      break;
2697
162
    case ZEND_AST_DO_WHILE:
2698
162
      smart_str_appends(str, "do {\n");
2699
162
      zend_ast_export_stmt(str, ast->child[0], indent + 1);
2700
162
      zend_ast_export_indent(str, indent);
2701
162
      smart_str_appends(str, "} while (");
2702
162
      zend_ast_export_ex(str, ast->child[1], 0, indent);
2703
162
      smart_str_appendc(str, ')');
2704
162
      break;
2705
2706
0
    case ZEND_AST_IF_ELEM:
2707
0
      if (ast->child[0]) {
2708
0
        smart_str_appends(str, "if (");
2709
0
        zend_ast_export_ex(str, ast->child[0], 0, indent);
2710
0
        smart_str_appends(str, ") {\n");
2711
0
        zend_ast_export_stmt(str, ast->child[1], indent + 1);
2712
0
      } else {
2713
0
        smart_str_appends(str, "else {\n");
2714
0
        zend_ast_export_stmt(str, ast->child[1], indent + 1);
2715
0
      }
2716
0
      zend_ast_export_indent(str, indent);
2717
0
      smart_str_appendc(str, '}');
2718
0
      break;
2719
295
    case ZEND_AST_SWITCH:
2720
295
      smart_str_appends(str, "switch (");
2721
295
      zend_ast_export_ex(str, ast->child[0], 0, indent);
2722
295
      smart_str_appends(str, ") {\n");
2723
295
      zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
2724
295
      zend_ast_export_indent(str, indent);
2725
295
      smart_str_appendc(str, '}');
2726
295
      break;
2727
903
    case ZEND_AST_SWITCH_CASE:
2728
903
      zend_ast_export_indent(str, indent);
2729
903
      if (ast->child[0]) {
2730
813
        smart_str_appends(str, "case ");
2731
813
        zend_ast_export_ex(str, ast->child[0], 0, indent);
2732
813
        smart_str_appends(str, ":\n");
2733
813
      } else {
2734
90
        smart_str_appends(str, "default:\n");
2735
90
      }
2736
903
      zend_ast_export_stmt(str, ast->child[1], indent + 1);
2737
903
      break;
2738
319
    case ZEND_AST_MATCH:
2739
319
      smart_str_appends(str, "match (");
2740
319
      zend_ast_export_ex(str, ast->child[0], 0, indent);
2741
319
      smart_str_appends(str, ") {\n");
2742
319
      zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
2743
319
      zend_ast_export_indent(str, indent);
2744
319
      smart_str_appendc(str, '}');
2745
319
      break;
2746
364
    case ZEND_AST_MATCH_ARM:
2747
364
      zend_ast_export_indent(str, indent);
2748
364
      if (ast->child[0]) {
2749
261
        zend_ast_export_list(str, zend_ast_get_list(ast->child[0]), true, 0, indent);
2750
261
        smart_str_appends(str, " => ");
2751
261
      } else {
2752
103
        smart_str_appends(str, "default => ");
2753
103
      }
2754
364
      zend_ast_export_ex(str, ast->child[1], 0, 0);
2755
364
      smart_str_appends(str, ",\n");
2756
364
      break;
2757
500
    case ZEND_AST_DECLARE:
2758
500
      smart_str_appends(str, "declare(");
2759
500
      ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_CONST_DECL);
2760
500
      zend_ast_export_list(str, zend_ast_get_list(ast->child[0]), true, 0, indent);
2761
500
      smart_str_appendc(str, ')');
2762
500
      if (ast->child[1]) {
2763
298
        smart_str_appends(str, " {\n");
2764
298
        zend_ast_export_stmt(str, ast->child[1], indent + 1);
2765
298
        zend_ast_export_indent(str, indent);
2766
298
        smart_str_appendc(str, '}');
2767
298
      } else {
2768
202
        smart_str_appendc(str, ';');
2769
202
      }
2770
500
      break;
2771
3.06k
    case ZEND_AST_PROP_ELEM:
2772
3.06k
      smart_str_appendc(str, '$');
2773
3.06k
      zend_ast_export_name(str, ast->child[0], 0, indent);
2774
2775
3.06k
      zend_ast *default_value = ast->child[1];
2776
3.06k
      if (default_value) {
2777
1.57k
        smart_str_appends(str, " = ");
2778
1.57k
        zend_ast_export_ex(str, default_value, 0, indent + 1);
2779
1.57k
      }
2780
2781
3.06k
      if (ast->child[3]) {
2782
1.22k
        zend_ast_export_hook_list(str, zend_ast_get_list(ast->child[3]), indent);
2783
1.22k
      }
2784
3.06k
      break;
2785
1.11k
    case ZEND_AST_CONST_ELEM:
2786
1.11k
      zend_ast_export_name(str, ast->child[0], 0, indent);
2787
1.11k
      APPEND_DEFAULT_VALUE(1);
2788
976
    case ZEND_AST_USE_TRAIT:
2789
976
      smart_str_appends(str, "use ");
2790
976
      zend_ast_export_ex(str, ast->child[0], 0, indent);
2791
976
      if (ast->child[1]) {
2792
316
        smart_str_appends(str, " {\n");
2793
316
        zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
2794
316
        zend_ast_export_indent(str, indent);
2795
316
        smart_str_appendc(str, '}');
2796
660
      } else {
2797
660
        smart_str_appendc(str, ';');
2798
660
      }
2799
976
      break;
2800
99
    case ZEND_AST_TRAIT_PRECEDENCE:
2801
99
      zend_ast_export_ex(str, ast->child[0], 0, indent);
2802
99
      smart_str_appends(str, " insteadof ");
2803
99
      zend_ast_export_ex(str, ast->child[1], 0, indent);
2804
99
      break;
2805
4.78k
    case ZEND_AST_TRAIT_METHOD_REFERENCE:
2806
4.78k
      if (ast->child[0]) {
2807
1.68k
        zend_ast_export_name(str, ast->child[0], 0, indent);
2808
1.68k
        smart_str_appends(str, "::");
2809
1.68k
      }
2810
4.78k
      zend_ast_export_name(str, ast->child[1], 0, indent);
2811
4.78k
      break;
2812
0
    case ZEND_AST_NAMESPACE:
2813
0
      smart_str_appends(str, "namespace");
2814
0
      if (ast->child[0]) {
2815
0
        smart_str_appendc(str, ' ');
2816
0
        zend_ast_export_name(str, ast->child[0], 0, indent);
2817
0
      }
2818
0
      if (ast->child[1]) {
2819
0
        smart_str_appends(str, " {\n");
2820
0
        zend_ast_export_stmt(str, ast->child[1], indent + 1);
2821
0
        zend_ast_export_indent(str, indent);
2822
0
        smart_str_appends(str, "}\n");
2823
0
      } else {
2824
0
        smart_str_appendc(str, ';');
2825
0
      }
2826
0
      break;
2827
0
    case ZEND_AST_USE_ELEM:
2828
4.69k
    case ZEND_AST_TRAIT_ALIAS:
2829
4.69k
      zend_ast_export_name(str, ast->child[0], 0, indent);
2830
4.69k
      if (ast->attr & ZEND_ACC_PUBLIC) {
2831
274
        smart_str_appends(str, " as public");
2832
4.41k
      } else if (ast->attr & ZEND_ACC_PROTECTED) {
2833
120
        smart_str_appends(str, " as protected");
2834
4.29k
      } else if (ast->attr & ZEND_ACC_PRIVATE) {
2835
291
        smart_str_appends(str, " as private");
2836
4.00k
      } else if (ast->child[1]) {
2837
3.40k
        smart_str_appends(str, " as");
2838
3.40k
      }
2839
4.69k
      if (ast->child[1]) {
2840
3.47k
        smart_str_appendc(str, ' ');
2841
3.47k
        zend_ast_export_name(str, ast->child[1], 0, indent);
2842
3.47k
      }
2843
4.69k
      break;
2844
175k
    case ZEND_AST_NAMED_ARG:
2845
175k
      smart_str_append(str, zend_ast_get_str(ast->child[0]));
2846
175k
      smart_str_appends(str, ": ");
2847
175k
      ast = ast->child[1];
2848
175k
      goto tail_call;
2849
2850
    /* 3 child nodes */
2851
377
    case ZEND_AST_METHOD_CALL:
2852
490
    case ZEND_AST_NULLSAFE_METHOD_CALL:
2853
490
      zend_ast_export_ex(str, ast->child[0], 0, indent);
2854
490
      smart_str_appends(str, ast->kind == ZEND_AST_NULLSAFE_METHOD_CALL ? "?->" : "->");
2855
490
      zend_ast_export_var(str, ast->child[1], indent);
2856
490
      smart_str_appendc(str, '(');
2857
490
      zend_ast_export_ex(str, ast->child[2], 0, indent);
2858
490
      smart_str_appendc(str, ')');
2859
490
      break;
2860
327
    case ZEND_AST_STATIC_CALL:
2861
327
      zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2862
327
      smart_str_appends(str, "::");
2863
327
      zend_ast_export_var(str, ast->child[1], indent);
2864
327
      smart_str_appendc(str, '(');
2865
327
      zend_ast_export_ex(str, ast->child[2], 0, indent);
2866
327
      smart_str_appendc(str, ')');
2867
327
      break;
2868
11.3k
    case ZEND_AST_CONDITIONAL:
2869
11.3k
      if (priority > 100) smart_str_appendc(str, '(');
2870
11.3k
      zend_ast_export_ex(str, ast->child[0], 100, indent);
2871
11.3k
      if (ast->child[1]) {
2872
936
        smart_str_appends(str, " ? ");
2873
936
        zend_ast_export_ex(str, ast->child[1], 101, indent);
2874
936
        smart_str_appends(str, " : ");
2875
10.3k
      } else {
2876
10.3k
        smart_str_appends(str, " ?: ");
2877
10.3k
      }
2878
11.3k
      zend_ast_export_ex(str, ast->child[2], 101, indent);
2879
11.3k
      if (priority > 100) smart_str_appendc(str, ')');
2880
11.3k
      break;
2881
2882
698
    case ZEND_AST_TRY:
2883
698
      smart_str_appends(str, "try {\n");
2884
698
      zend_ast_export_stmt(str, ast->child[0], indent + 1);
2885
698
      zend_ast_export_indent(str, indent);
2886
698
      zend_ast_export_ex(str, ast->child[1], 0, indent);
2887
698
      if (ast->child[2]) {
2888
343
        smart_str_appends(str, "} finally {\n");
2889
343
        zend_ast_export_stmt(str, ast->child[2], indent + 1);
2890
343
        zend_ast_export_indent(str, indent);
2891
343
      }
2892
698
      smart_str_appendc(str, '}');
2893
698
      break;
2894
352
    case ZEND_AST_CATCH:
2895
352
      smart_str_appends(str, "} catch (");
2896
352
      zend_ast_export_catch_name_list(str, zend_ast_get_list(ast->child[0]), indent);
2897
352
      if (ast->child[1]) {
2898
218
        smart_str_appends(str, " $");
2899
218
        zend_ast_export_var(str, ast->child[1], indent);
2900
218
      }
2901
352
      smart_str_appends(str, ") {\n");
2902
352
      zend_ast_export_stmt(str, ast->child[2], indent + 1);
2903
352
      zend_ast_export_indent(str, indent);
2904
352
      break;
2905
8.45k
    case ZEND_AST_PARAM:
2906
8.45k
      if (ast->child[3]) {
2907
428
        zend_ast_export_attributes(str, ast->child[3], indent, false);
2908
428
      }
2909
8.45k
      zend_ast_export_visibility(str, ast->attr, ZEND_MODIFIER_TARGET_CPP);
2910
8.45k
      if (ast->attr & ZEND_ACC_FINAL) {
2911
107
        smart_str_appends(str, "final ");
2912
107
      }
2913
8.45k
      if (ast->child[0]) {
2914
4.62k
        zend_ast_export_type(str, ast->child[0], indent);
2915
4.62k
        smart_str_appendc(str, ' ');
2916
4.62k
      }
2917
8.45k
      if (ast->attr & ZEND_PARAM_REF) {
2918
2.32k
        smart_str_appendc(str, '&');
2919
2.32k
      }
2920
8.45k
      if (ast->attr & ZEND_PARAM_VARIADIC) {
2921
899
        smart_str_appends(str, "...");
2922
899
      }
2923
8.45k
      smart_str_appendc(str, '$');
2924
8.45k
      zend_ast_export_name(str, ast->child[1], 0, indent);
2925
8.45k
      if (ast->child[2]) {
2926
1.16k
        smart_str_appends(str, " = ");
2927
1.16k
        zend_ast_export_ex(str, ast->child[2], 0, indent);
2928
1.16k
      }
2929
8.45k
      if (ast->child[5]) {
2930
44
        zend_ast_export_hook_list(str, zend_ast_get_list(ast->child[5]), indent);
2931
44
      }
2932
8.45k
      break;
2933
303
    case ZEND_AST_ENUM_CASE:
2934
303
      if (ast->child[3]) {
2935
61
        zend_ast_export_attributes(str, ast->child[3], indent, true);
2936
61
      }
2937
303
      smart_str_appends(str, "case ");
2938
303
      zend_ast_export_name(str, ast->child[0], 0, indent);
2939
303
      if (ast->child[1]) {
2940
213
        smart_str_appends(str, " = ");
2941
213
        zend_ast_export_ex(str, ast->child[1], 0, indent);
2942
213
      }
2943
303
      break;
2944
2945
    /* 4 child nodes */
2946
3.15k
    case ZEND_AST_FOR:
2947
3.15k
      smart_str_appends(str, "for (");
2948
3.15k
      zend_ast_export_ex(str, ast->child[0], 0, indent);
2949
3.15k
      smart_str_appendc(str, ';');
2950
3.15k
      if (ast->child[1]) {
2951
2.52k
        smart_str_appendc(str, ' ');
2952
2.52k
        zend_ast_export_ex(str, ast->child[1], 0, indent);
2953
2.52k
      }
2954
3.15k
      smart_str_appendc(str, ';');
2955
3.15k
      if (ast->child[2]) {
2956
1.78k
        smart_str_appendc(str, ' ');
2957
1.78k
        zend_ast_export_ex(str, ast->child[2], 0, indent);
2958
1.78k
      }
2959
3.15k
      smart_str_appends(str, ") {\n");
2960
3.15k
      zend_ast_export_stmt(str, ast->child[3], indent + 1);
2961
3.15k
      zend_ast_export_indent(str, indent);
2962
3.15k
      smart_str_appendc(str, '}');
2963
3.15k
      break;
2964
958
    case ZEND_AST_FOREACH:
2965
958
      smart_str_appends(str, "foreach (");
2966
958
      zend_ast_export_ex(str, ast->child[0], 0, indent);
2967
958
      smart_str_appends(str, " as ");
2968
958
      if (ast->child[2]) {
2969
307
        zend_ast_export_ex(str, ast->child[2], 0, indent);
2970
307
        smart_str_appends(str, " => ");
2971
307
      }
2972
958
      zend_ast_export_ex(str, ast->child[1], 0, indent);
2973
958
      smart_str_appends(str, ") {\n");
2974
958
      zend_ast_export_stmt(str, ast->child[3], indent + 1);
2975
958
      zend_ast_export_indent(str, indent);
2976
958
      smart_str_appendc(str, '}');
2977
958
      break;
2978
0
    default: ZEND_UNREACHABLE();
2979
3.11M
  }
2980
2.06M
  return;
2981
2982
2.06M
binary_op:
2983
532k
  if (priority > p) smart_str_appendc(str, '(');
2984
532k
  zend_ast_export_ex(str, ast->child[0], pl, indent);
2985
532k
  smart_str_appends(str, op);
2986
532k
  zend_ast_export_ex(str, ast->child[1], pr, indent);
2987
532k
  if (priority > p) smart_str_appendc(str, ')');
2988
532k
  return;
2989
2990
275k
prefix_op:
2991
275k
  if (priority > p) smart_str_appendc(str, '(');
2992
275k
  smart_str_appends(str, op);
2993
275k
  zend_ast_export_ex(str, ast->child[0], pl, indent);
2994
275k
  if (priority > p) smart_str_appendc(str, ')');
2995
275k
  return;
2996
2997
1.03k
postfix_op:
2998
1.03k
  if (priority > p) smart_str_appendc(str, '(');
2999
1.03k
  zend_ast_export_ex(str, ast->child[0], pl, indent);
3000
1.03k
  smart_str_appends(str, op);
3001
1.03k
  if (priority > p) smart_str_appendc(str, ')');
3002
1.03k
  return;
3003
3004
8.04k
func_op:
3005
8.04k
  smart_str_appends(str, op);
3006
8.04k
  smart_str_appendc(str, '(');
3007
8.04k
  zend_ast_export_ex(str, ast->child[0], 0, indent);
3008
8.04k
  smart_str_appendc(str, ')');
3009
8.04k
  return;
3010
3011
30.1k
append_node_1:
3012
30.1k
  smart_str_appends(str, op);
3013
30.1k
  if (ast->child[0]) {
3014
29.3k
    smart_str_appendc(str, ' ');
3015
29.3k
    ast = ast->child[0];
3016
29.3k
    goto tail_call;
3017
29.3k
  }
3018
847
  return;
3019
3020
23.8k
append_str:
3021
23.8k
  smart_str_appends(str, op);
3022
23.8k
  return;
3023
3024
1.32k
append_default_value:
3025
1.32k
  if (ast->child[p]) {
3026
1.14k
    smart_str_appends(str, " = ");
3027
1.14k
    ast = ast->child[p];
3028
1.14k
    goto tail_call;
3029
1.14k
  }
3030
185
  return;
3031
1.32k
}
3032
3033
ZEND_API ZEND_COLD zend_string *zend_ast_export(const char *prefix, zend_ast *ast, const char *suffix)
3034
14.4k
{
3035
14.4k
  smart_str str = {0};
3036
3037
14.4k
  smart_str_appends(&str, prefix);
3038
14.4k
  zend_ast_export_ex(&str, ast, 0, 0);
3039
14.4k
  smart_str_appends(&str, suffix);
3040
14.4k
  smart_str_0(&str);
3041
14.4k
  return str.s;
3042
14.4k
}
3043
3044
zend_ast * ZEND_FASTCALL zend_ast_with_attributes(zend_ast *ast, zend_ast *attr)
3045
12.1k
{
3046
12.1k
  ZEND_ASSERT(attr->kind == ZEND_AST_ATTRIBUTE_LIST);
3047
3048
12.1k
  switch (ast->kind) {
3049
481
  case ZEND_AST_FUNC_DECL:
3050
5.17k
  case ZEND_AST_CLOSURE:
3051
5.70k
  case ZEND_AST_METHOD:
3052
5.79k
  case ZEND_AST_ARROW_FUNC:
3053
6.04k
  case ZEND_AST_PROPERTY_HOOK:
3054
6.04k
    ((zend_ast_decl *) ast)->child[4] = attr;
3055
6.04k
    break;
3056
2.68k
  case ZEND_AST_CLASS:
3057
2.68k
    ((zend_ast_decl *) ast)->child[3] = attr;
3058
2.68k
    break;
3059
423
  case ZEND_AST_PROP_GROUP:
3060
423
    ast->child[2] = attr;
3061
423
    break;
3062
1.50k
  case ZEND_AST_PARAM:
3063
1.77k
  case ZEND_AST_ENUM_CASE:
3064
1.77k
    ast->child[3] = attr;
3065
1.77k
    break;
3066
340
  case ZEND_AST_CLASS_CONST_GROUP:
3067
340
    ast->child[1] = attr;
3068
340
    break;
3069
911
  case ZEND_AST_CONST_DECL:
3070
    /* Since constants are already stored in a list, just add the attributes
3071
     * to that list instead of storing them elsewhere;
3072
     * zend_compile_const_decl() checks the kind of the list elements. */
3073
911
    ast = zend_ast_list_add(ast, attr);
3074
911
    break;
3075
0
  default: ZEND_UNREACHABLE();
3076
12.1k
  }
3077
3078
12.1k
  return ast;
3079
12.1k
}
3080
3081
zend_ast * ZEND_FASTCALL zend_ast_call_get_args(zend_ast *ast)
3082
320
{
3083
320
  if (ast->kind == ZEND_AST_CALL) {
3084
229
    return ast->child[1];
3085
229
  } else if (ast->kind == ZEND_AST_STATIC_CALL || ast->kind == ZEND_AST_METHOD_CALL) {
3086
91
    return ast->child[2];
3087
91
  }
3088
3089
0
  ZEND_UNREACHABLE();
3090
0
  return NULL;
3091
0
}