Coverage Report

Created: 2026-04-01 06:49

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
9.60M
static inline void *zend_ast_alloc(size_t size) {
33
9.60M
  return zend_arena_alloc(&CG(ast_arena), size);
34
9.60M
}
35
36
140k
static inline void *zend_ast_realloc(const void *old, size_t old_size, size_t new_size) {
37
140k
  void *new = zend_ast_alloc(new_size);
38
140k
  memcpy(new, old, old_size);
39
140k
  return new;
40
140k
}
41
42
1.63M
static inline size_t zend_ast_list_size(uint32_t children) {
43
1.63M
  return sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * children;
44
1.63M
}
45
46
137k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_znode(const znode *node) {
47
137k
  zend_ast_znode *ast;
48
49
137k
  ast = zend_ast_alloc(sizeof(zend_ast_znode));
50
137k
  ast->kind = ZEND_AST_ZNODE;
51
137k
  ast->attr = 0;
52
137k
  ast->lineno = CG(zend_lineno);
53
137k
  ast->node = *node;
54
137k
  return (zend_ast *) ast;
55
137k
}
56
57
4.35k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_fcc(zend_ast *args) {
58
4.35k
  zend_ast_fcc *ast;
59
60
4.35k
  ast = zend_ast_alloc(sizeof(zend_ast_fcc));
61
4.35k
  ast->kind = ZEND_AST_CALLABLE_CONVERT;
62
4.35k
  ast->attr = 0;
63
4.35k
  ast->lineno = CG(zend_lineno);
64
4.35k
  ast->args = args;
65
4.35k
  ZEND_MAP_PTR_INIT(ast->fptr, NULL);
66
67
4.35k
  return (zend_ast *) ast;
68
4.35k
}
69
70
3.58M
static zend_always_inline zend_ast * zend_ast_create_zval_int(const zval *zv, uint32_t attr, uint32_t lineno) {
71
3.58M
  zend_ast_zval *ast;
72
73
3.58M
  ast = zend_ast_alloc(sizeof(zend_ast_zval));
74
3.58M
  ast->kind = ZEND_AST_ZVAL;
75
3.58M
  ast->attr = attr;
76
3.58M
  ZVAL_COPY_VALUE(&ast->val, zv);
77
3.58M
  Z_LINENO(ast->val) = lineno;
78
3.58M
  return (zend_ast *) ast;
79
3.58M
}
80
81
3.32M
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_with_lineno(const zval *zv, uint32_t lineno) {
82
3.32M
  return zend_ast_create_zval_int(zv, 0, lineno);
83
3.32M
}
84
85
936
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_ex(const zval *zv, zend_ast_attr attr) {
86
936
  return zend_ast_create_zval_int(zv, attr, CG(zend_lineno));
87
936
}
88
89
176k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval(const zval *zv) {
90
176k
  return zend_ast_create_zval_int(zv, 0, CG(zend_lineno));
91
176k
}
92
93
29.1k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_str(zend_string *str) {
94
29.1k
  zval zv;
95
29.1k
  ZVAL_STR(&zv, str);
96
29.1k
  return zend_ast_create_zval_int(&zv, 0, CG(zend_lineno));
97
29.1k
}
98
99
56.0k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_long(zend_long lval) {
100
56.0k
  zval zv;
101
56.0k
  ZVAL_LONG(&zv, lval);
102
56.0k
  return zend_ast_create_zval_int(&zv, 0, CG(zend_lineno));
103
56.0k
}
104
105
22.0k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_constant(zend_string *name, zend_ast_attr attr) {
106
22.0k
  zend_ast_zval *ast;
107
108
22.0k
  ast = zend_ast_alloc(sizeof(zend_ast_zval));
109
22.0k
  ast->kind = ZEND_AST_CONSTANT;
110
22.0k
  ast->attr = attr;
111
22.0k
  ZVAL_STR(&ast->val, name);
112
22.0k
  Z_LINENO(ast->val) = CG(zend_lineno);
113
22.0k
  return (zend_ast *) ast;
114
22.0k
}
115
116
139
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_op_array(zend_op_array *op_array) {
117
139
  zend_ast_op_array *ast;
118
119
139
  ast = zend_ast_alloc(sizeof(zend_ast_op_array));
120
139
  ast->kind = ZEND_AST_OP_ARRAY;
121
139
  ast->attr = 0;
122
139
  ast->lineno = CG(zend_lineno);
123
139
  ast->op_array = op_array;
124
125
139
  return (zend_ast *) ast;
126
139
}
127
128
32.3k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_class_const_or_name(zend_ast *class_name, zend_ast *name) {
129
32.3k
  zend_string *name_str = zend_ast_get_str(name);
130
32.3k
  if (zend_string_equals_ci(name_str, ZSTR_KNOWN(ZEND_STR_CLASS))) {
131
6.79k
    zend_string_release(name_str);
132
6.79k
    return zend_ast_create(ZEND_AST_CLASS_NAME, class_name);
133
25.5k
  } else {
134
25.5k
    return zend_ast_create(ZEND_AST_CLASS_CONST, class_name, name);
135
25.5k
  }
136
32.3k
}
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
130k
) {
142
130k
  zend_ast_decl *ast;
143
144
130k
  ast = zend_ast_alloc(sizeof(zend_ast_decl));
145
130k
  ast->kind = kind;
146
130k
  ast->attr = 0;
147
130k
  ast->start_lineno = start_lineno;
148
130k
  ast->end_lineno = CG(zend_lineno);
149
130k
  ast->flags = flags;
150
130k
  ast->doc_comment = doc_comment;
151
130k
  ast->name = name;
152
130k
  ast->child[0] = child0;
153
130k
  ast->child[1] = child1;
154
130k
  ast->child[2] = child2;
155
130k
  ast->child[3] = child3;
156
130k
  ast->child[4] = child4;
157
158
130k
  return (zend_ast *) ast;
159
130k
}
160
161
375k
static bool zend_ast_is_placeholder_arg(zend_ast *arg) {
162
375k
  return arg->kind == ZEND_AST_PLACEHOLDER_ARG
163
371k
    || (arg->kind == ZEND_AST_NAMED_ARG
164
11.4k
        && arg->child[1]->kind == ZEND_AST_PLACEHOLDER_ARG);
165
375k
}
166
167
#if ZEND_AST_SPEC
168
29.2k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_0(zend_ast_kind kind) {
169
29.2k
  zend_ast *ast;
170
171
29.2k
  ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 0);
172
29.2k
  ast = zend_ast_alloc(zend_ast_size(0));
173
29.2k
  ast->kind = kind;
174
29.2k
  ast->attr = 0;
175
29.2k
  ast->lineno = CG(zend_lineno);
176
177
29.2k
  return ast;
178
29.2k
}
179
180
2.09M
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_1(zend_ast_kind kind, zend_ast *child) {
181
2.09M
  zend_ast *ast;
182
2.09M
  uint32_t lineno;
183
184
2.09M
  ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 1);
185
2.09M
  ast = zend_ast_alloc(zend_ast_size(1));
186
2.09M
  ast->kind = kind;
187
2.09M
  ast->attr = 0;
188
2.09M
  ast->child[0] = child;
189
2.09M
  if (child) {
190
2.08M
    lineno = zend_ast_get_lineno(child);
191
2.08M
  } else {
192
2.51k
    lineno = CG(zend_lineno);
193
2.51k
  }
194
2.09M
  ast->lineno = lineno;
195
196
2.09M
  return ast;
197
2.09M
}
198
199
1.82M
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_2(zend_ast_kind kind, zend_ast *child1, zend_ast *child2) {
200
1.82M
  zend_ast *ast;
201
1.82M
  uint32_t lineno;
202
203
1.82M
  ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 2);
204
1.82M
  ast = zend_ast_alloc(zend_ast_size(2));
205
1.82M
  ast->kind = kind;
206
1.82M
  ast->attr = 0;
207
1.82M
  ast->child[0] = child1;
208
1.82M
  ast->child[1] = child2;
209
1.82M
  if (child1) {
210
1.82M
    lineno = zend_ast_get_lineno(child1);
211
1.82M
  } else if (child2) {
212
4.99k
    lineno = zend_ast_get_lineno(child2);
213
4.99k
  } else {
214
2.37k
    lineno = CG(zend_lineno);
215
2.37k
  }
216
1.82M
  ast->lineno = lineno;
217
218
1.82M
  return ast;
219
1.82M
}
220
221
174k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_3(zend_ast_kind kind, zend_ast *child1, zend_ast *child2, zend_ast *child3) {
222
174k
  zend_ast *ast;
223
174k
  uint32_t lineno;
224
225
174k
  ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 3);
226
174k
  ast = zend_ast_alloc(zend_ast_size(3));
227
174k
  ast->kind = kind;
228
174k
  ast->attr = 0;
229
174k
  ast->child[0] = child1;
230
174k
  ast->child[1] = child2;
231
174k
  ast->child[2] = child3;
232
174k
  if (child1) {
233
160k
    lineno = zend_ast_get_lineno(child1);
234
160k
  } else if (child2) {
235
13.2k
    lineno = zend_ast_get_lineno(child2);
236
13.2k
  } else if (child3) {
237
0
    lineno = zend_ast_get_lineno(child3);
238
0
  } else {
239
0
    lineno = CG(zend_lineno);
240
0
  }
241
174k
  ast->lineno = lineno;
242
243
174k
  return ast;
244
174k
}
245
246
60.3k
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
60.3k
  zend_ast *ast;
248
60.3k
  uint32_t lineno;
249
250
60.3k
  ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 4);
251
60.3k
  ast = zend_ast_alloc(zend_ast_size(4));
252
60.3k
  ast->kind = kind;
253
60.3k
  ast->attr = 0;
254
60.3k
  ast->child[0] = child1;
255
60.3k
  ast->child[1] = child2;
256
60.3k
  ast->child[2] = child3;
257
60.3k
  ast->child[3] = child4;
258
60.3k
  if (child1) {
259
55.8k
    lineno = zend_ast_get_lineno(child1);
260
55.8k
  } else if (child2) {
261
2.78k
    lineno = zend_ast_get_lineno(child2);
262
2.78k
  } else if (child3) {
263
330
    lineno = zend_ast_get_lineno(child3);
264
1.45k
  } else if (child4) {
265
1.18k
    lineno = zend_ast_get_lineno(child4);
266
1.18k
  } else {
267
270
    lineno = CG(zend_lineno);
268
270
  }
269
60.3k
  ast->lineno = lineno;
270
271
60.3k
  return ast;
272
60.3k
}
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
48.7k
    zend_ast_kind kind, zend_ast_attr attr, va_list *va) {
307
48.7k
  uint32_t lineno = (uint32_t)-1;
308
48.7k
  uint32_t children = kind >> ZEND_AST_NUM_CHILDREN_SHIFT;
309
48.7k
  zend_ast *ast = zend_ast_alloc(zend_ast_size(children));
310
48.7k
  ast->kind = kind;
311
48.7k
  ast->attr = attr;
312
341k
  for (uint32_t i = 0; i < children; i++) {
313
292k
    ast->child[i] = va_arg(*va, zend_ast *);
314
292k
    if (lineno == (uint32_t)-1 && ast->child[i]) {
315
48.7k
      lineno = zend_ast_get_lineno(ast->child[i]);
316
48.7k
    }
317
292k
  }
318
48.7k
  if (lineno == (uint32_t)-1) {
319
0
    lineno = CG(zend_lineno);
320
0
  }
321
48.7k
  ast->lineno = lineno;
322
48.7k
  return ast;
323
48.7k
}
324
325
1.31k
ZEND_API zend_ast * zend_ast_create_n(unsigned kind, ...) {
326
1.31k
  va_list va;
327
1.31k
  va_start(va, kind);
328
1.31k
  zend_ast *ast = zend_ast_create_va(kind, 0, &va);
329
1.31k
  va_end(va);
330
1.31k
  return ast;
331
1.31k
}
332
333
ZEND_API zend_ast * zend_ast_create_ex_n(
334
47.4k
    zend_ast_kind kind, unsigned attr, ...) {
335
47.4k
  va_list va;
336
47.4k
  va_start(va, attr);
337
47.4k
  zend_ast *ast = zend_ast_create_va(kind, attr, &va);
338
47.4k
  va_end(va);
339
47.4k
  return ast;
340
47.4k
}
341
342
568k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_0(zend_ast_kind kind) {
343
568k
  zend_ast *ast;
344
568k
  zend_ast_list *list;
345
346
568k
  ast = zend_ast_alloc(zend_ast_list_size(4));
347
568k
  list = (zend_ast_list *) ast;
348
568k
  list->kind = kind;
349
568k
  list->attr = 0;
350
568k
  list->lineno = CG(zend_lineno);
351
568k
  list->children = 0;
352
353
568k
  return ast;
354
568k
}
355
356
741k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_1(zend_ast_kind kind, zend_ast *child) {
357
741k
  zend_ast *ast;
358
741k
  zend_ast_list *list;
359
741k
  uint32_t lineno;
360
361
741k
  ast = zend_ast_alloc(zend_ast_list_size(4));
362
741k
  list = (zend_ast_list *) ast;
363
741k
  list->kind = kind;
364
741k
  list->attr = 0;
365
741k
  list->children = 1;
366
741k
  list->child[0] = child;
367
741k
  if (child) {
368
724k
    lineno = zend_ast_get_lineno(child);
369
724k
    if (lineno > CG(zend_lineno)) {
370
188
      lineno = CG(zend_lineno);
371
188
    }
372
724k
  } else {
373
16.8k
    lineno = CG(zend_lineno);
374
16.8k
  }
375
741k
  list->lineno = lineno;
376
377
741k
  return ast;
378
741k
}
379
380
44.6k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_2(zend_ast_kind kind, zend_ast *child1, zend_ast *child2) {
381
44.6k
  zend_ast *ast;
382
44.6k
  zend_ast_list *list;
383
44.6k
  uint32_t lineno;
384
385
44.6k
  ast = zend_ast_alloc(zend_ast_list_size(4));
386
44.6k
  list = (zend_ast_list *) ast;
387
44.6k
  list->kind = kind;
388
44.6k
  list->attr = 0;
389
44.6k
  list->children = 2;
390
44.6k
  list->child[0] = child1;
391
44.6k
  list->child[1] = child2;
392
44.6k
  if (child1) {
393
44.6k
    lineno = zend_ast_get_lineno(child1);
394
44.6k
    if (lineno > CG(zend_lineno)) {
395
0
      lineno = CG(zend_lineno);
396
0
    }
397
44.6k
  } 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
44.6k
  list->lineno = lineno;
407
408
44.6k
  return ast;
409
44.6k
}
410
411
81.6k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_arg_list_0(zend_ast_kind kind) {
412
81.6k
  return zend_ast_create_list(0, kind);
413
81.6k
}
414
415
249k
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_arg_list_1(zend_ast_kind kind, zend_ast *arg) {
416
249k
  zend_ast *list = zend_ast_create_list(1, kind, arg);
417
418
249k
  if (zend_ast_is_placeholder_arg(arg)) {
419
3.77k
    return zend_ast_create_fcc(list);
420
3.77k
  }
421
422
245k
  return list;
423
249k
}
424
425
461
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_arg_list_2(zend_ast_kind kind, zend_ast *arg1, zend_ast *arg2) {
426
461
  zend_ast *list = zend_ast_create_list(2, kind, arg1, arg2);
427
428
461
  if (zend_ast_is_placeholder_arg(arg1) || zend_ast_is_placeholder_arg(arg2)) {
429
107
    return zend_ast_create_fcc(list);
430
107
  }
431
432
354
  return list;
433
461
}
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
94.6k
zend_ast *zend_ast_create_concat_op(zend_ast *op0, zend_ast *op1) {
551
94.6k
  if (op0->kind == ZEND_AST_ZVAL && op1->kind == ZEND_AST_ZVAL) {
552
23.2k
    zval *zv0 = zend_ast_get_zval(op0);
553
23.2k
    zval *zv1 = zend_ast_get_zval(op1);
554
23.2k
    if (!zend_binary_op_produces_error(ZEND_CONCAT, zv0, zv1) &&
555
23.2k
        concat_function(zv0, zv0, zv1) == SUCCESS) {
556
23.2k
      zval_ptr_dtor_nogc(zv1);
557
23.2k
      return zend_ast_create_zval(zv0);
558
23.2k
    }
559
23.2k
  }
560
71.4k
  return zend_ast_create_binary_op(ZEND_CONCAT, op0, op1);
561
94.6k
}
562
563
1.06M
static inline bool is_power_of_two(uint32_t n) {
564
1.06M
  return ((n != 0) && (n == (n & (~n + 1))));
565
1.06M
}
566
567
1.94M
ZEND_ATTRIBUTE_NODISCARD ZEND_API zend_ast * ZEND_FASTCALL zend_ast_list_add(zend_ast *ast, zend_ast *op) {
568
1.94M
  zend_ast_list *list = zend_ast_get_list(ast);
569
1.94M
  if (list->children >= 4 && is_power_of_two(list->children)) {
570
140k
      list = zend_ast_realloc(list,
571
140k
      zend_ast_list_size(list->children), zend_ast_list_size(list->children * 2));
572
140k
  }
573
1.94M
  list->child[list->children++] = op;
574
1.94M
  return (zend_ast *) list;
575
1.94M
}
576
577
ZEND_API zend_ast * ZEND_FASTCALL zend_ast_arg_list_add(zend_ast *list, zend_ast *arg)
578
125k
{
579
125k
  if (list->kind == ZEND_AST_CALLABLE_CONVERT) {
580
359
    zend_ast_fcc *fcc_ast = (zend_ast_fcc*)list;
581
359
    fcc_ast->args = zend_ast_list_add(fcc_ast->args, arg);
582
359
    return (zend_ast*)fcc_ast;
583
359
  }
584
585
125k
  ZEND_ASSERT(list->kind == ZEND_AST_ARG_LIST);
586
587
125k
  if (zend_ast_is_placeholder_arg(arg)) {
588
471
    return zend_ast_create_fcc(zend_ast_list_add(list, arg));
589
471
  }
590
591
124k
  return zend_ast_list_add(list, arg);
592
125k
}
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
102
    if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), expr)) {
598
6
      zend_throw_error(NULL,
599
6
        "Cannot add element to the array as the next element is already occupied");
600
6
      return FAILURE;
601
6
    }
