Coverage Report

Created: 2026-07-25 06:39

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