Coverage Report

Created: 2025-06-13 06:43

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