602
96
    return SUCCESS;
603
102
  }
604
605
279
  if (array_set_zval_key(Z_ARRVAL_P(result), offset, expr) == FAILURE) {
606
8
    return FAILURE;
607
8
  }
608
609
271
  zval_ptr_dtor_nogc(offset);
610
271
  zval_ptr_dtor_nogc(expr);
611
271
  return SUCCESS;
612
279
}
613
614
22
static zend_result zend_ast_add_unpacked_element(const zval *result, const zval *expr) {
615
22
  if (EXPECTED(Z_TYPE_P(expr) == IS_ARRAY)) {
616
17
    const HashTable *ht = Z_ARRVAL_P(expr);
617
17
    zval *val;
618
17
    zend_string *key;
619
620
93
    ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) {
621
93
      if (key) {
622
0
        zend_hash_update(Z_ARRVAL_P(result), key, val);
623
38
      } else {
624
38
        if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), val)) {
625
10
          zend_throw_error(NULL,
626
10
            "Cannot add element to the array as the next element is already occupied");
627
10
          return FAILURE;
628
10
        }
629
38
      }
630
28
      Z_TRY_ADDREF_P(val);
631
28
    } ZEND_HASH_FOREACH_END();
632
7
    return SUCCESS;
633
17
  }
634
635
5
  zend_throw_error(NULL, "Only arrays can be unpacked in constant expression");
636
5
  return FAILURE;
637
22
}
638
639
static zend_class_entry *zend_ast_fetch_class(zend_ast *ast, zend_class_entry *scope)
640
575
{
641
575
  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
575
}
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.99k
) {
659
9.99k
  zend_string *previous_filename;
660
9.99k
  zend_long previous_lineno;
661
9.99k
  if (scope) {
662
6.61k
    previous_filename = EG(filename_override);
663
6.61k
    previous_lineno = EG(lineno_override);
664
6.61k
    EG(filename_override) = scope->info.user.filename;
665
6.61k
    EG(lineno_override) = zend_ast_get_lineno(ast);
666
6.61k
  }
667
9.99k
  zend_result r = zend_ast_evaluate_inner(result, ast, scope, short_circuited_ptr, ctx);
668
9.99k
  if (scope) {
669
6.60k
    EG(filename_override) = previous_filename;
670
6.60k
    EG(lineno_override) = previous_lineno;
671
6.60k
  }
672
9.99k
  return r;
673
9.99k
}
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.99k
) {
682
9.99k
  zval op1, op2;
683
9.99k
  zend_result ret = SUCCESS;
684
9.99k
  bool short_circuited;
685
9.99k
  *short_circuited_ptr = false;
686
687
9.99k
  switch (ast->kind) {
688
435
    case ZEND_AST_BINARY_OP:
689
435
      if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
690
37
        ret = FAILURE;
691
398
      } else if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
692
11
        zval_ptr_dtor_nogc(&op1);
693
11
        ret = FAILURE;
694
387
      } else {
695
387
        binary_op_type op = get_binary_op(ast->attr);
696
387
        op(result, &op1, &op2);
697
387
        zval_ptr_dtor_nogc(&op1);
698
387
        zval_ptr_dtor_nogc(&op2);
699
387
        ret = EG(exception) ? FAILURE : SUCCESS;
700
387
      }
701
435
      break;
702
15
    case ZEND_AST_GREATER:
703
20
    case ZEND_AST_GREATER_EQUAL:
704
20
      if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
705
0
        ret = FAILURE;
706
20
      } else if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
707
3
        zval_ptr_dtor_nogc(&op1);
708
3
        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
20
      break;
719
17
    case ZEND_AST_UNARY_OP:
720
17
      if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
721
0
        ret = FAILURE;
722
17
      } else {
723
17
        unary_op_type op = get_unary_op(ast->attr);
724
17
        ret = op(result, &op1);
725
17
        zval_ptr_dtor_nogc(&op1);
726
17
      }
727
17
      break;
728
3.60k
    case ZEND_AST_ZVAL:
729
3.60k
    {
730
3.60k
      zval *zv = zend_ast_get_zval(ast);
731
732
3.60k
      ZVAL_COPY(result, zv);
733
3.60k
      break;
734
15
    }
735
778
    case ZEND_AST_CONSTANT:
736
778
    {
737
778
      zend_string *name = zend_ast_get_constant_name(ast);
738
778
      zval *zv = zend_get_constant_ex(name, scope, ast->attr);
739
740
778
      if (UNEXPECTED(zv == NULL)) {
741
122
        ZVAL_UNDEF(result);
742
122
        return FAILURE;
743
122
      }
744
656
      ZVAL_COPY_OR_DUP(result, zv);
745
656
      break;
746
778
    }
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
61
    case ZEND_AST_CLASS_NAME:
755
61
      if (!scope) {
756
6
        zend_throw_error(NULL, "Cannot use \"self\" when no class scope is active");
757
6
        return FAILURE;
758
6
      }
759
55
      if (ast->attr == ZEND_FETCH_CLASS_SELF) {
760
55
        ZVAL_STR_COPY(result, scope->name);
761
55
      } 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
55
      break;
772
55
    case ZEND_AST_AND:
773
21
      if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
774
0
        ret = FAILURE;
775
0
        break;
776
0
      }
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
110
    case ZEND_AST_CAST:
791
110
      if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
792
3
        ret = FAILURE;
793
3
        break;
794
3
      }
795
107
      if (ast->attr == Z_TYPE(op1)) {
796
0
        ZVAL_COPY_VALUE(result, &op1);
797
107
      } else {
798
107
        switch (ast->attr) {
799
8
          case _IS_BOOL:
800
8
            ZVAL_BOOL(result, zend_is_true(&op1));
801
8
            break;
802
21
          case IS_LONG:
803
21
            ZVAL_LONG(result, zval_get_long_func(&op1, false));
804
21
            break;
805
5
          case IS_DOUBLE:
806
5
            ZVAL_DOUBLE(result, zval_get_double_func(&op1));
807
5
            break;
808
16
          case IS_STRING:
809
16
            ZVAL_STR(result, zval_get_string_func(&op1));
810
16
            break;
811
44
          case IS_ARRAY:
812
44
            zend_cast_zval_to_array(result, &op1, IS_VAR);
813
44
            break;
814
13
          case IS_OBJECT:
815
13
            zend_cast_zval_to_object(result, &op1, IS_VAR);
816
13
            break;
817
0
          EMPTY_SWITCH_DEFAULT_CASE();
818
107
        }
819
107
        zval_ptr_dtor_nogc(&op1);
820
107
        if (UNEXPECTED(EG(exception))) {
821
0
          ret = FAILURE;
822
0
        }
823
107
      }
824
107
      break;
825
107
    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
48
    case ZEND_AST_CONDITIONAL:
844
48
      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
48
      if (zend_is_true(&op1)) {
849
38
        if (!ast->child[1]) {
850
13
          *result = op1;
851
25
        } else {
852
25
          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
22
          zval_ptr_dtor_nogc(&op1);
858
22
        }
859
38
      } 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
45
      break;
868
80
    case ZEND_AST_COALESCE:
869
80
      if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
870
1
        ret = FAILURE;
871
1
        break;
872
1
      }
873
79
      if (Z_TYPE(op1) > IS_NULL) {
874
0
        *result = op1;
875
79
      } else {
876
79
        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
79
        zval_ptr_dtor_nogc(&op1);
882
79
      }
883
79
      break;
884
79
    case ZEND_AST_UNARY_PLUS:
885
16
      if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
886
0
        ret = FAILURE;
887
16
      } else {
888
16
        ZVAL_LONG(&op1, 0);
889
16
        ret = add_function(result, &op1, &op2);
890
16
        zval_ptr_dtor_nogc(&op2);
891
16
      }
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
402
    case ZEND_AST_ARRAY:
903
402
      {
904
402
        uint32_t i;
905
402
        zend_ast_list *list = zend_ast_get_list(ast);
906
907
402
        if (!list->children) {
908
0
          ZVAL_EMPTY_ARRAY(result);
909
0
          break;
910
0
        }
911
402
        array_init(result);
912
776
        for (i = 0; i < list->children; i++) {
913
515
          zend_ast *elem = list->child[i];
914
515
          if (elem->kind == ZEND_AST_UNPACK) {
915
40
            if (UNEXPECTED(zend_ast_evaluate_ex(&op1, elem->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
916
18
              zval_ptr_dtor_nogc(result);
917
18
              return FAILURE;
918
18
            }
919
22
            if (UNEXPECTED(zend_ast_add_unpacked_element(result, &op1) != SUCCESS)) {
920
15
              zval_ptr_dtor_nogc(&op1);
921
15
              zval_ptr_dtor_nogc(result);
922
15
              return FAILURE;
923
15
            }
924
7
            zval_ptr_dtor_nogc(&op1);
925
7
            continue;
926
22
          }
927
475
          if (elem->child[1]) {
928
339
            if (UNEXPECTED(zend_ast_evaluate_ex(&op1, elem->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
929
35
              zval_ptr_dtor_nogc(result);
930
35
              return FAILURE;
931
35
            }
932
339
          } else {
933
136
            ZVAL_UNDEF(&op1);
934
136
          }
935
440
          if (UNEXPECTED(zend_ast_evaluate_ex(&op2, elem->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
936
59
            zval_ptr_dtor_nogc(&op1);
937
59
            zval_ptr_dtor_nogc(result);
938
59
            return FAILURE;
939
59
          }
940
381
          if (UNEXPECTED(zend_ast_add_array_element(result, &op1, &op2) != SUCCESS)) {
941
14
            zval_ptr_dtor_nogc(&op1);
942
14
            zval_ptr_dtor_nogc(&op2);
943
14
            zval_ptr_dtor_nogc(result);
944
14
            return FAILURE;
945
14
          }
946
381
        }
947
402
      }
948
261
      break;
949
318
    case ZEND_AST_DIM:
950
318
      if (ast->child[1] == NULL) {
951
0
        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
952
0
      }
953
954
318
      if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
955
6
        ret = FAILURE;
956
6
        break;
957
6
      }
958
312
      if (short_circuited) {
959
8
        *short_circuited_ptr = true;
960
8
        ZVAL_NULL(result);
961
8
        return SUCCESS;
962
8
      }
963
964
      // DIM on objects is disallowed because it allows executing arbitrary expressions
965
304
      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
299
      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
298
      zend_fetch_dimension_const(result, &op1, &op2, (ast->attr & ZEND_DIM_IS) ? BP_VAR_IS : BP_VAR_R);
979
980
298
      zval_ptr_dtor_nogc(&op1);
981
298
      zval_ptr_dtor_nogc(&op2);
982
298
      if (UNEXPECTED(EG(exception))) {
983
4
        return FAILURE;
984
4
      }
985
986
294
      break;
987
1.53k
    case ZEND_AST_CONST_ENUM_INIT:
988
1.53k
    {
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.53k
      if (CG(in_compilation)) {
992
0
        return FAILURE;
993
0
      }
994
995
1.53k
      zend_ast *class_name_ast = ast->child[0];
996
1.53k
      zend_string *class_name = zend_ast_get_str(class_name_ast);
997
998
1.53k
      zend_ast *case_id_ast = ast->child[1];
999
1.53k
      int case_id = (int)Z_LVAL_P(zend_ast_get_zval(case_id_ast));
1000
1001
1.53k
      zend_ast *case_name_ast = ast->child[2];
1002
1.53k
      zend_string *case_name = zend_ast_get_str(case_name_ast);
1003
1004
1.53k
      zend_ast *case_value_ast = ast->child[3];
1005
1006
1.53k
      zval case_value_zv;
1007
1.53k
      ZVAL_UNDEF(&case_value_zv);
1008
1.53k
      if (case_value_ast != NULL) {
1009
701
        if (UNEXPECTED(zend_ast_evaluate_ex(&case_value_zv, case_value_ast, scope, &short_circuited, ctx) != SUCCESS)) {
1010
3
          return FAILURE;
1011
3
        }
1012
701
      }
1013
1014
1.53k
      zend_class_entry *ce = zend_lookup_class(class_name);
1015
1.53k
      zend_enum_new(result, ce, case_id, case_name, case_value_ast != NULL ? &case_value_zv : NULL);
1016
1.53k
      zval_ptr_dtor_nogc(&case_value_zv);
1017
1.53k
      break;
1018
1.53k
    }
1019
1.43k
    case ZEND_AST_CLASS_CONST:
1020
1.43k
    {
1021
1.43k
      zend_string *class_name = zend_ast_get_str(ast->child[0]);
1022
1.43k
      if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
1023
6
        return FAILURE;
1024
6
      }
1025
1.42k
      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.42k
      zend_string *const_name = Z_STR(op2);
1031
1032
1.42k
      zend_string *previous_filename;
1033
1.42k
      zend_long previous_lineno;
1034
1.42k
      if (scope) {
1035
1.24k
        previous_filename = EG(filename_override);
1036
1.24k
        previous_lineno = EG(lineno_override);
1037
1.24k
        EG(filename_override) = scope->info.user.filename;
1038
1.24k
        EG(lineno_override) = zend_ast_get_lineno(ast);
1039
1.24k
      }
1040
1.42k
      zval *zv = zend_get_class_constant_ex(class_name, const_name, scope, ast->attr);
1041
1.42k
      if (scope) {
1042
1.23k
        EG(filename_override) = previous_filename;
1043
1.23k
        EG(lineno_override) = previous_lineno;
1044
1.23k
      }
1045
1046
1.42k
      if (UNEXPECTED(zv == NULL)) {
1047
156
        ZVAL_UNDEF(result);
1048
156
        zval_ptr_dtor_nogc(&op2);
1049
156
        return FAILURE;
1050
156
      }
1051
1.26k
      ZVAL_COPY_OR_DUP(result, zv);
1052
1.26k
      zval_ptr_dtor_nogc(&op2);
1053
1.26k
      break;
1054
1.42k
    }
1055
485
    case ZEND_AST_NEW:
1056
485
    {
1057
485
      zend_class_entry *ce = zend_ast_fetch_class(ast->child[0], scope);
1058
485
      if (!ce) {
1059
20
        return FAILURE;
1060
20
      }
1061
1062
465
      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
465
      ctx->had_side_effects = true;
1068
1069
465
      zend_ast_list *args_ast = zend_ast_get_list(ast->child[1]);
1070
465
      if (args_ast->attr) {
1071
        /* Has named arguments. */
1072
80
        HashTable *args = zend_new_array(args_ast->children);
1073
156
        for (uint32_t i = 0; i < args_ast->children; i++) {
1074
80
          zend_ast *arg_ast = args_ast->child[i];
1075
80
          zend_string *name = NULL;
1076
80
          zval arg;
1077
80
          if (arg_ast->kind == ZEND_AST_NAMED_ARG) {
1078
80
            name = zend_ast_get_str(arg_ast->child[0]);
1079
80
            arg_ast = arg_ast->child[1];
1080
80
          }
1081
80
          if (zend_ast_evaluate_ex(&arg, arg_ast, scope, &short_circuited, ctx) == FAILURE) {
1082
4
            zend_array_destroy(args);
1083
4
            zval_ptr_dtor(result);
1084
4
            return FAILURE;
1085
4
          }
1086
76
          if (name) {
1087
76
            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
76
          } else {
1096
0
            zend_hash_next_index_insert(args, &arg);
1097
0
          }
1098
76
        }
1099
1100
76
        zend_function *ctor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result));
1101
76
        if (ctor) {
1102
73
          zend_call_known_function(
1103
73
            ctor, Z_OBJ_P(result), Z_OBJCE_P(result), NULL, 0, NULL, args);
1104
73
        }
1105
1106
76
        zend_array_destroy(args);
1107
385
      } else {
1108
385
        ALLOCA_FLAG(use_heap)
1109
385
        zval *args = do_alloca(sizeof(zval) * args_ast->children, use_heap);
1110
565
        for (uint32_t i = 0; i < args_ast->children; i++) {
1111
186
          if (zend_ast_evaluate_ex(&args[i], args_ast->child[i], scope, &short_circuited, ctx) == FAILURE) {
1112
6
            for (uint32_t j = 0; j < i; j++) {
1113
0
              zval_ptr_dtor(&args[j]);
1114
0
            }
1115
6
            free_alloca(args, use_heap);
1116
6
            zval_ptr_dtor(result);
1117
6
            return FAILURE;
1118
6
          }
1119
186
        }
1120
1121
379
        zend_function *ctor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result));
1122
379
        if (ctor) {
1123
215
          zend_call_known_instance_method(
1124
215
            ctor, Z_OBJ_P(result), NULL, args_ast->children, args);
1125
215
        }
1126
1127
559
        for (uint32_t i = 0; i < args_ast->children; i++) {
1128
180
          zval_ptr_dtor(&args[i]);
1129
180
        }
1130
379
        free_alloca(args, use_heap);
1131
379
      }
1132
1133
455
      if (EG(exception)) {
1134
3
        zend_object_store_ctor_failed(Z_OBJ_P(result));
1135
3
        zval_ptr_dtor(result);
1136
3
        return FAILURE;
1137
3
      }
1138
452
      return SUCCESS;
1139
455
    }
