Coverage Report

Created: 2025-09-27 06:26

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