Coverage Report

Created: 2026-10-28 06:20

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