1140
102
    case ZEND_AST_CALL:
1141
192
    case ZEND_AST_STATIC_CALL:
1142
192
    {
1143
192
      zend_function *fptr;
1144
192
      zend_class_entry *called_scope = NULL;
1145
1146
192
      zend_ast *args_ast = zend_ast_call_get_args(ast);
1147
192
      ZEND_ASSERT(args_ast->kind == ZEND_AST_CALLABLE_CONVERT);
1148
1149
192
      zend_ast_fcc *fcc_ast = (zend_ast_fcc*)args_ast;
1150
1151
192
      zend_ast_list *args = zend_ast_get_list(fcc_ast->args);
1152
192
      ZEND_ASSERT(args->children > 0);
1153
192
      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
192
      switch (ast->kind) {
1159
102
        case ZEND_AST_CALL: {
1160
102
          fptr = ZEND_MAP_PTR_GET(fcc_ast->fptr);
1161
1162
102
          if (!fptr) {
1163
95
            zend_string *function_name = zend_ast_get_str(ast->child[0]);
1164
95
            zend_string *function_name_lc = zend_string_tolower(function_name);
1165
95
            fptr = zend_fetch_function(function_name_lc);
1166
95
            if (!fptr && ast->child[0]->attr != ZEND_NAME_FQ) {
1167
21
              const char *backslash = zend_memrchr(ZSTR_VAL(function_name_lc), '\\', ZSTR_LEN(function_name_lc));
1168
21
              if (backslash) {
1169
17
                fptr = zend_fetch_function_str(backslash + 1, ZSTR_LEN(function_name_lc) - (backslash - ZSTR_VAL(function_name_lc) + 1));
1170
17
              }
1171
21
            }
1172
95
            zend_string_release(function_name_lc);
1173
95
            if (!fptr) {
1174
11
              zend_throw_error(NULL, "Call to undefined function %s()", ZSTR_VAL(function_name));
1175
11
              return FAILURE;
1176
11
            }
1177
1178
84
            ZEND_MAP_PTR_SET(fcc_ast->fptr, fptr);
1179
84
          }
1180
1181
91
          break;
1182
102
        }
1183
91
        case ZEND_AST_STATIC_CALL: {
1184
90
          zend_class_entry *ce = zend_ast_fetch_class(ast->child[0], scope);
1185
90
          if (!ce) {
1186
7
            return FAILURE;
1187
7
          }
1188
83
          called_scope = ce;
1189
1190
83
          fptr = ZEND_MAP_PTR_GET(fcc_ast->fptr);
1191
1192
83
          if (!fptr) {
1193
83
            zend_string *method_name = zend_ast_get_str(ast->child[1]);
1194
83
            if (ce->get_static_method) {
1195
0
              fptr = ce->get_static_method(ce, method_name);
1196
83
            } else {
1197
83
              fptr = zend_hash_find_ptr_lc(&ce->function_table, method_name);
1198
83
              if (fptr) {
1199
73
                if (!zend_check_method_accessible(fptr, scope)) {
1200
11
                  if (ce->__callstatic) {
1201
0
                    zend_throw_error(NULL, "Creating a callable for the magic __callStatic() method is not supported in constant expressions");
1202
11
                  } else {
1203
11
                    zend_bad_method_call(fptr, method_name, scope);
1204
11
                  }
1205
1206
11
                  return FAILURE;
1207
11
                }
1208
73
              } else {
1209
10
                if (ce->__callstatic) {
1210
6
                  zend_throw_error(NULL, "Creating a callable for the magic __callStatic() method is not supported in constant expressions");
1211
6
                } else {
1212
4
                  zend_undefined_method(ce, method_name);
1213
4
                }
1214
1215
10
                return FAILURE;
1216
10
              }
1217
83
            }
1218
1219
62
            if (!(fptr->common.fn_flags & ZEND_ACC_STATIC)) {
1220
6
              zend_non_static_method_call(fptr);
1221
1222
6
              return FAILURE;
1223
6
            }
1224
56
            if ((fptr->common.fn_flags & ZEND_ACC_ABSTRACT)) {
1225
6
              zend_abstract_method_call(fptr);
1226
1227
6
              return FAILURE;
1228
50
            } else if (fptr->common.scope->ce_flags & ZEND_ACC_TRAIT) {
1229
6
              zend_error(E_DEPRECATED,
1230
6
                "Calling static trait method %s::%s is deprecated, "
1231
6
                "it should only be called on a class using the trait",
1232
6
                ZSTR_VAL(fptr->common.scope->name), ZSTR_VAL(fptr->common.function_name));
1233
6
              if (EG(exception)) {
1234
0
                return FAILURE;
1235
0
              }
1236
6
            }
1237
1238
50
            ZEND_MAP_PTR_SET(fcc_ast->fptr, fptr);
1239
50
          }
1240
1241
50
          break;
1242
83
        }
1243
192
        EMPTY_SWITCH_DEFAULT_CASE()
1244
192
      }
1245
1246
141
      zend_create_fake_closure(result, fptr, fptr->common.scope, called_scope, NULL);
1247
1248
141
      return SUCCESS;
1249
192
    }
1250
57
    case ZEND_AST_OP_ARRAY:
1251
57
    {
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
57
      if (CG(in_compilation)) {
1255
0
        return FAILURE;
1256
0
      }
1257
1258
57
      zend_function *func = (zend_function *)zend_ast_get_op_array(ast)->op_array;
1259
1260
57
      zend_create_closure(result, func, scope, scope, NULL);
1261
57
      return SUCCESS;
1262
57
    }
1263
173
    case ZEND_AST_PROP:
1264
337
    case ZEND_AST_NULLSAFE_PROP:
1265
337
    {
1266
337
      if (UNEXPECTED(zend_ast_evaluate_ex(&op1, ast->child[0], scope, &short_circuited, ctx) != SUCCESS)) {
1267
11
        return FAILURE;
1268
11
      }
1269
326
      if (short_circuited) {
1270
8
        *short_circuited_ptr = true;
1271
8
        ZVAL_NULL(result);
1272
8
        return SUCCESS;
1273
8
      }
1274
318
      if (ast->kind == ZEND_AST_NULLSAFE_PROP && Z_TYPE(op1) == IS_NULL) {
1275
55
        *short_circuited_ptr = true;
1276
55
        ZVAL_NULL(result);
1277
55
        return SUCCESS;
1278
55
      }
1279
1280
263
      if (UNEXPECTED(zend_ast_evaluate_ex(&op2, ast->child[1], scope, &short_circuited, ctx) != SUCCESS)) {
1281
4
        zval_ptr_dtor_nogc(&op1);
1282
4
        return FAILURE;
1283
4
      }
1284
1285
259
      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
255
      if (Z_TYPE(op1) != IS_OBJECT) {
1292
28
        zend_wrong_property_read(&op1, &op2);
1293
1294
28
        zval_ptr_dtor_nogc(&op1);
1295
28
        zval_ptr_dtor_nogc(&op2);
1296
1297
28
        ZVAL_NULL(result);
1298
28
        return SUCCESS;
1299
28
      }
1300
1301
227
      zend_object *zobj = Z_OBJ(op1);
1302
227
      if (!(zobj->ce->ce_flags & ZEND_ACC_ENUM)) {
1303
26
        zend_throw_error(NULL, "Fetching properties on non-enums in constant expressions is not allowed");
1304
26
        zval_ptr_dtor_nogc(&op1);
1305
26
        zval_ptr_dtor_nogc(&op2);
1306
26
        return FAILURE;
1307
26
      }
1308
1309
201
      zend_string *name = Z_STR(op2);
1310
201
      zval *property_result = zend_read_property_ex(scope, zobj, name, 0, result);
1311
201
      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
201
      if (result != property_result) {
1318
201
        ZVAL_COPY(result, property_result);
1319
201
      }
1320
201
      zval_ptr_dtor_nogc(&op1);
1321
201
      zval_ptr_dtor_nogc(&op2);
1322
201
      return SUCCESS;
1323
201
    }
1324
0
    default:
1325
0
      zend_throw_error(NULL, "Unsupported constant expression");
1326
0
      ret = FAILURE;
1327
9.99k
  }
1328
8.46k
  return ret;
1329
9.99k
}
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
80.3k
{
1340
80.3k
  size_t size;
1341
1342
80.3k
  if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) {
1343
53.4k
    size = sizeof(zend_ast_zval);
1344
53.4k
  } else if (ast->kind == ZEND_AST_OP_ARRAY) {
1345
139
    size = sizeof(zend_ast_op_array);
1346
26.7k
  } else if (ast->kind == ZEND_AST_CALLABLE_CONVERT) {
1347
365
    zend_ast *args_ast = ((zend_ast_fcc*)ast)->args;
1348
365
    size = sizeof(zend_ast_fcc) + zend_ast_tree_size(args_ast);
1349
26.4k
  } else if (zend_ast_is_list(ast)) {
1350
2.05k
    uint32_t i;
1351
2.05k
    const zend_ast_list *list = zend_ast_get_list(ast);
1352
1353
2.05k
    size = zend_ast_list_size(list->children);
1354
4.50k
    for (i = 0; i < list->children; i++) {
1355
2.44k
      if (list->child[i]) {
1356
2.44k
        size += zend_ast_tree_size(list->child[i]);
1357
2.44k
      }
1358
2.44k
    }
1359
24.3k
  } else if (zend_ast_is_decl(ast)) {
1360
    /* Not implemented. */
1361
0
    ZEND_UNREACHABLE();
1362
24.3k
  } else {
1363
24.3k
    uint32_t i, children = zend_ast_get_num_children(ast);
1364
1365
24.3k
    size = zend_ast_size(children);
1366
82.3k
    for (i = 0; i < children; i++) {
1367
57.9k
      if (ast->child[i]) {
1368
50.9k
        size += zend_ast_tree_size(ast->child[i]);
1369
50.9k
      }
1370
57.9k
    }
1371
24.3k
  }
1372
80.3k
  return size;
