Coverage Report

Created: 2025-07-23 06:33

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