Coverage Report

Created: 2026-06-02 06:37

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