1373
80.3k
}
1374
1375
static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf)
1376
80.3k
{
1377
80.3k
  if (ast->kind == ZEND_AST_ZVAL) {
1378
31.6k
    zend_ast_zval *new = (zend_ast_zval*)buf;
1379
31.6k
    new->kind = ZEND_AST_ZVAL;
1380
31.6k
    new->attr = ast->attr;
1381
31.6k
    ZVAL_COPY(&new->val, zend_ast_get_zval(ast));
1382
31.6k
    Z_LINENO(new->val) = zend_ast_get_lineno(ast);
1383
31.6k
    buf = (void*)((char*)buf + sizeof(zend_ast_zval));
1384
48.6k
  } else if (ast->kind == ZEND_AST_CONSTANT) {
1385
21.7k
    zend_ast_zval *new = (zend_ast_zval*)buf;
1386
21.7k
    new->kind = ZEND_AST_CONSTANT;
1387
21.7k
    new->attr = ast->attr;
1388
21.7k
    ZVAL_STR_COPY(&new->val, zend_ast_get_constant_name(ast));
1389
21.7k
    Z_LINENO(new->val) = zend_ast_get_lineno(ast);
1390
21.7k
    buf = (void*)((char*)buf + sizeof(zend_ast_zval));
1391
26.9k
  } else if (zend_ast_is_list(ast)) {
1392
2.05k
    const zend_ast_list *list = zend_ast_get_list(ast);
1393
2.05k
    zend_ast_list *new = (zend_ast_list*)buf;
1394
2.05k
    uint32_t i;
1395
2.05k
    new->kind = list->kind;
1396
2.05k
    new->attr = list->attr;
1397
2.05k
    new->children = list->children;
1398
2.05k
    new->lineno = list->lineno;
1399
2.05k
    buf = (void*)((char*)buf + zend_ast_list_size(list->children));
1400
4.50k
    for (i = 0; i < list->children; i++) {
1401
2.44k
      if (list->child[i]) {
1402
2.44k
        new->child[i] = (zend_ast*)buf;
1403
2.44k
        buf = zend_ast_tree_copy(list->child[i], buf);
1404
2.44k
      } else {
1405
0
        new->child[i] = NULL;
1406
0
      }
1407
2.44k
    }
1408
24.8k
  } else if (ast->kind == ZEND_AST_OP_ARRAY) {
1409
139
    const zend_ast_op_array *old = zend_ast_get_op_array(ast);
1410
139
    zend_ast_op_array *new = (zend_ast_op_array*)buf;
1411
139
    new->kind = old->kind;
1412
139
    new->attr = old->attr;
1413
139
    new->lineno = old->lineno;
1414
139
    new->op_array = old->op_array;
1415
139
    function_add_ref((zend_function *)new->op_array);
1416
139
    buf = (void*)((char*)buf + sizeof(zend_ast_op_array));
1417
24.7k
  } else if (ast->kind == ZEND_AST_CALLABLE_CONVERT) {
1418
365
    const zend_ast_fcc *old = (zend_ast_fcc*)ast;
1419
365
    zend_ast_fcc *new = (zend_ast_fcc*)buf;
1420
365
    new->kind = old->kind;
1421
365
    new->attr = old->attr;
1422
365
    new->lineno = old->lineno;
1423
365
    ZEND_MAP_PTR_INIT(new->fptr, ZEND_MAP_PTR(old->fptr));
1424
365
    buf = (void*)((char*)buf + sizeof(zend_ast_fcc));
1425
365
    new->args = buf;
1426
365
    buf = zend_ast_tree_copy(old->args, buf);
1427
24.3k
  } else if (zend_ast_is_decl(ast)) {
1428
    /* Not implemented. */
1429
0
    ZEND_UNREACHABLE();
1430
24.3k
  } else {
1431
24.3k
    uint32_t i, children = zend_ast_get_num_children(ast);
1432
24.3k
    zend_ast *new = (zend_ast*)buf;
1433
24.3k
    new->kind = ast->kind;
1434
24.3k
    new->attr = ast->attr;
1435
24.3k
    new->lineno = ast->lineno;
1436
24.3k
    buf = (void*)((char*)buf + zend_ast_size(children));
1437
82.3k
    for (i = 0; i < children; i++) {
1438
57.9k
      if (ast->child[i]) {
1439
50.9k
        new->child[i] = (zend_ast*)buf;
1440
50.9k
        buf = zend_ast_tree_copy(ast->child[i], buf);
1441
50.9k
      } else {
1442
6.97k
        new->child[i] = NULL;
1443
6.97k
      }
1444
57.9k
    }
1445
24.3k
  }
1446
80.3k
  return buf;
1447
80.3k
}
1448
1449
ZEND_API zend_ast_ref * ZEND_FASTCALL zend_ast_copy(zend_ast *ast)
1450
26.5k
{
1451
26.5k
  size_t tree_size;
1452
26.5k
  zend_ast_ref *ref;
1453
1454
26.5k
  ZEND_ASSERT(ast != NULL);
1455
26.5k
  tree_size = zend_ast_tree_size(ast) + sizeof(zend_ast_ref);
1456
26.5k
  ref = emalloc(tree_size);
1457
26.5k
  zend_ast_tree_copy(ast, GC_AST(ref));
1458
26.5k
  GC_SET_REFCOUNT(ref, 1);
1459
26.5k
  GC_TYPE_INFO(ref) = GC_CONSTANT_AST;
1460
26.5k
  return ref;
1461
26.5k
}
1462
1463
ZEND_API void ZEND_FASTCALL zend_ast_destroy(zend_ast *ast)
1464
4.89M
{
1465
9.86M
tail_call:
1466
9.86M
  if (!ast) {
1467
1.31M
    return;
1468
1.31M
  }
1469
1470
8.55M
  if (EXPECTED(ast->kind >= ZEND_AST_VAR)) {
1471
3.96M
    uint32_t i, children = zend_ast_get_num_children(ast);
1472
1473
6.37M
    for (i = 1; i < children; i++) {
1474
2.40M
      zend_ast_destroy(ast->child[i]);
1475
2.40M
    }
1476
3.96M
    ast = ast->child[0];
1477
3.96M
    goto tail_call;
1478
4.58M
  } else if (EXPECTED(ast->kind == ZEND_AST_ZVAL)) {
1479
3.24M
    zval_ptr_dtor_nogc(zend_ast_get_zval(ast));
1480
3.24M
  } else if (EXPECTED(zend_ast_is_list(ast))) {
1481
1.15M
    const zend_ast_list *list = zend_ast_get_list(ast);
1482
1.15M
    if (list->children) {
1483
884k
      uint32_t i;
1484
1485
2.48M
      for (i = 1; i < list->children; i++) {
1486
1.60M
        zend_ast_destroy(list->child[i]);
1487
1.60M
      }
1488
884k
      ast = list->child[0];
1489
884k
      goto tail_call;
1490
884k
    }
1491
1.15M
  } else if (EXPECTED(ast->kind == ZEND_AST_CONSTANT)) {
1492
40.6k
    zend_string_release_ex(zend_ast_get_constant_name(ast), 0);
1493
145k
  } else if (EXPECTED(ast->kind == ZEND_AST_OP_ARRAY)) {
1494
216
    destroy_op_array(zend_ast_get_op_array(ast)->op_array);
1495
144k
  } else if (EXPECTED(zend_ast_is_decl(ast))) {
1496
113k
    const zend_ast_decl *decl = (const zend_ast_decl *) ast;
1497
1498
113k
    if (decl->name) {
1499
87.7k
        zend_string_release_ex(decl->name, 0);
1500
87.7k
    }
1501
113k
    if (decl->doc_comment) {
1502
253
      zend_string_release_ex(decl->doc_comment, 0);
1503
253
    }
1504
113k
    zend_ast_destroy(decl->child[0]);
1505
113k
    zend_ast_destroy(decl->child[1]);
1506
113k
    zend_ast_destroy(decl->child[2]);
1507
113k
    zend_ast_destroy(decl->child[3]);
1508
113k
    ast = decl->child[4];
1509
113k
    goto tail_call;
1510
113k
  } else if (EXPECTED(ast->kind == ZEND_AST_CALLABLE_CONVERT)) {
1511
3.89k
    zend_ast_fcc *fcc_ast = (zend_ast_fcc*) ast;
1512
1513
3.89k
    ast = fcc_ast->args;
1514
3.89k
    goto tail_call;
1515
3.89k
  }
1516
8.55M
}
1517
1518
ZEND_API void ZEND_FASTCALL zend_ast_ref_destroy(zend_ast_ref *ast)
1519
21.0k
{
1520
21.0k
  zend_ast_destroy(GC_AST(ast));
1521
21.0k
  efree(ast);
1522
21.0k
}
1523
1524
71.3k
ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn, void *context) {
1525
71.3k
  if (zend_ast_is_list(ast)) {
1526
6.71k
    zend_ast_list *list = zend_ast_get_list(ast);
1527
6.71k
    uint32_t i;
1528
15.8k
    for (i = 0; i < list->children; ++i) {
1529
9.15k
      fn(&list->child[i], context);
1530
9.15k
    }
1531
64.6k
  } else if (zend_ast_is_decl(ast)) {
1532
    /* Not implemented. */
1533
0
    ZEND_UNREACHABLE();
1534
64.6k
  } else {
1535
64.6k
    uint32_t i, children = zend_ast_get_num_children(ast);
1536
171k
    for (i = 0; i < children; ++i) {
1537
107k
      fn(&ast->child[i], context);
1538
107k
    }
1539
64.6k
  }
1540
71.3k
}
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
47.0k
{
1582
47.0k
  size_t i;
1583
1584
1.64M
  for (i = 0; i < ZSTR_LEN(s); i++) {
1585
1.60M
    unsigned char c = ZSTR_VAL(s)[i];
1586
1.60M
    if (c == '\'' || c == '\\') {
1587
15.8k
      smart_str_appendc(str, '\\');
1588
15.8k
      smart_str_appendc(str, c);
1589
1.58M
    } else {
1590
1.58M
      smart_str_appendc(str, c);
1591
1.58M
    }
1592
1.60M
  }
1593
47.0k
}
1594
1595
static ZEND_COLD void zend_ast_export_qstr(smart_str *str, char quote, const zend_string *s)
1596
63.7k
{
1597
63.7k
  size_t i;
1598
1599
1.28M
  for (i = 0; i < ZSTR_LEN(s); i++) {
1600
1.22M
    unsigned char c = ZSTR_VAL(s)[i];
1601
1.22M
    if (c < ' ') {
1602
581k
      switch (c) {
1603
28.2k
        case '\n':
1604
28.2k
          smart_str_appends(str, "\\n");
1605
28.2k
          break;
1606
15.6k
        case '\r':
1607
15.6k
          smart_str_appends(str, "\\r");
1608
15.6k
          break;
1609
9.02k
        case '\t':
1610
9.02k
          smart_str_appends(str, "\\t");
1611
9.02k
          break;
1612
7.04k
        case '\f':
1613
7.04k
          smart_str_appends(str, "\\f");
1614
7.04k
          break;
1615
11.7k
        case '\v':
1616
11.7k
          smart_str_appends(str, "\\v");
1617
11.7k
          break;
1618
#ifdef ZEND_WIN32
1619
        case VK_ESCAPE:
1620
#else
1621
13.3k
        case '\e':
1622
13.3k
#endif
1623
13.3k
          smart_str_appends(str, "\\e");
1624
13.3k
          break;
1625
496k
        default:
1626
496k
          smart_str_appends(str, "\\0");
1627
496k
          smart_str_appendc(str, '0' + (c / 8));
1628
496k
          smart_str_appendc(str, '0' + (c % 8));
1629
496k
          break;
1630
581k
      }
1631
642k
    } else {
1632
642k
      if (c == quote || c == '$' || c == '\\') {
1633
74.5k
        smart_str_appendc(str, '\\');
1634
74.5k
      }
1635
642k
      smart_str_appendc(str, c);
1636
642k
    }
1637
1.22M
  }
1638
63.7k
}
1639
1640
static ZEND_COLD void zend_ast_export_indent(smart_str *str, int indent)
1641
197k
{
1642
2.02M
  while (indent > 0) {
1643
1.82M
    smart_str_appends(str, "    ");
1644
1.82M
    indent--;
1645
1.82M
  }
1646
197k
}
1647
1648
static ZEND_COLD void zend_ast_export_name(smart_str *str, zend_ast *ast, int priority, int indent)
1649
37.6k
{
1650
37.6k
  if (ast->kind == ZEND_AST_ZVAL) {
1651
33.2k
    const zval *zv = zend_ast_get_zval(ast);
1652
1653
33.2k
    if (Z_TYPE_P(zv) == IS_STRING) {
1654
31.0k
      smart_str_append(str, Z_STR_P(zv));
1655
31.0k
      return;
1656
31.0k
    }
1657
33.2k
  }
1658
6.57k
  zend_ast_export_ex(str, ast, priority, indent);
1659
6.57k
}
1660
1661
static ZEND_COLD void zend_ast_export_ns_name(smart_str *str, zend_ast *ast, int priority, int indent)
1662
1.56M
{
1663
1.56M
  if (ast->kind == ZEND_AST_ZVAL) {
1664
1.55M
    const zval *zv = zend_ast_get_zval(ast);
1665
1666
1.55M
    if (Z_TYPE_P(zv) == IS_STRING) {
1667
1.55M
        if (ast->attr == ZEND_NAME_FQ) {
1668
120k
        smart_str_appendc(str, '\\');
1669
1.43M
        } else if (ast->attr == ZEND_NAME_RELATIVE) {
1670
1.16k
        smart_str_appends(str, "namespace\\");
1671
1.16k
        }
1672
1.55M
      smart_str_append(str, Z_STR_P(zv));
1673
1.55M
      return;
1674
1.55M
    }
1675
1.55M
  }
1676
7.77k
  zend_ast_export_ex(str, ast, priority, indent);
1677
7.77k
}
1678
1679
static ZEND_COLD bool zend_ast_valid_var_char(char ch)
1680
40.6k
{
1681
40.6k
  unsigned char c = (unsigned char)ch;
1682
1683
40.6k
  if (c != '_' && c < 127 &&
1684
38.5k
      (c < '0' || c > '9') &&
1685
36.4k
      (c < 'A' || c > 'Z') &&
1686
35.9k
      (c < 'a' || c > 'z')) {
1687
35.1k
    return false;
1688
35.1k
  }
1689
5.43k
  return true;
1690
40.6k
}
1691
1692
static ZEND_COLD bool zend_ast_valid_var_name(const char *s, size_t len)
1693
125k
{
1694
125k
  unsigned char c;
1695
125k
  size_t i;
1696
1697
125k
  if (len == 0) {
1698
1.48k
    return false;
1699
1.48k
  }
1700
124k
  c = (unsigned char)s[0];
1701
124k
  if (c != '_' && c < 127 &&
1702
105k
      (c < 'A' || c > 'Z') &&
1703
86.8k
      (c < 'a' || c > 'z')) {
1704
2.01k
    return false;
1705
2.01k
  }
1706
413k
  for (i = 1; i < len; i++) {
1707
291k
    c = (unsigned char)s[i];
1708
291k
    if (c != '_' && c < 127 &&
1709
211k
        (c < '0' || c > '9') &&
1710
208k
        (c < 'A' || c > 'Z') &&
1711
169k
        (c < 'a' || c > 'z')) {
1712
775
      return false;
1713
775
    }
1714
291k
  }
1715
121k
  return true;
1716
122k
}
1717
1718
static ZEND_COLD bool zend_ast_var_needs_braces(char ch)
1719
40.8k
{
1720
40.8k
  return ch == '[' || zend_ast_valid_var_char(ch);
1721
40.8k
}
1722
1723
static ZEND_COLD void zend_ast_export_var(smart_str *str, zend_ast *ast, int indent)
1724
131k
{
1725
131k
  if (ast->kind == ZEND_AST_ZVAL) {
1726
127k
    zval *zv = zend_ast_get_zval(ast);
1727
127k
    if (Z_TYPE_P(zv) == IS_STRING &&
1728
125k
        zend_ast_valid_var_name(Z_STRVAL_P(zv), Z_STRLEN_P(zv))) {
1729
121k
      smart_str_append(str, Z_STR_P(zv));
1730
121k
      return;
1731
121k
    }
1732
127k
  } else if (ast->kind == ZEND_AST_VAR) {
1733
2.47k
    zend_ast_export_ex(str, ast, 0, indent);
1734
2.47k
    return;
1735
2.47k
  }
1736
7.95k
  smart_str_appendc(str, '{');
1737
7.95k
  zend_ast_export_name(str, ast, 0, indent);
1738
7.95k
  smart_str_appendc(str, '}');
1739
7.95k
}
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
964k
{
1745
964k
  ZEND_ASSERT(children <= list->children);
1746
964k
  uint32_t i = 0;
1747
1748
2.25M
  while (i < children) {
1749
1.28M
    if (i != 0 && separator) {
1750
358k
      smart_str_appends(str, ", ");
1751
358k
    }
1752
1.28M
    zend_ast_export_ex(str, list->child[i], priority, indent);
1753
1.28M
    i++;
1754
1.28M
  }
1755
964k
}
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
964k
{
1759
964k
  zend_ast_export_list_ex(str, list, separator, priority, indent, list->children);
1760
964k
}
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.01k
{
1764
5.01k
  uint32_t i = 0;
1765
5.01k
  zend_ast *ast;
1766
1767
133k
  while (i < list->children) {
1768
128k
    ast = list->child[i];
1769
128k
    if (ast->kind == ZEND_AST_ZVAL) {
1770
61.9k
      const zval *zv = zend_ast_get_zval(ast);
1771
1772
61.9k
      ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
1773
61.9k
      zend_ast_export_qstr(str, quote, Z_STR_P(zv));
1774
66.1k
    } else if (ast->kind == ZEND_AST_VAR &&
1775
46.4k
               ast->child[0]->kind == ZEND_AST_ZVAL &&
1776
45.1k
               (i + 1 == list->children ||
1777
44.4k
                list->child[i + 1]->kind != ZEND_AST_ZVAL ||
1778
40.8k
                !zend_ast_var_needs_braces(
1779
40.8k
                    *Z_STRVAL_P(
1780
40.8k
                        zend_ast_get_zval(list->child[i + 1]))))) {
1781
39.5k
      zend_ast_export_ex(str, ast, 0, indent);
1782
39.5k
    } else {
1783
26.6k
      smart_str_appendc(str, '{');
1784
26.6k
      zend_ast_export_ex(str, ast, 0, indent);
1785
26.6k
      smart_str_appendc(str, '}');
1786
26.6k
    }
1787
128k
    i++;
1788
128k
  }
1789
5.01k
}
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
2.90k
{
1793
2.90k
  uint32_t i = 0;
1794
1795
7.17k
  while (i < list->children) {
1796
4.26k
    if (i != 0) {
1797
1.36k
      smart_str_appends(str, separator);
1798
1.36k
    }
1799
4.26k
    zend_ast_export_name(str, list->child[i], 0, indent);
1800
4.26k
    i++;
1801
4.26k
  }
1802
2.90k
}
1803
1804
2.58k
#define zend_ast_export_name_list(s, l, i) zend_ast_export_name_list_ex(s, l, i, ", ")
1805
323
#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
723
{
1809
723
  uint32_t i = 0;
1810
1811
3.19k
  while (i < list->children) {
1812
2.46k
    if (i != 0) {
1813
1.74k
      smart_str_appends(str, ", ");
1814
1.74k
    }
1815
2.46k
    if (list->child[i]->attr & ZEND_BIND_REF) {
1816
1.27k
      smart_str_appendc(str, '&');
1817
1.27k
    }
1818
2.46k
    smart_str_appendc(str, '$');
1819
2.46k
    zend_ast_export_name(str, list->child[i], 20, indent);
1820
2.46k
    i++;
1821
2.46k
  }
1822
723
}
1823
1824
static ZEND_COLD void zend_ast_export_stmt(smart_str *str, zend_ast *ast, int indent)
1825
184k
{
1826
184k
  if (!ast) {
1827
8.34k
    return;
1828
8.34k
  }
1829
1830
176k
  if (ast->kind == ZEND_AST_STMT_LIST ||
1831
124k
      ast->kind == ZEND_AST_TRAIT_ADAPTATIONS) {
1832
52.5k
    const zend_ast_list *list = (const zend_ast_list*)ast;
1833
52.5k
    uint32_t i = 0;
1834
1835
177k
    while (i < list->children) {
1836
124k
      ast = list->child[i];
1837
124k
      zend_ast_export_stmt(str, ast, indent);
1838
124k
      i++;
1839
124k
    }
1840
123k
  } else {
1841
123k
    zend_ast_export_indent(str, indent);
1842
123k
    zend_ast_export_ex(str, ast, 0, indent);
1843
123k
    switch (ast->kind) {
1844
1.44k
      case ZEND_AST_LABEL:
1845
8.68k
      case ZEND_AST_IF:
1846
8.74k
      case ZEND_AST_SWITCH:
1847
9.07k
      case ZEND_AST_WHILE:
1848
9.69k
      case ZEND_AST_TRY:
1849
12.6k
      case ZEND_AST_FOR:
1850
13.7k
      case ZEND_AST_FOREACH:
1851
15.5k
      case ZEND_AST_FUNC_DECL:
1852
16.3k
      case ZEND_AST_METHOD:
1853
22.3k
      case ZEND_AST_CLASS:
1854
22.8k
      case ZEND_AST_USE_TRAIT:
1855
22.8k
      case ZEND_AST_NAMESPACE:
1856
23.4k
      case ZEND_AST_DECLARE:
1857
23.4k
        break;
1858
4.15k
      case ZEND_AST_PROP_GROUP: {
1859
4.15k
        const zend_ast *first_prop = zend_ast_get_list(ast->child[1])->child[0];
1860
4.15k
        const zend_ast *hook_list = first_prop->child[3];
1861
4.15k
        if (hook_list == NULL) {
1862
2.37k
          smart_str_appendc(str, ';');
1863
2.37k
        }
1864
4.15k
        break;
1865
22.8k
      }
1866
96.3k
      default:
1867
96.3k
        smart_str_appendc(str, ';');
1868
96.3k
        break;
1869
123k
    }
1870
123k
    smart_str_appendc(str, '\n');
1871
123k
  }
1872
176k
}
1873
1874
static ZEND_COLD void zend_ast_export_if_stmt(smart_str *str, const zend_ast_list *list, int indent)
1875
7.23k
{
1876
7.23k
  uint32_t i;
1877
7.23k
  zend_ast *ast;
1878
1879
7.41k
tail_call:
1880
7.41k
  i = 0;
1881
27.5k
  while (i < list->children) {
1882
20.2k
    ast = list->child[i];
1883
20.2k
    ZEND_ASSERT(ast->kind == ZEND_AST_IF_ELEM);
1884
20.2k
    if (ast->child[0]) {
1885
15.1k
      if (i == 0) {
1886
7.41k
        smart_str_appends(str, "if (");
1887
7.72k
      } else {
1888
7.72k
        zend_ast_export_indent(str, indent);
1889
7.72k
        smart_str_appends(str, "} elseif (");
1890
7.72k
      }
1891
15.1k
      zend_ast_export_ex(str, ast->child[0], 0, indent);
1892
15.1k
      smart_str_appends(str, ") {\n");
1893
15.1k
      zend_ast_export_stmt(str, ast->child[1], indent + 1);
1894
15.1k
    } else {
1895
5.13k
      zend_ast_export_indent(str, indent);
1896
5.13k
      smart_str_appends(str, "} else ");
1897
5.13k
      if (ast->child[1] && ast->child[1]->kind == ZEND_AST_IF) {
1898
187
        list = (const zend_ast_list*)ast->child[1];
1899
187
        goto tail_call;
1900
4.95k
      } else {
1901
4.95k
        smart_str_appends(str, "{\n");
1902
4.95k
        zend_ast_export_stmt(str, ast->child[1], indent + 1);
1903
4.95k
      }
1904
5.13k
    }
1905
20.0k
    i++;
1906
20.0k
  }
1907
7.23k
  zend_ast_export_indent(str, indent);
1908
7.23k
  smart_str_appendc(str, '}');
1909
7.23k
}
1910
1911
static ZEND_COLD void zend_ast_export_zval(smart_str *str, const zval *zv, int priority, int indent)
1912
491k
{
1913
491k
  ZVAL_DEREF(zv);
1914
491k
  switch (Z_TYPE_P(zv)) {
1915
2
    case IS_NULL:
1916
2
      smart_str_appends(str, "null");
1917
2
      break;
1918
70
    case IS_FALSE:
1919
70
      smart_str_appends(str, "false");
1920
70
      break;
1921
0
    case IS_TRUE:
1922
0
      smart_str_appends(str, "true");
1923
0
      break;
1924
269k
    case IS_LONG:
1925
269k
      smart_str_append_long(str, Z_LVAL_P(zv));
1926
269k
      break;
1927
174k
    case IS_DOUBLE:
1928
174k
      smart_str_append_double(
1929
174k
        str, Z_DVAL_P(zv), (int) EG(precision), /* zero_fraction */ true);
1930
174k
      break;
1931
47.0k
    case IS_STRING:
1932
47.0k
      smart_str_appendc(str, '\'');
1933
47.0k
      zend_ast_export_str(str, Z_STR_P(zv));
1934
47.0k
      smart_str_appendc(str, '\'');
1935
47.0k
      break;
1936
90
    case IS_ARRAY: {
1937
90
      zend_long idx;
1938
90
      zend_string *key;
1939
90
      zval *val;
1940
90
      bool first = true;
1941
90
      smart_str_appendc(str, '[');
1942
420
      ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(zv), idx, key, val) {
1943
420
        if (first) {
1944
85
          first = false;
1945
85
        } else {
1946
80
          smart_str_appends(str, ", ");
1947
80
        }
1948
420
        if (key) {
1949
0
          smart_str_appendc(str, '\'');
1950
0
          zend_ast_export_str(str, key);
1951
0
          smart_str_appends(str, "' => ");
1952
165
        } else {
1953
165
          smart_str_append_long(str, idx);
1954
165
          smart_str_appends(str, " => ");
1955
165
        }
1956
420
        zend_ast_export_zval(str, val, 0, indent);
1957
420
      } ZEND_HASH_FOREACH_END();
1958
90
      smart_str_appendc(str, ']');
1959
90
      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
491k
  }
1966
491k
}
1967
1968
8.64k
static ZEND_COLD void zend_ast_export_class_no_header(smart_str *str, const zend_ast_decl *decl, int indent) {
1969
8.64k
  if (decl->child[0]) {
1970
934
    smart_str_appends(str, " extends ");
1971
934
    zend_ast_export_ns_name(str, decl->child[0], 0, indent);
1972
934
  }
1973
8.64k
  if (decl->child[1]) {
1974
1.92k
    smart_str_appends(str, " implements ");
1975
1.92k
    zend_ast_export_ex(str, decl->child[1], 0, indent);
1976
1.92k
  }
1977
8.64k
  smart_str_appends(str, " {\n");
1978
8.64k
  zend_ast_export_stmt(str, decl->child[2], indent + 1);
1979
8.64k
  zend_ast_export_indent(str, indent);
1980
8.64k
  smart_str_appendc(str, '}');
1981
8.64k
}
1982
1983
6.28k
static ZEND_COLD void zend_ast_export_attribute_group(smart_str *str, zend_ast *ast, int indent) {
1984
6.28k
  const zend_ast_list *list = zend_ast_get_list(ast);
1985
12.9k
  for (uint32_t i = 0; i < list->children; i++) {
1986
6.68k
    const zend_ast *attr = list->child[i];
1987
1988
6.68k
    if (i) {
1989
399
      smart_str_appends(str, ", ");
1990
399
    }
1991
6.68k
    zend_ast_export_ns_name(str, attr->child[0], 0, indent);
1992
1993
6.68k
    if (attr->child[1]) {
1994
450
      smart_str_appendc(str, '(');
1995
450
      zend_ast_export_ex(str, attr->child[1], 0, indent);
1996
450
      smart_str_appendc(str, ')');
1997
450
    }
1998
6.68k
  }
1999
6.28k
}
2000
2001
2.31k
static ZEND_COLD void zend_ast_export_attributes(smart_str *str, zend_ast *ast, int indent, bool newlines) {
2002
2.31k
  const zend_ast_list *list = zend_ast_get_list(ast);
2003
2.31k
  uint32_t i;
2004
2005
8.60k
  for (i = 0; i < list->children; i++) {
2006
6.28k
    smart_str_appends(str, "#[");
2007
6.28k
    zend_ast_export_attribute_group(str, list->child[i], indent);
2008
6.28k
    smart_str_appendc(str, ']');
2009
2010
6.28k
    if (newlines) {
2011
5.35k
      smart_str_appendc(str, '\n');
2012
5.35k
      zend_ast_export_indent(str, indent);
2013
5.35k
    } else {
2014
927
      smart_str_appendc(str, ' ');
2015
927
    }
2016
6.28k
  }
2017
2.31k
}
2018
2019
49.5k
static ZEND_COLD void zend_ast_export_visibility(smart_str *str, uint32_t flags, zend_modifier_target target) {
2020
49.5k
  if (flags & ZEND_ACC_PUBLIC) {
2021
3.95k
    smart_str_appends(str, "public ");
2022
45.5k
  } else if (flags & ZEND_ACC_PROTECTED) {
2023
256
    smart_str_appends(str, "protected ");
2024
45.3k
  } else if (flags & ZEND_ACC_PRIVATE) {
2025
680
    smart_str_appends(str, "private ");
2026
680
  }
2027
2028
49.5k
  if (target == ZEND_MODIFIER_TARGET_PROPERTY || target == ZEND_MODIFIER_TARGET_CPP) {
2029
15.9k
    if (flags & ZEND_ACC_PRIVATE_SET) {
2030
1.09k
      smart_str_appends(str, "private(set) ");
2031
14.8k
    } else if (flags & ZEND_ACC_PROTECTED_SET) {
2032
43
      smart_str_appends(str, "protected(set) ");
2033
14.8k
    } else if (flags & ZEND_ACC_PUBLIC_SET) {
2034
954
      smart_str_appends(str, "public(set) ");
2035
954
    }
2036
15.9k
  }
2037
49.5k
}
2038
2039
14.0k
static ZEND_COLD void zend_ast_export_type(smart_str *str, zend_ast *ast, int indent) {
2040
14.0k
  if (ast->kind == ZEND_AST_TYPE_UNION) {
2041
1.54k
    const zend_ast_list *list = zend_ast_get_list(ast);
2042
5.83k
    for (uint32_t i = 0; i < list->children; i++) {
2043
4.29k
      if (i != 0) {
2044
2.74k
        smart_str_appendc(str, '|');
2045
2.74k
      }
2046
4.29k
      zend_ast_export_type(str, list->child[i], indent);
2047
4.29k
    }
2048
1.54k
    return;
2049
1.54k
  }
2050
12.5k
  if (ast->kind == ZEND_AST_TYPE_INTERSECTION) {
2051
481
    const zend_ast_list *list = zend_ast_get_list(ast);
2052
1.74k
    for (uint32_t i = 0; i < list->children; i++) {
2053
1.25k
      if (i != 0) {
2054
778
        smart_str_appendc(str, '&');
2055
778
      }
2056
1.25k
      zend_ast_export_type(str, list->child[i], indent);
2057
1.25k
    }
2058
481
    return;
2059
481
  }
2060
12.0k
  if (ast->attr & ZEND_TYPE_NULLABLE) {
2061
694
    smart_str_appendc(str, '?');
2062
694
  }
2063
12.0k
  zend_ast_export_ns_name(str, ast, 0, indent);
2064
12.0k
}
2065
2066
static ZEND_COLD void zend_ast_export_hook_list(smart_str *str, const zend_ast_list *hook_list, int indent)
2067
1.82k
{
2068
1.82k
  smart_str_appends(str, " {");
2069
1.82k
  smart_str_appendc(str, '\n');
2070
1.82k
  indent++;
2071
1.82k
  zend_ast_export_indent(str, indent);
2072
2073
6.72k
  for (uint32_t i = 0; i < hook_list->children; i++) {
2074
4.89k
    const zend_ast_decl *hook = (const zend_ast_decl *)hook_list->child[i];
2075
4.89k
    zend_ast_export_visibility(str, hook->flags, ZEND_MODIFIER_TARGET_PROPERTY);
2076
4.89k
    if (hook->flags & ZEND_ACC_FINAL) {
2077
790
      smart_str_appends(str, "final ");
2078
790
    }
2079
4.89k
    smart_str_append(str, hook->name);
2080
4.89k
    zend_ast *body = hook->child[2];
2081
4.89k
    if (body == NULL) {
2082
1.99k
      smart_str_appendc(str, ';');
2083
2.90k
    } else if (body->kind == ZEND_AST_PROPERTY_HOOK_SHORT_BODY) {
2084
1.02k
      smart_str_appends(str, " => ");
2085
1.02k
      zend_ast_export_ex(str, body->child[0], 0, indent);
2086
1.02k
      smart_str_appendc(str, ';');
2087
1.88k
    } else {
2088
1.88k
      smart_str_appends(str, " {\n");
2089
1.88k
      zend_ast_export_stmt(str, body, indent + 1);
2090
1.88k
      zend_ast_export_indent(str, indent);
2091
1.88k
      smart_str_appendc(str, '}');
2092
1.88k
    }
2093
4.89k
    if (i < (hook_list->children - 1)) {
2094
3.16k
      smart_str_appendc(str, '\n');
2095
3.16k
      zend_ast_export_indent(str, indent);
2096
3.16k
    }
2097
4.89k
  }
2098
1.82k
  smart_str_appendc(str, '\n');
2099
1.82k
  indent--;
2100
1.82k
  zend_ast_export_indent(str, indent);
2101
1.82k
  smart_str_appendc(str, '}');
2102
1.82k
}
2103
2104
669k
#define BINARY_OP(_op, _p, _pl, _pr) do { \
2105
669k
    op = _op; \
