Coverage Report

Created: 2026-01-18 06:49

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