Coverage Report

Created: 2026-02-09 07:07

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