2106
669k
    p = _p; \
2107
669k
    pl = _pl; \
2108
669k
    pr = _pr; \
2109
669k
    goto binary_op; \
2110
669k
  } while (0)
2111
2112
377k
#define PREFIX_OP(_op, _p, _pl) do { \
2113
377k
    op = _op; \
2114
377k
    p = _p; \
2115
377k
    pl = _pl; \
2116
377k
    goto prefix_op; \
2117
377k
  } while (0)
2118
2119
12.5k
#define FUNC_OP(_op) do { \
2120
12.5k
    op = _op; \
2121
12.5k
    goto func_op; \
2122
12.5k
  } while (0)
2123
2124
1.15k
#define POSTFIX_OP(_op, _p, _pl) do { \
2125
1.15k
    op = _op; \
2126
1.15k
    p = _p; \
2127
1.15k
    pl = _pl; \
2128
1.15k
    goto postfix_op; \
2129
1.15k
  } while (0)
2130
2131
37.2k
#define APPEND_NODE_1(_op) do { \
2132
37.2k
    op = _op; \
2133
37.2k
    goto append_node_1; \
2134
37.2k
  } while (0)
2135
2136
45.1k
#define APPEND_STR(_op) do { \
2137
45.1k
    op = _op; \
2138
45.1k
    goto append_str; \
