Coverage Report

Created: 2026-09-14 06:25

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