Coverage Report

Created: 2026-02-14 06:52

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