2139
45.1k
  } while (0)
2140
2141
1.18k
#define APPEND_DEFAULT_VALUE(n) do { \
2142
1.18k
    p = n; \
2143
1.18k
    goto append_default_value; \
2144
1.18k
  } while (0)
2145
2146
static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int priority, int indent)
2147
4.44M
{
2148
4.44M
  const zend_ast_decl *decl;
2149
4.44M
  int p, pl, pr;
2150
4.44M
  const char *op;
2151
2152
4.76M
tail_call:
2153
4.76M
  if (!ast) {
2154
35.4k
    return;
2155
35.4k
  }
2156
4.72M
  switch (ast->kind) {
2157
    /* special nodes */
2158
491k
    case ZEND_AST_ZVAL:
2159
491k
      zend_ast_export_zval(str, zend_ast_get_zval(ast), priority, indent);
2160
491k
      break;
2161
233
    case ZEND_AST_CONSTANT: {
2162
233
      zend_string *name = zend_ast_get_constant_name(ast);
2163
233
      smart_str_append(str, name);
2164
233
      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.88k
    case ZEND_AST_FUNC_DECL:
2181
22.5k
    case ZEND_AST_CLOSURE:
2182
32.5k
    case ZEND_AST_ARROW_FUNC:
2183
33.3k
    case ZEND_AST_METHOD:
2184
33.3k
      decl = (const zend_ast_decl *) ast;
2185
33.3k
      if (decl->kind == ZEND_AST_ARROW_FUNC && (decl->attr & ZEND_PARENTHESIZED_ARROW_FUNC)) {
2186
33
        smart_str_appendc(str, '(');
2187
33
      }
2188
33.3k
      if (decl->child[4]) {
2189
1.45k
        bool newlines = !(ast->kind == ZEND_AST_CLOSURE || ast->kind == ZEND_AST_ARROW_FUNC);
2190
1.45k
        zend_ast_export_attributes(str, decl->child[4], indent, newlines);
2191
1.45k
      }
2192
2193
33.3k
      zend_ast_export_visibility(str, decl->flags, ZEND_MODIFIER_TARGET_METHOD);
2194
2195
33.3k
      if (decl->flags & ZEND_ACC_STATIC) {
2196
437
        smart_str_appends(str, "static ");
2197
437
      }
2198
33.3k
      if (decl->flags & ZEND_ACC_ABSTRACT) {
2199
143
        smart_str_appends(str, "abstract ");
2200
143
      }
2201
33.3k
      if (decl->flags & ZEND_ACC_FINAL) {
2202
21
        smart_str_appends(str, "final ");
2203
21
      }
2204
33.3k
      if (decl->kind == ZEND_AST_ARROW_FUNC) {
2205
9.94k
        smart_str_appends(str, "fn");
2206
23.3k
      } else {
2207
23.3k
        smart_str_appends(str, "function ");
2208
23.3k
      }
2209
33.3k
      if (decl->flags & ZEND_ACC_RETURN_REFERENCE) {
2210
765
        smart_str_appendc(str, '&');
2211
765
      }
2212
33.3k
      if (ast->kind != ZEND_AST_CLOSURE && ast->kind != ZEND_AST_ARROW_FUNC) {
2213
2.66k
        smart_str_append(str, decl->name);
2214
2.66k
      }
2215
33.3k
      smart_str_appendc(str, '(');
2216
33.3k
      zend_ast_export_ex(str, decl->child[0], 0, indent);
2217
33.3k
      smart_str_appendc(str, ')');
2218
33.3k
      zend_ast_export_ex(str, decl->child[1], 0, indent);
2219
33.3k
      if (decl->child[3]) {
2220
2.50k
        smart_str_appends(str, ": ");
2221
2.50k
        zend_ast_export_type(str, decl->child[3], indent);
2222
2.50k
      }
2223
33.3k
      if (decl->child[2]) {
2224
32.7k
        if (decl->kind == ZEND_AST_ARROW_FUNC) {
2225
9.94k
          zend_ast *body = decl->child[2];
2226
9.94k
          if (body->kind == ZEND_AST_RETURN) {
2227
0
            body = body->child[0];
2228
0
          }
2229
9.94k
          smart_str_appends(str, " => ");
2230
9.94k
          zend_ast_export_ex(str, body, 0, indent);
2231
9.94k
          if (decl->attr & ZEND_PARENTHESIZED_ARROW_FUNC) {
2232
33
            smart_str_appendc(str, ')');
2233
33
          }
2234
9.94k
          break;
2235
9.94k
        }
2236
2237
22.8k
        smart_str_appends(str, " {\n");
2238
22.8k
        zend_ast_export_stmt(str, decl->child[2], indent + 1);
2239
22.8k
        zend_ast_export_indent(str, indent);
2240
22.8k
        smart_str_appendc(str, '}');
2241
22.8k
        if (ast->kind != ZEND_AST_CLOSURE) {
2242
2.12k
          smart_str_appendc(str, '\n');
2243
2.12k
        }
2244
22.8k
      } else {
2245
543
        smart_str_appends(str, ";\n");
2246
543
      }
2247
23.3k
      break;
2248
23.3k
    case ZEND_AST_CLASS:
2249
6.02k
      decl = (const zend_ast_decl *) ast;
2250
6.02k
      if (decl->child[3]) {
2251
289
        zend_ast_export_attributes(str, decl->child[3], indent, true);
2252
289
      }
2253
6.02k
      if (decl->flags & ZEND_ACC_INTERFACE) {
2254
1.26k
        smart_str_appends(str, "interface ");
2255
4.76k
      } else if (decl->flags & ZEND_ACC_TRAIT) {
2256
195
        smart_str_appends(str, "trait ");
2257
4.56k
      } else if (decl->flags & ZEND_ACC_ENUM) {
2258
1.14k
        smart_str_appends(str, "enum ");
2259
3.42k
      } else {
2260
3.42k
        if (decl->flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) {
2261
847
          smart_str_appends(str, "abstract ");
2262
847
        }
2263
3.42k
        if (decl->flags & ZEND_ACC_FINAL) {
2264
230
          smart_str_appends(str, "final ");
2265
230
        }
2266
3.42k
        if (decl->flags & ZEND_ACC_READONLY_CLASS) {
2267
106
          smart_str_appends(str, "readonly ");
2268
106
        }
2269
3.42k
        smart_str_appends(str, "class ");
2270
3.42k
      }
2271
6.02k
      smart_str_append(str, decl->name);
2272
6.02k
      if (decl->flags & ZEND_ACC_ENUM && decl->child[4]) {
2273
352
        smart_str_appends(str, ": ");
2274
352
        zend_ast_export_type(str, decl->child[4], indent);
2275
352
      }
2276
6.02k
      zend_ast_export_class_no_header(str, decl, indent);
2277
6.02k
      smart_str_appendc(str, '\n');
2278
6.02k
      break;
2279
2280
    /* list nodes */
2281
916k
    case ZEND_AST_ARG_LIST:
2282
920k
    case ZEND_AST_EXPR_LIST:
2283
953k
    case ZEND_AST_PARAM_LIST:
2284
958k
simple_list:
2285
958k
      zend_ast_export_list(str, zend_ast_get_list(ast), true, 20, indent);
2286
958k
      break;
2287
3.80k
    case ZEND_AST_ARRAY:
2288
3.80k
      smart_str_appendc(str, '[');
2289
3.80k
      zend_ast_export_list(str, zend_ast_get_list(ast), true, 20, indent);
2290
3.80k
      smart_str_appendc(str, ']');
2291
3.80k
      break;
2292
4.28k
    case ZEND_AST_ENCAPS_LIST:
2293
4.28k
      smart_str_appendc(str, '"');
2294
4.28k
      zend_ast_export_encaps_list(str, '"', zend_ast_get_list(ast), indent);
2295
4.28k
      smart_str_appendc(str, '"');
2296
4.28k
      break;
2297
0
    case ZEND_AST_STMT_LIST:
2298
291
    case ZEND_AST_TRAIT_ADAPTATIONS:
2299
291
      zend_ast_export_stmt(str, ast, indent);
2300
291
      break;
2301
7.23k
    case ZEND_AST_IF:
2302
7.23k
      zend_ast_export_if_stmt(str, zend_ast_get_list(ast), indent);
2303
7.23k
      break;
2304
61
    case ZEND_AST_SWITCH_LIST:
2305
686
    case ZEND_AST_CATCH_LIST:
2306
1.43k
    case ZEND_AST_MATCH_ARM_LIST:
2307
1.43k
      zend_ast_export_list(str, zend_ast_get_list(ast), false, 0, indent);
2308
1.43k
      break;
2309
723
    case ZEND_AST_CLOSURE_USES:
2310
723
      smart_str_appends(str, " use(");
2311
723
      zend_ast_export_var_list(str, zend_ast_get_list(ast), indent);
2312
723
      smart_str_appendc(str, ')');
2313
723
      break;
2314
4.15k
    case ZEND_AST_PROP_GROUP: {
2315
4.15k
      zend_ast *type_ast = ast->child[0];
2316
4.15k
      zend_ast *prop_ast = ast->child[1];
2317
2318
4.15k
      if (ast->child[2]) {
2319
156
        zend_ast_export_attributes(str, ast->child[2], indent, true);
2320
156
      }
2321
2322
4.15k
      zend_ast_export_visibility(str, ast->attr, ZEND_MODIFIER_TARGET_PROPERTY);
2323
2324
4.15k
      if (ast->attr & ZEND_ACC_STATIC) {
2325
625
        smart_str_appends(str, "static ");
2326
625
      }
2327
4.15k
      if (ast->attr & ZEND_ACC_READONLY) {
2328
74
        smart_str_appends(str, "readonly ");
2329
74
      }
2330
2331
4.15k
      if (type_ast) {
2332
1.75k
        zend_ast_export_type(str, type_ast, indent);
2333
1.75k
        smart_str_appendc(str, ' ');
2334
1.75k
      }
2335
2336
4.15k
      ast = prop_ast;
2337
4.15k
      goto simple_list;
2338
686
    }
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
265
    case ZEND_AST_CLASS_CONST_GROUP:
2361
265
      if (ast->child[1]) {
2362
45
        zend_ast_export_attributes(str, ast->child[1], indent, true);
2363
45
      }
2364
2365
265
      zend_ast_export_visibility(str, ast->attr, ZEND_MODIFIER_TARGET_CONSTANT);
2366
265
      smart_str_appends(str, "const ");
2367
265
      if (ast->child[2]) {
2368
114
        zend_ast_export_type(str, ast->child[2], indent);
2369
114
        smart_str_appendc(str, ' ');
2370
114
      }
2371
2372
265
      ast = ast->child[0];
2373
2374
265
      goto simple_list;
2375
2.58k
    case ZEND_AST_NAME_LIST:
2376
2.58k
      zend_ast_export_name_list(str, zend_ast_get_list(ast), indent);
2377
2.58k
      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
43.6k
    case ZEND_AST_MAGIC_CONST:
2389
43.6k
      switch (ast->attr) {
2390
17
        case T_LINE:     APPEND_STR("__LINE__");
2391
2
        case T_FILE:     APPEND_STR("__FILE__");
2392
0
        case T_DIR:      APPEND_STR("__DIR__");
2393
43.5k
        case T_TRAIT_C:  APPEND_STR("__TRAIT__");
2394
101
        case T_METHOD_C: APPEND_STR("__METHOD__");
2395
0
        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
0
        case T_CLASS_C:  APPEND_STR("__CLASS__");
2399
0
        EMPTY_SWITCH_DEFAULT_CASE();
2400
43.6k
      }
2401
0
      break;
2402
1.01k
    case ZEND_AST_TYPE:
2403
1.01k
      switch (ast->attr & ~ZEND_TYPE_NULLABLE) {
2404
111
        case IS_ARRAY:    APPEND_STR("array");
2405
20
        case IS_CALLABLE: APPEND_STR("callable");
2406
887
        case IS_STATIC:   APPEND_STR("static");
2407
0
        case IS_MIXED:    APPEND_STR("mixed");
2408
0
        EMPTY_SWITCH_DEFAULT_CASE();
2409
1.01k
      }
2410
0
      break;
2411
417
    case ZEND_AST_PLACEHOLDER_ARG:
2412
417
      if (ast->attr == ZEND_PLACEHOLDER_VARIADIC) {
2413
175
        APPEND_STR("...");
2414
242
      } else  {
2415
242
        APPEND_STR("?");
2416
242
      }
2417
0
      break;
2418
2419
    /* 1 child node */
2420
105k
    case ZEND_AST_VAR:
2421
105k
      smart_str_appendc(str, '$');
2422
105k
      zend_ast_export_var(str, ast->child[0], indent);
2423
105k
      break;
2424
629k
    case ZEND_AST_CONST:
2425
629k
      zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2426
629k
      break;
2427
1.23k
    case ZEND_AST_UNPACK:
2428
1.23k
      smart_str_appends(str, "...");
2429
1.23k
      ast = ast->child[0];
2430
1.23k
      goto tail_call;
2431
47.0k
    case ZEND_AST_UNARY_PLUS:  PREFIX_OP("+", 240, 241);
2432
79.7k
    case ZEND_AST_UNARY_MINUS: PREFIX_OP("-", 240, 241);
2433
1.33k
    case ZEND_AST_CAST:
2434
1.33k
      switch (ast->attr) {
2435
256
        case IS_NULL:      PREFIX_OP("(unset)",  240, 241);
2436
237
        case _IS_BOOL:     PREFIX_OP("(bool)",   240, 241);
2437
61
        case IS_LONG:      PREFIX_OP("(int)",    240, 241);
2438
560
        case IS_DOUBLE:    PREFIX_OP("(float)", 240, 241);
2439
70
        case IS_STRING:    PREFIX_OP("(string)", 240, 241);
2440
128
        case IS_ARRAY:     PREFIX_OP("(array)",  240, 241);
2441
18
        case IS_OBJECT:    PREFIX_OP("(object)", 240, 241);
2442
0
        EMPTY_SWITCH_DEFAULT_CASE();
2443
1.33k
      }
2444
0
      break;
2445
754
    case ZEND_AST_CAST_VOID:
2446
754
      PREFIX_OP("(void)", 240, 241);
2447
0
      break;
2448
169
    case ZEND_AST_EMPTY:
2449
169
      FUNC_OP("empty");
2450
11.0k
    case ZEND_AST_ISSET:
2451
11.0k
      FUNC_OP("isset");
2452
46.2k
    case ZEND_AST_SILENCE:
2453
46.2k
      PREFIX_OP("@", 240, 241);
2454
2.54k
    case ZEND_AST_SHELL_EXEC:
2455
2.54k
      smart_str_appendc(str, '`');
2456
2.54k
      if (ast->child[0]->kind == ZEND_AST_ENCAPS_LIST) {
2457
722
        zend_ast_export_encaps_list(str, '`', zend_ast_get_list(ast->child[0]), indent);
2458
1.81k
      } else {
2459
1.81k
        zval *zv;
2460
1.81k
        ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_ZVAL);
2461
1.81k
        zv = zend_ast_get_zval(ast->child[0]);
2462
1.81k
        ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
2463
1.81k
        zend_ast_export_qstr(str, '`', Z_STR_P(zv));
2464
1.81k
      }
2465
2.54k
      smart_str_appendc(str, '`');
2466
2.54k
      break;
2467
136
    case ZEND_AST_PRINT:
2468
136
      PREFIX_OP("print ", 60, 61);
2469
1.27k
    case ZEND_AST_INCLUDE_OR_EVAL:
2470
1.27k
      switch (ast->attr) {
2471
182
        case ZEND_INCLUDE_ONCE: FUNC_OP("include_once");
2472
184
        case ZEND_INCLUDE:      FUNC_OP("include");
2473
236
        case ZEND_REQUIRE_ONCE: FUNC_OP("require_once");
2474
446
        case ZEND_REQUIRE:      FUNC_OP("require");
2475
224
        case ZEND_EVAL:         FUNC_OP("eval");
2476
0
        EMPTY_SWITCH_DEFAULT_CASE();
2477
1.27k
      }
2478
0
      break;
2479
201k
    case ZEND_AST_UNARY_OP:
2480
201k
      switch (ast->attr) {
2481
106k
        case ZEND_BW_NOT:   PREFIX_OP("~", 240, 241);
2482
94.1k
        case ZEND_BOOL_NOT: PREFIX_OP("!", 240, 241);
2483
0
        EMPTY_SWITCH_DEFAULT_CASE();
2484
201k
      }
2485
0
      break;
2486
321
    case ZEND_AST_PRE_INC:
2487
321
      PREFIX_OP("++", 240, 241);
2488
274
    case ZEND_AST_PRE_DEC:
2489
274
      PREFIX_OP("--", 240, 241);
2490
1.03k
    case ZEND_AST_POST_INC:
2491
1.03k
      POSTFIX_OP("++", 240, 241);
2492
125
    case ZEND_AST_POST_DEC:
2493
125
      POSTFIX_OP("--", 240, 241);
2494
2495
483
    case ZEND_AST_GLOBAL:
2496
483
      APPEND_NODE_1("global");
2497
104
    case ZEND_AST_UNSET:
2498
104
      FUNC_OP("unset");
2499
1.13k
    case ZEND_AST_RETURN:
2500
1.13k
      APPEND_NODE_1("return");
2501
1.44k
    case ZEND_AST_LABEL:
2502
1.44k
      zend_ast_export_name(str, ast->child[0], 0, indent);
2503
1.44k
      smart_str_appendc(str, ':');
2504
1.44k
      break;
2505
520
    case ZEND_AST_REF:
2506
520
      smart_str_appendc(str, '&');
2507
520
      ast = ast->child[0];
2508
520
      goto tail_call;
2509
0
    case ZEND_AST_HALT_COMPILER:
2510
0
      APPEND_STR("__HALT_COMPILER()");
2511
34.8k
    case ZEND_AST_ECHO:
2512
34.8k
      APPEND_NODE_1("echo");
2513
298
    case ZEND_AST_THROW:
2514
298
      APPEND_NODE_1("throw");
2515
271
    case ZEND_AST_GOTO:
2516
271
      smart_str_appends(str, "goto ");
2517
271
      zend_ast_export_name(str, ast->child[0], 0, indent);
2518
271
      break;
2519
55
    case ZEND_AST_BREAK:
2520
55
      APPEND_NODE_1("break");
2521
435
    case ZEND_AST_CONTINUE:
2522
435
      APPEND_NODE_1("continue");
2523
2524
    /* 2 child nodes */
2525
5.20k
    case ZEND_AST_DIM:
2526
5.20k
      zend_ast_export_ex(str, ast->child[0], 260, indent);
2527
5.20k
      smart_str_appendc(str, '[');
2528
5.20k
      if (ast->child[1]) {
2529
4.93k
        zend_ast_export_ex(str, ast->child[1], 0, indent);
2530
4.93k
      }
2531
5.20k
      smart_str_appendc(str, ']');
2532
5.20k
      break;
2533
8.56k
    case ZEND_AST_PROP:
2534
23.3k
    case ZEND_AST_NULLSAFE_PROP:
2535
23.3k
      zend_ast_export_ex(str, ast->child[0], 0, indent);
2536
23.3k
      smart_str_appends(str, ast->kind == ZEND_AST_NULLSAFE_PROP ? "?->" : "->");
2537
23.3k
      zend_ast_export_var(str, ast->child[1], indent);
2538
23.3k
      break;
2539
1.63k
    case ZEND_AST_STATIC_PROP:
2540
1.63k
      zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2541
1.63k
      smart_str_appends(str, "::$");
2542
1.63k
      zend_ast_export_var(str, ast->child[1], indent);
2543
1.63k
      break;
2544
912k
    case ZEND_AST_CALL: {
2545
912k
      zend_ast *left = ast->child[0];
2546
912k
      if (left->kind == ZEND_AST_ARROW_FUNC || left->kind == ZEND_AST_CLOSURE) {
2547
175
        smart_str_appendc(str, '(');
2548
175
        zend_ast_export_ns_name(str, left, 0, indent);
2549
175
        smart_str_appendc(str, ')');
2550
912k
      } else {
2551
912k
        zend_ast_export_ns_name(str, left, 0, indent);
2552
912k
      }
2553
912k
      smart_str_appendc(str, '(');
2554
912k
      zend_ast_export_ex(str, ast->child[1], 0, indent);
2555
912k
      smart_str_appendc(str, ')');
2556
912k
      break;
2557
8.56k
    }
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
417
    case ZEND_AST_CALLABLE_CONVERT: {
2565
417
      zend_ast_fcc *fcc_ast = (zend_ast_fcc*)ast;
2566
417
      ast = fcc_ast->args;
2567
417
      goto simple_list;
2568
8.56k
    }
2569
1.59k
    case ZEND_AST_CLASS_CONST:
2570
1.59k
      zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2571
1.59k
      smart_str_appends(str, "::");
2572
1.59k
      zend_ast_export_name(str, ast->child[1], 0, indent);
2573
1.59k
      break;
2574
58
    case ZEND_AST_CLASS_NAME:
2575
58
      if (ast->child[0] == NULL) {
2576
        /* The const expr representation stores the fetch type instead. */
2577
3
        switch (ast->attr) {
2578
3
          case ZEND_FETCH_CLASS_SELF:
2579
3
            smart_str_append(str, ZSTR_KNOWN(ZEND_STR_SELF));
2580
3
            break;
2581
0
          case ZEND_FETCH_CLASS_PARENT:
2582
0
            smart_str_append(str, ZSTR_KNOWN(ZEND_STR_PARENT));
2583
0
            break;
2584
3
          EMPTY_SWITCH_DEFAULT_CASE()
2585
3
        }
2586
55
      } else {
2587
55
        zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2588
55
      }
2589
58
      smart_str_appends(str, "::class");
2590
58
      break;
2591
12.9k
    case ZEND_AST_ASSIGN:            BINARY_OP(" = ",   90, 91, 90);
2592
283
    case ZEND_AST_ASSIGN_REF:        BINARY_OP(" =& ",  90, 91, 90);
2593
8.71k
    case ZEND_AST_ASSIGN_OP:
2594
8.71k
      switch (ast->attr) {
2595
11
        case ZEND_ADD:    BINARY_OP(" += ",  90, 91, 90);
2596
164
        case ZEND_SUB:    BINARY_OP(" -= ",  90, 91, 90);
2597
7.44k
        case ZEND_MUL:    BINARY_OP(" *= ",  90, 91, 90);
2598
60
        case ZEND_DIV:    BINARY_OP(" /= ",  90, 91, 90);
2599
44
        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
605
        case ZEND_CONCAT: BINARY_OP(" .= ",  90, 91, 90);
2603
39
        case ZEND_BW_OR:  BINARY_OP(" |= ",  90, 91, 90);
2604
11
        case ZEND_BW_AND: BINARY_OP(" &= ",  90, 91, 90);
2605
335
        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
8.71k
      }
2609
0
      break;
2610
780
    case ZEND_AST_ASSIGN_COALESCE: BINARY_OP(" \?\?= ", 90, 91, 90);
2611
624k
    case ZEND_AST_BINARY_OP:
2612
624k
      switch (ast->attr) {
2613
12.1k
        case ZEND_ADD:                 BINARY_OP(" + ",   200, 200, 201);
2614
135k
        case ZEND_SUB:                 BINARY_OP(" - ",   200, 200, 201);
2615
128k
        case ZEND_MUL:                 BINARY_OP(" * ",   210, 210, 211);
2616
64.8k
        case ZEND_DIV:                 BINARY_OP(" / ",   210, 210, 211);
2617
4.42k
        case ZEND_MOD:                 BINARY_OP(" % ",   210, 210, 211);
2618
496
        case ZEND_SL:                  BINARY_OP(" << ",  190, 190, 191);
2619
342
        case ZEND_SR:                  BINARY_OP(" >> ",  190, 190, 191);
2620
60.0k
        case ZEND_CONCAT:              BINARY_OP(" . ",   185, 185, 186);
2621
33.4k
        case ZEND_BW_OR:               BINARY_OP(" | ",   140, 140, 141);
2622
171k
        case ZEND_BW_AND:              BINARY_OP(" & ",   160, 160, 161);
2623
1.38k
        case ZEND_BW_XOR:              BINARY_OP(" ^ ",   150, 150, 151);
2624
697
        case ZEND_IS_IDENTICAL:        BINARY_OP(" === ", 170, 171, 171);
2625
57
        case ZEND_IS_NOT_IDENTICAL:    BINARY_OP(" !== ", 170, 171, 171);
2626
937
        case ZEND_IS_EQUAL:            BINARY_OP(" == ",  170, 171, 171);
2627
5.02k
        case ZEND_IS_NOT_EQUAL:        BINARY_OP(" != ",  170, 171, 171);
2628
2.09k
        case ZEND_IS_SMALLER:          BINARY_OP(" < ",   180, 181, 181);
2629
629
        case ZEND_IS_SMALLER_OR_EQUAL: BINARY_OP(" <= ",  180, 181, 181);
2630
273
        case ZEND_POW:                 BINARY_OP(" ** ",  250, 251, 250);
2631
1.32k
        case ZEND_BOOL_XOR:            BINARY_OP(" xor ",  40,  40,  41);
2632
505
        case ZEND_SPACESHIP:           BINARY_OP(" <=> ", 180, 181, 181);
2633
0
        EMPTY_SWITCH_DEFAULT_CASE();
2634
624k
      }
2635
0
      break;
2636
5.59k
    case ZEND_AST_GREATER:                 BINARY_OP(" > ",   180, 181, 181);
2637
1.64k
    case ZEND_AST_GREATER_EQUAL:           BINARY_OP(" >= ",  180, 181, 181);
2638
12.0k
    case ZEND_AST_AND:                     BINARY_OP(" && ",  130, 130, 131);
2639
546
    case ZEND_AST_OR:                      BINARY_OP(" || ",  120, 120, 121);
2640
2.01k
    case ZEND_AST_PIPE:                    BINARY_OP(" |> ",  183, 183, 184);
2641
5.60k
    case ZEND_AST_ARRAY_ELEM:
2642
5.60k
      if (ast->child[1]) {
2643
491
        zend_ast_export_ex(str, ast->child[1], 80, indent);
2644
491
        smart_str_appends(str, " => ");
2645
491
      }
2646
5.60k
      if (ast->attr)
2647
1.40k
        smart_str_appendc(str, '&');
2648
5.60k
      zend_ast_export_ex(str, ast->child[0], 80, indent);
2649
5.60k
      break;
2650
4.37k
    case ZEND_AST_NEW:
2651
4.37k
      smart_str_appends(str, "new ");
2652
4.37k
      if (ast->child[0]->kind == ZEND_AST_CLASS) {
2653
2.62k
        const zend_ast_decl *decl = (const zend_ast_decl *) ast->child[0];
2654
2.62k
        if (decl->child[3]) {
2655
15
          zend_ast_export_attributes(str, decl->child[3], indent, false);
2656
15
        }
2657
2.62k
        smart_str_appends(str, "class");
2658
2.62k
        if (!zend_ast_is_list(ast->child[1])
2659
2.54k
            || zend_ast_get_list(ast->child[1])->children) {
2660
843
          smart_str_appendc(str, '(');
2661
843
          zend_ast_export_ex(str, ast->child[1], 0, indent);
2662
843
          smart_str_appendc(str, ')');
2663
843
        }
2664
2.62k
        zend_ast_export_class_no_header(str, decl, indent);
2665
2.62k
      } else {
2666
1.75k
        zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2667
1.75k
        smart_str_appendc(str, '(');
2668
1.75k
        zend_ast_export_ex(str, ast->child[1], 0, indent);
2669
1.75k
        smart_str_appendc(str, ')');
2670
1.75k
      }
2671
4.37k
      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
8.68k
    case ZEND_AST_YIELD:
2678
8.68k
      if (priority > 70) smart_str_appendc(str, '(');
2679
8.68k
      smart_str_appends(str, "yield ");
2680
8.68k
      if (ast->child[0]) {
2681
8.40k
        if (ast->child[1]) {
2682
47
          zend_ast_export_ex(str, ast->child[1], 70, indent);
2683
47
          smart_str_appends(str, " => ");
2684
47
        }
2685
8.40k
        zend_ast_export_ex(str, ast->child[0], 70, indent);
2686
8.40k
      }
2687
8.68k
      if (priority > 70) smart_str_appendc(str, ')');
2688
8.68k
      break;
2689
626
    case ZEND_AST_YIELD_FROM:
2690
626
      PREFIX_OP("yield from ", 85, 86);
2691
1.15k
    case ZEND_AST_COALESCE: BINARY_OP(" ?? ", 110, 111, 110);
2692
318
    case ZEND_AST_STATIC:
2693
318
      smart_str_appends(str, "static $");
2694
318
      zend_ast_export_name(str, ast->child[0], 0, indent);
2695
318
      APPEND_DEFAULT_VALUE(1);
2696
333
    case ZEND_AST_WHILE:
2697
333
      smart_str_appends(str, "while (");
2698
333
      zend_ast_export_ex(str, ast->child[0], 0, indent);
2699
333
      smart_str_appends(str, ") {\n");
2700
333
      zend_ast_export_stmt(str, ast->child[1], indent + 1);
2701
333
      zend_ast_export_indent(str, indent);
2702
333
      smart_str_appendc(str, '}');
2703
333
      break;
2704
224
    case ZEND_AST_DO_WHILE:
2705
224
      smart_str_appends(str, "do {\n");
2706
224
      zend_ast_export_stmt(str, ast->child[0], indent + 1);
2707
224
      zend_ast_export_indent(str, indent);
2708
224
      smart_str_appends(str, "} while (");
2709
224
      zend_ast_export_ex(str, ast->child[1], 0, indent);
2710
224
      smart_str_appendc(str, ')');
2711
224
      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
61
    case ZEND_AST_SWITCH:
2727
61
      smart_str_appends(str, "switch (");
2728
61
      zend_ast_export_ex(str, ast->child[0], 0, indent);
2729
61
      smart_str_appends(str, ") {\n");
2730
61
      zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
2731
61
      zend_ast_export_indent(str, indent);
2732
61
      smart_str_appendc(str, '}');
2733
61
      break;
2734
365
    case ZEND_AST_SWITCH_CASE:
2735
365
      zend_ast_export_indent(str, indent);
2736
365
      if (ast->child[0]) {
2737
306
        smart_str_appends(str, "case ");
2738
306
        zend_ast_export_ex(str, ast->child[0], 0, indent);
2739
306
        smart_str_appends(str, ":\n");
2740
306
      } else {
2741
59
        smart_str_appends(str, "default:\n");
2742
59
      }
2743
365
      zend_ast_export_stmt(str, ast->child[1], indent + 1);
2744
365
      break;
2745
752
    case ZEND_AST_MATCH:
2746
752
      smart_str_appends(str, "match (");
2747
752
      zend_ast_export_ex(str, ast->child[0], 0, indent);
2748
752
      smart_str_appends(str, ") {\n");
2749
752
      zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
2750
752
      zend_ast_export_indent(str, indent);
2751
752
      smart_str_appendc(str, '}');
2752
752
      break;
2753
803
    case ZEND_AST_MATCH_ARM:
2754
803
      zend_ast_export_indent(str, indent);
2755
803
      if (ast->child[0]) {
2756
571
        zend_ast_export_list(str, zend_ast_get_list(ast->child[0]), true, 0, indent);
2757
571
        smart_str_appends(str, " => ");
2758
571
      } else {
2759
232
        smart_str_appends(str, "default => ");
2760
232
      }
2761
803
      zend_ast_export_ex(str, ast->child[1], 0, 0);
2762
803
      smart_str_appends(str, ",\n");
2763
803
      break;
2764
518
    case ZEND_AST_DECLARE:
2765
518
      smart_str_appends(str, "declare(");
2766
518
      ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_CONST_DECL);
2767
518
      zend_ast_export_list(str, zend_ast_get_list(ast->child[0]), true, 0, indent);
2768
518
      smart_str_appendc(str, ')');
2769
518
      if (ast->child[1]) {
2770
201
        smart_str_appends(str, " {\n");
2771
201
        zend_ast_export_stmt(str, ast->child[1], indent + 1);
2772
201
        zend_ast_export_indent(str, indent);
2773
201
        smart_str_appendc(str, '}');
2774
317
      } else {
2775
317
        smart_str_appendc(str, ';');
2776
317
      }
2777
518
      break;
2778
4.17k
    case ZEND_AST_PROP_ELEM:
2779
4.17k
      smart_str_appendc(str, '$');
2780
4.17k
      zend_ast_export_name(str, ast->child[0], 0, indent);
2781
2782
4.17k
      zend_ast *default_value = ast->child[1];
2783
4.17k
      if (default_value) {
2784
2.12k
        smart_str_appends(str, " = ");
2785
2.12k
        zend_ast_export_ex(str, default_value, 0, indent + 1);
2786
2.12k
      }
2787
2788
4.17k
      if (ast->child[3]) {
2789
1.78k
        zend_ast_export_hook_list(str, zend_ast_get_list(ast->child[3]), indent);
2790
1.78k
      }
2791
4.17k
      break;
2792
863
    case ZEND_AST_CONST_ELEM:
2793
863
      zend_ast_export_name(str, ast->child[0], 0, indent);
2794
863
      APPEND_DEFAULT_VALUE(1);
2795
502
    case ZEND_AST_USE_TRAIT:
2796
502
      smart_str_appends(str, "use ");
2797
502
      zend_ast_export_ex(str, ast->child[0], 0, indent);
2798
502
      if (ast->child[1]) {
2799
291
        smart_str_appends(str, " {\n");
2800
291
        zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
2801
291
        zend_ast_export_indent(str, indent);
2802
291
        smart_str_appendc(str, '}');
2803
291
      } else {
2804
211
        smart_str_appendc(str, ';');
2805
211
      }
2806
502
      break;
2807
159
    case ZEND_AST_TRAIT_PRECEDENCE:
2808
159
      zend_ast_export_ex(str, ast->child[0], 0, indent);
2809
159
      smart_str_appends(str, " insteadof ");
2810
159
      zend_ast_export_ex(str, ast->child[1], 0, indent);
2811
159
      break;
2812
2.71k
    case ZEND_AST_METHOD_REFERENCE:
2813
2.71k
      if (ast->child[0]) {
2814
636
        zend_ast_export_name(str, ast->child[0], 0, indent);
2815
636
        smart_str_appends(str, "::");
2816
636
      }
2817
2.71k
      zend_ast_export_name(str, ast->child[1], 0, indent);
2818
2.71k
      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
2.55k
    case ZEND_AST_TRAIT_ALIAS:
2836
2.55k
      zend_ast_export_name(str, ast->child[0], 0, indent);
2837
2.55k
      if (ast->attr & ZEND_ACC_PUBLIC) {
2838
357
        smart_str_appends(str, " as public");
2839
2.20k
      } else if (ast->attr & ZEND_ACC_PROTECTED) {
2840
196
        smart_str_appends(str, " as protected");
2841
2.00k
      } else if (ast->attr & ZEND_ACC_PRIVATE) {
2842
305
        smart_str_appends(str, " as private");
2843
1.69k
      } else if (ast->child[1]) {
2844
1.03k
        smart_str_appends(str, " as");
2845
1.03k
      }
2846
2.55k
      if (ast->child[1]) {
2847
1.16k
        smart_str_appendc(str, ' ');
2848
1.16k
        zend_ast_export_name(str, ast->child[1], 0, indent);
2849
1.16k
      }
2850
2.55k
      break;
2851
283k
    case ZEND_AST_NAMED_ARG:
2852
283k
      smart_str_append(str, zend_ast_get_str(ast->child[0]));
2853
283k
      smart_str_appends(str, ": ");
2854
283k
      ast = ast->child[1];
2855
283k
      goto tail_call;
2856
2857
    /* 3 child nodes */
2858
640
    case ZEND_AST_METHOD_CALL:
2859
708
    case ZEND_AST_NULLSAFE_METHOD_CALL:
2860
708
      zend_ast_export_ex(str, ast->child[0], 0, indent);
2861
708
      smart_str_appends(str, ast->kind == ZEND_AST_NULLSAFE_METHOD_CALL ? "?->" : "->");
2862
708
      zend_ast_export_var(str, ast->child[1], indent);
2863
708
      smart_str_appendc(str, '(');
2864
708
      zend_ast_export_ex(str, ast->child[2], 0, indent);
2865
708
      smart_str_appendc(str, ')');
2866
708
      break;
2867
541
    case ZEND_AST_STATIC_CALL:
2868
541
      zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2869
541
      smart_str_appends(str, "::");
2870
541
      zend_ast_export_var(str, ast->child[1], indent);
2871
541
      smart_str_appendc(str, '(');
2872
541
      zend_ast_export_ex(str, ast->child[2], 0, indent);
2873
541
      smart_str_appendc(str, ')');
2874
541
      break;
2875
60.7k
    case ZEND_AST_CONDITIONAL:
2876
60.7k
      if (priority > 100) smart_str_appendc(str, '(');
2877
60.7k
      zend_ast_export_ex(str, ast->child[0], 100, indent);
2878
60.7k
      if (ast->child[1]) {
2879
1.08k
        smart_str_appends(str, " ? ");
2880
1.08k
        zend_ast_export_ex(str, ast->child[1], 101, indent);
2881
1.08k
        smart_str_appends(str, " : ");
2882
59.6k
      } else {
2883
59.6k
        smart_str_appends(str, " ?: ");
2884
59.6k
      }
2885
60.7k
      zend_ast_export_ex(str, ast->child[2], 101, indent);
2886
60.7k
      if (priority > 100) smart_str_appendc(str, ')');
2887
60.7k
      break;
2888
2889
625
    case ZEND_AST_TRY:
2890
625
      smart_str_appends(str, "try {\n");
2891
625
      zend_ast_export_stmt(str, ast->child[0], indent + 1);
2892
625
      zend_ast_export_indent(str, indent);
2893
625
      zend_ast_export_ex(str, ast->child[1], 0, indent);
2894
625
      if (ast->child[2]) {
2895
338
        smart_str_appends(str, "} finally {\n");
2896
338
        zend_ast_export_stmt(str, ast->child[2], indent + 1);
2897
338
        zend_ast_export_indent(str, indent);
2898
338
      }
2899
625
      smart_str_appendc(str, '}');
2900
625
      break;
2901
323
    case ZEND_AST_CATCH:
2902
323
      smart_str_appends(str, "} catch (");
2903
323
      zend_ast_export_catch_name_list(str, zend_ast_get_list(ast->child[0]), indent);
2904
323
      if (ast->child[1]) {
2905
304
        smart_str_appends(str, " $");
2906
304
        zend_ast_export_var(str, ast->child[1], indent);
2907
304
      }
2908
323
      smart_str_appends(str, ") {\n");
2909
323
      zend_ast_export_stmt(str, ast->child[2], indent + 1);
2910
323
      zend_ast_export_indent(str, indent);
2911
323
      break;
2912
6.90k
    case ZEND_AST_PARAM:
2913
6.90k
      if (ast->child[3]) {
2914
287
        zend_ast_export_attributes(str, ast->child[3], indent, false);
2915
287
      }
2916
6.90k
      zend_ast_export_visibility(str, ast->attr, ZEND_MODIFIER_TARGET_CPP);
2917
6.90k
      if (ast->attr & ZEND_ACC_FINAL) {
2918
100
        smart_str_appends(str, "final ");
2919
100
      }
2920
6.90k
      if (ast->child[0]) {
2921
3.79k
        zend_ast_export_type(str, ast->child[0], indent);
2922
3.79k
        smart_str_appendc(str, ' ');
2923
3.79k
      }
2924
6.90k
      if (ast->attr & ZEND_PARAM_REF) {
2925
1.89k
        smart_str_appendc(str, '&');
2926
1.89k
      }
2927
6.90k
      if (ast->attr & ZEND_PARAM_VARIADIC) {
2928
916
        smart_str_appends(str, "...");
2929
916
      }
2930
6.90k
      smart_str_appendc(str, '$');
2931
6.90k
      zend_ast_export_name(str, ast->child[1], 0, indent);
2932
6.90k
      if (ast->child[2]) {
2933
1.04k
        smart_str_appends(str, " = ");
2934
1.04k
        zend_ast_export_ex(str, ast->child[2], 0, indent);
2935
1.04k
      }
2936
6.90k
      if (ast->child[5]) {
2937
43
        zend_ast_export_hook_list(str, zend_ast_get_list(ast->child[5]), indent);
2938
43
      }
2939
6.90k
      break;
2940
273
    case ZEND_AST_ENUM_CASE:
2941
273
      if (ast->child[3]) {
2942
68
        zend_ast_export_attributes(str, ast->child[3], indent, true);
2943
68
      }
2944
273
      smart_str_appends(str, "case ");
2945
273
      zend_ast_export_name(str, ast->child[0], 0, indent);
2946
273
      if (ast->child[1]) {
2947
176
        smart_str_appends(str, " = ");
2948
176
        zend_ast_export_ex(str, ast->child[1], 0, indent);
2949
176
      }
2950
273
      break;
2951
2952
    /* 4 child nodes */
2953
2.92k
    case ZEND_AST_FOR:
2954
2.92k
      smart_str_appends(str, "for (");
2955
2.92k
      zend_ast_export_ex(str, ast->child[0], 0, indent);
2956
2.92k
      smart_str_appendc(str, ';');
2957
2.92k
      if (ast->child[1]) {
2958
2.73k
        smart_str_appendc(str, ' ');
2959
2.73k
        zend_ast_export_ex(str, ast->child[1], 0, indent);
2960
2.73k
      }
2961
2.92k
      smart_str_appendc(str, ';');
2962
2.92k
      if (ast->child[2]) {
2963
625
        smart_str_appendc(str, ' ');
2964
625
        zend_ast_export_ex(str, ast->child[2], 0, indent);
2965
625
      }
2966
2.92k
      smart_str_appends(str, ") {\n");
2967
2.92k
      zend_ast_export_stmt(str, ast->child[3], indent + 1);
2968
2.92k
      zend_ast_export_indent(str, indent);
2969
2.92k
      smart_str_appendc(str, '}');
2970
2.92k
      break;
2971
1.07k
    case ZEND_AST_FOREACH:
2972
1.07k
      smart_str_appends(str, "foreach (");
2973
1.07k
      zend_ast_export_ex(str, ast->child[0], 0, indent);
2974
1.07k
      smart_str_appends(str, " as ");
2975
1.07k
      if (ast->child[2]) {
2976
142
        zend_ast_export_ex(str, ast->child[2], 0, indent);
2977
142
        smart_str_appends(str, " => ");
2978
142
      }
2979
1.07k
      zend_ast_export_ex(str, ast->child[1], 0, indent);
2980
1.07k
      smart_str_appends(str, ") {\n");
2981
1.07k
      zend_ast_export_stmt(str, ast->child[3], indent + 1);
2982
1.07k
      zend_ast_export_indent(str, indent);
2983
1.07k
      smart_str_appendc(str, '}');
2984
1.07k
      break;
2985
0
    EMPTY_SWITCH_DEFAULT_CASE();
2986
4.72M
  }
2987
3.29M
  return;
2988
2989
3.29M
binary_op:
2990
669k
  if (priority > p) smart_str_appendc(str, '(');
2991
669k
  zend_ast_export_ex(str, ast->child[0], pl, indent);
2992
669k
  smart_str_appends(str, op);
2993
669k
  zend_ast_export_ex(str, ast->child[1], pr, indent);
2994
669k
  if (priority > p) smart_str_appendc(str, ')');
2995
669k
  return;
2996
2997
377k
prefix_op:
2998
377k
  if (priority > p) smart_str_appendc(str, '(');
2999
377k
  smart_str_appends(str, op);
3000
377k
  zend_ast_export_ex(str, ast->child[0], pl, indent);
3001
377k
  if (priority > p) smart_str_appendc(str, ')');
3002
377k
  return;
3003
3004
1.15k
postfix_op:
3005
1.15k
  if (priority > p) smart_str_appendc(str, '(');
3006
1.15k
  zend_ast_export_ex(str, ast->child[0], pl, indent);
3007
1.15k
  smart_str_appends(str, op);
3008
1.15k
  if (priority > p) smart_str_appendc(str, ')');
3009
1.15k
  return;
3010
3011
12.5k
func_op:
3012
12.5k
  smart_str_appends(str, op);
3013
12.5k
  smart_str_appendc(str, '(');
3014
12.5k
  zend_ast_export_ex(str, ast->child[0], 0, indent);
3015
12.5k
  smart_str_appendc(str, ')');
3016
12.5k
  return;
3017
3018
37.2k
append_node_1:
3019
37.2k
  smart_str_appends(str, op);
3020
37.2k
  if (ast->child[0]) {
3021
36.7k
    smart_str_appendc(str, ' ');
3022
36.7k
    ast = ast->child[0];
3023
36.7k
    goto tail_call;
3024
36.7k
  }
3025
498
  return;
3026
3027
45.1k
append_str:
3028
45.1k
  smart_str_appends(str, op);
3029
45.1k
  return;
3030
3031
1.18k
append_default_value:
3032
1.18k
  if (ast->child[p]) {
3033
903
    smart_str_appends(str, " = ");
3034
903
    ast = ast->child[p];
3035
903
    goto tail_call;
3036
903
  }
3037
278
  return;
3038
1.18k
}
3039
3040
ZEND_API ZEND_COLD zend_string *zend_ast_export(const char *prefix, zend_ast *ast, const char *suffix)
3041
17.8k
{
3042
17.8k
  smart_str str = {0};
3043
3044
17.8k
  smart_str_appends(&str, prefix);
3045
17.8k
  zend_ast_export_ex(&str, ast, 0, 0);
3046
17.8k
  smart_str_appends(&str, suffix);
3047
17.8k
  smart_str_0(&str);
3048
17.8k
  return str.s;
3049
17.8k
}
3050
3051
zend_ast * ZEND_FASTCALL zend_ast_with_attributes(zend_ast *ast, zend_ast *attr)
3052
10.5k
{
3053
10.5k
  ZEND_ASSERT(attr->kind == ZEND_AST_ATTRIBUTE_LIST);
3054
3055
10.5k
  switch (ast->kind) {
3056
490
  case ZEND_AST_FUNC_DECL:
3057
4.55k
  case ZEND_AST_CLOSURE:
3058
5.10k
  case ZEND_AST_METHOD:
3059
5.19k
  case ZEND_AST_ARROW_FUNC:
3060
5.39k
  case ZEND_AST_PROPERTY_HOOK:
3061
5.39k
    ((zend_ast_decl *) ast)->child[4] = attr;
3062
5.39k
    break;
3063
2.33k
  case ZEND_AST_CLASS:
3064
2.33k
    ((zend_ast_decl *) ast)->child[3] = attr;
3065
2.33k
    break;
3066
359
  case ZEND_AST_PROP_GROUP:
3067
359
    ast->child[2] = attr;
3068
359
    break;
3069
1.37k
  case ZEND_AST_PARAM:
3070
1.54k
  case ZEND_AST_ENUM_CASE:
3071
1.54k
    ast->child[3] = attr;
3072
1.54k
    break;
3073
266
  case ZEND_AST_CLASS_CONST_GROUP:
3074
266
    ast->child[1] = attr;
3075
266
    break;
3076
696
  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
696
    ast = zend_ast_list_add(ast, attr);
3081
696
    break;
3082
10.5k
  EMPTY_SWITCH_DEFAULT_CASE()
3083
10.5k
  }
3084
3085
10.5k
  return ast;
3086
10.5k
}
3087
3088
zend_ast * ZEND_FASTCALL zend_ast_call_get_args(zend_ast *ast)
3089
249
{
3090
249
  if (ast->kind == ZEND_AST_CALL) {
3091
155
    return ast->child[1];
3092
155
  } else if (ast->kind == ZEND_AST_STATIC_CALL || ast->kind == ZEND_AST_METHOD_CALL) {
3093
94
    return ast->child[2];
3094
94
  }
3095
3096
0
  ZEND_UNREACHABLE();
3097
0
  return NULL;
3098
0
}