1/*
2   +----------------------------------------------------------------------+
3   | Zend Engine                                                          |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1998-2015 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: Andi Gutmans <andi@zend.com>                                |
16   |          Zeev Suraski <zeev@zend.com>                                |
17   |          Nikita Popov <nikic@php.net>                                |
18   +----------------------------------------------------------------------+
19*/
20
21/* $Id$ */
22
23#include <zend_language_parser.h>
24#include "zend.h"
25#include "zend_compile.h"
26#include "zend_constants.h"
27#include "zend_llist.h"
28#include "zend_API.h"
29#include "zend_exceptions.h"
30#include "zend_virtual_cwd.h"
31#include "zend_multibyte.h"
32#include "zend_language_scanner.h"
33#include "zend_inheritance.h"
34
35#define SET_NODE(target, src) do { \
36        target ## _type = (src)->op_type; \
37        if ((src)->op_type == IS_CONST) { \
38            target.constant = zend_add_literal(CG(active_op_array), &(src)->u.constant); \
39        } else { \
40            target = (src)->u.op; \
41        } \
42    } while (0)
43
44#define GET_NODE(target, src) do { \
45        (target)->op_type = src ## _type; \
46        if ((target)->op_type == IS_CONST) { \
47            ZVAL_COPY_VALUE(&(target)->u.constant, CT_CONSTANT(src)); \
48        } else { \
49            (target)->u.op = src; \
50        } \
51    } while (0)
52
53static inline void zend_alloc_cache_slot(uint32_t literal) {
54    zend_op_array *op_array = CG(active_op_array);
55    Z_CACHE_SLOT(op_array->literals[literal]) = op_array->last_cache_slot++;
56}
57
58#define POLYMORPHIC_CACHE_SLOT_SIZE 2
59
60static inline void zend_alloc_polymorphic_cache_slot(uint32_t literal) {
61    zend_op_array *op_array = CG(active_op_array);
62    Z_CACHE_SLOT(op_array->literals[literal]) = op_array->last_cache_slot;
63    op_array->last_cache_slot += POLYMORPHIC_CACHE_SLOT_SIZE;
64}
65
66ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type);
67ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename);
68
69#ifndef ZTS
70ZEND_API zend_compiler_globals compiler_globals;
71ZEND_API zend_executor_globals executor_globals;
72#endif
73
74static void zend_destroy_property_info(zval *zv) /* {{{ */
75{
76    zend_property_info *property_info = Z_PTR_P(zv);
77
78    zend_string_release(property_info->name);
79    if (property_info->doc_comment) {
80        zend_string_release(property_info->doc_comment);
81    }
82}
83/* }}} */
84
85static void zend_destroy_property_info_internal(zval *zv) /* {{{ */
86{
87    zend_property_info *property_info = Z_PTR_P(zv);
88
89    zend_string_release(property_info->name);
90    free(property_info);
91}
92/* }}} */
93
94static zend_string *zend_new_interned_string_safe(zend_string *str) /* {{{ */ {
95    zend_string *interned_str;
96
97    zend_string_addref(str);
98    interned_str = zend_new_interned_string(str);
99    if (str != interned_str) {
100        return interned_str;
101    } else {
102        zend_string_release(str);
103        return str;
104    }
105}
106/* }}} */
107
108static zend_string *zend_build_runtime_definition_key(zend_string *name, unsigned char *lex_pos) /* {{{ */
109{
110    zend_string *result;
111    char char_pos_buf[32];
112    size_t filename_len, char_pos_len = zend_sprintf(char_pos_buf, "%p", lex_pos);
113
114    const char *filename;
115    if (CG(active_op_array)->filename) {
116        filename = CG(active_op_array)->filename->val;
117        filename_len = CG(active_op_array)->filename->len;
118    } else {
119        filename = "-";
120        filename_len = sizeof("-") - 1;
121    }
122    /* NULL, name length, filename length, last accepting char position length */
123    result = zend_string_alloc(1 + name->len + filename_len + char_pos_len, 0);
124    sprintf(result->val, "%c%s%s%s", '\0', name->val, filename, char_pos_buf);
125    return zend_new_interned_string(result);
126}
127/* }}} */
128
129static zend_bool zend_get_unqualified_name(const zend_string *name, const char **result, size_t *result_len) /* {{{ */
130{
131    const char *ns_separator = zend_memrchr(name->val, '\\', name->len);
132    if (ns_separator != NULL) {
133        *result = ns_separator + 1;
134        *result_len = name->val + name->len - *result;
135        return 1;
136    }
137
138    return 0;
139}
140/* }}} */
141
142static void init_compiler_declarables(void) /* {{{ */
143{
144    ZVAL_LONG(&CG(declarables).ticks, 0);
145}
146/* }}} */
147
148void zend_init_compiler_context(void) /* {{{ */
149{
150    CG(context).opcodes_size = INITIAL_OP_ARRAY_SIZE;
151    CG(context).vars_size = 0;
152    CG(context).literals_size = 0;
153    CG(context).current_brk_cont = -1;
154    CG(context).backpatch_count = 0;
155    CG(context).in_finally = 0;
156    CG(context).fast_call_var = -1;
157    CG(context).labels = NULL;
158}
159/* }}} */
160
161void zend_init_compiler_data_structures(void) /* {{{ */
162{
163    zend_stack_init(&CG(loop_var_stack), sizeof(znode));
164    zend_stack_init(&CG(delayed_oplines_stack), sizeof(zend_op));
165    CG(active_class_entry) = NULL;
166    CG(in_compilation) = 0;
167    CG(start_lineno) = 0;
168    CG(current_namespace) = NULL;
169    CG(in_namespace) = 0;
170    CG(has_bracketed_namespaces) = 0;
171    CG(current_import) = NULL;
172    CG(current_import_function) = NULL;
173    CG(current_import_const) = NULL;
174    zend_hash_init(&CG(const_filenames), 8, NULL, NULL, 0);
175    init_compiler_declarables();
176    zend_stack_init(&CG(context_stack), sizeof(CG(context)));
177
178    CG(encoding_declared) = 0;
179}
180/* }}} */
181
182ZEND_API void file_handle_dtor(zend_file_handle *fh) /* {{{ */
183{
184
185    zend_file_handle_dtor(fh);
186}
187/* }}} */
188
189void init_compiler(void) /* {{{ */
190{
191    CG(arena) = zend_arena_create(64 * 1024);
192    CG(active_op_array) = NULL;
193    memset(&CG(context), 0, sizeof(CG(context)));
194    zend_init_compiler_data_structures();
195    zend_init_rsrc_list();
196    zend_hash_init(&CG(filenames_table), 8, NULL, free_string_zval, 0);
197    zend_llist_init(&CG(open_files), sizeof(zend_file_handle), (void (*)(void *)) file_handle_dtor, 0);
198    CG(unclean_shutdown) = 0;
199}
200/* }}} */
201
202void shutdown_compiler(void) /* {{{ */
203{
204    zend_stack_destroy(&CG(loop_var_stack));
205    zend_stack_destroy(&CG(delayed_oplines_stack));
206    zend_hash_destroy(&CG(filenames_table));
207    zend_hash_destroy(&CG(const_filenames));
208    zend_stack_destroy(&CG(context_stack));
209    zend_arena_destroy(CG(arena));
210}
211/* }}} */
212
213ZEND_API zend_string *zend_set_compiled_filename(zend_string *new_compiled_filename) /* {{{ */
214{
215    zend_string *p;
216
217    p = zend_hash_find_ptr(&CG(filenames_table), new_compiled_filename);
218    if (p != NULL) {
219        CG(compiled_filename) = p;
220        return p;
221    }
222    p = zend_string_copy(new_compiled_filename);
223    zend_hash_update_ptr(&CG(filenames_table), new_compiled_filename, p);
224    CG(compiled_filename) = p;
225    return p;
226}
227/* }}} */
228
229ZEND_API void zend_restore_compiled_filename(zend_string *original_compiled_filename) /* {{{ */
230{
231    CG(compiled_filename) = original_compiled_filename;
232}
233/* }}} */
234
235ZEND_API zend_string *zend_get_compiled_filename(void) /* {{{ */
236{
237    return CG(compiled_filename);
238}
239/* }}} */
240
241ZEND_API int zend_get_compiled_lineno(void) /* {{{ */
242{
243    return CG(zend_lineno);
244}
245/* }}} */
246
247ZEND_API zend_bool zend_is_compiling(void) /* {{{ */
248{
249    return CG(in_compilation);
250}
251/* }}} */
252
253static uint32_t get_temporary_variable(zend_op_array *op_array) /* {{{ */
254{
255    return (uint32_t)op_array->T++;
256}
257/* }}} */
258
259static int lookup_cv(zend_op_array *op_array, zend_string* name) /* {{{ */{
260    int i = 0;
261    zend_ulong hash_value = zend_string_hash_val(name);
262
263    while (i < op_array->last_var) {
264        if (op_array->vars[i]->val == name->val ||
265            (op_array->vars[i]->h == hash_value &&
266             op_array->vars[i]->len == name->len &&
267             memcmp(op_array->vars[i]->val, name->val, name->len) == 0)) {
268            zend_string_release(name);
269            return (int)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, i);
270        }
271        i++;
272    }
273    i = op_array->last_var;
274    op_array->last_var++;
275    if (op_array->last_var > CG(context).vars_size) {
276        CG(context).vars_size += 16; /* FIXME */
277        op_array->vars = erealloc(op_array->vars, CG(context).vars_size * sizeof(zend_string*));
278    }
279
280    op_array->vars[i] = zend_new_interned_string(name);
281    return (int)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, i);
282}
283/* }}} */
284
285void zend_del_literal(zend_op_array *op_array, int n) /* {{{ */
286{
287    zval_dtor(CT_CONSTANT_EX(op_array, n));
288    if (n + 1 == op_array->last_literal) {
289        op_array->last_literal--;
290    } else {
291        ZVAL_UNDEF(CT_CONSTANT_EX(op_array, n));
292    }
293}
294/* }}} */
295
296/* Common part of zend_add_literal and zend_append_individual_literal */
297static inline void zend_insert_literal(zend_op_array *op_array, zval *zv, int literal_position) /* {{{ */
298{
299    if (Z_TYPE_P(zv) == IS_STRING || Z_TYPE_P(zv) == IS_CONSTANT) {
300        zend_string_hash_val(Z_STR_P(zv));
301        Z_STR_P(zv) = zend_new_interned_string(Z_STR_P(zv));
302        if (IS_INTERNED(Z_STR_P(zv))) {
303            Z_TYPE_FLAGS_P(zv) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
304        }
305    }
306    ZVAL_COPY_VALUE(CT_CONSTANT_EX(op_array, literal_position), zv);
307    Z_CACHE_SLOT(op_array->literals[literal_position]) = -1;
308}
309/* }}} */
310
311/* Is used while compiling a function, using the context to keep track
312   of an approximate size to avoid to relocate to often.
313   Literals are truncated to actual size in the second compiler pass (pass_two()). */
314int zend_add_literal(zend_op_array *op_array, zval *zv) /* {{{ */
315{
316    int i = op_array->last_literal;
317    op_array->last_literal++;
318    if (i >= CG(context).literals_size) {
319        while (i >= CG(context).literals_size) {
320            CG(context).literals_size += 16; /* FIXME */
321        }
322        op_array->literals = (zval*)erealloc(op_array->literals, CG(context).literals_size * sizeof(zval));
323    }
324    zend_insert_literal(op_array, zv, i);
325    return i;
326}
327/* }}} */
328
329static inline int zend_add_literal_string(zend_op_array *op_array, zend_string **str) /* {{{ */
330{
331    int ret;
332    zval zv;
333    ZVAL_STR(&zv, *str);
334    ret = zend_add_literal(op_array, &zv);
335    *str = Z_STR(zv);
336    return ret;
337}
338/* }}} */
339
340static int zend_add_func_name_literal(zend_op_array *op_array, zend_string *name) /* {{{ */
341{
342    /* Original name */
343    int ret = zend_add_literal_string(op_array, &name);
344
345    /* Lowercased name */
346    zend_string *lc_name = zend_string_tolower(name);
347    zend_add_literal_string(op_array, &lc_name);
348
349    return ret;
350}
351/* }}} */
352
353static int zend_add_ns_func_name_literal(zend_op_array *op_array, zend_string *name) /* {{{ */
354{
355    const char *unqualified_name;
356    size_t unqualified_name_len;
357
358    /* Original name */
359    int ret = zend_add_literal_string(op_array, &name);
360
361    /* Lowercased name */
362    zend_string *lc_name = zend_string_tolower(name);
363    zend_add_literal_string(op_array, &lc_name);
364
365    /* Lowercased unqualfied name */
366    if (zend_get_unqualified_name(name, &unqualified_name, &unqualified_name_len)) {
367        lc_name = zend_string_alloc(unqualified_name_len, 0);
368        zend_str_tolower_copy(lc_name->val, unqualified_name, unqualified_name_len);
369        zend_add_literal_string(op_array, &lc_name);
370    }
371
372    return ret;
373}
374/* }}} */
375
376static int zend_add_class_name_literal(zend_op_array *op_array, zend_string *name) /* {{{ */
377{
378    /* Original name */
379    int ret = zend_add_literal_string(op_array, &name);
380
381    /* Lowercased name */
382    zend_string *lc_name = zend_string_tolower(name);
383    zend_add_literal_string(op_array, &lc_name);
384
385    zend_alloc_cache_slot(ret);
386
387    return ret;
388}
389/* }}} */
390
391static int zend_add_const_name_literal(zend_op_array *op_array, zend_string *name, zend_bool unqualified) /* {{{ */
392{
393    zend_string *tmp_name;
394
395    int ret = zend_add_literal_string(op_array, &name);
396
397    size_t ns_len = 0, after_ns_len = name->len;
398    const char *after_ns = zend_memrchr(name->val, '\\', name->len);
399    if (after_ns) {
400        after_ns += 1;
401        ns_len = after_ns - name->val - 1;
402        after_ns_len = name->len - ns_len - 1;
403
404        /* lowercased namespace name & original constant name */
405        tmp_name = zend_string_init(name->val, name->len, 0);
406        zend_str_tolower(tmp_name->val, ns_len);
407        zend_add_literal_string(op_array, &tmp_name);
408
409        /* lowercased namespace name & lowercased constant name */
410        tmp_name = zend_string_tolower(name);
411        zend_add_literal_string(op_array, &tmp_name);
412
413        if (!unqualified) {
414            return ret;
415        }
416    } else {
417        after_ns = name->val;
418    }
419
420    /* original unqualified constant name */
421    tmp_name = zend_string_init(after_ns, after_ns_len, 0);
422    zend_add_literal_string(op_array, &tmp_name);
423
424    /* lowercased unqualified constant name */
425    tmp_name = zend_string_alloc(after_ns_len, 0);
426    zend_str_tolower_copy(tmp_name->val, after_ns, after_ns_len);
427    zend_add_literal_string(op_array, &tmp_name);
428
429    return ret;
430}
431/* }}} */
432
433#define LITERAL_STR(op, str) do { \
434        zval _c; \
435        ZVAL_STR(&_c, str); \
436        op.constant = zend_add_literal(CG(active_op_array), &_c); \
437    } while (0)
438
439void zend_stop_lexing(void) {
440    LANG_SCNG(yy_cursor) = LANG_SCNG(yy_limit);
441}
442
443static inline void zend_begin_loop(void) /* {{{ */
444{
445    zend_brk_cont_element *brk_cont_element;
446    int parent;
447
448    parent = CG(context).current_brk_cont;
449    CG(context).current_brk_cont = CG(active_op_array)->last_brk_cont;
450    brk_cont_element = get_next_brk_cont_element(CG(active_op_array));
451    brk_cont_element->start = get_next_op_number(CG(active_op_array));
452    brk_cont_element->parent = parent;
453}
454/* }}} */
455
456static inline void zend_end_loop(int cont_addr, int has_loop_var) /* {{{ */
457{
458    if (!has_loop_var) {
459        /* The start fileld is used to free temporary variables in case of exceptions.
460         * We won't try to free something of we don't have loop variable.
461         */
462        CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].start = -1;
463    }
464    CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].cont = cont_addr;
465    CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].brk = get_next_op_number(CG(active_op_array));
466    CG(context).current_brk_cont = CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].parent;
467}
468/* }}} */
469
470void zend_do_free(znode *op1) /* {{{ */
471{
472    if (op1->op_type==IS_TMP_VAR) {
473        zend_op *opline = get_next_op(CG(active_op_array));
474
475        opline->opcode = ZEND_FREE;
476        SET_NODE(opline->op1, op1);
477        SET_UNUSED(opline->op2);
478    } else if (op1->op_type==IS_VAR) {
479        zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
480
481        while (opline->opcode == ZEND_END_SILENCE || opline->opcode == ZEND_EXT_FCALL_END || opline->opcode == ZEND_OP_DATA) {
482            opline--;
483        }
484        if (opline->result_type == IS_VAR
485            && opline->result.var == op1->u.op.var) {
486            if (opline->opcode == ZEND_FETCH_R ||
487                opline->opcode == ZEND_FETCH_DIM_R ||
488                opline->opcode == ZEND_FETCH_OBJ_R) {
489                /* It's very rare and useless case. It's better to use
490                   additional FREE opcode and simplify the FETCH handlers
491                   their selves */
492                opline = get_next_op(CG(active_op_array));
493                opline->opcode = ZEND_FREE;
494                SET_NODE(opline->op1, op1);
495                SET_UNUSED(opline->op2);
496            } else {
497                opline->result_type |= EXT_TYPE_UNUSED;
498            }
499        } else {
500            while (opline >= CG(active_op_array)->opcodes) {
501                if (opline->opcode == ZEND_FETCH_LIST &&
502                    opline->op1_type == IS_VAR &&
503                    opline->op1.var == op1->u.op.var) {
504                    opline = get_next_op(CG(active_op_array));
505
506                    opline->opcode = ZEND_FREE;
507                    SET_NODE(opline->op1, op1);
508                    SET_UNUSED(opline->op2);
509                    return;
510                }
511                if (opline->result_type==IS_VAR
512                    && opline->result.var == op1->u.op.var) {
513                    if (opline->opcode == ZEND_NEW) {
514                        opline->result_type |= EXT_TYPE_UNUSED;
515                        opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
516                        while (opline->opcode != ZEND_DO_FCALL || opline->op1.num != ZEND_CALL_CTOR) {
517                            opline--;
518                        }
519                        opline->op1.num |= ZEND_CALL_CTOR_RESULT_UNUSED;
520                    }
521                    break;
522                }
523                opline--;
524            }
525        }
526    } else if (op1->op_type == IS_CONST) {
527        /* Destroy value without using GC: When opcache moves arrays into SHM it will
528         * free the zend_array structure, so references to it from outside the op array
529         * become invalid. GC would cause such a reference in the root buffer. */
530        zval_ptr_dtor_nogc(&op1->u.constant);
531    }
532}
533/* }}} */
534
535uint32_t zend_add_class_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */
536{
537    uint32_t new_flags = flags | new_flag;
538    if ((flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) && (new_flag & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
539        zend_error_noreturn(E_COMPILE_ERROR, "Multiple abstract modifiers are not allowed");
540    }
541    if ((flags & ZEND_ACC_FINAL) && (new_flag & ZEND_ACC_FINAL)) {
542        zend_error_noreturn(E_COMPILE_ERROR, "Multiple final modifiers are not allowed");
543    }
544    if ((new_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) && (new_flags & ZEND_ACC_FINAL)) {
545        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use the final modifier on an abstract class");
546    }
547    return new_flags;
548}
549/* }}} */
550
551uint32_t zend_add_member_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */
552{
553    uint32_t new_flags = flags | new_flag;
554    if ((flags & ZEND_ACC_PPP_MASK) && (new_flag & ZEND_ACC_PPP_MASK)) {
555        zend_error_noreturn(E_COMPILE_ERROR, "Multiple access type modifiers are not allowed");
556    }
557    if ((flags & ZEND_ACC_ABSTRACT) && (new_flag & ZEND_ACC_ABSTRACT)) {
558        zend_error_noreturn(E_COMPILE_ERROR, "Multiple abstract modifiers are not allowed");
559    }
560    if ((flags & ZEND_ACC_STATIC) && (new_flag & ZEND_ACC_STATIC)) {
561        zend_error_noreturn(E_COMPILE_ERROR, "Multiple static modifiers are not allowed");
562    }
563    if ((flags & ZEND_ACC_FINAL) && (new_flag & ZEND_ACC_FINAL)) {
564        zend_error_noreturn(E_COMPILE_ERROR, "Multiple final modifiers are not allowed");
565    }
566    if ((new_flags & ZEND_ACC_ABSTRACT) && (new_flags & ZEND_ACC_FINAL)) {
567        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use the final modifier on an abstract class member");
568    }
569    return new_flags;
570}
571/* }}} */
572
573zend_string *zend_concat3(char *str1, size_t str1_len, char *str2, size_t str2_len, char *str3, size_t str3_len) /* {{{ */
574{
575    size_t len = str1_len + str2_len + str3_len;
576    zend_string *res = zend_string_alloc(len, 0);
577
578    memcpy(res->val, str1, str1_len);
579    memcpy(res->val + str1_len, str2, str2_len);
580    memcpy(res->val + str1_len + str2_len, str3, str3_len);
581    res->val[len] = '\0';
582
583    return res;
584}
585
586zend_string *zend_concat_names(char *name1, size_t name1_len, char *name2, size_t name2_len) {
587    return zend_concat3(name1, name1_len, "\\", 1, name2, name2_len);
588}
589
590zend_string *zend_prefix_with_ns(zend_string *name) {
591    if (CG(current_namespace)) {
592        zend_string *ns = CG(current_namespace);
593        return zend_concat_names(ns->val, ns->len, name->val, name->len);
594    } else {
595        return zend_string_copy(name);
596    }
597}
598
599void *zend_hash_find_ptr_lc(HashTable *ht, const char *str, size_t len) {
600    void *result;
601    zend_string *lcname;
602    ALLOCA_FLAG(use_heap);
603
604    STR_ALLOCA_ALLOC(lcname, len, use_heap);
605    zend_str_tolower_copy(lcname->val, str, len);
606    result = zend_hash_find_ptr(ht, lcname);
607    STR_ALLOCA_FREE(lcname, use_heap);
608
609    return result;
610}
611
612zend_string *zend_resolve_non_class_name(
613    zend_string *name, uint32_t type, zend_bool *is_fully_qualified,
614    zend_bool case_sensitive, HashTable *current_import_sub
615) {
616    char *compound;
617    *is_fully_qualified = 0;
618
619    if (name->val[0] == '\\') {
620        /* Remove \ prefix (only relevant if this is a string rather than a label) */
621        return zend_string_init(name->val + 1, name->len - 1, 0);
622    }
623
624    if (type == ZEND_NAME_FQ) {
625        *is_fully_qualified = 1;
626        return zend_string_copy(name);
627    }
628
629    if (type == ZEND_NAME_RELATIVE) {
630        *is_fully_qualified = 1;
631        return zend_prefix_with_ns(name);
632    }
633
634    if (current_import_sub) {
635        /* If an unqualified name is a function/const alias, replace it. */
636        zend_string *import_name;
637        if (case_sensitive) {
638            import_name = zend_hash_find_ptr(current_import_sub, name);
639        } else {
640            import_name = zend_hash_find_ptr_lc(current_import_sub, name->val, name->len);
641        }
642
643        if (import_name) {
644            *is_fully_qualified = 1;
645            return zend_string_copy(import_name);
646        }
647    }
648
649    compound = memchr(name->val, '\\', name->len);
650    if (compound) {
651        *is_fully_qualified = 1;
652    }
653
654    if (compound && CG(current_import)) {
655        /* If the first part of a qualified name is an alias, substitute it. */
656        size_t len = compound - name->val;
657        zend_string *import_name = zend_hash_find_ptr_lc(CG(current_import), name->val, len);
658
659        if (import_name) {
660            return zend_concat_names(
661                import_name->val, import_name->len, name->val + len + 1, name->len - len - 1);
662        }
663    }
664
665    return zend_prefix_with_ns(name);
666}
667/* }}} */
668
669zend_string *zend_resolve_function_name(zend_string *name, uint32_t type, zend_bool *is_fully_qualified) /* {{{ */
670{
671    return zend_resolve_non_class_name(
672        name, type, is_fully_qualified, 0, CG(current_import_function));
673}
674/* }}} */
675
676zend_string *zend_resolve_const_name(zend_string *name, uint32_t type, zend_bool *is_fully_qualified) /* {{{ */ {
677    return zend_resolve_non_class_name(
678        name, type, is_fully_qualified, 1, CG(current_import_const));
679}
680/* }}} */
681
682zend_string *zend_resolve_class_name(zend_string *name, uint32_t type) /* {{{ */
683{
684    char *compound;
685
686    if (type == ZEND_NAME_RELATIVE) {
687        return zend_prefix_with_ns(name);
688    }
689
690    if (type == ZEND_NAME_FQ || name->val[0] == '\\') {
691        /* Remove \ prefix (only relevant if this is a string rather than a label) */
692        if (name->val[0] == '\\') {
693            name = zend_string_init(name->val + 1, name->len - 1, 0);
694        } else {
695            zend_string_addref(name);
696        }
697        /* Ensure that \self, \parent and \static are not used */
698        if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
699            zend_error_noreturn(E_COMPILE_ERROR, "'\\%s' is an invalid class name", name->val);
700        }
701        return name;
702    }
703
704    if (CG(current_import)) {
705        compound = memchr(name->val, '\\', name->len);
706        if (compound) {
707            /* If the first part of a qualified name is an alias, substitute it. */
708            size_t len = compound - name->val;
709            zend_string *import_name = zend_hash_find_ptr_lc(CG(current_import), name->val, len);
710
711            if (import_name) {
712                return zend_concat_names(
713                    import_name->val, import_name->len, name->val + len + 1, name->len - len - 1);
714            }
715        } else {
716            /* If an unqualified name is an alias, replace it. */
717            zend_string *import_name
718                = zend_hash_find_ptr_lc(CG(current_import), name->val, name->len);
719
720            if (import_name) {
721                return zend_string_copy(import_name);
722            }
723        }
724    }
725
726    /* If not fully qualified and not an alias, prepend the current namespace */
727    return zend_prefix_with_ns(name);
728}
729/* }}} */
730
731zend_string *zend_resolve_class_name_ast(zend_ast *ast) /* {{{ */
732{
733    zend_string *name = zend_ast_get_str(ast);
734    return zend_resolve_class_name(name, ast->attr);
735}
736/* }}} */
737
738static void ptr_dtor(zval *zv) /* {{{ */
739{
740    efree(Z_PTR_P(zv));
741}
742/* }}} */
743
744static void str_dtor(zval *zv)  /* {{{ */ {
745    zend_string_release(Z_STR_P(zv));
746}
747/* }}} */
748
749void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2) /* {{{ */
750{
751    zend_label *dest;
752    int current, distance;
753    zval *label;
754
755    if (pass2) {
756        label = RT_CONSTANT(op_array, opline->op2);
757    } else {
758        label = CT_CONSTANT_EX(op_array, opline->op2.constant);
759    }
760    if (CG(context).labels == NULL ||
761        (dest = zend_hash_find_ptr(CG(context).labels, Z_STR_P(label))) == NULL) {
762
763        if (pass2) {
764            CG(in_compilation) = 1;
765            CG(active_op_array) = op_array;
766            CG(zend_lineno) = opline->lineno;
767            zend_error_noreturn(E_COMPILE_ERROR, "'goto' to undefined label '%s'", Z_STRVAL_P(label));
768        } else {
769            /* Label is not defined. Delay to pass 2. */
770            return;
771        }
772    }
773
774    opline->op1.opline_num = dest->opline_num;
775    zval_dtor(label);
776    ZVAL_NULL(label);
777
778    /* Check that we are not moving into loop or switch */
779    current = opline->extended_value;
780    for (distance = 0; current != dest->brk_cont; distance++) {
781        if (current == -1) {
782            if (pass2) {
783                CG(in_compilation) = 1;
784                CG(active_op_array) = op_array;
785                CG(zend_lineno) = opline->lineno;
786            }
787            zend_error_noreturn(E_COMPILE_ERROR, "'goto' into loop or switch statement is disallowed");
788        }
789        current = op_array->brk_cont_array[current].parent;
790    }
791
792    if (distance == 0) {
793        /* Nothing to break out of, optimize to ZEND_JMP */
794        opline->opcode = ZEND_JMP;
795        opline->extended_value = 0;
796        SET_UNUSED(opline->op2);
797    } else {
798        /* Set real break distance */
799        ZVAL_LONG(label, distance);
800    }
801}
802/* }}} */
803
804void zend_release_labels(int temporary) /* {{{ */
805{
806    if (CG(context).labels) {
807        zend_hash_destroy(CG(context).labels);
808        FREE_HASHTABLE(CG(context).labels);
809        CG(context).labels = NULL;
810    }
811    if (!temporary && !zend_stack_is_empty(&CG(context_stack))) {
812        zend_compiler_context *ctx = zend_stack_top(&CG(context_stack));
813        CG(context) = *ctx;
814        zend_stack_del_top(&CG(context_stack));
815    }
816}
817/* }}} */
818
819static zend_bool zend_is_call(zend_ast *ast);
820
821static int generate_free_loop_var(znode *var) /* {{{ */
822{
823    switch (var->op_type) {
824        case IS_UNUSED:
825            /* Stack separator on function boundary, stop applying */
826            return 1;
827        case IS_VAR:
828        case IS_TMP_VAR:
829        {
830            zend_op *opline = get_next_op(CG(active_op_array));
831
832            opline->opcode = ZEND_FREE;
833            SET_NODE(opline->op1, var);
834            SET_UNUSED(opline->op2);
835        }
836    }
837
838    return 0;
839}
840/* }}} */
841
842static uint32_t zend_add_try_element(uint32_t try_op) /* {{{ */
843{
844    zend_op_array *op_array = CG(active_op_array);
845    uint32_t try_catch_offset = op_array->last_try_catch++;
846    zend_try_catch_element *elem;
847
848    op_array->try_catch_array = safe_erealloc(
849        op_array->try_catch_array, sizeof(zend_try_catch_element), op_array->last_try_catch, 0);
850
851    elem = &op_array->try_catch_array[try_catch_offset];
852    elem->try_op = try_op;
853    elem->catch_op = 0;
854    elem->finally_op = 0;
855    elem->finally_end = 0;
856
857    return try_catch_offset;
858}
859/* }}} */
860
861ZEND_API void function_add_ref(zend_function *function) /* {{{ */
862{
863    if (function->type == ZEND_USER_FUNCTION) {
864        zend_op_array *op_array = &function->op_array;
865
866        (*op_array->refcount)++;
867        if (op_array->static_variables) {
868            HashTable *static_variables = op_array->static_variables;
869
870            ALLOC_HASHTABLE(op_array->static_variables);
871            zend_array_dup(op_array->static_variables, static_variables);
872        }
873        op_array->run_time_cache = NULL;
874    } else if (function->type == ZEND_INTERNAL_FUNCTION) {
875        if (function->common.function_name) {
876            zend_string_addref(function->common.function_name);
877        }
878    }
879}
880/* }}} */
881
882ZEND_API int do_bind_function(const zend_op_array *op_array, const zend_op *opline, HashTable *function_table, zend_bool compile_time) /* {{{ */
883{
884    zend_function *function, *new_function;
885    zval *op1, *op2;
886
887    if (compile_time) {
888        op1 = CT_CONSTANT_EX(op_array, opline->op1.constant);
889        op2 = CT_CONSTANT_EX(op_array, opline->op2.constant);
890    } else {
891        op1 = RT_CONSTANT(op_array, opline->op1);
892        op2 = RT_CONSTANT(op_array, opline->op2);
893    }
894
895    function = zend_hash_find_ptr(function_table, Z_STR_P(op1));
896    new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
897    memcpy(new_function, function, sizeof(zend_op_array));
898    if (zend_hash_add_ptr(function_table, Z_STR_P(op2), new_function) == NULL) {
899        int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR;
900        zend_function *old_function;
901
902        if ((old_function = zend_hash_find_ptr(function_table, Z_STR_P(op2))) != NULL
903            && old_function->type == ZEND_USER_FUNCTION
904            && old_function->op_array.last > 0) {
905            zend_error(error_level, "Cannot redeclare %s() (previously declared in %s:%d)",
906                        function->common.function_name->val,
907                        old_function->op_array.filename->val,
908                        old_function->op_array.opcodes[0].lineno);
909        } else {
910            zend_error(error_level, "Cannot redeclare %s()", function->common.function_name->val);
911        }
912        return FAILURE;
913    } else {
914        (*function->op_array.refcount)++;
915        function->op_array.static_variables = NULL; /* NULL out the unbound function */
916        return SUCCESS;
917    }
918}
919/* }}} */
920
921ZEND_API zend_class_entry *do_bind_class(const zend_op_array* op_array, const zend_op *opline, HashTable *class_table, zend_bool compile_time) /* {{{ */
922{
923    zend_class_entry *ce;
924    zval *op1, *op2;
925
926    if (compile_time) {
927        op1 = CT_CONSTANT_EX(op_array, opline->op1.constant);
928        op2 = CT_CONSTANT_EX(op_array, opline->op2.constant);
929    } else {
930        op1 = RT_CONSTANT(op_array, opline->op1);
931        op2 = RT_CONSTANT(op_array, opline->op2);
932    }
933    if ((ce = zend_hash_find_ptr(class_table, Z_STR_P(op1))) == NULL) {
934        zend_error_noreturn(E_COMPILE_ERROR, "Internal Zend error - Missing class information for %s", Z_STRVAL_P(op1));
935        return NULL;
936    }
937    ce->refcount++;
938    if (zend_hash_add_ptr(class_table, Z_STR_P(op2), ce) == NULL) {
939        ce->refcount--;
940        if (!compile_time) {
941            /* If we're in compile time, in practice, it's quite possible
942             * that we'll never reach this class declaration at runtime,
943             * so we shut up about it.  This allows the if (!defined('FOO')) { return; }
944             * approach to work.
945             */
946            zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare class %s", ce->name->val);
947        }
948        return NULL;
949    } else {
950        if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLEMENT_INTERFACES|ZEND_ACC_IMPLEMENT_TRAITS))) {
951            zend_verify_abstract_class(ce);
952        }
953        return ce;
954    }
955}
956/* }}} */
957
958ZEND_API zend_class_entry *do_bind_inherited_class(const zend_op_array *op_array, const zend_op *opline, HashTable *class_table, zend_class_entry *parent_ce, zend_bool compile_time) /* {{{ */
959{
960    zend_class_entry *ce;
961    zval *op1, *op2;
962
963    if (compile_time) {
964        op1 = CT_CONSTANT_EX(op_array, opline->op1.constant);
965        op2 = CT_CONSTANT_EX(op_array, opline->op2.constant);
966    } else {
967        op1 = RT_CONSTANT(op_array, opline->op1);
968        op2 = RT_CONSTANT(op_array, opline->op2);
969    }
970
971    ce = zend_hash_find_ptr(class_table, Z_STR_P(op1));
972
973    if (!ce) {
974        if (!compile_time) {
975            /* If we're in compile time, in practice, it's quite possible
976             * that we'll never reach this class declaration at runtime,
977             * so we shut up about it.  This allows the if (!defined('FOO')) { return; }
978             * approach to work.
979             */
980            zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare class %s", Z_STRVAL_P(op2));
981        }
982        return NULL;
983    }
984
985    if (parent_ce->ce_flags & ZEND_ACC_INTERFACE) {
986        zend_error_noreturn(E_COMPILE_ERROR, "Class %s cannot extend from interface %s", ce->name->val, parent_ce->name->val);
987    } else if ((parent_ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
988        zend_error_noreturn(E_COMPILE_ERROR, "Class %s cannot extend from trait %s", ce->name->val, parent_ce->name->val);
989    }
990
991    zend_do_inheritance(ce, parent_ce);
992
993    ce->refcount++;
994
995    /* Register the derived class */
996    if (zend_hash_add_ptr(class_table, Z_STR_P(op2), ce) == NULL) {
997        zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare class %s", ce->name->val);
998    }
999    return ce;
1000}
1001/* }}} */
1002
1003void zend_do_early_binding(void) /* {{{ */
1004{
1005    zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
1006    HashTable *table;
1007
1008    while (opline->opcode == ZEND_TICKS && opline > CG(active_op_array)->opcodes) {
1009        opline--;
1010    }
1011
1012    switch (opline->opcode) {
1013        case ZEND_DECLARE_FUNCTION:
1014            if (do_bind_function(CG(active_op_array), opline, CG(function_table), 1) == FAILURE) {
1015                return;
1016            }
1017            table = CG(function_table);
1018            break;
1019        case ZEND_DECLARE_CLASS:
1020            if (do_bind_class(CG(active_op_array), opline, CG(class_table), 1) == NULL) {
1021                return;
1022            }
1023            table = CG(class_table);
1024            break;
1025        case ZEND_DECLARE_INHERITED_CLASS:
1026            {
1027                zend_op *fetch_class_opline = opline-1;
1028                zval *parent_name;
1029                zend_class_entry *ce;
1030
1031                parent_name = CT_CONSTANT(fetch_class_opline->op2);
1032                if (((ce = zend_lookup_class(Z_STR_P(parent_name))) == NULL) ||
1033                    ((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES) &&
1034                     (ce->type == ZEND_INTERNAL_CLASS))) {
1035                    if (CG(compiler_options) & ZEND_COMPILE_DELAYED_BINDING) {
1036                        uint32_t *opline_num = &CG(active_op_array)->early_binding;
1037
1038                        while (*opline_num != (uint32_t)-1) {
1039                            opline_num = &CG(active_op_array)->opcodes[*opline_num].result.opline_num;
1040                        }
1041                        *opline_num = opline - CG(active_op_array)->opcodes;
1042                        opline->opcode = ZEND_DECLARE_INHERITED_CLASS_DELAYED;
1043                        opline->result_type = IS_UNUSED;
1044                        opline->result.opline_num = -1;
1045                    }
1046                    return;
1047                }
1048                if (do_bind_inherited_class(CG(active_op_array), opline, CG(class_table), ce, 1) == NULL) {
1049                    return;
1050                }
1051                /* clear unnecessary ZEND_FETCH_CLASS opcode */
1052                zend_del_literal(CG(active_op_array), fetch_class_opline->op2.constant);
1053                MAKE_NOP(fetch_class_opline);
1054
1055                table = CG(class_table);
1056                break;
1057            }
1058        case ZEND_VERIFY_ABSTRACT_CLASS:
1059        case ZEND_ADD_INTERFACE:
1060        case ZEND_ADD_TRAIT:
1061        case ZEND_BIND_TRAITS:
1062            /* We currently don't early-bind classes that implement interfaces */
1063            /* Classes with traits are handled exactly the same, no early-bind here */
1064            return;
1065        default:
1066            zend_error_noreturn(E_COMPILE_ERROR, "Invalid binding type");
1067            return;
1068    }
1069
1070    zend_hash_del(table, Z_STR_P(CT_CONSTANT(opline->op1)));
1071    zend_del_literal(CG(active_op_array), opline->op1.constant);
1072    zend_del_literal(CG(active_op_array), opline->op2.constant);
1073    MAKE_NOP(opline);
1074}
1075/* }}} */
1076
1077ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array) /* {{{ */
1078{
1079    if (op_array->early_binding != (uint32_t)-1) {
1080        zend_bool orig_in_compilation = CG(in_compilation);
1081        uint32_t opline_num = op_array->early_binding;
1082        zend_class_entry *ce;
1083
1084        CG(in_compilation) = 1;
1085        while (opline_num != (uint32_t)-1) {
1086            if ((ce = zend_lookup_class(Z_STR_P(RT_CONSTANT(op_array, op_array->opcodes[opline_num-1].op2)))) != NULL) {
1087                do_bind_inherited_class(op_array, &op_array->opcodes[opline_num], EG(class_table), ce, 0);
1088            }
1089            opline_num = op_array->opcodes[opline_num].result.opline_num;
1090        }
1091        CG(in_compilation) = orig_in_compilation;
1092    }
1093}
1094/* }}} */
1095
1096ZEND_API zend_string *zend_mangle_property_name(const char *src1, size_t src1_length, const char *src2, size_t src2_length, int internal) /* {{{ */
1097{
1098    size_t prop_name_length = 1 + src1_length + 1 + src2_length;
1099    zend_string *prop_name = zend_string_alloc(prop_name_length, internal);
1100
1101    prop_name->val[0] = '\0';
1102    memcpy(prop_name->val + 1, src1, src1_length+1);
1103    memcpy(prop_name->val + 1 + src1_length + 1, src2, src2_length+1);
1104    return prop_name;
1105}
1106/* }}} */
1107
1108static size_t zend_strnlen(const char* s, size_t maxlen) /* {{{ */
1109{
1110    size_t len = 0;
1111    while (*s++ && maxlen--) len++;
1112    return len;
1113}
1114/* }}} */
1115
1116ZEND_API int zend_unmangle_property_name_ex(const zend_string *name, const char **class_name, const char **prop_name, size_t *prop_len) /* {{{ */
1117{
1118    size_t class_name_len;
1119
1120    *class_name = NULL;
1121
1122    if (name->val[0] != '\0') {
1123        *prop_name = name->val;
1124        if (prop_len) {
1125            *prop_len = name->len;
1126        }
1127        return SUCCESS;
1128    }
1129    if (name->len < 3 || name->val[1] == '\0') {
1130        zend_error(E_NOTICE, "Illegal member variable name");
1131        *prop_name = name->val;
1132        if (prop_len) {
1133            *prop_len = name->len;
1134        }
1135        return FAILURE;
1136    }
1137
1138    class_name_len = zend_strnlen(name->val + 1, name->len - 2);
1139    if (class_name_len >= name->len - 2 || name->val[class_name_len + 1] != '\0') {
1140        zend_error(E_NOTICE, "Corrupt member variable name");
1141        *prop_name = name->val;
1142        if (prop_len) {
1143            *prop_len = name->len;
1144        }
1145        return FAILURE;
1146    }
1147
1148    *class_name = name->val + 1;
1149    *prop_name = name->val + class_name_len + 2;
1150    if (prop_len) {
1151        *prop_len = name->len - class_name_len - 2;
1152    }
1153    return SUCCESS;
1154}
1155/* }}} */
1156
1157static zend_constant *zend_lookup_reserved_const(const char *name, size_t len) /* {{{ */
1158{
1159    zend_constant *c = zend_hash_find_ptr_lc(EG(zend_constants), name, len);
1160    if (c && !(c->flags & CONST_CS) && (c->flags & CONST_CT_SUBST)) {
1161        return c;
1162    }
1163    return NULL;
1164}
1165/* }}} */
1166
1167static zend_bool zend_try_ct_eval_const(zval *zv, zend_string *name, zend_bool is_fully_qualified) /* {{{ */
1168{
1169    zend_constant *c;
1170
1171    if (!(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) {
1172        /* Substitute case-sensitive (or lowercase) persistent constants */
1173        c = zend_hash_find_ptr(EG(zend_constants), name);
1174        if (c && (c->flags & CONST_PERSISTENT)) {
1175            ZVAL_DUP(zv, &c->value);
1176            return 1;
1177        }
1178    }
1179
1180    {
1181        /* Substitute true, false and null (including unqualified usage in namespaces) */
1182        const char *lookup_name = name->val;
1183        size_t lookup_len = name->len;
1184
1185        if (!is_fully_qualified) {
1186            zend_get_unqualified_name(name, &lookup_name, &lookup_len);
1187        }
1188
1189        c = zend_lookup_reserved_const(lookup_name, lookup_len);
1190        if (c) {
1191            ZVAL_DUP(zv, &c->value);
1192            return 1;
1193        }
1194    }
1195
1196    return 0;
1197}
1198/* }}} */
1199
1200void zend_init_list(void *result, void *item) /* {{{ */
1201{
1202    void** list = emalloc(sizeof(void*) * 2);
1203
1204    list[0] = item;
1205    list[1] = NULL;
1206
1207    *(void**)result = list;
1208}
1209/* }}} */
1210
1211void zend_add_to_list(void *result, void *item) /* {{{ */
1212{
1213    void** list = *(void**)result;
1214    size_t n = 0;
1215
1216    if (list) {
1217        while (list[n]) {
1218            n++;
1219        }
1220    }
1221
1222    list = erealloc(list, sizeof(void*) * (n+2));
1223
1224    list[n]   = item;
1225    list[n+1] = NULL;
1226
1227    *(void**)result = list;
1228}
1229/* }}} */
1230
1231void zend_do_extended_info(void) /* {{{ */
1232{
1233    zend_op *opline;
1234
1235    if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
1236        return;
1237    }
1238
1239    opline = get_next_op(CG(active_op_array));
1240
1241    opline->opcode = ZEND_EXT_STMT;
1242    SET_UNUSED(opline->op1);
1243    SET_UNUSED(opline->op2);
1244}
1245/* }}} */
1246
1247void zend_do_extended_fcall_begin(void) /* {{{ */
1248{
1249    zend_op *opline;
1250
1251    if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
1252        return;
1253    }
1254
1255    opline = get_next_op(CG(active_op_array));
1256
1257    opline->opcode = ZEND_EXT_FCALL_BEGIN;
1258    SET_UNUSED(opline->op1);
1259    SET_UNUSED(opline->op2);
1260}
1261/* }}} */
1262
1263void zend_do_extended_fcall_end(void) /* {{{ */
1264{
1265    zend_op *opline;
1266
1267    if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
1268        return;
1269    }
1270
1271    opline = get_next_op(CG(active_op_array));
1272
1273    opline->opcode = ZEND_EXT_FCALL_END;
1274    SET_UNUSED(opline->op1);
1275    SET_UNUSED(opline->op2);
1276}
1277/* }}} */
1278
1279zend_bool zend_is_auto_global(zend_string *name) /* {{{ */
1280{
1281    zend_auto_global *auto_global;
1282
1283    if ((auto_global = zend_hash_find_ptr(CG(auto_globals), name)) != NULL) {
1284        if (auto_global->armed) {
1285            auto_global->armed = auto_global->auto_global_callback(auto_global->name);
1286        }
1287        return 1;
1288    }
1289    return 0;
1290}
1291/* }}} */
1292
1293int zend_register_auto_global(zend_string *name, zend_bool jit, zend_auto_global_callback auto_global_callback) /* {{{ */
1294{
1295    zend_auto_global auto_global;
1296    int retval;
1297
1298    auto_global.name = zend_new_interned_string(name);
1299    auto_global.auto_global_callback = auto_global_callback;
1300    auto_global.jit = jit;
1301
1302    retval = zend_hash_add_mem(CG(auto_globals), auto_global.name, &auto_global, sizeof(zend_auto_global)) != NULL ? SUCCESS : FAILURE;
1303
1304    zend_string_release(name);
1305    return retval;
1306}
1307/* }}} */
1308
1309ZEND_API void zend_activate_auto_globals(void) /* {{{ */
1310{
1311    zend_auto_global *auto_global;
1312
1313    ZEND_HASH_FOREACH_PTR(CG(auto_globals), auto_global) {
1314        if (auto_global->jit) {
1315            auto_global->armed = 1;
1316        } else if (auto_global->auto_global_callback) {
1317            auto_global->armed = auto_global->auto_global_callback(auto_global->name);
1318        } else {
1319            auto_global->armed = 0;
1320        }
1321    } ZEND_HASH_FOREACH_END();
1322}
1323/* }}} */
1324
1325int zendlex(zend_parser_stack_elem *elem) /* {{{ */
1326{
1327    zval zv;
1328    int retval;
1329
1330    if (CG(increment_lineno)) {
1331        CG(zend_lineno)++;
1332        CG(increment_lineno) = 0;
1333    }
1334
1335again:
1336    ZVAL_UNDEF(&zv);
1337    retval = lex_scan(&zv);
1338    switch (retval) {
1339        case T_COMMENT:
1340        case T_DOC_COMMENT:
1341        case T_OPEN_TAG:
1342        case T_WHITESPACE:
1343            goto again;
1344
1345        case T_CLOSE_TAG:
1346            if (LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-1] != '>') {
1347                CG(increment_lineno) = 1;
1348            }
1349            retval = ';'; /* implicit ; */
1350            break;
1351        case T_OPEN_TAG_WITH_ECHO:
1352            retval = T_ECHO;
1353            break;
1354    }
1355    if (Z_TYPE(zv) != IS_UNDEF) {
1356        elem->ast = zend_ast_create_zval(&zv);
1357    }
1358
1359    return retval;
1360}
1361/* }}} */
1362
1363ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers) /* {{{ */
1364{
1365    zend_bool persistent_hashes = (ce->type == ZEND_INTERNAL_CLASS) ? 1 : 0;
1366    dtor_func_t zval_ptr_dtor_func = ((persistent_hashes) ? ZVAL_INTERNAL_PTR_DTOR : ZVAL_PTR_DTOR);
1367
1368    ce->refcount = 1;
1369    ce->ce_flags = ZEND_ACC_CONSTANTS_UPDATED;
1370
1371    ce->default_properties_table = NULL;
1372    ce->default_static_members_table = NULL;
1373    zend_hash_init_ex(&ce->properties_info, 8, NULL, (persistent_hashes ? zend_destroy_property_info_internal : zend_destroy_property_info), persistent_hashes, 0);
1374    zend_hash_init_ex(&ce->constants_table, 8, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
1375    zend_hash_init_ex(&ce->function_table, 8, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0);
1376
1377    if (ce->type == ZEND_INTERNAL_CLASS) {
1378#ifdef ZTS
1379        int n = zend_hash_num_elements(CG(class_table));
1380
1381        if (CG(static_members_table) && n >= CG(last_static_member)) {
1382            /* Support for run-time declaration: dl() */
1383            CG(last_static_member) = n+1;
1384            CG(static_members_table) = realloc(CG(static_members_table), (n+1)*sizeof(zval*));
1385            CG(static_members_table)[n] = NULL;
1386        }
1387        ce->static_members_table = (zval*)(zend_intptr_t)n;
1388#else
1389        ce->static_members_table = NULL;
1390#endif
1391    } else {
1392        ce->static_members_table = ce->default_static_members_table;
1393        ce->info.user.doc_comment = NULL;
1394    }
1395
1396    ce->default_properties_count = 0;
1397    ce->default_static_members_count = 0;
1398
1399    if (nullify_handlers) {
1400        ce->constructor = NULL;
1401        ce->destructor = NULL;
1402        ce->clone = NULL;
1403        ce->__get = NULL;
1404        ce->__set = NULL;
1405        ce->__unset = NULL;
1406        ce->__isset = NULL;
1407        ce->__call = NULL;
1408        ce->__callstatic = NULL;
1409        ce->__tostring = NULL;
1410        ce->create_object = NULL;
1411        ce->get_iterator = NULL;
1412        ce->iterator_funcs.funcs = NULL;
1413        ce->interface_gets_implemented = NULL;
1414        ce->get_static_method = NULL;
1415        ce->parent = NULL;
1416        ce->num_interfaces = 0;
1417        ce->interfaces = NULL;
1418        ce->num_traits = 0;
1419        ce->traits = NULL;
1420        ce->trait_aliases = NULL;
1421        ce->trait_precedences = NULL;
1422        ce->serialize = NULL;
1423        ce->unserialize = NULL;
1424        ce->serialize_func = NULL;
1425        ce->unserialize_func = NULL;
1426        ce->__debugInfo = NULL;
1427        if (ce->type == ZEND_INTERNAL_CLASS) {
1428            ce->info.internal.module = NULL;
1429            ce->info.internal.builtin_functions = NULL;
1430        }
1431    }
1432}
1433/* }}} */
1434
1435uint32_t zend_get_class_fetch_type(zend_string *name) /* {{{ */
1436{
1437    if (zend_string_equals_literal_ci(name, "self")) {
1438        return ZEND_FETCH_CLASS_SELF;
1439    } else if (zend_string_equals_literal_ci(name, "parent")) {
1440        return ZEND_FETCH_CLASS_PARENT;
1441    } else if (zend_string_equals_literal_ci(name, "static")) {
1442        return ZEND_FETCH_CLASS_STATIC;
1443    } else {
1444        return ZEND_FETCH_CLASS_DEFAULT;
1445    }
1446}
1447/* }}} */
1448
1449ZEND_API zend_string *zend_get_compiled_variable_name(const zend_op_array *op_array, uint32_t var) /* {{{ */
1450{
1451    return op_array->vars[EX_VAR_TO_NUM(var)];
1452}
1453/* }}} */
1454
1455zend_ast *zend_ast_append_str(zend_ast *left_ast, zend_ast *right_ast) /* {{{ */
1456{
1457    zval *left_zv = zend_ast_get_zval(left_ast);
1458    zend_string *left = Z_STR_P(left_zv);
1459    zend_string *right = zend_ast_get_str(right_ast);
1460
1461    zend_string *result;
1462    size_t left_len = left->len;
1463    size_t len = left_len + right->len + 1; /* left\right */
1464
1465    result = zend_string_realloc(left, len, 0);
1466    result->val[left_len] = '\\';
1467    memcpy(&result->val[left_len + 1], right->val, right->len);
1468    result->val[len] = '\0';
1469    zend_string_release(right);
1470
1471    ZVAL_STR(left_zv, result);
1472    return left_ast;
1473}
1474/* }}} */
1475
1476/* A hacky way that is used to store the doc comment for properties */
1477zend_ast *zend_ast_append_doc_comment(zend_ast *list) /* {{{ */
1478{
1479    if (CG(doc_comment)) {
1480        list = zend_ast_list_add(list, zend_ast_create_zval_from_str(CG(doc_comment)));
1481        CG(doc_comment) = NULL;
1482    }
1483
1484    return list;
1485}
1486/* }}} */
1487
1488void zend_verify_namespace(void) /* {{{ */
1489{
1490    if (CG(has_bracketed_namespaces) && !CG(in_namespace)) {
1491        zend_error_noreturn(E_COMPILE_ERROR, "No code may exist outside of namespace {}");
1492    }
1493}
1494/* }}} */
1495
1496static void zend_reset_import_tables(void) /* {{{ */
1497{
1498    if (CG(current_import)) {
1499        zend_hash_destroy(CG(current_import));
1500        efree(CG(current_import));
1501        CG(current_import) = NULL;
1502    }
1503
1504    if (CG(current_import_function)) {
1505        zend_hash_destroy(CG(current_import_function));
1506        efree(CG(current_import_function));
1507        CG(current_import_function) = NULL;
1508    }
1509
1510    if (CG(current_import_const)) {
1511        zend_hash_destroy(CG(current_import_const));
1512        efree(CG(current_import_const));
1513        CG(current_import_const) = NULL;
1514    }
1515}
1516/* }}} */
1517
1518static void zend_end_namespace(void) /* {{{ */ {
1519    CG(in_namespace) = 0;
1520    zend_reset_import_tables();
1521    if (CG(current_namespace)) {
1522        zend_string_release(CG(current_namespace));
1523        CG(current_namespace) = NULL;
1524    }
1525}
1526/* }}} */
1527
1528void zend_do_end_compilation(void) /* {{{ */
1529{
1530    CG(has_bracketed_namespaces) = 0;
1531    zend_end_namespace();
1532}
1533/* }}} */
1534
1535/* {{{ zend_dirname
1536   Returns directory name component of path */
1537ZEND_API size_t zend_dirname(char *path, size_t len)
1538{
1539    register char *end = path + len - 1;
1540    unsigned int len_adjust = 0;
1541
1542#ifdef PHP_WIN32
1543    /* Note that on Win32 CWD is per drive (heritage from CP/M).
1544     * This means dirname("c:foo") maps to "c:." or "c:" - which means CWD on C: drive.
1545     */
1546    if ((2 <= len) && isalpha((int)((unsigned char *)path)[0]) && (':' == path[1])) {
1547        /* Skip over the drive spec (if any) so as not to change */
1548        path += 2;
1549        len_adjust += 2;
1550        if (2 == len) {
1551            /* Return "c:" on Win32 for dirname("c:").
1552             * It would be more consistent to return "c:."
1553             * but that would require making the string *longer*.
1554             */
1555            return len;
1556        }
1557    }
1558#elif defined(NETWARE)
1559    /*
1560     * Find the first occurrence of : from the left
1561     * move the path pointer to the position just after :
1562     * increment the len_adjust to the length of path till colon character(inclusive)
1563     * If there is no character beyond : simple return len
1564     */
1565    char *colonpos = NULL;
1566    colonpos = strchr(path, ':');
1567    if (colonpos != NULL) {
1568        len_adjust = ((colonpos - path) + 1);
1569        path += len_adjust;
1570        if (len_adjust == len) {
1571            return len;
1572        }
1573    }
1574#endif
1575
1576    if (len == 0) {
1577        /* Illegal use of this function */
1578        return 0;
1579    }
1580
1581    /* Strip trailing slashes */
1582    while (end >= path && IS_SLASH_P(end)) {
1583        end--;
1584    }
1585    if (end < path) {
1586        /* The path only contained slashes */
1587        path[0] = DEFAULT_SLASH;
1588        path[1] = '\0';
1589        return 1 + len_adjust;
1590    }
1591
1592    /* Strip filename */
1593    while (end >= path && !IS_SLASH_P(end)) {
1594        end--;
1595    }
1596    if (end < path) {
1597        /* No slash found, therefore return '.' */
1598#ifdef NETWARE
1599        if (len_adjust == 0) {
1600            path[0] = '.';
1601            path[1] = '\0';
1602            return 1; /* only one character */
1603        } else {
1604            path[0] = '\0';
1605            return len_adjust;
1606        }
1607#else
1608        path[0] = '.';
1609        path[1] = '\0';
1610        return 1 + len_adjust;
1611#endif
1612    }
1613
1614    /* Strip slashes which came before the file name */
1615    while (end >= path && IS_SLASH_P(end)) {
1616        end--;
1617    }
1618    if (end < path) {
1619        path[0] = DEFAULT_SLASH;
1620        path[1] = '\0';
1621        return 1 + len_adjust;
1622    }
1623    *(end+1) = '\0';
1624
1625    return (size_t)(end + 1 - path) + len_adjust;
1626}
1627/* }}} */
1628
1629static inline zend_bool zend_string_equals_str_ci(zend_string *str1, zend_string *str2) /* {{{ */
1630{
1631    return str1->len == str2->len
1632        && !zend_binary_strcasecmp(str1->val, str1->len, str2->val, str2->len);
1633}
1634/* }}} */
1635
1636static void zend_adjust_for_fetch_type(zend_op *opline, uint32_t type) /* {{{ */
1637{
1638    switch (type & BP_VAR_MASK) {
1639        case BP_VAR_R:
1640            return;
1641        case BP_VAR_W:
1642        case BP_VAR_REF:
1643            opline->opcode += 3;
1644            return;
1645        case BP_VAR_RW:
1646            opline->opcode += 6;
1647            return;
1648        case BP_VAR_IS:
1649            opline->opcode += 9;
1650            return;
1651        case BP_VAR_FUNC_ARG:
1652            opline->opcode += 12;
1653            opline->extended_value |= type >> BP_VAR_SHIFT;
1654            return;
1655        case BP_VAR_UNSET:
1656            opline->opcode += 15;
1657            return;
1658        EMPTY_SWITCH_DEFAULT_CASE()
1659    }
1660}
1661/* }}} */
1662
1663static inline void zend_make_var_result(znode *result, zend_op *opline) /* {{{ */
1664{
1665    opline->result_type = IS_VAR;
1666    opline->result.var = get_temporary_variable(CG(active_op_array));
1667    GET_NODE(result, opline->result);
1668}
1669/* }}} */
1670
1671static inline void zend_make_tmp_result(znode *result, zend_op *opline) /* {{{ */
1672{
1673    opline->result_type = IS_TMP_VAR;
1674    opline->result.var = get_temporary_variable(CG(active_op_array));
1675    GET_NODE(result, opline->result);
1676}
1677/* }}} */
1678
1679static zend_op *zend_emit_op(znode *result, zend_uchar opcode, znode *op1, znode *op2) /* {{{ */
1680{
1681    zend_op *opline = get_next_op(CG(active_op_array));
1682    opline->opcode = opcode;
1683
1684    if (op1 == NULL) {
1685        SET_UNUSED(opline->op1);
1686    } else {
1687        SET_NODE(opline->op1, op1);
1688    }
1689
1690    if (op2 == NULL) {
1691        SET_UNUSED(opline->op2);
1692    } else {
1693        SET_NODE(opline->op2, op2);
1694    }
1695
1696    if (result) {
1697        zend_make_var_result(result, opline);
1698    }
1699    return opline;
1700}
1701/* }}} */
1702
1703static zend_op *zend_emit_op_tmp(znode *result, zend_uchar opcode, znode *op1, znode *op2) /* {{{ */
1704{
1705    zend_op *opline = get_next_op(CG(active_op_array));
1706    opline->opcode = opcode;
1707
1708    if (op1 == NULL) {
1709        SET_UNUSED(opline->op1);
1710    } else {
1711        SET_NODE(opline->op1, op1);
1712    }
1713
1714    if (op2 == NULL) {
1715        SET_UNUSED(opline->op2);
1716    } else {
1717        SET_NODE(opline->op2, op2);
1718    }
1719
1720    if (result) {
1721        zend_make_tmp_result(result, opline);
1722    }
1723
1724    return opline;
1725}
1726/* }}} */
1727
1728static void zend_emit_tick(void) /* {{{ */
1729{
1730    zend_op *opline = get_next_op(CG(active_op_array));
1731
1732    opline->opcode = ZEND_TICKS;
1733    SET_UNUSED(opline->op1);
1734    SET_UNUSED(opline->op2);
1735    opline->extended_value = Z_LVAL(CG(declarables).ticks);
1736}
1737/* }}} */
1738
1739static inline zend_op *zend_emit_op_data(znode *value) /* {{{ */
1740{
1741    return zend_emit_op(NULL, ZEND_OP_DATA, value, NULL);
1742}
1743/* }}} */
1744
1745static inline uint32_t zend_emit_jump(uint32_t opnum_target) /* {{{ */
1746{
1747    uint32_t opnum = get_next_op_number(CG(active_op_array));
1748    zend_op *opline = zend_emit_op(NULL, ZEND_JMP, NULL, NULL);
1749    opline->op1.opline_num = opnum_target;
1750    return opnum;
1751}
1752/* }}} */
1753
1754static inline uint32_t zend_emit_cond_jump(zend_uchar opcode, znode *cond, uint32_t opnum_target) /* {{{ */
1755{
1756    uint32_t opnum = get_next_op_number(CG(active_op_array));
1757    zend_op *opline = zend_emit_op(NULL, opcode, cond, NULL);
1758    opline->op2.opline_num = opnum_target;
1759    return opnum;
1760}
1761/* }}} */
1762
1763static inline void zend_update_jump_target(uint32_t opnum_jump, uint32_t opnum_target) /* {{{ */
1764{
1765    zend_op *opline = &CG(active_op_array)->opcodes[opnum_jump];
1766    switch (opline->opcode) {
1767        case ZEND_JMP:
1768            opline->op1.opline_num = opnum_target;
1769            break;
1770        case ZEND_JMPZ:
1771        case ZEND_JMPNZ:
1772        case ZEND_JMPZ_EX:
1773        case ZEND_JMPNZ_EX:
1774            opline->op2.opline_num = opnum_target;
1775            break;
1776        EMPTY_SWITCH_DEFAULT_CASE()
1777    }
1778}
1779/* }}} */
1780
1781static inline void zend_update_jump_target_to_next(uint32_t opnum_jump) /* {{{ */
1782{
1783    zend_update_jump_target(opnum_jump, get_next_op_number(CG(active_op_array)));
1784}
1785/* }}} */
1786
1787static inline zend_op *zend_delayed_emit_op(znode *result, zend_uchar opcode, znode *op1, znode *op2) /* {{{ */
1788{
1789    zend_op tmp_opline;
1790    init_op(&tmp_opline);
1791    tmp_opline.opcode = opcode;
1792    SET_NODE(tmp_opline.op1, op1);
1793    SET_NODE(tmp_opline.op2, op2);
1794    if (result) {
1795        zend_make_var_result(result, &tmp_opline);
1796    }
1797
1798    zend_stack_push(&CG(delayed_oplines_stack), &tmp_opline);
1799    return zend_stack_top(&CG(delayed_oplines_stack));
1800}
1801/* }}} */
1802
1803static inline uint32_t zend_delayed_compile_begin(void) /* {{{ */
1804{
1805    return zend_stack_count(&CG(delayed_oplines_stack));
1806}
1807/* }}} */
1808
1809static zend_op *zend_delayed_compile_end(uint32_t offset) /* {{{ */
1810{
1811    zend_op *opline = NULL, *oplines = zend_stack_base(&CG(delayed_oplines_stack));
1812    uint32_t i, count = zend_stack_count(&CG(delayed_oplines_stack));
1813
1814    ZEND_ASSERT(count > offset);
1815    for (i = offset; i < count; ++i) {
1816        opline = get_next_op(CG(active_op_array));
1817        memcpy(opline, &oplines[i], sizeof(zend_op));
1818    }
1819    CG(delayed_oplines_stack).top = offset;
1820    return opline;
1821}
1822/* }}} */
1823
1824
1825static void zend_emit_return_type_check(znode *expr, zend_arg_info *return_info) /* {{{ */
1826{
1827    if (return_info->type_hint != IS_UNDEF) {
1828        zend_emit_op(NULL, ZEND_VERIFY_RETURN_TYPE, expr, NULL);
1829    }
1830}
1831/* }}} */
1832
1833
1834void zend_emit_final_return(zval *zv) /* {{{ */
1835{
1836    znode zn;
1837    zend_bool returns_reference = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
1838
1839    if (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
1840        zend_emit_return_type_check(NULL, CG(active_op_array)->arg_info - 1);
1841    }
1842
1843    zn.op_type = IS_CONST;
1844    if (zv) {
1845        ZVAL_COPY_VALUE(&zn.u.constant, zv);
1846    } else {
1847        ZVAL_NULL(&zn.u.constant);
1848    }
1849
1850    zend_emit_op(NULL, returns_reference ? ZEND_RETURN_BY_REF : ZEND_RETURN, &zn, NULL);
1851}
1852/* }}} */
1853
1854static inline zend_bool zend_is_variable(zend_ast *ast) /* {{{ */
1855{
1856    return ast->kind == ZEND_AST_VAR || ast->kind == ZEND_AST_DIM
1857        || ast->kind == ZEND_AST_PROP || ast->kind == ZEND_AST_STATIC_PROP
1858        || ast->kind == ZEND_AST_CALL || ast->kind == ZEND_AST_METHOD_CALL
1859        || ast->kind == ZEND_AST_STATIC_CALL;
1860}
1861/* }}} */
1862
1863static inline zend_bool zend_is_call(zend_ast *ast) /* {{{ */
1864{
1865    return ast->kind == ZEND_AST_CALL
1866        || ast->kind == ZEND_AST_METHOD_CALL
1867        || ast->kind == ZEND_AST_STATIC_CALL;
1868}
1869/* }}} */
1870
1871static inline zend_bool zend_is_unticked_stmt(zend_ast *ast) /* {{{ */
1872{
1873    return ast->kind == ZEND_AST_STMT_LIST || ast->kind == ZEND_AST_LABEL;
1874}
1875/* }}} */
1876
1877static inline zend_bool zend_can_write_to_variable(zend_ast *ast) /* {{{ */
1878{
1879    while (ast->kind == ZEND_AST_DIM || ast->kind == ZEND_AST_PROP) {
1880        ast = ast->child[0];
1881    }
1882
1883    return zend_is_variable(ast);
1884}
1885/* }}} */
1886
1887static inline zend_bool zend_is_const_default_class_ref(zend_ast *name_ast) /* {{{ */
1888{
1889    zend_string *name;
1890
1891    if (name_ast->kind != ZEND_AST_ZVAL) {
1892        return 0;
1893    }
1894
1895    /* Fully qualified names are always default refs */
1896    if (!name_ast->attr) {
1897        return 1;
1898    }
1899
1900    name = zend_ast_get_str(name_ast);
1901    return ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(name);
1902}
1903/* }}} */
1904
1905static inline void zend_handle_numeric_op(znode *node) /* {{{ */
1906{
1907    if (node->op_type == IS_CONST && Z_TYPE(node->u.constant) == IS_STRING) {
1908        zend_ulong index;
1909
1910        if (ZEND_HANDLE_NUMERIC(Z_STR(node->u.constant), index)) {
1911            zval_ptr_dtor(&node->u.constant);
1912            ZVAL_LONG(&node->u.constant, index);
1913        }
1914    }
1915}
1916/* }}} */
1917
1918static inline void zend_set_class_name_op1(zend_op *opline, znode *class_node) /* {{{ */
1919{
1920    if (class_node->op_type == IS_CONST) {
1921        opline->op1_type = IS_CONST;
1922        opline->op1.constant = zend_add_class_name_literal(
1923            CG(active_op_array), Z_STR(class_node->u.constant));
1924    } else {
1925        SET_NODE(opline->op1, class_node);
1926    }
1927}
1928/* }}} */
1929
1930static zend_op *zend_compile_class_ref(znode *result, zend_ast *name_ast) /* {{{ */
1931{
1932    zend_op *opline;
1933    znode name_node;
1934    zend_compile_expr(&name_node, name_ast);
1935
1936    if (name_node.op_type == IS_CONST) {
1937        zend_string *name = Z_STR(name_node.u.constant);
1938        uint32_t fetch_type = zend_get_class_fetch_type(name);
1939
1940        opline = zend_emit_op(result, ZEND_FETCH_CLASS, NULL, NULL);
1941        opline->extended_value = fetch_type;
1942
1943        if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
1944            uint32_t type = name_ast->kind == ZEND_AST_ZVAL ? name_ast->attr : ZEND_NAME_FQ;
1945            opline->op2_type = IS_CONST;
1946            opline->op2.constant = zend_add_class_name_literal(CG(active_op_array),
1947                zend_resolve_class_name(name, type));
1948        }
1949
1950        zend_string_release(name);
1951    } else {
1952        opline = zend_emit_op(result, ZEND_FETCH_CLASS, NULL, &name_node);
1953        opline->extended_value = ZEND_FETCH_CLASS_DEFAULT;
1954    }
1955
1956    return opline;
1957}
1958/* }}} */
1959
1960static int zend_try_compile_cv(znode *result, zend_ast *ast) /* {{{ */
1961{
1962    zend_ast *name_ast = ast->child[0];
1963    if (name_ast->kind == ZEND_AST_ZVAL) {
1964        zend_string *name = zval_get_string(zend_ast_get_zval(name_ast));
1965
1966        if (zend_is_auto_global(name)) {
1967            zend_string_release(name);
1968            return FAILURE;
1969        }
1970
1971        result->op_type = IS_CV;
1972        result->u.op.var = lookup_cv(CG(active_op_array), name);
1973
1974        /* lookup_cv may be using another zend_string instance  */
1975        name = CG(active_op_array)->vars[EX_VAR_TO_NUM(result->u.op.var)];
1976
1977        if (zend_string_equals_literal(name, "this")) {
1978            CG(active_op_array)->this_var = result->u.op.var;
1979        }
1980        return SUCCESS;
1981    }
1982
1983    return FAILURE;
1984}
1985/* }}} */
1986
1987static zend_op *zend_compile_simple_var_no_cv(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
1988{
1989    zend_ast *name_ast = ast->child[0];
1990    znode name_node;
1991    zend_op *opline;
1992
1993    /* there is a chance someone is accessing $this */
1994    if (ast->kind != ZEND_AST_ZVAL
1995        && CG(active_op_array)->scope && CG(active_op_array)->this_var == (uint32_t)-1
1996    ) {
1997        zend_string *key = zend_string_init("this", sizeof("this") - 1, 0);
1998        CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), key);
1999    }
2000
2001    zend_compile_expr(&name_node, name_ast);
2002    if (name_node.op_type == IS_CONST) {
2003        convert_to_string(&name_node.u.constant);
2004    }
2005
2006    opline = zend_emit_op(result, ZEND_FETCH_R, &name_node, NULL);
2007
2008    opline->extended_value = ZEND_FETCH_LOCAL;
2009    if (name_node.op_type == IS_CONST) {
2010        if (zend_is_auto_global(Z_STR(name_node.u.constant))) {
2011            opline->extended_value = ZEND_FETCH_GLOBAL;
2012        }
2013    }
2014
2015    return opline;
2016}
2017/* }}} */
2018
2019static void zend_compile_simple_var(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
2020{
2021    if (zend_try_compile_cv(result, ast) == FAILURE) {
2022        zend_op *opline = zend_compile_simple_var_no_cv(result, ast, type);
2023        zend_adjust_for_fetch_type(opline, type);
2024    }
2025}
2026/* }}} */
2027
2028static void zend_separate_if_call_and_write(znode *node, zend_ast *ast, uint32_t type) /* {{{ */
2029{
2030    if (type != BP_VAR_R && type != BP_VAR_IS && zend_is_call(ast)) {
2031        if (node->op_type == IS_VAR) {
2032            zend_op *opline = zend_emit_op(NULL, ZEND_SEPARATE, node, NULL);
2033            opline->result_type = IS_VAR;
2034            opline->result.var = opline->op1.var;
2035        } else {
2036            zend_error_noreturn(E_COMPILE_ERROR, "Cannot use result of built-in function in write context");
2037        }
2038    }
2039}
2040/* }}} */
2041
2042void zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type);
2043void zend_compile_assign(znode *result, zend_ast *ast);
2044static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_node);
2045
2046static inline void zend_emit_assign_znode(zend_ast *var_ast, znode *value_node) /* {{{ */
2047{
2048    znode dummy_node;
2049    if (var_ast->kind == ZEND_AST_LIST) {
2050        zend_compile_list_assign(&dummy_node, var_ast, value_node);
2051    } else {
2052        zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN, var_ast,
2053            zend_ast_create_znode(value_node));
2054        zend_compile_assign(&dummy_node, assign_ast);
2055    }
2056    zend_do_free(&dummy_node);
2057}
2058/* }}} */
2059
2060static zend_op *zend_delayed_compile_dim(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
2061{
2062    zend_ast *var_ast = ast->child[0];
2063    zend_ast *dim_ast = ast->child[1];
2064
2065    znode var_node, dim_node;
2066
2067    zend_delayed_compile_var(&var_node, var_ast, type);
2068    zend_separate_if_call_and_write(&var_node, var_ast, type);
2069
2070    if (dim_ast == NULL) {
2071        if (type == BP_VAR_R || type == BP_VAR_IS) {
2072            zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
2073        }
2074        if (type == BP_VAR_UNSET) {
2075            zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for unsetting");
2076        }
2077        dim_node.op_type = IS_UNUSED;
2078    } else {
2079        zend_compile_expr(&dim_node, dim_ast);
2080        zend_handle_numeric_op(&dim_node);
2081    }
2082
2083    return zend_delayed_emit_op(result, ZEND_FETCH_DIM_R, &var_node, &dim_node);
2084}
2085/* }}} */
2086
2087static inline zend_op *zend_compile_dim_common(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
2088{
2089    uint32_t offset = zend_delayed_compile_begin();
2090    zend_delayed_compile_dim(result, ast, type);
2091    return zend_delayed_compile_end(offset);
2092}
2093/* }}} */
2094
2095void zend_compile_dim(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
2096{
2097    zend_op *opline = zend_compile_dim_common(result, ast, type);
2098    zend_adjust_for_fetch_type(opline, type);
2099}
2100/* }}} */
2101
2102static zend_bool is_this_fetch(zend_ast *ast) /* {{{ */
2103{
2104    if (ast->kind == ZEND_AST_VAR && ast->child[0]->kind == ZEND_AST_ZVAL) {
2105        zval *name = zend_ast_get_zval(ast->child[0]);
2106        return Z_TYPE_P(name) == IS_STRING && zend_string_equals_literal(Z_STR_P(name), "this");
2107    }
2108
2109    return 0;
2110}
2111/* }}} */
2112
2113static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
2114{
2115    zend_ast *obj_ast = ast->child[0];
2116    zend_ast *prop_ast = ast->child[1];
2117
2118    znode obj_node, prop_node;
2119    zend_op *opline;
2120
2121    if (is_this_fetch(obj_ast)) {
2122        obj_node.op_type = IS_UNUSED;
2123    } else {
2124        zend_delayed_compile_var(&obj_node, obj_ast, type);
2125        zend_separate_if_call_and_write(&obj_node, obj_ast, type);
2126    }
2127    zend_compile_expr(&prop_node, prop_ast);
2128
2129    opline = zend_delayed_emit_op(result, ZEND_FETCH_OBJ_R, &obj_node, &prop_node);
2130    if (opline->op2_type == IS_CONST) {
2131        convert_to_string(CT_CONSTANT(opline->op2));
2132        zend_alloc_polymorphic_cache_slot(opline->op2.constant);
2133    }
2134
2135    return opline;
2136}
2137/* }}} */
2138
2139static zend_op *zend_compile_prop_common(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
2140{
2141    uint32_t offset = zend_delayed_compile_begin();
2142    zend_delayed_compile_prop(result, ast, type);
2143    return zend_delayed_compile_end(offset);
2144}
2145/* }}} */
2146
2147void zend_compile_prop(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
2148{
2149    zend_op *opline = zend_compile_prop_common(result, ast, type);
2150    zend_adjust_for_fetch_type(opline, type);
2151}
2152/* }}} */
2153
2154zend_op *zend_compile_static_prop_common(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
2155{
2156    zend_ast *class_ast = ast->child[0];
2157    zend_ast *prop_ast = ast->child[1];
2158
2159    znode class_node, prop_node;
2160    zend_op *opline;
2161
2162    if (zend_is_const_default_class_ref(class_ast)) {
2163        class_node.op_type = IS_CONST;
2164        ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast));
2165    } else {
2166        zend_compile_class_ref(&class_node, class_ast);
2167    }
2168
2169    zend_compile_expr(&prop_node, prop_ast);
2170
2171    opline = zend_emit_op(result, ZEND_FETCH_R, &prop_node, NULL);
2172    if (opline->op1_type == IS_CONST) {
2173        zend_alloc_polymorphic_cache_slot(opline->op1.constant);
2174    }
2175    if (class_node.op_type == IS_CONST) {
2176        opline->op2_type = IS_CONST;
2177        opline->op2.constant = zend_add_class_name_literal(
2178            CG(active_op_array), Z_STR(class_node.u.constant));
2179    } else {
2180        SET_NODE(opline->op2, &class_node);
2181    }
2182    opline->extended_value |= ZEND_FETCH_STATIC_MEMBER;
2183
2184    return opline;
2185}
2186/* }}} */
2187
2188void zend_compile_static_prop(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
2189{
2190    zend_op *opline = zend_compile_static_prop_common(result, ast, type);
2191    zend_adjust_for_fetch_type(opline, type);
2192}
2193/* }}} */
2194
2195static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_node) /* {{{ */
2196{
2197    zend_ast_list *list = zend_ast_get_list(ast);
2198    uint32_t i;
2199    zend_bool has_elems = 0;
2200
2201    for (i = 0; i < list->children; ++i) {
2202        zend_ast *var_ast = list->child[i];
2203        znode fetch_result, dim_node;
2204
2205        if (var_ast == NULL) {
2206            continue;
2207        }
2208        has_elems = 1;
2209
2210        dim_node.op_type = IS_CONST;
2211        ZVAL_LONG(&dim_node.u.constant, i);
2212
2213        if (expr_node->op_type == IS_CONST) {
2214            Z_TRY_ADDREF(expr_node->u.constant);
2215        }
2216
2217        zend_emit_op(&fetch_result, ZEND_FETCH_LIST, expr_node, &dim_node);
2218        zend_emit_assign_znode(var_ast, &fetch_result);
2219    }
2220
2221    if (!has_elems) {
2222        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use empty list");
2223    }
2224
2225    *result = *expr_node;
2226}
2227/* }}} */
2228
2229void zend_ensure_writable_variable(const zend_ast *ast) /* {{{ */
2230{
2231    if (ast->kind == ZEND_AST_CALL) {
2232        zend_error_noreturn(E_COMPILE_ERROR, "Can't use function return value in write context");
2233    }
2234    if (ast->kind == ZEND_AST_METHOD_CALL || ast->kind == ZEND_AST_STATIC_CALL) {
2235        zend_error_noreturn(E_COMPILE_ERROR, "Can't use method return value in write context");
2236    }
2237}
2238/* }}} */
2239
2240/* Detects $a... = $a pattern */
2241zend_bool zend_is_assign_to_self(zend_ast *var_ast, zend_ast *expr_ast) /* {{{ */
2242{
2243    if (expr_ast->kind != ZEND_AST_VAR || expr_ast->child[0]->kind != ZEND_AST_ZVAL) {
2244        return 0;
2245    }
2246
2247    while (zend_is_variable(var_ast) && var_ast->kind != ZEND_AST_VAR) {
2248        var_ast = var_ast->child[0];
2249    }
2250
2251    if (var_ast->kind != ZEND_AST_VAR || var_ast->child[0]->kind != ZEND_AST_ZVAL) {
2252        return 0;
2253    }
2254
2255    {
2256        zend_string *name1 = zval_get_string(zend_ast_get_zval(var_ast->child[0]));
2257        zend_string *name2 = zval_get_string(zend_ast_get_zval(expr_ast->child[0]));
2258        zend_bool result = zend_string_equals(name1, name2);
2259        zend_string_release(name1);
2260        zend_string_release(name2);
2261        return result;
2262    }
2263}
2264/* }}} */
2265
2266void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
2267{
2268    zend_ast *var_ast = ast->child[0];
2269    zend_ast *expr_ast = ast->child[1];
2270
2271    znode var_node, expr_node;
2272    zend_op *opline;
2273    uint32_t offset;
2274
2275    if (is_this_fetch(var_ast)) {
2276        zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
2277    }
2278
2279    zend_ensure_writable_variable(var_ast);
2280
2281    switch (var_ast->kind) {
2282        case ZEND_AST_VAR:
2283        case ZEND_AST_STATIC_PROP:
2284            zend_compile_var(&var_node, var_ast, BP_VAR_W);
2285            zend_compile_expr(&expr_node, expr_ast);
2286            zend_emit_op(result, ZEND_ASSIGN, &var_node, &expr_node);
2287            return;
2288        case ZEND_AST_DIM:
2289            offset = zend_delayed_compile_begin();
2290            zend_delayed_compile_dim(result, var_ast, BP_VAR_W);
2291
2292            if (zend_is_assign_to_self(var_ast, expr_ast)) {
2293                /* $a[0] = $a should evaluate the right $a first */
2294                zend_compile_simple_var_no_cv(&expr_node, expr_ast, BP_VAR_R);
2295            } else {
2296                zend_compile_expr(&expr_node, expr_ast);
2297            }
2298
2299            opline = zend_delayed_compile_end(offset);
2300            opline->opcode = ZEND_ASSIGN_DIM;
2301
2302            opline = zend_emit_op_data(&expr_node);
2303            return;
2304        case ZEND_AST_PROP:
2305            offset = zend_delayed_compile_begin();
2306            zend_delayed_compile_prop(result, var_ast, BP_VAR_W);
2307            zend_compile_expr(&expr_node, expr_ast);
2308
2309            opline = zend_delayed_compile_end(offset);
2310            opline->opcode = ZEND_ASSIGN_OBJ;
2311
2312            zend_emit_op_data(&expr_node);
2313            return;
2314        case ZEND_AST_LIST:
2315            zend_compile_expr(&expr_node, expr_ast);
2316            zend_compile_list_assign(result, var_ast, &expr_node);
2317            return;
2318        EMPTY_SWITCH_DEFAULT_CASE();
2319    }
2320}
2321/* }}} */
2322
2323void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */
2324{
2325    zend_ast *target_ast = ast->child[0];
2326    zend_ast *source_ast = ast->child[1];
2327
2328    znode target_node, source_node;
2329    zend_op *opline;
2330
2331    if (is_this_fetch(target_ast)) {
2332        zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
2333    }
2334    zend_ensure_writable_variable(target_ast);
2335
2336    zend_compile_var(&target_node, target_ast, BP_VAR_W);
2337    zend_compile_var(&source_node, source_ast, BP_VAR_REF);
2338
2339    if (source_node.op_type != IS_VAR && zend_is_call(source_ast)) {
2340        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use result of built-in function in write context");
2341    }
2342
2343    opline = zend_emit_op(result, ZEND_ASSIGN_REF, &target_node, &source_node);
2344    if (!result) {
2345        opline->result_type |= EXT_TYPE_UNUSED;
2346    }
2347
2348    if (zend_is_call(source_ast)) {
2349        opline->extended_value = ZEND_RETURNS_FUNCTION;
2350    }
2351}
2352/* }}} */
2353
2354static inline void zend_emit_assign_ref_znode(zend_ast *var_ast, znode *value_node) /* {{{ */
2355{
2356    zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN_REF, var_ast,
2357        zend_ast_create_znode(value_node));
2358    zend_compile_assign_ref(NULL, assign_ast);
2359}
2360/* }}} */
2361
2362void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */
2363{
2364    zend_ast *var_ast = ast->child[0];
2365    zend_ast *expr_ast = ast->child[1];
2366    uint32_t opcode = ast->attr;
2367
2368    znode var_node, expr_node;
2369    zend_op *opline;
2370    uint32_t offset;
2371
2372    zend_ensure_writable_variable(var_ast);
2373
2374    switch (var_ast->kind) {
2375        case ZEND_AST_VAR:
2376        case ZEND_AST_STATIC_PROP:
2377            zend_compile_var(&var_node, var_ast, BP_VAR_RW);
2378            zend_compile_expr(&expr_node, expr_ast);
2379            zend_emit_op(result, opcode, &var_node, &expr_node);
2380            return;
2381        case ZEND_AST_DIM:
2382            offset = zend_delayed_compile_begin();
2383            zend_delayed_compile_dim(result, var_ast, BP_VAR_RW);
2384            zend_compile_expr(&expr_node, expr_ast);
2385
2386            opline = zend_delayed_compile_end(offset);
2387            opline->opcode = opcode;
2388            opline->extended_value = ZEND_ASSIGN_DIM;
2389
2390            opline = zend_emit_op_data(&expr_node);
2391            return;
2392        case ZEND_AST_PROP:
2393            offset = zend_delayed_compile_begin();
2394            zend_delayed_compile_prop(result, var_ast, BP_VAR_RW);
2395            zend_compile_expr(&expr_node, expr_ast);
2396
2397            opline = zend_delayed_compile_end(offset);
2398            opline->opcode = opcode;
2399            opline->extended_value = ZEND_ASSIGN_OBJ;
2400
2401            zend_emit_op_data(&expr_node);
2402            return;
2403        EMPTY_SWITCH_DEFAULT_CASE()
2404    }
2405}
2406/* }}} */
2407
2408uint32_t zend_compile_args(zend_ast *ast, zend_function *fbc) /* {{{ */
2409{
2410    /* TODO.AST &var error */
2411    zend_ast_list *args = zend_ast_get_list(ast);
2412    uint32_t i;
2413    zend_bool uses_arg_unpack = 0;
2414    uint32_t arg_count = 0; /* number of arguments not including unpacks */
2415
2416    for (i = 0; i < args->children; ++i) {
2417        zend_ast *arg = args->child[i];
2418        uint32_t arg_num = i + 1;
2419
2420        znode arg_node;
2421        zend_op *opline;
2422        zend_uchar opcode;
2423        zend_ulong flags = 0;
2424
2425        if (arg->kind == ZEND_AST_UNPACK) {
2426            uses_arg_unpack = 1;
2427            fbc = NULL;
2428
2429            zend_compile_expr(&arg_node, arg->child[0]);
2430            opline = zend_emit_op(NULL, ZEND_SEND_UNPACK, &arg_node, NULL);
2431            opline->op2.num = arg_count;
2432            opline->result.var = (uint32_t)(zend_intptr_t)ZEND_CALL_ARG(NULL, arg_count);
2433            continue;
2434        }
2435
2436        if (uses_arg_unpack) {
2437            zend_error_noreturn(E_COMPILE_ERROR,
2438                "Cannot use positional argument after argument unpacking");
2439        }
2440
2441        arg_count++;
2442        if (zend_is_variable(arg)) {
2443            if (zend_is_call(arg)) {
2444                zend_compile_var(&arg_node, arg, BP_VAR_R);
2445                if (arg_node.op_type & (IS_CONST|IS_TMP_VAR)) {
2446                    /* Function call was converted into builtin instruction */
2447                    opcode = ZEND_SEND_VAL;
2448                } else {
2449                    opcode = ZEND_SEND_VAR_NO_REF;
2450                    flags |= ZEND_ARG_SEND_FUNCTION;
2451                    if (fbc && ARG_SHOULD_BE_SENT_BY_REF(fbc, arg_num)) {
2452                        flags |= ZEND_ARG_SEND_BY_REF;
2453                        if (ARG_MAY_BE_SENT_BY_REF(fbc, arg_num)) {
2454                            flags |= ZEND_ARG_SEND_SILENT;
2455                        }
2456                    }
2457                }
2458            } else if (fbc) {
2459                if (ARG_SHOULD_BE_SENT_BY_REF(fbc, arg_num)) {
2460                    zend_compile_var(&arg_node, arg, BP_VAR_W);
2461                    opcode = ZEND_SEND_REF;
2462                } else {
2463                    zend_compile_var(&arg_node, arg, BP_VAR_R);
2464                    opcode = ZEND_SEND_VAR;
2465                }
2466            } else {
2467                zend_compile_var(&arg_node, arg,
2468                    BP_VAR_FUNC_ARG | (arg_num << BP_VAR_SHIFT));
2469                opcode = ZEND_SEND_VAR_EX;
2470            }
2471        } else {
2472            zend_compile_expr(&arg_node, arg);
2473            if (arg_node.op_type & (IS_VAR|IS_CV)) {
2474                opcode = ZEND_SEND_VAR_NO_REF;
2475                if (fbc && ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
2476                    flags |= ZEND_ARG_SEND_BY_REF;
2477                }
2478            } else {
2479                if (fbc) {
2480                    opcode = ZEND_SEND_VAL;
2481                    if (ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
2482                        zend_error_noreturn(E_COMPILE_ERROR, "Only variables can be passed by reference");
2483                    }
2484                } else {
2485                    opcode = ZEND_SEND_VAL_EX;
2486                }
2487            }
2488        }
2489
2490        opline = get_next_op(CG(active_op_array));
2491        opline->opcode = opcode;
2492        SET_NODE(opline->op1, &arg_node);
2493        SET_UNUSED(opline->op2);
2494        opline->op2.opline_num = arg_num;
2495        opline->result.var = (uint32_t)(zend_intptr_t)ZEND_CALL_ARG(NULL, arg_num);
2496
2497        if (opcode == ZEND_SEND_VAR_NO_REF) {
2498            if (fbc) {
2499                flags |= ZEND_ARG_COMPILE_TIME_BOUND;
2500            }
2501            if ((flags & ZEND_ARG_COMPILE_TIME_BOUND) && !(flags & ZEND_ARG_SEND_BY_REF)) {
2502                opline->opcode = ZEND_SEND_VAR;
2503                opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
2504            } else {
2505                opline->extended_value = flags;
2506            }
2507        } else if (fbc) {
2508            opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
2509        }
2510    }
2511
2512    return arg_count;
2513}
2514/* }}} */
2515
2516void zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *fbc) /* {{{ */
2517{
2518    zend_op *opline;
2519    uint32_t opnum_init = get_next_op_number(CG(active_op_array)) - 1;
2520    uint32_t arg_count;
2521    uint32_t call_flags;
2522
2523    zend_do_extended_fcall_begin();
2524
2525    arg_count = zend_compile_args(args_ast, fbc);
2526
2527    opline = &CG(active_op_array)->opcodes[opnum_init];
2528    opline->extended_value = arg_count;
2529
2530    if (opline->opcode == ZEND_INIT_FCALL) {
2531        opline->op1.num = zend_vm_calc_used_stack(arg_count, fbc);
2532    }
2533
2534    call_flags = (opline->opcode == ZEND_NEW ? ZEND_CALL_CTOR : 0);
2535    opline = zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL);
2536    opline->op1.num = call_flags;
2537
2538    zend_do_extended_fcall_end();
2539}
2540/* }}} */
2541
2542zend_bool zend_compile_function_name(znode *name_node, zend_ast *name_ast) /* {{{ */
2543{
2544    zend_string *orig_name = zend_ast_get_str(name_ast);
2545    zend_bool is_fully_qualified;
2546
2547    name_node->op_type = IS_CONST;
2548    ZVAL_STR(&name_node->u.constant, zend_resolve_function_name(
2549        orig_name, name_ast->attr, &is_fully_qualified));
2550
2551    return !is_fully_qualified && CG(current_namespace);
2552}
2553/* }}} */
2554
2555void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args_ast) /* {{{ */
2556{
2557    zend_op *opline = get_next_op(CG(active_op_array));
2558    opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
2559    SET_UNUSED(opline->op1);
2560    opline->op2_type = IS_CONST;
2561    opline->op2.constant = zend_add_ns_func_name_literal(
2562        CG(active_op_array), Z_STR(name_node->u.constant));
2563    zend_alloc_cache_slot(opline->op2.constant);
2564
2565    zend_compile_call_common(result, args_ast, NULL);
2566}
2567/* }}} */
2568
2569void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_ast) /* {{{ */
2570{
2571    zend_op *opline = get_next_op(CG(active_op_array));
2572    opline->opcode = ZEND_INIT_FCALL_BY_NAME;
2573    SET_UNUSED(opline->op1);
2574    if (name_node->op_type == IS_CONST && Z_TYPE(name_node->u.constant) == IS_STRING) {
2575        opline->op2_type = IS_CONST;
2576        opline->op2.constant = zend_add_func_name_literal(CG(active_op_array),
2577            Z_STR(name_node->u.constant));
2578        zend_alloc_cache_slot(opline->op2.constant);
2579    } else {
2580        SET_NODE(opline->op2, name_node);
2581    }
2582
2583    zend_compile_call_common(result, args_ast, NULL);
2584}
2585/* }}} */
2586
2587static zend_bool zend_args_contain_unpack(zend_ast_list *args) /* {{{ */
2588{
2589    uint32_t i;
2590    for (i = 0; i < args->children; ++i) {
2591        if (args->child[i]->kind == ZEND_AST_UNPACK) {
2592            return 1;
2593        }
2594    }
2595    return 0;
2596}
2597/* }}} */
2598
2599int zend_compile_func_strlen(znode *result, zend_ast_list *args) /* {{{ */
2600{
2601    znode arg_node;
2602
2603    if ((CG(compiler_options) & ZEND_COMPILE_NO_BUILTIN_STRLEN)
2604        || args->children != 1 || args->child[0]->kind == ZEND_AST_UNPACK
2605    ) {
2606        return FAILURE;
2607    }
2608
2609    zend_compile_expr(&arg_node, args->child[0]);
2610    zend_emit_op_tmp(result, ZEND_STRLEN, &arg_node, NULL);
2611    return SUCCESS;
2612}
2613/* }}} */
2614
2615int zend_compile_func_typecheck(znode *result, zend_ast_list *args, uint32_t type) /* {{{ */
2616{
2617    znode arg_node;
2618    zend_op *opline;
2619
2620    if (args->children != 1 || args->child[0]->kind == ZEND_AST_UNPACK) {
2621        return FAILURE;
2622    }
2623
2624    zend_compile_expr(&arg_node, args->child[0]);
2625    opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &arg_node, NULL);
2626    opline->extended_value = type;
2627    return SUCCESS;
2628}
2629/* }}} */
2630
2631int zend_compile_func_defined(znode *result, zend_ast_list *args) /* {{{ */
2632{
2633    zend_string *name;
2634    zend_op *opline;
2635
2636    if (args->children != 1 || args->child[0]->kind != ZEND_AST_ZVAL) {
2637        return FAILURE;
2638    }
2639
2640    name = zval_get_string(zend_ast_get_zval(args->child[0]));
2641    if (zend_memrchr(name->val, '\\', name->len) || zend_memrchr(name->val, ':', name->len)) {
2642        zend_string_release(name);
2643        return FAILURE;
2644    }
2645
2646    opline = zend_emit_op_tmp(result, ZEND_DEFINED, NULL, NULL);
2647    opline->op1_type = IS_CONST;
2648    LITERAL_STR(opline->op1, name);
2649    zend_alloc_cache_slot(opline->op1.constant);
2650
2651    /* Lowercase constant name in a separate literal */
2652    {
2653        zval c;
2654        zend_string *lcname = zend_string_tolower(name);
2655        ZVAL_NEW_STR(&c, lcname);
2656        zend_add_literal(CG(active_op_array), &c);
2657    }
2658    return SUCCESS;
2659}
2660/* }}} */
2661
2662static int zend_try_compile_ct_bound_init_user_func(zend_ast *name_ast, uint32_t num_args) /* {{{ */
2663{
2664    zend_string *name, *lcname;
2665    zend_function *fbc;
2666    zend_op *opline;
2667
2668    if (name_ast->kind != ZEND_AST_ZVAL || Z_TYPE_P(zend_ast_get_zval(name_ast)) != IS_STRING) {
2669        return FAILURE;
2670    }
2671
2672    name = zend_ast_get_str(name_ast);
2673    lcname = zend_string_tolower(name);
2674
2675    fbc = zend_hash_find_ptr(CG(function_table), lcname);
2676    if (!fbc || (fbc->type == ZEND_INTERNAL_FUNCTION &&
2677        (CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS))
2678    ) {
2679        zend_string_release(lcname);
2680        return FAILURE;
2681    }
2682
2683    opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, NULL);
2684    opline->extended_value = num_args;
2685    opline->op1.num = zend_vm_calc_used_stack(num_args, fbc);
2686    opline->op2_type = IS_CONST;
2687    LITERAL_STR(opline->op2, lcname);
2688    zend_alloc_cache_slot(opline->op2.constant);
2689
2690    return SUCCESS;
2691}
2692/* }}} */
2693
2694static void zend_compile_init_user_func(zend_ast *name_ast, uint32_t num_args, zend_string *orig_func_name) /* {{{ */
2695{
2696    zend_op *opline;
2697    znode name_node;
2698
2699    if (zend_try_compile_ct_bound_init_user_func(name_ast, num_args) == SUCCESS) {
2700        return;
2701    }
2702
2703    zend_compile_expr(&name_node, name_ast);
2704
2705    opline = zend_emit_op(NULL, ZEND_INIT_USER_CALL, NULL, &name_node);
2706    opline->op1_type = IS_CONST;
2707    LITERAL_STR(opline->op1, zend_string_copy(orig_func_name));
2708    opline->extended_value = num_args;
2709}
2710/* }}} */
2711
2712/* cufa = call_user_func_array */
2713int zend_compile_func_cufa(znode *result, zend_ast_list *args, zend_string *lcname) /* {{{ */
2714{
2715    znode arg_node;
2716
2717    if (args->children != 2 || zend_args_contain_unpack(args)) {
2718        return FAILURE;
2719    }
2720
2721    zend_compile_init_user_func(args->child[0], 0, lcname);
2722    zend_compile_expr(&arg_node, args->child[1]);
2723    zend_emit_op(NULL, ZEND_SEND_ARRAY, &arg_node, NULL);
2724    zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL);
2725
2726    return SUCCESS;
2727}
2728/* }}} */
2729
2730/* cuf = call_user_func */
2731int zend_compile_func_cuf(znode *result, zend_ast_list *args, zend_string *lcname) /* {{{ */
2732{
2733    uint32_t i;
2734
2735    if (args->children < 1 || zend_args_contain_unpack(args)) {
2736        return FAILURE;
2737    }
2738
2739    zend_compile_init_user_func(args->child[0], args->children - 1, lcname);
2740    for (i = 1; i < args->children; ++i) {
2741        zend_ast *arg_ast = args->child[i];
2742        znode arg_node;
2743        zend_op *opline;
2744        zend_bool send_user = 0;
2745
2746        if (zend_is_variable(arg_ast) && !zend_is_call(arg_ast)) {
2747            zend_compile_var(&arg_node, arg_ast, BP_VAR_FUNC_ARG | (i << BP_VAR_SHIFT));
2748            send_user = 1;
2749        } else {
2750            zend_compile_expr(&arg_node, arg_ast);
2751            if (arg_node.op_type & (IS_VAR|IS_CV)) {
2752                send_user = 1;
2753            }
2754        }
2755
2756        if (send_user) {
2757            opline = zend_emit_op(NULL, ZEND_SEND_USER, &arg_node, NULL);
2758        } else {
2759            opline = zend_emit_op(NULL, ZEND_SEND_VAL, &arg_node, NULL);
2760        }
2761
2762        opline->op2.num = i;
2763        opline->result.var = (uint32_t)(zend_intptr_t)ZEND_CALL_ARG(NULL, i);
2764    }
2765    zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL);
2766
2767    return SUCCESS;
2768}
2769/* }}} */
2770
2771int zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_list *args) /* {{{ */
2772{
2773    if (zend_string_equals_literal(lcname, "strlen")) {
2774        return zend_compile_func_strlen(result, args);
2775    } else if (zend_string_equals_literal(lcname, "is_null")) {
2776        return zend_compile_func_typecheck(result, args, IS_NULL);
2777    } else if (zend_string_equals_literal(lcname, "is_bool")) {
2778        return zend_compile_func_typecheck(result, args, _IS_BOOL);
2779    } else if (zend_string_equals_literal(lcname, "is_long")
2780        || zend_string_equals_literal(lcname, "is_int")
2781        || zend_string_equals_literal(lcname, "is_integer")
2782    ) {
2783        return zend_compile_func_typecheck(result, args, IS_LONG);
2784    } else if (zend_string_equals_literal(lcname, "is_float")
2785        || zend_string_equals_literal(lcname, "is_double")
2786        || zend_string_equals_literal(lcname, "is_real")
2787    ) {
2788        return zend_compile_func_typecheck(result, args, IS_DOUBLE);
2789    } else if (zend_string_equals_literal(lcname, "is_string")) {
2790        return zend_compile_func_typecheck(result, args, IS_STRING);
2791    } else if (zend_string_equals_literal(lcname, "is_array")) {
2792        return zend_compile_func_typecheck(result, args, IS_ARRAY);
2793    } else if (zend_string_equals_literal(lcname, "is_object")) {
2794        return zend_compile_func_typecheck(result, args, IS_OBJECT);
2795    } else if (zend_string_equals_literal(lcname, "is_resource")) {
2796        return zend_compile_func_typecheck(result, args, IS_RESOURCE);
2797    } else if (zend_string_equals_literal(lcname, "defined")) {
2798        return zend_compile_func_defined(result, args);
2799    } else if (zend_string_equals_literal(lcname, "call_user_func_array")) {
2800        return zend_compile_func_cufa(result, args, lcname);
2801    } else if (zend_string_equals_literal(lcname, "call_user_func")) {
2802        return zend_compile_func_cuf(result, args, lcname);
2803    } else {
2804        return FAILURE;
2805    }
2806}
2807/* }}} */
2808
2809void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
2810{
2811    zend_ast *name_ast = ast->child[0];
2812    zend_ast *args_ast = ast->child[1];
2813
2814    znode name_node;
2815
2816    if (name_ast->kind != ZEND_AST_ZVAL || Z_TYPE_P(zend_ast_get_zval(name_ast)) != IS_STRING) {
2817        zend_compile_expr(&name_node, name_ast);
2818        zend_compile_dynamic_call(result, &name_node, args_ast);
2819        return;
2820    }
2821
2822    {
2823        zend_bool runtime_resolution = zend_compile_function_name(&name_node, name_ast);
2824        if (runtime_resolution) {
2825            zend_compile_ns_call(result, &name_node, args_ast);
2826            return;
2827        }
2828    }
2829
2830    {
2831        zval *name = &name_node.u.constant;
2832        zend_string *lcname;
2833        zend_function *fbc;
2834        zend_op *opline;
2835
2836        lcname = zend_string_tolower(Z_STR_P(name));
2837
2838        fbc = zend_hash_find_ptr(CG(function_table), lcname);
2839        if (!fbc || (fbc->type == ZEND_INTERNAL_FUNCTION &&
2840            (CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS))
2841        ) {
2842            zend_string_release(lcname);
2843            zend_compile_dynamic_call(result, &name_node, args_ast);
2844            return;
2845        }
2846
2847        if (zend_try_compile_special_func(result, lcname,
2848                zend_ast_get_list(args_ast)) == SUCCESS
2849        ) {
2850            zend_string_release(lcname);
2851            zval_ptr_dtor(&name_node.u.constant);
2852            return;
2853        }
2854
2855        zval_ptr_dtor(&name_node.u.constant);
2856        ZVAL_NEW_STR(&name_node.u.constant, lcname);
2857
2858        opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, &name_node);
2859        zend_alloc_cache_slot(opline->op2.constant);
2860
2861        zend_compile_call_common(result, args_ast, fbc);
2862    }
2863}
2864/* }}} */
2865
2866void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
2867{
2868    zend_ast *obj_ast = ast->child[0];
2869    zend_ast *method_ast = ast->child[1];
2870    zend_ast *args_ast = ast->child[2];
2871
2872    znode obj_node, method_node;
2873    zend_op *opline;
2874
2875    if (is_this_fetch(obj_ast)) {
2876        obj_node.op_type = IS_UNUSED;
2877    } else {
2878        zend_compile_expr(&obj_node, obj_ast);
2879    }
2880
2881    zend_compile_expr(&method_node, method_ast);
2882    opline = zend_emit_op(NULL, ZEND_INIT_METHOD_CALL, &obj_node, NULL);
2883
2884    if (method_node.op_type == IS_CONST) {
2885        if (Z_TYPE(method_node.u.constant) != IS_STRING) {
2886            zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string");
2887        }
2888
2889        opline->op2_type = IS_CONST;
2890        opline->op2.constant = zend_add_func_name_literal(CG(active_op_array),
2891            Z_STR(method_node.u.constant));
2892        zend_alloc_polymorphic_cache_slot(opline->op2.constant);
2893    } else {
2894        SET_NODE(opline->op2, &method_node);
2895    }
2896
2897    zend_compile_call_common(result, args_ast, NULL);
2898}
2899/* }}} */
2900
2901zend_bool zend_is_constructor(zend_string *name) /* {{{ */
2902{
2903    return zend_string_equals_literal_ci(name, ZEND_CONSTRUCTOR_FUNC_NAME);
2904}
2905/* }}} */
2906
2907void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
2908{
2909    zend_ast *class_ast = ast->child[0];
2910    zend_ast *method_ast = ast->child[1];
2911    zend_ast *args_ast = ast->child[2];
2912
2913    znode class_node, method_node;
2914    zend_op *opline;
2915    zend_ulong extended_value = 0;
2916
2917    if (zend_is_const_default_class_ref(class_ast)) {
2918        class_node.op_type = IS_CONST;
2919        ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast));
2920    } else {
2921        opline = zend_compile_class_ref(&class_node, class_ast);
2922        extended_value = opline->extended_value;
2923    }
2924
2925    zend_compile_expr(&method_node, method_ast);
2926    if (method_node.op_type == IS_CONST) {
2927        zval *name = &method_node.u.constant;
2928        if (Z_TYPE_P(name) != IS_STRING) {
2929            zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string");
2930        }
2931        if (zend_is_constructor(Z_STR_P(name))) {
2932            zval_ptr_dtor(name);
2933            method_node.op_type = IS_UNUSED;
2934        }
2935    }
2936
2937    opline = get_next_op(CG(active_op_array));
2938    opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
2939    opline->extended_value = extended_value;
2940
2941    zend_set_class_name_op1(opline, &class_node);
2942
2943    if (method_node.op_type == IS_CONST) {
2944        opline->op2_type = IS_CONST;
2945        opline->op2.constant = zend_add_func_name_literal(CG(active_op_array),
2946            Z_STR(method_node.u.constant));
2947        if (opline->op1_type == IS_CONST) {
2948            zend_alloc_cache_slot(opline->op2.constant);
2949        } else {
2950            zend_alloc_polymorphic_cache_slot(opline->op2.constant);
2951        }
2952    } else {
2953        SET_NODE(opline->op2, &method_node);
2954    }
2955
2956    zend_compile_call_common(result, args_ast, NULL);
2957}
2958/* }}} */
2959
2960void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */
2961{
2962    zend_ast *class_ast = ast->child[0];
2963    zend_ast *args_ast = ast->child[1];
2964
2965    znode class_node, ctor_result;
2966    zend_op *opline;
2967    uint32_t opnum;
2968
2969    if (zend_is_const_default_class_ref(class_ast)) {
2970        class_node.op_type = IS_CONST;
2971        ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast));
2972    } else {
2973        zend_compile_class_ref(&class_node, class_ast);
2974    }
2975
2976    opnum = get_next_op_number(CG(active_op_array));
2977    opline = zend_emit_op(result, ZEND_NEW, NULL, NULL);
2978
2979    if (class_node.op_type == IS_CONST) {
2980        opline->op1_type = IS_CONST;
2981        opline->op1.constant = zend_add_class_name_literal(
2982            CG(active_op_array), Z_STR(class_node.u.constant));
2983    } else {
2984        SET_NODE(opline->op1, &class_node);
2985    }
2986
2987    zend_compile_call_common(&ctor_result, args_ast, NULL);
2988    zend_do_free(&ctor_result);
2989
2990    /* New jumps over ctor call if ctor does not exist */
2991    opline = &CG(active_op_array)->opcodes[opnum];
2992    opline->op2.opline_num = get_next_op_number(CG(active_op_array));
2993}
2994/* }}} */
2995
2996void zend_compile_clone(znode *result, zend_ast *ast) /* {{{ */
2997{
2998    zend_ast *obj_ast = ast->child[0];
2999
3000    znode obj_node;
3001    zend_compile_expr(&obj_node, obj_ast);
3002
3003    zend_emit_op(result, ZEND_CLONE, &obj_node, NULL);
3004}
3005/* }}} */
3006
3007void zend_compile_global_var(zend_ast *ast) /* {{{ */
3008{
3009    zend_ast *var_ast = ast->child[0];
3010    zend_ast *name_ast = var_ast->child[0];
3011
3012    znode name_node, result;
3013
3014    zend_compile_expr(&name_node, name_ast);
3015    if (name_node.op_type == IS_CONST) {
3016        convert_to_string(&name_node.u.constant);
3017    }
3018
3019    if (zend_try_compile_cv(&result, var_ast) == SUCCESS) {
3020        zend_op *opline = zend_emit_op(NULL, ZEND_BIND_GLOBAL, &result, &name_node);
3021        zend_alloc_cache_slot(opline->op2.constant);
3022    } else {
3023        zend_emit_op(&result, ZEND_FETCH_W, &name_node, NULL);
3024
3025        // TODO.AST Avoid double fetch
3026        //opline->extended_value = ZEND_FETCH_GLOBAL_LOCK;
3027
3028        zend_emit_assign_ref_znode(var_ast, &result);
3029    }
3030}
3031/* }}} */
3032
3033static void zend_compile_static_var_common(zend_ast *var_ast, zval *value, zend_bool by_ref) /* {{{ */
3034{
3035    znode var_node, result;
3036    zend_op *opline;
3037
3038    zend_compile_expr(&var_node, var_ast);
3039
3040    if (!CG(active_op_array)->static_variables) {
3041        if (CG(active_op_array)->scope) {
3042            CG(active_op_array)->scope->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
3043        }
3044        ALLOC_HASHTABLE(CG(active_op_array)->static_variables);
3045        zend_hash_init(CG(active_op_array)->static_variables, 8, NULL, ZVAL_PTR_DTOR, 0);
3046    }
3047
3048    zend_hash_update(CG(active_op_array)->static_variables, Z_STR(var_node.u.constant), value);
3049
3050    opline = zend_emit_op(&result, by_ref ? ZEND_FETCH_W : ZEND_FETCH_R, &var_node, NULL);
3051    opline->extended_value = ZEND_FETCH_STATIC;
3052
3053    if (by_ref) {
3054        zend_ast *fetch_ast = zend_ast_create(ZEND_AST_VAR, var_ast);
3055        zend_emit_assign_ref_znode(fetch_ast, &result);
3056    } else {
3057        zend_ast *fetch_ast = zend_ast_create(ZEND_AST_VAR, var_ast);
3058        zend_emit_assign_znode(fetch_ast, &result);
3059    }
3060}
3061/* }}} */
3062
3063void zend_compile_static_var(zend_ast *ast) /* {{{ */
3064{
3065    zend_ast *var_ast = ast->child[0];
3066    zend_ast *value_ast = ast->child[1];
3067    zval value_zv;
3068
3069    if (value_ast) {
3070        zend_const_expr_to_zval(&value_zv, value_ast);
3071    } else {
3072        ZVAL_NULL(&value_zv);
3073    }
3074
3075    zend_compile_static_var_common(var_ast, &value_zv, 1);
3076}
3077/* }}} */
3078
3079void zend_compile_unset(zend_ast *ast) /* {{{ */
3080{
3081    zend_ast *var_ast = ast->child[0];
3082
3083    znode var_node;
3084    zend_op *opline;
3085    switch (var_ast->kind) {
3086        case ZEND_AST_VAR:
3087            if (zend_try_compile_cv(&var_node, var_ast) == SUCCESS) {
3088                opline = zend_emit_op(NULL, ZEND_UNSET_VAR, &var_node, NULL);
3089                opline->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
3090            } else {
3091                opline = zend_compile_simple_var_no_cv(NULL, var_ast, BP_VAR_UNSET);
3092                opline->opcode = ZEND_UNSET_VAR;
3093            }
3094            return;
3095        case ZEND_AST_DIM:
3096            opline = zend_compile_dim_common(NULL, var_ast, BP_VAR_UNSET);
3097            opline->opcode = ZEND_UNSET_DIM;
3098            return;
3099        case ZEND_AST_PROP:
3100            opline = zend_compile_prop_common(NULL, var_ast, BP_VAR_UNSET);
3101            opline->opcode = ZEND_UNSET_OBJ;
3102            return;
3103        case ZEND_AST_STATIC_PROP:
3104            opline = zend_compile_static_prop_common(NULL, var_ast, BP_VAR_UNSET);
3105            opline->opcode = ZEND_UNSET_VAR;
3106            return;
3107        EMPTY_SWITCH_DEFAULT_CASE()
3108    }
3109}
3110/* }}} */
3111
3112static void zend_free_foreach_and_switch_variables(void) /* {{{ */
3113{
3114    uint32_t opnum_start, opnum_end, i;
3115
3116    opnum_start = get_next_op_number(CG(active_op_array));
3117
3118    zend_stack_apply(&CG(loop_var_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_loop_var);
3119
3120    opnum_end = get_next_op_number(CG(active_op_array));
3121
3122    for (i = opnum_start; i < opnum_end; ++i) {
3123        CG(active_op_array)->opcodes[i].extended_value |= EXT_TYPE_FREE_ON_RETURN;
3124    }
3125}
3126/* }}} */
3127
3128
3129void zend_compile_return(zend_ast *ast) /* {{{ */
3130{
3131    zend_ast *expr_ast = ast->child[0];
3132    zend_bool by_ref = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
3133
3134    znode expr_node;
3135    zend_op *opline;
3136
3137    if (!expr_ast) {
3138        expr_node.op_type = IS_CONST;
3139        ZVAL_NULL(&expr_node.u.constant);
3140    } else if (by_ref && zend_is_variable(expr_ast) && !zend_is_call(expr_ast)) {
3141        zend_compile_var(&expr_node, expr_ast, BP_VAR_REF);
3142    } else {
3143        zend_compile_expr(&expr_node, expr_ast);
3144    }
3145
3146    zend_free_foreach_and_switch_variables();
3147
3148    if (CG(context).in_finally) {
3149        opline = zend_emit_op(NULL, ZEND_DISCARD_EXCEPTION, NULL, NULL);
3150        opline->op1_type = IS_TMP_VAR;
3151        opline->op1.var = CG(context).fast_call_var;
3152    }
3153
3154    if (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
3155        zend_emit_return_type_check(&expr_node, CG(active_op_array)->arg_info - 1);
3156        if (expr_node.op_type == IS_CONST) {
3157            zval_copy_ctor(&expr_node.u.constant);
3158        }
3159    }
3160    opline = zend_emit_op(NULL, by_ref ? ZEND_RETURN_BY_REF : ZEND_RETURN,
3161        &expr_node, NULL);
3162
3163    if (expr_ast) {
3164        if (zend_is_call(expr_ast)) {
3165            opline->extended_value = ZEND_RETURNS_FUNCTION;
3166        } else if (by_ref && !zend_is_variable(expr_ast)) {
3167            opline->extended_value = ZEND_RETURNS_VALUE;
3168        }
3169    }
3170}
3171/* }}} */
3172
3173void zend_compile_echo(zend_ast *ast) /* {{{ */
3174{
3175    zend_ast *expr_ast = ast->child[0];
3176
3177    znode expr_node;
3178    zend_compile_expr(&expr_node, expr_ast);
3179
3180    zend_emit_op(NULL, ZEND_ECHO, &expr_node, NULL);
3181}
3182/* }}} */
3183
3184void zend_compile_throw(zend_ast *ast) /* {{{ */
3185{
3186    zend_ast *expr_ast = ast->child[0];
3187
3188    znode expr_node;
3189    zend_compile_expr(&expr_node, expr_ast);
3190
3191    zend_emit_op(NULL, ZEND_THROW, &expr_node, NULL);
3192}
3193/* }}} */
3194
3195void zend_compile_break_continue(zend_ast *ast) /* {{{ */
3196{
3197    zend_ast *depth_ast = ast->child[0];
3198
3199    znode depth_node;
3200    zend_op *opline;
3201
3202    ZEND_ASSERT(ast->kind == ZEND_AST_BREAK || ast->kind == ZEND_AST_CONTINUE);
3203
3204    if (depth_ast) {
3205        if (depth_ast->kind != ZEND_AST_ZVAL) {
3206            zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator with non-constant operand "
3207                "is no longer supported", ast->kind == ZEND_AST_BREAK ? "break" : "continue");
3208        }
3209
3210        zend_compile_expr(&depth_node, depth_ast);
3211
3212        if (Z_TYPE(depth_node.u.constant) != IS_LONG || Z_LVAL(depth_node.u.constant) < 1) {
3213            zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator accepts only positive numbers",
3214                ast->kind == ZEND_AST_BREAK ? "break" : "continue");
3215        }
3216    } else {
3217        depth_node.op_type = IS_CONST;
3218        ZVAL_LONG(&depth_node.u.constant, 1);
3219    }
3220
3221    opline = zend_emit_op(NULL, ast->kind == ZEND_AST_BREAK ? ZEND_BRK : ZEND_CONT,
3222        NULL, &depth_node);
3223    opline->op1.opline_num = CG(context).current_brk_cont;
3224}
3225/* }}} */
3226
3227void zend_compile_goto(zend_ast *ast) /* {{{ */
3228{
3229    zend_ast *label_ast = ast->child[0];
3230    znode label_node;
3231    zend_op *opline;
3232
3233    zend_compile_expr(&label_node, label_ast);
3234    opline = zend_emit_op(NULL, ZEND_GOTO, NULL, &label_node);
3235    opline->extended_value = CG(context).current_brk_cont;
3236    zend_resolve_goto_label(CG(active_op_array), opline, 0);
3237}
3238/* }}} */
3239
3240void zend_compile_label(zend_ast *ast) /* {{{ */
3241{
3242    zend_string *label = zend_ast_get_str(ast->child[0]);
3243    zend_label dest;
3244
3245    if (!CG(context).labels) {
3246        ALLOC_HASHTABLE(CG(context).labels);
3247        zend_hash_init(CG(context).labels, 8, NULL, ptr_dtor, 0);
3248    }
3249
3250    dest.brk_cont = CG(context).current_brk_cont;
3251    dest.opline_num = get_next_op_number(CG(active_op_array));
3252
3253    if (!zend_hash_add_mem(CG(context).labels, label, &dest, sizeof(zend_label))) {
3254        zend_error_noreturn(E_COMPILE_ERROR, "Label '%s' already defined", label->val);
3255    }
3256}
3257/* }}} */
3258
3259void zend_compile_while(zend_ast *ast) /* {{{ */
3260{
3261    zend_ast *cond_ast = ast->child[0];
3262    zend_ast *stmt_ast = ast->child[1];
3263    znode cond_node;
3264    uint32_t opnum_start, opnum_jmp, opnum_cond;
3265
3266    opnum_jmp = zend_emit_jump(0);
3267
3268    zend_begin_loop();
3269
3270    opnum_start = get_next_op_number(CG(active_op_array));
3271    zend_compile_stmt(stmt_ast);
3272
3273    opnum_cond = get_next_op_number(CG(active_op_array));
3274    zend_update_jump_target(opnum_jmp, opnum_cond);
3275    zend_compile_expr(&cond_node, cond_ast);
3276
3277    zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, opnum_start);
3278
3279    zend_end_loop(opnum_cond, 0);
3280}
3281/* }}} */
3282
3283void zend_compile_do_while(zend_ast *ast) /* {{{ */
3284{
3285    zend_ast *stmt_ast = ast->child[0];
3286    zend_ast *cond_ast = ast->child[1];
3287
3288    znode cond_node;
3289    uint32_t opnum_start, opnum_cond;
3290
3291    zend_begin_loop();
3292
3293    opnum_start = get_next_op_number(CG(active_op_array));
3294    zend_compile_stmt(stmt_ast);
3295
3296    opnum_cond = get_next_op_number(CG(active_op_array));
3297    zend_compile_expr(&cond_node, cond_ast);
3298
3299    zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, opnum_start);
3300
3301    zend_end_loop(opnum_cond, 0);
3302}
3303/* }}} */
3304
3305void zend_compile_expr_list(znode *result, zend_ast *ast) /* {{{ */
3306{
3307    zend_ast_list *list;
3308    uint32_t i;
3309
3310    result->op_type = IS_CONST;
3311    ZVAL_TRUE(&result->u.constant);
3312
3313    if (!ast) {
3314        return;
3315    }
3316
3317    list = zend_ast_get_list(ast);
3318    for (i = 0; i < list->children; ++i) {
3319        zend_ast *expr_ast = list->child[i];
3320
3321        zend_do_free(result);
3322        zend_compile_expr(result, expr_ast);
3323    }
3324}
3325/* }}} */
3326
3327void zend_compile_for(zend_ast *ast) /* {{{ */
3328{
3329    zend_ast *init_ast = ast->child[0];
3330    zend_ast *cond_ast = ast->child[1];
3331    zend_ast *loop_ast = ast->child[2];
3332    zend_ast *stmt_ast = ast->child[3];
3333
3334    znode result;
3335    uint32_t opnum_start, opnum_jmp, opnum_loop;
3336
3337    zend_compile_expr_list(&result, init_ast);
3338    zend_do_free(&result);
3339
3340    opnum_jmp = zend_emit_jump(0);
3341
3342    zend_begin_loop();
3343
3344    opnum_start = get_next_op_number(CG(active_op_array));
3345    zend_compile_stmt(stmt_ast);
3346
3347    opnum_loop = get_next_op_number(CG(active_op_array));
3348    zend_compile_expr_list(&result, loop_ast);
3349    zend_do_free(&result);
3350
3351    zend_update_jump_target_to_next(opnum_jmp);
3352    zend_compile_expr_list(&result, cond_ast);
3353    zend_do_extended_info();
3354
3355    zend_emit_cond_jump(ZEND_JMPNZ, &result, opnum_start);
3356
3357    zend_end_loop(opnum_loop, 0);
3358}
3359/* }}} */
3360
3361void zend_compile_foreach(zend_ast *ast) /* {{{ */
3362{
3363    zend_ast *expr_ast = ast->child[0];
3364    zend_ast *value_ast = ast->child[1];
3365    zend_ast *key_ast = ast->child[2];
3366    zend_ast *stmt_ast = ast->child[3];
3367    zend_bool by_ref = value_ast->kind == ZEND_AST_REF;
3368    zend_bool is_variable = zend_is_variable(expr_ast) && !zend_is_call(expr_ast)
3369        && zend_can_write_to_variable(expr_ast);
3370
3371    znode expr_node, reset_node, value_node, key_node;
3372    zend_op *opline;
3373    uint32_t opnum_reset, opnum_fetch;
3374
3375    if (key_ast) {
3376        if (key_ast->kind == ZEND_AST_REF) {
3377            zend_error_noreturn(E_COMPILE_ERROR, "Key element cannot be a reference");
3378        }
3379        if (key_ast->kind == ZEND_AST_LIST) {
3380            zend_error_noreturn(E_COMPILE_ERROR, "Cannot use list as key element");
3381        }
3382    }
3383
3384    if (by_ref) {
3385        value_ast = value_ast->child[0];
3386    }
3387
3388    if (by_ref && is_variable) {
3389        zend_compile_var(&expr_node, expr_ast, BP_VAR_W);
3390    } else {
3391        zend_compile_expr(&expr_node, expr_ast);
3392    }
3393
3394    if (by_ref) {
3395        zend_separate_if_call_and_write(&expr_node, expr_ast, BP_VAR_W);
3396    }
3397
3398    opnum_reset = get_next_op_number(CG(active_op_array));
3399    opline = zend_emit_op(&reset_node, ZEND_FE_RESET, &expr_node, NULL);
3400    if (by_ref && is_variable) {
3401        opline->extended_value = ZEND_FE_FETCH_BYREF;
3402    }
3403
3404    zend_stack_push(&CG(loop_var_stack), &reset_node);
3405
3406    opnum_fetch = get_next_op_number(CG(active_op_array));
3407    opline = zend_emit_op(&value_node, ZEND_FE_FETCH, &reset_node, NULL);
3408    if (by_ref) {
3409        opline->extended_value |= ZEND_FE_FETCH_BYREF;
3410    }
3411    if (key_ast) {
3412        opline->extended_value |= ZEND_FE_FETCH_WITH_KEY;
3413    }
3414
3415    opline = zend_emit_op(NULL, ZEND_OP_DATA, NULL, NULL);
3416
3417    /* Allocate enough space to keep HashPointer on VM stack */
3418    opline->op1_type = IS_TMP_VAR;
3419    opline->op1.var = get_temporary_variable(CG(active_op_array));
3420    if (sizeof(HashPointer) > sizeof(zval)) {
3421        /* Make sure 1 zval is enough for HashPointer (2 must be enough) */
3422        get_temporary_variable(CG(active_op_array));
3423    }
3424
3425    if (key_ast) {
3426        zend_make_tmp_result(&key_node, opline);
3427    }
3428
3429    if (by_ref) {
3430        zend_emit_assign_ref_znode(value_ast, &value_node);
3431    } else {
3432        zend_emit_assign_znode(value_ast, &value_node);
3433    }
3434
3435    if (key_ast) {
3436        zend_emit_assign_znode(key_ast, &key_node);
3437    }
3438
3439    zend_begin_loop();
3440
3441    zend_compile_stmt(stmt_ast);
3442
3443    zend_emit_jump(opnum_fetch);
3444
3445    opline = &CG(active_op_array)->opcodes[opnum_reset];
3446    opline->op2.opline_num = get_next_op_number(CG(active_op_array));
3447
3448    opline = &CG(active_op_array)->opcodes[opnum_fetch];
3449    opline->op2.opline_num = get_next_op_number(CG(active_op_array));
3450
3451    zend_end_loop(opnum_fetch, 1);
3452
3453    generate_free_loop_var(&reset_node);
3454    zend_stack_del_top(&CG(loop_var_stack));
3455}
3456/* }}} */
3457
3458void zend_compile_if(zend_ast *ast) /* {{{ */
3459{
3460    zend_ast_list *list = zend_ast_get_list(ast);
3461    uint32_t i;
3462    uint32_t *jmp_opnums = NULL;
3463
3464    if (list->children > 1) {
3465        jmp_opnums = safe_emalloc(sizeof(uint32_t), list->children - 1, 0);
3466    }
3467
3468    for (i = 0; i < list->children; ++i) {
3469        zend_ast *elem_ast = list->child[i];
3470        zend_ast *cond_ast = elem_ast->child[0];
3471        zend_ast *stmt_ast = elem_ast->child[1];
3472
3473        znode cond_node;
3474        uint32_t opnum_jmpz;
3475        if (cond_ast) {
3476            zend_compile_expr(&cond_node, cond_ast);
3477            opnum_jmpz = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0);
3478        }
3479
3480        zend_compile_stmt(stmt_ast);
3481
3482        if (i != list->children - 1) {
3483            jmp_opnums[i] = zend_emit_jump(0);
3484        }
3485
3486        if (cond_ast) {
3487            zend_update_jump_target_to_next(opnum_jmpz);
3488        }
3489    }
3490
3491    if (list->children > 1) {
3492        for (i = 0; i < list->children - 1; ++i) {
3493            zend_update_jump_target_to_next(jmp_opnums[i]);
3494        }
3495        efree(jmp_opnums);
3496    }
3497}
3498/* }}} */
3499
3500void zend_compile_switch(zend_ast *ast) /* {{{ */
3501{
3502    zend_ast *expr_ast = ast->child[0];
3503    zend_ast_list *cases = zend_ast_get_list(ast->child[1]);
3504
3505    uint32_t i;
3506    zend_bool has_default_case = 0;
3507
3508    znode expr_node, case_node;
3509    zend_op *opline;
3510    uint32_t *jmpnz_opnums = safe_emalloc(sizeof(uint32_t), cases->children, 0);
3511    uint32_t opnum_default_jmp;
3512
3513    zend_compile_expr(&expr_node, expr_ast);
3514
3515    zend_stack_push(&CG(loop_var_stack), &expr_node);
3516
3517    zend_begin_loop();
3518
3519    case_node.op_type = IS_TMP_VAR;
3520    case_node.u.op.var = get_temporary_variable(CG(active_op_array));
3521
3522    for (i = 0; i < cases->children; ++i) {
3523        zend_ast *case_ast = cases->child[i];
3524        zend_ast *cond_ast = case_ast->child[0];
3525        znode cond_node;
3526
3527        if (!cond_ast) {
3528            if (has_default_case) {
3529                CG(zend_lineno) = case_ast->lineno;
3530                zend_error_noreturn(E_COMPILE_ERROR,
3531                    "Switch statements may only contain one default clause");
3532            }
3533            has_default_case = 1;
3534            continue;
3535        }
3536
3537        zend_compile_expr(&cond_node, cond_ast);
3538
3539        if (expr_node.op_type == IS_CONST
3540            && Z_TYPE(expr_node.u.constant) == IS_FALSE) {
3541            jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0);
3542        } else if (expr_node.op_type == IS_CONST
3543            && Z_TYPE(expr_node.u.constant) == IS_TRUE) {
3544            jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, 0);
3545        } else {
3546            opline = zend_emit_op(NULL, ZEND_CASE, &expr_node, &cond_node);
3547            SET_NODE(opline->result, &case_node);
3548            if (opline->op1_type == IS_CONST) {
3549                zval_copy_ctor(CT_CONSTANT(opline->op1));
3550            }
3551
3552            jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPNZ, &case_node, 0);
3553        }
3554    }
3555
3556    opnum_default_jmp = zend_emit_jump(0);
3557
3558    for (i = 0; i < cases->children; ++i) {
3559        zend_ast *case_ast = cases->child[i];
3560        zend_ast *cond_ast = case_ast->child[0];
3561        zend_ast *stmt_ast = case_ast->child[1];
3562
3563        if (cond_ast) {
3564            zend_update_jump_target_to_next(jmpnz_opnums[i]);
3565        } else {
3566            zend_update_jump_target_to_next(opnum_default_jmp);
3567        }
3568
3569        zend_compile_stmt(stmt_ast);
3570    }
3571
3572    if (!has_default_case) {
3573        zend_update_jump_target_to_next(opnum_default_jmp);
3574    }
3575
3576    zend_end_loop(get_next_op_number(CG(active_op_array)), 1);
3577
3578    if (expr_node.op_type == IS_VAR || expr_node.op_type == IS_TMP_VAR) {
3579        zend_emit_op(NULL, ZEND_FREE,
3580            &expr_node, NULL);
3581    } else if (expr_node.op_type == IS_CONST) {
3582        zval_dtor(&expr_node.u.constant);
3583    }
3584
3585    zend_stack_del_top(&CG(loop_var_stack));
3586    efree(jmpnz_opnums);
3587}
3588/* }}} */
3589
3590void zend_compile_try(zend_ast *ast) /* {{{ */
3591{
3592    zend_ast *try_ast = ast->child[0];
3593    zend_ast_list *catches = zend_ast_get_list(ast->child[1]);
3594    zend_ast *finally_ast = ast->child[2];
3595
3596    uint32_t i;
3597    zend_op *opline;
3598    uint32_t try_catch_offset = zend_add_try_element(
3599        get_next_op_number(CG(active_op_array)));
3600    uint32_t *jmp_opnums = safe_emalloc(sizeof(uint32_t), catches->children, 0);
3601
3602    if (catches->children == 0 && !finally_ast) {
3603        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use try without catch or finally");
3604    }
3605
3606    zend_compile_stmt(try_ast);
3607
3608    if (catches->children != 0) {
3609        jmp_opnums[0] = zend_emit_jump(0);
3610    }
3611
3612    for (i = 0; i < catches->children; ++i) {
3613        zend_ast *catch_ast = catches->child[i];
3614        zend_ast *class_ast = catch_ast->child[0];
3615        zend_ast *var_ast = catch_ast->child[1];
3616        zend_ast *stmt_ast = catch_ast->child[2];
3617        zval *var_name = zend_ast_get_zval(var_ast);
3618        zend_bool is_last_catch = (i + 1 == catches->children);
3619
3620        uint32_t opnum_catch;
3621
3622        if (!zend_is_const_default_class_ref(class_ast)) {
3623            zend_error_noreturn(E_COMPILE_ERROR, "Bad class name in the catch statement");
3624        }
3625
3626        opnum_catch = get_next_op_number(CG(active_op_array));
3627        if (i == 0) {
3628            CG(active_op_array)->try_catch_array[try_catch_offset].catch_op = opnum_catch;
3629        }
3630
3631        CG(zend_lineno) = catch_ast->lineno;
3632
3633        opline = get_next_op(CG(active_op_array));
3634        opline->opcode = ZEND_CATCH;
3635        opline->op1_type = IS_CONST;
3636        opline->op1.constant = zend_add_class_name_literal(CG(active_op_array),
3637            zend_resolve_class_name_ast(class_ast));
3638
3639        opline->op2_type = IS_CV;
3640        opline->op2.var = lookup_cv(CG(active_op_array), zend_string_copy(Z_STR_P(var_name)));
3641        opline->result.num = is_last_catch;
3642
3643        zend_compile_stmt(stmt_ast);
3644
3645        if (!is_last_catch) {
3646            jmp_opnums[i + 1] = zend_emit_jump(0);
3647        }
3648
3649        opline = &CG(active_op_array)->opcodes[opnum_catch];
3650        opline->extended_value = get_next_op_number(CG(active_op_array));
3651    }
3652
3653    for (i = 0; i < catches->children; ++i) {
3654        zend_update_jump_target_to_next(jmp_opnums[i]);
3655    }
3656
3657    if (finally_ast) {
3658        uint32_t opnum_jmp = get_next_op_number(CG(active_op_array)) + 1;
3659
3660        if (!(CG(active_op_array)->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK)) {
3661            CG(active_op_array)->fn_flags |= ZEND_ACC_HAS_FINALLY_BLOCK;
3662            CG(context).fast_call_var = get_temporary_variable(CG(active_op_array));
3663        }
3664
3665        opline = zend_emit_op(NULL, ZEND_FAST_CALL, NULL, NULL);
3666        opline->op1.opline_num = opnum_jmp + 1;
3667        opline->result_type = IS_TMP_VAR;
3668        opline->result.var = CG(context).fast_call_var;
3669
3670        zend_emit_op(NULL, ZEND_JMP, NULL, NULL);
3671
3672        CG(context).in_finally++;
3673        zend_compile_stmt(finally_ast);
3674        CG(context).in_finally--;
3675
3676        CG(active_op_array)->try_catch_array[try_catch_offset].finally_op = opnum_jmp + 1;
3677        CG(active_op_array)->try_catch_array[try_catch_offset].finally_end
3678            = get_next_op_number(CG(active_op_array));
3679
3680        opline = zend_emit_op(NULL, ZEND_FAST_RET, NULL, NULL);
3681        opline->op1_type = IS_TMP_VAR;
3682        opline->op1.var = CG(context).fast_call_var;
3683
3684        zend_update_jump_target_to_next(opnum_jmp);
3685    }
3686
3687    efree(jmp_opnums);
3688}
3689/* }}} */
3690
3691/* Encoding declarations must already be handled during parsing */
3692void zend_handle_encoding_declaration(zend_ast *ast) /* {{{ */
3693{
3694    zend_ast_list *declares = zend_ast_get_list(ast);
3695    uint32_t i;
3696    for (i = 0; i < declares->children; ++i) {
3697        zend_ast *declare_ast = declares->child[i];
3698        zend_ast *name_ast = declare_ast->child[0];
3699        zend_ast *value_ast = declare_ast->child[1];
3700        zend_string *name = zend_ast_get_str(name_ast);
3701
3702        if (zend_string_equals_literal_ci(name, "encoding")) {
3703            if (value_ast->kind != ZEND_AST_ZVAL) {
3704                zend_error_noreturn(E_COMPILE_ERROR, "Encoding must be a literal");
3705            }
3706
3707            if (CG(multibyte)) {
3708                zend_string *encoding_name = zval_get_string(zend_ast_get_zval(value_ast));
3709
3710                const zend_encoding *new_encoding, *old_encoding;
3711                zend_encoding_filter old_input_filter;
3712
3713                CG(encoding_declared) = 1;
3714
3715                new_encoding = zend_multibyte_fetch_encoding(encoding_name->val);
3716                if (!new_encoding) {
3717                    zend_error(E_COMPILE_WARNING, "Unsupported encoding [%s]", encoding_name->val);
3718                } else {
3719                    old_input_filter = LANG_SCNG(input_filter);
3720                    old_encoding = LANG_SCNG(script_encoding);
3721                    zend_multibyte_set_filter(new_encoding);
3722
3723                    /* need to re-scan if input filter changed */
3724                    if (old_input_filter != LANG_SCNG(input_filter) ||
3725                         (old_input_filter && new_encoding != old_encoding)) {
3726                        zend_multibyte_yyinput_again(old_input_filter, old_encoding);
3727                    }
3728                }
3729
3730                zend_string_release(encoding_name);
3731            } else {
3732                zend_error(E_COMPILE_WARNING, "declare(encoding=...) ignored because "
3733                    "Zend multibyte feature is turned off by settings");
3734            }
3735        }
3736    }
3737}
3738/* }}} */
3739
3740void zend_compile_declare(zend_ast *ast) /* {{{ */
3741{
3742    zend_ast_list *declares = zend_ast_get_list(ast->child[0]);
3743    zend_ast *stmt_ast = ast->child[1];
3744    zend_declarables orig_declarables = CG(declarables);
3745    uint32_t i;
3746
3747    for (i = 0; i < declares->children; ++i) {
3748        zend_ast *declare_ast = declares->child[i];
3749        zend_ast *name_ast = declare_ast->child[0];
3750        zend_ast *value_ast = declare_ast->child[1];
3751
3752        zend_string *name = zend_ast_get_str(name_ast);
3753        if (zend_string_equals_literal_ci(name, "ticks")) {
3754            zval value_zv;
3755            zend_const_expr_to_zval(&value_zv, value_ast);
3756            convert_to_long(&value_zv);
3757            ZVAL_COPY_VALUE(&CG(declarables).ticks, &value_zv);
3758            zval_dtor(&value_zv);
3759        } else if (zend_string_equals_literal_ci(name, "encoding")) {
3760            /* Encoding declaration was already handled during parsing. Here we
3761             * only check that it is the first statement in the file. */
3762            uint32_t num = CG(active_op_array)->last;
3763            while (num > 0 &&
3764                   (CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
3765                    CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
3766                --num;
3767            }
3768
3769            if (num > 0) {
3770                zend_error_noreturn(E_COMPILE_ERROR, "Encoding declaration pragma must be "
3771                    "the very first statement in the script");
3772            }
3773        } else {
3774            zend_error(E_COMPILE_WARNING, "Unsupported declare '%s'", name->val);
3775        }
3776    }
3777
3778    if (stmt_ast) {
3779        zend_compile_stmt(stmt_ast);
3780
3781        CG(declarables) = orig_declarables;
3782    }
3783}
3784/* }}} */
3785
3786void zend_compile_stmt_list(zend_ast *ast) /* {{{ */
3787{
3788    zend_ast_list *list = zend_ast_get_list(ast);
3789    uint32_t i;
3790    for (i = 0; i < list->children; ++i) {
3791        zend_compile_stmt(list->child[i]);
3792    }
3793}
3794/* }}} */
3795
3796void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, zend_bool is_method) /* {{{ */
3797{
3798    zend_ast_list *list = zend_ast_get_list(ast);
3799    uint32_t i;
3800    zend_op_array *op_array = CG(active_op_array);
3801    zend_arg_info *arg_infos;
3802
3803    if (return_type_ast) {
3804        /* Use op_array->arg_info[-1] for return type hinting */
3805        arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children + 1, 0);
3806        arg_infos->name = NULL;
3807        arg_infos->pass_by_reference = (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
3808        arg_infos->is_variadic = 0;
3809        arg_infos->type_hint = 0;
3810        arg_infos->allow_null = 0;
3811        arg_infos->class_name = NULL;
3812
3813        if (return_type_ast->kind == ZEND_AST_TYPE) {
3814            arg_infos->type_hint = return_type_ast->attr;
3815        } else {
3816            zend_string *class_name = zend_ast_get_str(return_type_ast);
3817
3818            if (zend_is_const_default_class_ref(return_type_ast)) {
3819                class_name = zend_resolve_class_name_ast(return_type_ast);
3820            } else {
3821                zend_string_addref(class_name);
3822                if (!is_method) {
3823                    zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare a return type of %s outside of a class scope", class_name->val);
3824                    return;
3825                }
3826            }
3827
3828            arg_infos->type_hint = IS_OBJECT;
3829            arg_infos->class_name = class_name;
3830        }
3831
3832        arg_infos++;
3833        op_array->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
3834    } else {
3835        if (list->children == 0) {
3836            return;
3837        }
3838        arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children, 0);
3839    }
3840
3841    for (i = 0; i < list->children; ++i) {
3842        zend_ast *param_ast = list->child[i];
3843        zend_ast *type_ast = param_ast->child[0];
3844        zend_ast *var_ast = param_ast->child[1];
3845        zend_ast *default_ast = param_ast->child[2];
3846        zend_string *name = zend_ast_get_str(var_ast);
3847        zend_bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0;
3848        zend_bool is_variadic = (param_ast->attr & ZEND_PARAM_VARIADIC) != 0;
3849
3850        znode var_node, default_node;
3851        zend_uchar opcode;
3852        zend_op *opline;
3853        zend_arg_info *arg_info;
3854
3855        if (zend_is_auto_global(name)) {
3856            zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign auto-global variable %s",
3857                name->val);
3858        }
3859
3860        var_node.op_type = IS_CV;
3861        var_node.u.op.var = lookup_cv(CG(active_op_array), zend_string_copy(name));
3862
3863        if (EX_VAR_TO_NUM(var_node.u.op.var) != i) {
3864            zend_error_noreturn(E_COMPILE_ERROR, "Redefinition of parameter $%s",
3865                name->val);
3866        } else if (zend_string_equals_literal(name, "this")) {
3867            if (op_array->scope && (op_array->fn_flags & ZEND_ACC_STATIC) == 0) {
3868                zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
3869            }
3870            op_array->this_var = var_node.u.op.var;
3871        }
3872
3873        if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
3874            zend_error_noreturn(E_COMPILE_ERROR, "Only the last parameter can be variadic");
3875        }
3876
3877        if (is_variadic) {
3878            opcode = ZEND_RECV_VARIADIC;
3879            default_node.op_type = IS_UNUSED;
3880            op_array->fn_flags |= ZEND_ACC_VARIADIC;
3881
3882            if (default_ast) {
3883                zend_error_noreturn(E_COMPILE_ERROR,
3884                    "Variadic parameter cannot have a default value");
3885            }
3886        } else if (default_ast) {
3887            opcode = ZEND_RECV_INIT;
3888            default_node.op_type = IS_CONST;
3889            zend_const_expr_to_zval(&default_node.u.constant, default_ast);
3890        } else {
3891            opcode = ZEND_RECV;
3892            default_node.op_type = IS_UNUSED;
3893            op_array->required_num_args = i + 1;
3894        }
3895
3896        opline = zend_emit_op(NULL, opcode, NULL, &default_node);
3897        SET_NODE(opline->result, &var_node);
3898        opline->op1.num = i + 1;
3899
3900        arg_info = &arg_infos[i];
3901        arg_info->name = zend_string_copy(name);
3902        arg_info->pass_by_reference = is_ref;
3903        arg_info->is_variadic = is_variadic;
3904        arg_info->type_hint = 0;
3905        arg_info->allow_null = 1;
3906        arg_info->class_name = NULL;
3907
3908        if (type_ast) {
3909            zend_bool has_null_default = default_ast
3910                && (Z_TYPE(default_node.u.constant) == IS_NULL
3911                    || (Z_TYPE(default_node.u.constant) == IS_CONSTANT
3912                        && strcasecmp(Z_STRVAL(default_node.u.constant), "NULL") == 0));
3913
3914            op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
3915            arg_info->allow_null = has_null_default;
3916
3917            if (type_ast->kind == ZEND_AST_TYPE) {
3918                arg_info->type_hint = type_ast->attr;
3919                if (arg_info->type_hint == IS_ARRAY) {
3920                    if (default_ast && !has_null_default
3921                        && Z_TYPE(default_node.u.constant) != IS_ARRAY
3922                        && !Z_CONSTANT(default_node.u.constant)
3923                    ) {
3924                        zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
3925                            "with array type hint can only be an array or NULL");
3926                    }
3927                } else if (arg_info->type_hint == IS_CALLABLE && default_ast) {
3928                    if (!has_null_default && !Z_CONSTANT(default_node.u.constant)) {
3929                        zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
3930                            "with callable type hint can only be NULL");
3931                    }
3932                }
3933            } else {
3934                zend_string *class_name = zend_ast_get_str(type_ast);
3935
3936                if (zend_is_const_default_class_ref(type_ast)) {
3937                    class_name = zend_resolve_class_name_ast(type_ast);
3938                } else {
3939                    zend_string_addref(class_name);
3940                }
3941
3942                arg_info->type_hint = IS_OBJECT;
3943                arg_info->class_name = class_name;
3944
3945                if (default_ast && !has_null_default && !Z_CONSTANT(default_node.u.constant)) {
3946                        zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
3947                            "with a class type hint can only be NULL");
3948                }
3949            }
3950        }
3951    }
3952
3953    /* These are assigned at the end to avoid unitialized memory in case of an error */
3954    op_array->num_args = list->children;
3955    op_array->arg_info = arg_infos;
3956
3957    /* Don't count the variadic argument */
3958    if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
3959        op_array->num_args--;
3960    }
3961}
3962/* }}} */
3963
3964void zend_compile_closure_uses(zend_ast *ast) /* {{{ */
3965{
3966    zend_ast_list *list = zend_ast_get_list(ast);
3967    uint32_t i;
3968
3969    for (i = 0; i < list->children; ++i) {
3970        zend_ast *var_ast = list->child[i];
3971        zend_string *name = zend_ast_get_str(var_ast);
3972        zend_bool by_ref = var_ast->attr;
3973        zval zv;
3974
3975        if (zend_string_equals_literal(name, "this")) {
3976            zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as lexical variable");
3977        }
3978
3979        ZVAL_NULL(&zv);
3980        Z_CONST_FLAGS(zv) = by_ref ? IS_LEXICAL_REF : IS_LEXICAL_VAR;
3981
3982        zend_compile_static_var_common(var_ast, &zv, by_ref);
3983    }
3984}
3985/* }}} */
3986
3987void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_bool has_body) /* {{{ */
3988{
3989    zend_class_entry *ce = CG(active_class_entry);
3990    zend_bool in_interface = (ce->ce_flags & ZEND_ACC_INTERFACE) != 0;
3991    zend_bool in_trait = ZEND_CE_IS_TRAIT(ce);
3992    zend_bool is_public = (op_array->fn_flags & ZEND_ACC_PUBLIC) != 0;
3993    zend_bool is_static = (op_array->fn_flags & ZEND_ACC_STATIC) != 0;
3994
3995    zend_string *lcname;
3996
3997    if (in_interface) {
3998        if ((op_array->fn_flags & ZEND_ACC_PPP_MASK) != ZEND_ACC_PUBLIC) {
3999            zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface method "
4000                "%s::%s() must be omitted", ce->name->val, name->val);
4001        }
4002        op_array->fn_flags |= ZEND_ACC_ABSTRACT;
4003    } else if (is_static && (op_array->fn_flags & ZEND_ACC_ABSTRACT)) {
4004        zend_error(E_STRICT, "Static function %s::%s() should not be abstract",
4005            ce->name->val, name->val);
4006    }
4007
4008    if (op_array->fn_flags & ZEND_ACC_ABSTRACT) {
4009        if (op_array->fn_flags & ZEND_ACC_PRIVATE) {
4010            zend_error_noreturn(E_COMPILE_ERROR, "%s function %s::%s() cannot be declared private",
4011                in_interface ? "Interface" : "Abstract", ce->name->val, name->val);
4012        }
4013
4014        if (has_body) {
4015            zend_error_noreturn(E_COMPILE_ERROR, "%s function %s::%s() cannot contain body",
4016                in_interface ? "Interface" : "Abstract", ce->name->val, name->val);
4017        }
4018
4019        ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
4020    } else if (!has_body) {
4021        zend_error_noreturn(E_COMPILE_ERROR, "Non-abstract method %s::%s() must contain body",
4022            ce->name->val, name->val);
4023    }
4024
4025    op_array->scope = ce;
4026    op_array->function_name = zend_string_copy(name);
4027
4028    lcname = zend_string_tolower(name);
4029    lcname = zend_new_interned_string(lcname);
4030
4031    if (zend_hash_add_ptr(&ce->function_table, lcname, op_array) == NULL) {
4032        zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::%s()",
4033            ce->name->val, name->val);
4034    }
4035
4036    if (in_interface) {
4037        if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) {
4038            if (!is_public || is_static) {
4039                zend_error(E_WARNING, "The magic method __call() must have "
4040                    "public visibility and cannot be static");
4041            }
4042        } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) {
4043            if (!is_public || !is_static) {
4044                zend_error(E_WARNING, "The magic method __callStatic() must have "
4045                    "public visibility and be static");
4046            }
4047        } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) {
4048            if (!is_public || is_static) {
4049                zend_error(E_WARNING, "The magic method __get() must have "
4050                    "public visibility and cannot be static");
4051            }
4052        } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) {
4053            if (!is_public || is_static) {
4054                zend_error(E_WARNING, "The magic method __set() must have "
4055                    "public visibility and cannot be static");
4056            }
4057        } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) {
4058            if (!is_public || is_static) {
4059                zend_error(E_WARNING, "The magic method __unset() must have "
4060                    "public visibility and cannot be static");
4061            }
4062        } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) {
4063            if (!is_public || is_static) {
4064                zend_error(E_WARNING, "The magic method __isset() must have "
4065                    "public visibility and cannot be static");
4066            }
4067        } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) {
4068            if (!is_public || is_static) {
4069                zend_error(E_WARNING, "The magic method __toString() must have "
4070                    "public visibility and cannot be static");
4071            }
4072        } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) {
4073            if (!is_public || is_static) {
4074                zend_error(E_WARNING, "The magic method __invoke() must have "
4075                    "public visibility and cannot be static");
4076            }
4077        } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) {
4078            if (!is_public || is_static) {
4079                zend_error(E_WARNING, "The magic method __debugInfo() must have "
4080                    "public visibility and cannot be static");
4081            }
4082        }
4083    } else {
4084        if (!in_trait && zend_string_equals_str_ci(lcname, ce->name)) {
4085            if (!ce->constructor) {
4086                ce->constructor = (zend_function *) op_array;
4087            }
4088        } else if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
4089            if (CG(active_class_entry)->constructor) {
4090                zend_error(E_STRICT, "Redefining already defined constructor for class %s",
4091                    ce->name->val);
4092            }
4093            ce->constructor = (zend_function *) op_array;
4094        } else if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) {
4095            ce->destructor = (zend_function *) op_array;
4096        } else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) {
4097            ce->clone = (zend_function *) op_array;
4098        } else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) {
4099            if (!is_public || is_static) {
4100                zend_error(E_WARNING, "The magic method __call() must have "
4101                    "public visibility and cannot be static");
4102            }
4103            ce->__call = (zend_function *) op_array;
4104        } else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) {
4105            if (!is_public || !is_static) {
4106                zend_error(E_WARNING, "The magic method __callStatic() must have "
4107                    "public visibility and be static");
4108            }
4109            ce->__callstatic = (zend_function *) op_array;
4110        } else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) {
4111            if (!is_public || is_static) {
4112                zend_error(E_WARNING, "The magic method __get() must have "
4113                    "public visibility and cannot be static");
4114            }
4115            ce->__get = (zend_function *) op_array;
4116        } else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) {
4117            if (!is_public || is_static) {
4118                zend_error(E_WARNING, "The magic method __set() must have "
4119                    "public visibility and cannot be static");
4120            }
4121            ce->__set = (zend_function *) op_array;
4122        } else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) {
4123            if (!is_public || is_static) {
4124                zend_error(E_WARNING, "The magic method __unset() must have "
4125                    "public visibility and cannot be static");
4126            }
4127            ce->__unset = (zend_function *) op_array;
4128        } else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) {
4129            if (!is_public || is_static) {
4130                zend_error(E_WARNING, "The magic method __isset() must have "
4131                    "public visibility and cannot be static");
4132            }
4133            ce->__isset = (zend_function *) op_array;
4134        } else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) {
4135            if (!is_public || is_static) {
4136                zend_error(E_WARNING, "The magic method __toString() must have "
4137                    "public visibility and cannot be static");
4138            }
4139            ce->__tostring = (zend_function *) op_array;
4140        } else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) {
4141            if (!is_public || is_static) {
4142                zend_error(E_WARNING, "The magic method __invoke() must have "
4143                    "public visibility and cannot be static");
4144            }
4145        } else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) {
4146            if (!is_public || is_static) {
4147                zend_error(E_WARNING, "The magic method __debugInfo() must have "
4148                    "public visibility and cannot be static");
4149            }
4150            ce->__debugInfo = (zend_function *) op_array;
4151        } else if (!is_static) {
4152            op_array->fn_flags |= ZEND_ACC_ALLOW_STATIC;
4153        }
4154    }
4155
4156    zend_string_release(lcname);
4157}
4158/* }}} */
4159
4160static void zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_ast_decl *decl) /* {{{ */
4161{
4162    zend_ast *params_ast = decl->child[0];
4163    zend_string *name = decl->name, *lcname;
4164    zend_op *opline;
4165
4166    op_array->function_name = name = zend_prefix_with_ns(name);
4167
4168    lcname = zend_string_tolower(name);
4169
4170    if (CG(current_import_function)) {
4171        zend_string *import_name = zend_hash_find_ptr(CG(current_import_function), lcname);
4172        if (import_name && !zend_string_equals_str_ci(lcname, import_name)) {
4173            zend_error(E_COMPILE_ERROR, "Cannot declare function %s "
4174                "because the name is already in use", name->val);
4175        }
4176    }
4177
4178    if (zend_string_equals_literal(lcname, ZEND_AUTOLOAD_FUNC_NAME)
4179        && zend_ast_get_list(params_ast)->children != 1
4180    ) {
4181        zend_error_noreturn(E_COMPILE_ERROR, "%s() must take exactly 1 argument",
4182            ZEND_AUTOLOAD_FUNC_NAME);
4183    }
4184
4185    if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
4186        opline = zend_emit_op_tmp(result, ZEND_DECLARE_LAMBDA_FUNCTION, NULL, NULL);
4187    } else {
4188        opline = get_next_op(CG(active_op_array));
4189        opline->opcode = ZEND_DECLARE_FUNCTION;
4190        opline->op2_type = IS_CONST;
4191        LITERAL_STR(opline->op2, zend_string_copy(lcname));
4192    }
4193
4194    {
4195        zend_string *key = zend_build_runtime_definition_key(lcname, decl->lex_pos);
4196
4197        opline->op1_type = IS_CONST;
4198        LITERAL_STR(opline->op1, key);
4199
4200        zend_hash_update_ptr(CG(function_table), key, op_array);
4201    }
4202
4203    zend_string_release(lcname);
4204}
4205/* }}} */
4206
4207void zend_compile_func_decl(znode *result, zend_ast *ast) /* {{{ */
4208{
4209    zend_ast_decl *decl = (zend_ast_decl *) ast;
4210    zend_ast *params_ast = decl->child[0];
4211    zend_ast *uses_ast = decl->child[1];
4212    zend_ast *stmt_ast = decl->child[2];
4213    zend_ast *return_type_ast = decl->child[3];
4214    zend_bool is_method = decl->kind == ZEND_AST_METHOD;
4215
4216    zend_op_array *orig_op_array = CG(active_op_array);
4217    zend_op_array *op_array = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
4218
4219    // TODO.AST interactive (not just here - also bpc etc!)
4220
4221    init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE);
4222
4223    op_array->fn_flags |= decl->flags;
4224    op_array->line_start = decl->start_lineno;
4225    op_array->line_end = decl->end_lineno;
4226    if (decl->doc_comment) {
4227        op_array->doc_comment = zend_string_copy(decl->doc_comment);
4228    }
4229    if (decl->kind == ZEND_AST_CLOSURE) {
4230        op_array->fn_flags |= ZEND_ACC_CLOSURE;
4231    }
4232
4233    if (is_method) {
4234        zend_bool has_body = stmt_ast != NULL;
4235        zend_begin_method_decl(op_array, decl->name, has_body);
4236    } else {
4237        zend_begin_func_decl(result, op_array, decl);
4238    }
4239
4240    CG(active_op_array) = op_array;
4241    zend_stack_push(&CG(context_stack), (void *) &CG(context));
4242    zend_init_compiler_context();
4243
4244    if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
4245        zend_op *opline_ext = zend_emit_op(NULL, ZEND_EXT_NOP, NULL, NULL);
4246        opline_ext->lineno = decl->start_lineno;
4247    }
4248
4249    {
4250        /* Push a separator to the loop variable stack */
4251        znode dummy_var;
4252        dummy_var.op_type = IS_UNUSED;
4253
4254        zend_stack_push(&CG(loop_var_stack), (void *) &dummy_var);
4255    }
4256
4257    zend_compile_params(params_ast, return_type_ast, is_method);
4258    if (uses_ast) {
4259        zend_compile_closure_uses(uses_ast);
4260    }
4261    zend_compile_stmt(stmt_ast);
4262
4263    if (is_method) {
4264        zend_check_magic_method_implementation(
4265            CG(active_class_entry), (zend_function *) op_array, E_COMPILE_ERROR);
4266    }
4267
4268    zend_do_extended_info();
4269    zend_emit_final_return(NULL);
4270
4271    pass_two(CG(active_op_array));
4272    zend_release_labels(0);
4273
4274    /* Pop the loop variable stack separator */
4275    zend_stack_del_top(&CG(loop_var_stack));
4276
4277    CG(active_op_array) = orig_op_array;
4278}
4279/* }}} */
4280
4281void zend_compile_prop_decl(zend_ast *ast) /* {{{ */
4282{
4283    zend_ast_list *list = zend_ast_get_list(ast);
4284    uint32_t flags = list->attr;
4285    zend_class_entry *ce = CG(active_class_entry);
4286    uint32_t i, children = list->children;
4287    zend_string *doc_comment = NULL;
4288
4289    if (ce->ce_flags & ZEND_ACC_INTERFACE) {
4290        zend_error_noreturn(E_COMPILE_ERROR, "Interfaces may not include member variables");
4291    }
4292
4293    if (flags & ZEND_ACC_ABSTRACT) {
4294        zend_error_noreturn(E_COMPILE_ERROR, "Properties cannot be declared abstract");
4295    }
4296
4297    /* Doc comment has been appended as last element in property list */
4298    if (list->child[children - 1]->kind == ZEND_AST_ZVAL) {
4299        doc_comment = zend_string_copy(zend_ast_get_str(list->child[children - 1]));
4300        children -= 1;
4301    }
4302
4303    for (i = 0; i < children; ++i) {
4304        zend_ast *prop_ast = list->child[i];
4305        zend_ast *name_ast = prop_ast->child[0];
4306        zend_ast *value_ast = prop_ast->child[1];
4307        zend_string *name = zend_ast_get_str(name_ast);
4308        zval value_zv;
4309
4310        if (flags & ZEND_ACC_FINAL) {
4311            zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare property %s::$%s final, "
4312                "the final modifier is allowed only for methods and classes",
4313                ce->name->val, name->val);
4314        }
4315
4316        if (zend_hash_exists(&ce->properties_info, name)) {
4317            zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::$%s",
4318                ce->name->val, name->val);
4319        }
4320
4321        if (value_ast) {
4322            zend_const_expr_to_zval(&value_zv, value_ast);
4323        } else {
4324            ZVAL_NULL(&value_zv);
4325        }
4326
4327        name = zend_new_interned_string_safe(name);
4328        zend_declare_property_ex(ce, name, &value_zv, flags, doc_comment);
4329
4330        /* Doc comment is only assigned to first property */
4331        doc_comment = NULL;
4332    }
4333}
4334/* }}} */
4335
4336void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */
4337{
4338    zend_ast_list *list = zend_ast_get_list(ast);
4339    zend_class_entry *ce = CG(active_class_entry);
4340    uint32_t i;
4341
4342    for (i = 0; i < list->children; ++i) {
4343        zend_ast *const_ast = list->child[i];
4344        zend_ast *name_ast = const_ast->child[0];
4345        zend_ast *value_ast = const_ast->child[1];
4346        zend_string *name = zend_ast_get_str(name_ast);
4347        zval value_zv;
4348
4349        if (ZEND_CE_IS_TRAIT(ce)) {
4350            zend_error_noreturn(E_COMPILE_ERROR, "Traits cannot have constants");
4351            return;
4352        }
4353
4354        zend_const_expr_to_zval(&value_zv, value_ast);
4355
4356        name = zend_new_interned_string_safe(name);
4357        if (zend_hash_add(&ce->constants_table, name, &value_zv) == NULL) {
4358            zend_error_noreturn(E_COMPILE_ERROR, "Cannot redefine class constant %s::%s",
4359                ce->name->val, name->val);
4360        }
4361
4362        if (Z_CONSTANT(value_zv)) {
4363            ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
4364        }
4365    }
4366}
4367/* }}} */
4368
4369static zend_trait_method_reference *zend_compile_method_ref(zend_ast *ast) /* {{{ */
4370{
4371    zend_ast *class_ast = ast->child[0];
4372    zend_ast *method_ast = ast->child[1];
4373
4374    zend_trait_method_reference *method_ref = emalloc(sizeof(zend_trait_method_reference));
4375    method_ref->ce = NULL;
4376    method_ref->method_name = zend_string_copy(zend_ast_get_str(method_ast));
4377
4378    if (class_ast) {
4379        method_ref->class_name = zend_resolve_class_name_ast(class_ast);
4380    } else {
4381        method_ref->class_name = NULL;
4382    }
4383
4384    return method_ref;
4385}
4386/* }}} */
4387
4388static zend_string **zend_compile_name_list(zend_ast *ast) /* {{{ */
4389{
4390    zend_ast_list *list = zend_ast_get_list(ast);
4391    zend_string **names = safe_emalloc(sizeof(zend_string *), list->children + 1, 0);
4392    uint32_t i;
4393
4394    for (i = 0; i < list->children; ++i) {
4395        zend_ast *name_ast = list->child[i];
4396        names[i] = zend_resolve_class_name_ast(name_ast);
4397    }
4398
4399    names[list->children] = NULL;
4400
4401    return names;
4402}
4403/* }}} */
4404
4405static void zend_compile_trait_precedence(zend_ast *ast) /* {{{ */
4406{
4407    zend_ast *method_ref_ast = ast->child[0];
4408    zend_ast *insteadof_ast = ast->child[1];
4409
4410    zend_trait_precedence *precedence = emalloc(sizeof(zend_trait_precedence));
4411    precedence->trait_method = zend_compile_method_ref(method_ref_ast);
4412    precedence->exclude_from_classes
4413        = (void *) zend_compile_name_list(insteadof_ast);
4414
4415    zend_add_to_list(&CG(active_class_entry)->trait_precedences, precedence);
4416}
4417/* }}} */
4418
4419static void zend_compile_trait_alias(zend_ast *ast) /* {{{ */
4420{
4421    zend_ast *method_ref_ast = ast->child[0];
4422    zend_ast *alias_ast = ast->child[1];
4423    uint32_t modifiers = ast->attr;
4424
4425    zend_trait_alias *alias;
4426
4427    if (modifiers == ZEND_ACC_STATIC) {
4428        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as method modifier");
4429    } else if (modifiers == ZEND_ACC_ABSTRACT) {
4430        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as method modifier");
4431    } else if (modifiers == ZEND_ACC_FINAL) {
4432        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as method modifier");
4433    }
4434
4435    alias = emalloc(sizeof(zend_trait_alias));
4436    alias->trait_method = zend_compile_method_ref(method_ref_ast);
4437    alias->modifiers = modifiers;
4438
4439    if (alias_ast) {
4440        alias->alias = zend_string_copy(zend_ast_get_str(alias_ast));
4441    } else {
4442        alias->alias = NULL;
4443    }
4444
4445    zend_add_to_list(&CG(active_class_entry)->trait_aliases, alias);
4446}
4447/* }}} */
4448
4449void zend_compile_use_trait(zend_ast *ast) /* {{{ */
4450{
4451    zend_ast_list *traits = zend_ast_get_list(ast->child[0]);
4452    zend_ast_list *adaptations = ast->child[1] ? zend_ast_get_list(ast->child[1]) : NULL;
4453    zend_class_entry *ce = CG(active_class_entry);
4454    zend_op *opline;
4455    uint32_t i;
4456
4457    for (i = 0; i < traits->children; ++i) {
4458        zend_ast *trait_ast = traits->child[i];
4459        zend_string *name = zend_ast_get_str(trait_ast);
4460
4461        if (ce->ce_flags & ZEND_ACC_INTERFACE) {
4462            zend_error_noreturn(E_COMPILE_ERROR, "Cannot use traits inside of interfaces. "
4463                "%s is used in %s", name->val, ce->name->val);
4464        }
4465
4466        switch (zend_get_class_fetch_type(name)) {
4467            case ZEND_FETCH_CLASS_SELF:
4468            case ZEND_FETCH_CLASS_PARENT:
4469            case ZEND_FETCH_CLASS_STATIC:
4470                zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as trait name "
4471                    "as it is reserved", name->val);
4472                break;
4473        }
4474
4475        opline = get_next_op(CG(active_op_array));
4476        opline->opcode = ZEND_ADD_TRAIT;
4477        SET_NODE(opline->op1, &CG(implementing_class));
4478        opline->op2_type = IS_CONST;
4479        opline->op2.constant = zend_add_class_name_literal(CG(active_op_array),
4480            zend_resolve_class_name_ast(trait_ast));
4481
4482        ce->num_traits++;
4483    }
4484
4485    if (!adaptations) {
4486        return;
4487    }
4488
4489    for (i = 0; i < adaptations->children; ++i) {
4490        zend_ast *adaptation_ast = adaptations->child[i];
4491        switch (adaptation_ast->kind) {
4492            case ZEND_AST_TRAIT_PRECEDENCE:
4493                zend_compile_trait_precedence(adaptation_ast);
4494                break;
4495            case ZEND_AST_TRAIT_ALIAS:
4496                zend_compile_trait_alias(adaptation_ast);
4497                break;
4498            EMPTY_SWITCH_DEFAULT_CASE()
4499        }
4500    }
4501}
4502/* }}} */
4503
4504void zend_compile_implements(znode *class_node, zend_ast *ast) /* {{{ */
4505{
4506    zend_ast_list *list = zend_ast_get_list(ast);
4507    uint32_t i;
4508    for (i = 0; i < list->children; ++i) {
4509        zend_ast *class_ast = list->child[i];
4510        zend_string *name = zend_ast_get_str(class_ast);
4511
4512        zend_op *opline;
4513
4514        if (!zend_is_const_default_class_ref(class_ast)) {
4515            zend_error_noreturn(E_COMPILE_ERROR,
4516                "Cannot use '%s' as interface name as it is reserved", name->val);
4517        }
4518
4519        opline = zend_emit_op(NULL, ZEND_ADD_INTERFACE, class_node, NULL);
4520        opline->op2_type = IS_CONST;
4521        opline->op2.constant = zend_add_class_name_literal(CG(active_op_array),
4522            zend_resolve_class_name_ast(class_ast));
4523
4524        CG(active_class_entry)->num_interfaces++;
4525    }
4526}
4527/* }}} */
4528
4529void zend_compile_class_decl(zend_ast *ast) /* {{{ */
4530{
4531    zend_ast_decl *decl = (zend_ast_decl *) ast;
4532    zend_ast *extends_ast = decl->child[0];
4533    zend_ast *implements_ast = decl->child[1];
4534    zend_ast *stmt_ast = decl->child[2];
4535
4536    zend_string *name = decl->name, *lcname, *import_name = NULL;
4537    zend_class_entry *ce = zend_arena_alloc(&CG(arena), sizeof(zend_class_entry));
4538    zend_op *opline;
4539    znode declare_node, extends_node;
4540
4541    if (CG(active_class_entry)) {
4542        zend_error_noreturn(E_COMPILE_ERROR, "Class declarations may not be nested");
4543        return;
4544    }
4545
4546    if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
4547        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved",
4548            name->val);
4549    }
4550
4551    lcname = zend_string_tolower(name);
4552
4553    if (CG(current_import)) {
4554        import_name = zend_hash_find_ptr(CG(current_import), lcname);
4555    }
4556
4557    if (CG(current_namespace)) {
4558        name = zend_prefix_with_ns(name);
4559
4560        zend_string_release(lcname);
4561        lcname = zend_string_tolower(name);
4562    } else {
4563        zend_string_addref(name);
4564    }
4565
4566    if (import_name && !zend_string_equals_str_ci(lcname, import_name)) {
4567        zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare class %s "
4568            "because the name is already in use", name->val);
4569    }
4570
4571    name = zend_new_interned_string(name);
4572    lcname = zend_new_interned_string(lcname);
4573
4574    ce->type = ZEND_USER_CLASS;
4575    ce->name = name;
4576    zend_initialize_class_data(ce, 1);
4577
4578    ce->ce_flags |= decl->flags;
4579    ce->info.user.filename = zend_get_compiled_filename();
4580    ce->info.user.line_start = decl->start_lineno;
4581    ce->info.user.line_end = decl->end_lineno;
4582    if (decl->doc_comment) {
4583        ce->info.user.doc_comment = zend_string_copy(decl->doc_comment);
4584    }
4585
4586    if (extends_ast) {
4587        if (!zend_is_const_default_class_ref(extends_ast)) {
4588            zend_string *extends_name = zend_ast_get_str(extends_ast);
4589            zend_error_noreturn(E_COMPILE_ERROR,
4590                "Cannot use '%s' as class name as it is reserved", extends_name->val);
4591        }
4592
4593        zend_compile_class_ref(&extends_node, extends_ast);
4594    }
4595
4596    opline = get_next_op(CG(active_op_array));
4597    zend_make_var_result(&declare_node, opline);
4598
4599    // TODO.AST drop this
4600    GET_NODE(&CG(implementing_class), opline->result);
4601
4602    opline->op2_type = IS_CONST;
4603    LITERAL_STR(opline->op2, lcname);
4604
4605    if (extends_ast) {
4606        opline->opcode = ZEND_DECLARE_INHERITED_CLASS;
4607        opline->extended_value = extends_node.u.op.var;
4608    } else {
4609        opline->opcode = ZEND_DECLARE_CLASS;
4610    }
4611
4612    {
4613        zend_string *key = zend_build_runtime_definition_key(lcname, decl->lex_pos);
4614
4615        opline->op1_type = IS_CONST;
4616        LITERAL_STR(opline->op1, key);
4617
4618        zend_hash_update_ptr(CG(class_table), key, ce);
4619    }
4620
4621    CG(active_class_entry) = ce;
4622
4623    if (implements_ast) {
4624        zend_compile_implements(&declare_node, implements_ast);
4625    }
4626
4627    zend_compile_stmt(stmt_ast);
4628
4629    if (ce->constructor) {
4630        ce->constructor->common.fn_flags |= ZEND_ACC_CTOR;
4631        if (ce->constructor->common.fn_flags & ZEND_ACC_STATIC) {
4632            zend_error_noreturn(E_COMPILE_ERROR, "Constructor %s::%s() cannot be static",
4633                ce->name->val, ce->constructor->common.function_name->val);
4634        }
4635        if (ce->constructor->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
4636            zend_error_noreturn(E_COMPILE_ERROR,
4637                "Constructor %s::%s() cannot declare a return type",
4638                ce->name->val, ce->constructor->common.function_name->val);
4639        }
4640    }
4641    if (ce->destructor) {
4642        ce->destructor->common.fn_flags |= ZEND_ACC_DTOR;
4643        if (ce->destructor->common.fn_flags & ZEND_ACC_STATIC) {
4644            zend_error_noreturn(E_COMPILE_ERROR, "Destructor %s::%s() cannot be static",
4645                ce->name->val, ce->destructor->common.function_name->val);
4646        } else if (ce->destructor->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
4647            zend_error_noreturn(E_COMPILE_ERROR,
4648                "Destructor %s::%s() cannot declare a return type",
4649                ce->name->val, ce->destructor->common.function_name->val);
4650        }
4651    }
4652    if (ce->clone) {
4653        ce->clone->common.fn_flags |= ZEND_ACC_CLONE;
4654        if (ce->clone->common.fn_flags & ZEND_ACC_STATIC) {
4655            zend_error_noreturn(E_COMPILE_ERROR, "Clone method %s::%s() cannot be static",
4656                ce->name->val, ce->clone->common.function_name->val);
4657        } else if (ce->clone->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
4658            zend_error_noreturn(E_COMPILE_ERROR,
4659                "%s::%s() cannot declare a return type",
4660                ce->name->val, ce->clone->common.function_name->val);
4661        }
4662    }
4663
4664    /* Check for traits and proceed like with interfaces.
4665     * The only difference will be a combined handling of them in the end.
4666     * Thus, we need another opcode here. */
4667    if (ce->num_traits > 0) {
4668        ce->traits = NULL;
4669        ce->num_traits = 0;
4670        ce->ce_flags |= ZEND_ACC_IMPLEMENT_TRAITS;
4671
4672        zend_emit_op(NULL, ZEND_BIND_TRAITS, &declare_node, NULL);
4673    }
4674
4675    if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))
4676        && (extends_ast || ce->num_interfaces > 0)
4677    ) {
4678        zend_verify_abstract_class(ce);
4679        if (ce->num_interfaces && !(ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS)) {
4680            zend_emit_op(NULL, ZEND_VERIFY_ABSTRACT_CLASS, &declare_node, NULL);
4681        }
4682    }
4683
4684    /* Inherit interfaces; reset number to zero, we need it for above check and
4685     * will restore it during actual implementation.
4686     * The ZEND_ACC_IMPLEMENT_INTERFACES flag disables double call to
4687     * zend_verify_abstract_class() */
4688    if (ce->num_interfaces > 0) {
4689        ce->interfaces = NULL;
4690        ce->num_interfaces = 0;
4691        ce->ce_flags |= ZEND_ACC_IMPLEMENT_INTERFACES;
4692    }
4693
4694    CG(active_class_entry) = NULL;
4695}
4696/* }}} */
4697
4698static HashTable *zend_get_import_ht(uint32_t type) /* {{{ */
4699{
4700    switch (type) {
4701        case T_CLASS:
4702            if (!CG(current_import)) {
4703                CG(current_import) = emalloc(sizeof(HashTable));
4704                zend_hash_init(CG(current_import), 8, NULL, str_dtor, 0);
4705            }
4706            return CG(current_import);
4707        case T_FUNCTION:
4708            if (!CG(current_import_function)) {
4709                CG(current_import_function) = emalloc(sizeof(HashTable));
4710                zend_hash_init(CG(current_import_function), 8, NULL, str_dtor, 0);
4711            }
4712            return CG(current_import_function);
4713        case T_CONST:
4714            if (!CG(current_import_const)) {
4715                CG(current_import_const) = emalloc(sizeof(HashTable));
4716                zend_hash_init(CG(current_import_const), 8, NULL, str_dtor, 0);
4717            }
4718            return CG(current_import_const);
4719        EMPTY_SWITCH_DEFAULT_CASE()
4720    }
4721
4722    return NULL;
4723}
4724/* }}} */
4725
4726static char *zend_get_use_type_str(uint32_t type) /* {{{ */
4727{
4728    switch (type) {
4729        case T_CLASS:
4730            return "";
4731        case T_FUNCTION:
4732            return " function";
4733        case T_CONST:
4734            return " const";
4735        EMPTY_SWITCH_DEFAULT_CASE()
4736    }
4737
4738    return " unknown";
4739}
4740/* }}} */
4741
4742static void zend_check_already_in_use(uint32_t type, zend_string *old_name, zend_string *new_name, zend_string *check_name) /* {{{ */
4743{
4744    if (zend_string_equals_str_ci(old_name, check_name)) {
4745        return;
4746    }
4747
4748    zend_error_noreturn(E_COMPILE_ERROR, "Cannot use%s %s as %s because the name "
4749        "is already in use", zend_get_use_type_str(type), old_name->val, new_name->val);
4750}
4751/* }}} */
4752
4753void zend_compile_use(zend_ast *ast) /* {{{ */
4754{
4755    zend_ast_list *list = zend_ast_get_list(ast);
4756    uint32_t i;
4757    zend_string *current_ns = CG(current_namespace);
4758    uint32_t type = ast->attr;
4759    HashTable *current_import = zend_get_import_ht(type);
4760    zend_bool case_sensitive = type == T_CONST;
4761
4762    for (i = 0; i < list->children; ++i) {
4763        zend_ast *use_ast = list->child[i];
4764        zend_ast *old_name_ast = use_ast->child[0];
4765        zend_ast *new_name_ast = use_ast->child[1];
4766        zend_string *old_name = zend_ast_get_str(old_name_ast);
4767        zend_string *new_name, *lookup_name;
4768
4769        if (new_name_ast) {
4770            new_name = zend_string_copy(zend_ast_get_str(new_name_ast));
4771        } else {
4772            const char *unqualified_name;
4773            size_t unqualified_name_len;
4774            if (zend_get_unqualified_name(old_name, &unqualified_name, &unqualified_name_len)) {
4775                /* The form "use A\B" is eqivalent to "use A\B as B" */
4776                new_name = zend_string_init(unqualified_name, unqualified_name_len, 0);
4777            } else {
4778                new_name = zend_string_copy(old_name);
4779
4780                if (!current_ns) {
4781                    if (type == T_CLASS && zend_string_equals_literal(new_name, "strict")) {
4782                        zend_error_noreturn(E_COMPILE_ERROR,
4783                            "You seem to be trying to use a different language...");
4784                    }
4785
4786                    zend_error(E_WARNING, "The use statement with non-compound name '%s' "
4787                        "has no effect", new_name->val);
4788                }
4789            }
4790        }
4791
4792        if (case_sensitive) {
4793            lookup_name = zend_string_copy(new_name);
4794        } else {
4795            lookup_name = zend_string_tolower(new_name);
4796        }
4797
4798        if (type == T_CLASS && (zend_string_equals_literal(lookup_name, "self")
4799            || zend_string_equals_literal(lookup_name, "parent"))
4800        ) {
4801            zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because '%s' "
4802                "is a special class name", old_name->val, new_name->val, new_name->val);
4803        }
4804
4805        if (current_ns) {
4806            zend_string *ns_name = zend_string_alloc(current_ns->len + 1 + new_name->len, 0);
4807            zend_str_tolower_copy(ns_name->val, current_ns->val, current_ns->len);
4808            ns_name->val[current_ns->len] = '\\';
4809            memcpy(ns_name->val + current_ns->len + 1, lookup_name->val, lookup_name->len);
4810
4811            if (zend_hash_exists(CG(class_table), ns_name)) {
4812                zend_check_already_in_use(type, old_name, new_name, ns_name);
4813            }
4814
4815            zend_string_free(ns_name);
4816        } else {
4817            switch (type) {
4818                case T_CLASS:
4819                {
4820                    zend_class_entry *ce = zend_hash_find_ptr(CG(class_table), lookup_name);
4821                    if (ce && ce->type == ZEND_USER_CLASS
4822                        && ce->info.user.filename == CG(compiled_filename)
4823                    ) {
4824                        zend_check_already_in_use(type, old_name, new_name, lookup_name);
4825                    }
4826                    break;
4827                }
4828                case T_FUNCTION:
4829                {
4830                    zend_function *fn = zend_hash_find_ptr(CG(function_table), lookup_name);
4831                    if (fn && fn->type == ZEND_USER_FUNCTION
4832                        && fn->op_array.filename == CG(compiled_filename)
4833                    ) {
4834                        zend_check_already_in_use(type, old_name, new_name, lookup_name);
4835                    }
4836                    break;
4837                }
4838                case T_CONST:
4839                {
4840                    zend_string *filename = zend_hash_find_ptr(&CG(const_filenames), lookup_name);
4841                    if (filename && filename == CG(compiled_filename)) {
4842                        zend_check_already_in_use(type, old_name, new_name, lookup_name);
4843                    }
4844                    break;
4845                }
4846                EMPTY_SWITCH_DEFAULT_CASE()
4847            }
4848        }
4849
4850        zend_string_addref(old_name);
4851        if (!zend_hash_add_ptr(current_import, lookup_name, old_name)) {
4852            zend_error_noreturn(E_COMPILE_ERROR, "Cannot use%s %s as %s because the name "
4853                "is already in use", zend_get_use_type_str(type), old_name->val, new_name->val);
4854        }
4855
4856        zend_string_release(lookup_name);
4857        zend_string_release(new_name);
4858    }
4859}
4860/* }}} */
4861
4862void zend_compile_const_decl(zend_ast *ast) /* {{{ */
4863{
4864    zend_ast_list *list = zend_ast_get_list(ast);
4865    uint32_t i;
4866    for (i = 0; i < list->children; ++i) {
4867        zend_ast *const_ast = list->child[i];
4868        zend_ast *name_ast = const_ast->child[0];
4869        zend_ast *value_ast = const_ast->child[1];
4870        zend_string *name = zend_ast_get_str(name_ast);
4871
4872        zend_string *import_name;
4873        znode name_node, value_node;
4874        zval *value_zv = &value_node.u.constant;
4875
4876        value_node.op_type = IS_CONST;
4877        zend_const_expr_to_zval(value_zv, value_ast);
4878
4879        if (zend_lookup_reserved_const(name->val, name->len)) {
4880            zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare constant '%s'", name->val);
4881        }
4882
4883        name = zend_prefix_with_ns(name);
4884        name = zend_new_interned_string(name);
4885
4886        if (CG(current_import_const)
4887            && (import_name = zend_hash_find_ptr(CG(current_import_const), name))
4888        ) {
4889            if (!zend_string_equals(import_name, name)) {
4890                zend_error(E_COMPILE_ERROR, "Cannot declare const %s because "
4891                    "the name is already in use", name->val);
4892            }
4893        }
4894
4895        name_node.op_type = IS_CONST;
4896        ZVAL_STR(&name_node.u.constant, name);
4897
4898        zend_emit_op(NULL, ZEND_DECLARE_CONST, &name_node, &value_node);
4899
4900        zend_hash_add_ptr(&CG(const_filenames), name, CG(compiled_filename));
4901    }
4902}
4903/* }}}*/
4904
4905void zend_compile_namespace(zend_ast *ast) /* {{{ */
4906{
4907    zend_ast *name_ast = ast->child[0];
4908    zend_ast *stmt_ast = ast->child[1];
4909    zend_string *name;
4910    zend_bool with_bracket = stmt_ast != NULL;
4911
4912    /* handle mixed syntax declaration or nested namespaces */
4913    if (!CG(has_bracketed_namespaces)) {
4914        if (CG(current_namespace)) {
4915            /* previous namespace declarations were unbracketed */
4916            if (with_bracket) {
4917                zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations "
4918                    "with unbracketed namespace declarations");
4919            }
4920        }
4921    } else {
4922        /* previous namespace declarations were bracketed */
4923        if (!with_bracket) {
4924            zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations "
4925                "with unbracketed namespace declarations");
4926        } else if (CG(current_namespace) || CG(in_namespace)) {
4927            zend_error_noreturn(E_COMPILE_ERROR, "Namespace declarations cannot be nested");
4928        }
4929    }
4930
4931    if (((!with_bracket && !CG(current_namespace))
4932         || (with_bracket && !CG(has_bracketed_namespaces))) && CG(active_op_array)->last > 0
4933    ) {
4934        /* ignore ZEND_EXT_STMT and ZEND_TICKS */
4935        uint32_t num = CG(active_op_array)->last;
4936        while (num > 0 &&
4937               (CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
4938                CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
4939            --num;
4940        }
4941        if (num > 0) {
4942            zend_error_noreturn(E_COMPILE_ERROR, "Namespace declaration statement has to be "
4943                "the very first statement in the script");
4944        }
4945    }
4946
4947    if (CG(current_namespace)) {
4948        zend_string_release(CG(current_namespace));
4949    }
4950
4951    if (name_ast) {
4952        name = zend_ast_get_str(name_ast);
4953
4954        if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
4955            zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as namespace name", name->val);
4956        }
4957
4958        CG(current_namespace) = zend_string_copy(name);
4959    } else {
4960        CG(current_namespace) = NULL;
4961    }
4962
4963    zend_reset_import_tables();
4964
4965    CG(in_namespace) = 1;
4966    if (with_bracket) {
4967        CG(has_bracketed_namespaces) = 1;
4968    }
4969
4970    if (stmt_ast) {
4971        zend_compile_top_stmt(stmt_ast);
4972        zend_end_namespace();
4973    }
4974}
4975/* }}} */
4976
4977void zend_compile_halt_compiler(zend_ast *ast) /* {{{ */
4978{
4979    zend_ast *offset_ast = ast->child[0];
4980    zend_long offset = Z_LVAL_P(zend_ast_get_zval(offset_ast));
4981
4982    zend_string *filename, *name;
4983    const char const_name[] = "__COMPILER_HALT_OFFSET__";
4984
4985    if (CG(has_bracketed_namespaces) && CG(in_namespace)) {
4986        zend_error_noreturn(E_COMPILE_ERROR,
4987            "__HALT_COMPILER() can only be used from the outermost scope");
4988    }
4989
4990    filename = zend_get_compiled_filename();
4991    name = zend_mangle_property_name(const_name, sizeof(const_name) - 1,
4992        filename->val, filename->len, 0);
4993
4994    zend_register_long_constant(name->val, name->len, offset, CONST_CS, 0);
4995    zend_string_release(name);
4996}
4997/* }}} */
4998
4999static zend_bool zend_try_ct_eval_magic_const(zval *zv, zend_ast *ast) /* {{{ */
5000{
5001    zend_op_array *op_array = CG(active_op_array);
5002    zend_class_entry *ce = CG(active_class_entry);
5003
5004    switch (ast->attr) {
5005        case T_LINE:
5006            ZVAL_LONG(zv, ast->lineno);
5007            break;
5008        case T_FILE:
5009            ZVAL_STR_COPY(zv, CG(compiled_filename));
5010            break;
5011        case T_DIR:
5012        {
5013            zend_string *filename = CG(compiled_filename);
5014            zend_string *dirname = zend_string_init(filename->val, filename->len, 0);
5015            zend_dirname(dirname->val, dirname->len);
5016
5017            if (strcmp(dirname->val, ".") == 0) {
5018                dirname = zend_string_realloc(dirname, MAXPATHLEN, 0);
5019#if HAVE_GETCWD
5020                VCWD_GETCWD(dirname->val, MAXPATHLEN);
5021#elif HAVE_GETWD
5022                VCWD_GETWD(dirname->val);
5023#endif
5024            }
5025
5026            dirname->len = strlen(dirname->val);
5027            ZVAL_STR(zv, dirname);
5028            break;
5029        }
5030        case T_FUNC_C:
5031            if (op_array && op_array->function_name) {
5032                ZVAL_STR_COPY(zv, op_array->function_name);
5033            } else {
5034                ZVAL_EMPTY_STRING(zv);
5035            }
5036            break;
5037        case T_METHOD_C:
5038            if (ce) {
5039                if (op_array && op_array->function_name) {
5040                    ZVAL_NEW_STR(zv, zend_concat3(ce->name->val, ce->name->len, "::", 2,
5041                        op_array->function_name->val, op_array->function_name->len));
5042                } else {
5043                    ZVAL_STR_COPY(zv, ce->name);
5044                }
5045            } else if (op_array && op_array->function_name) {
5046                ZVAL_STR_COPY(zv, op_array->function_name);
5047            } else {
5048                ZVAL_EMPTY_STRING(zv);
5049            }
5050            break;
5051        case T_CLASS_C:
5052            if (ce) {
5053                if (ZEND_CE_IS_TRAIT(ce)) {
5054                    return 0;
5055                } else {
5056                    ZVAL_STR_COPY(zv, ce->name);
5057                }
5058            } else {
5059                ZVAL_EMPTY_STRING(zv);
5060            }
5061            break;
5062        case T_TRAIT_C:
5063            if (ce && ZEND_CE_IS_TRAIT(ce)) {
5064                ZVAL_STR_COPY(zv, ce->name);
5065            } else {
5066                ZVAL_EMPTY_STRING(zv);
5067            }
5068            break;
5069        case T_NS_C:
5070            if (CG(current_namespace)) {
5071                ZVAL_STR_COPY(zv, CG(current_namespace));
5072            } else {
5073                ZVAL_EMPTY_STRING(zv);
5074            }
5075            break;
5076        EMPTY_SWITCH_DEFAULT_CASE()
5077    }
5078
5079    return 1;
5080}
5081/* }}} */
5082
5083static inline void zend_ct_eval_binary_op(zval *result, uint32_t opcode, zval *op1, zval *op2) /* {{{ */
5084{
5085    binary_op_type fn = get_binary_op(opcode);
5086    fn(result, op1, op2);
5087}
5088/* }}} */
5089
5090static inline void zend_ct_eval_unary_pm(zval *result, zend_ast_kind kind, zval *op) /* {{{ */
5091{
5092    binary_op_type fn = kind == ZEND_AST_UNARY_PLUS
5093        ? add_function : sub_function;
5094
5095    zval left;
5096    ZVAL_LONG(&left, 0);
5097    fn(result, &left, op);
5098}
5099/* }}} */
5100
5101static inline void zend_ct_eval_greater(zval *result, zend_ast_kind kind, zval *op1, zval *op2) /* {{{ */
5102{
5103    binary_op_type fn = kind == ZEND_AST_GREATER
5104        ? is_smaller_function : is_smaller_or_equal_function;
5105    fn(result, op2, op1);
5106}
5107/* }}} */
5108
5109static zend_bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */
5110{
5111    zend_ast_list *list = zend_ast_get_list(ast);
5112    uint32_t i;
5113
5114    /* First ensure that *all* child nodes are constant and by-val */
5115    for (i = 0; i < list->children; ++i) {
5116        zend_ast *elem_ast = list->child[i];
5117        zend_bool by_ref = elem_ast->attr;
5118        zend_eval_const_expr(&elem_ast->child[0]);
5119        zend_eval_const_expr(&elem_ast->child[1]);
5120
5121        if (by_ref || elem_ast->child[0]->kind != ZEND_AST_ZVAL
5122            || (elem_ast->child[1] && elem_ast->child[1]->kind != ZEND_AST_ZVAL)
5123        ) {
5124            return 0;
5125        }
5126    }
5127
5128    array_init_size(result, list->children);
5129    for (i = 0; i < list->children; ++i) {
5130        zend_ast *elem_ast = list->child[i];
5131        zend_ast *value_ast = elem_ast->child[0];
5132        zend_ast *key_ast = elem_ast->child[1];
5133
5134        zval *value = zend_ast_get_zval(value_ast);
5135        if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value);
5136
5137        if (key_ast) {
5138            zval *key = zend_ast_get_zval(key_ast);
5139            switch (Z_TYPE_P(key)) {
5140                case IS_LONG:
5141                    zend_hash_index_update(Z_ARRVAL_P(result), Z_LVAL_P(key), value);
5142                    break;
5143                case IS_STRING:
5144                    zend_symtable_update(Z_ARRVAL_P(result), Z_STR_P(key), value);
5145                    break;
5146                case IS_DOUBLE:
5147                    zend_hash_index_update(Z_ARRVAL_P(result),
5148                        zend_dval_to_lval(Z_DVAL_P(key)), value);
5149                    break;
5150                case IS_FALSE:
5151                    zend_hash_index_update(Z_ARRVAL_P(result), 0, value);
5152                    break;
5153                case IS_TRUE:
5154                    zend_hash_index_update(Z_ARRVAL_P(result), 1, value);
5155                    break;
5156                case IS_NULL:
5157                    zend_hash_update(Z_ARRVAL_P(result), STR_EMPTY_ALLOC(), value);
5158                    break;
5159                default:
5160                    zend_error(E_COMPILE_ERROR, "Illegal offset type");
5161                    break;
5162            }
5163        } else {
5164            zend_hash_next_index_insert(Z_ARRVAL_P(result), value);
5165        }
5166    }
5167
5168    return 1;
5169}
5170/* }}} */
5171
5172void zend_compile_binary_op(znode *result, zend_ast *ast) /* {{{ */
5173{
5174    zend_ast *left_ast = ast->child[0];
5175    zend_ast *right_ast = ast->child[1];
5176    uint32_t opcode = ast->attr;
5177
5178    znode left_node, right_node;
5179    zend_compile_expr(&left_node, left_ast);
5180    zend_compile_expr(&right_node, right_ast);
5181
5182    if (left_node.op_type == IS_CONST && right_node.op_type == IS_CONST) {
5183        result->op_type = IS_CONST;
5184        zend_ct_eval_binary_op(&result->u.constant, opcode,
5185            &left_node.u.constant, &right_node.u.constant);
5186        zval_ptr_dtor(&left_node.u.constant);
5187        zval_ptr_dtor(&right_node.u.constant);
5188        return;
5189    }
5190
5191    do {
5192        if (opcode == ZEND_IS_EQUAL || opcode == ZEND_IS_NOT_EQUAL) {
5193            if (left_node.op_type == IS_CONST) {
5194                if (Z_TYPE(left_node.u.constant) == IS_FALSE) {
5195                    opcode = (opcode == ZEND_IS_NOT_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
5196                    zend_emit_op_tmp(result, opcode, &right_node, NULL);
5197                    break;
5198                } else if (Z_TYPE(left_node.u.constant) == IS_TRUE) {
5199                    opcode = (opcode == ZEND_IS_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
5200                    zend_emit_op_tmp(result, opcode, &right_node, NULL);
5201                    break;
5202                }
5203            } else if (right_node.op_type == IS_CONST) {
5204                if (Z_TYPE(right_node.u.constant) == IS_FALSE) {
5205                    opcode = (opcode == ZEND_IS_NOT_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
5206                    zend_emit_op_tmp(result, opcode, &left_node, NULL);
5207                    break;
5208                } else if (Z_TYPE(right_node.u.constant) == IS_TRUE) {
5209                    opcode = (opcode == ZEND_IS_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
5210                    zend_emit_op_tmp(result, opcode, &left_node, NULL);
5211                    break;
5212                }
5213            }
5214        }
5215        zend_emit_op_tmp(result, opcode, &left_node, &right_node);
5216    } while (0);
5217}
5218/* }}} */
5219
5220/* We do not use zend_compile_binary_op for this because we want to retain the left-to-right
5221 * evaluation order. */
5222void zend_compile_greater(znode *result, zend_ast *ast) /* {{{ */
5223{
5224    zend_ast *left_ast = ast->child[0];
5225    zend_ast *right_ast = ast->child[1];
5226    znode left_node, right_node;
5227
5228    ZEND_ASSERT(ast->kind == ZEND_AST_GREATER || ast->kind == ZEND_AST_GREATER_EQUAL);
5229
5230    zend_compile_expr(&left_node, left_ast);
5231    zend_compile_expr(&right_node, right_ast);
5232
5233    if (left_node.op_type == IS_CONST && right_node.op_type == IS_CONST) {
5234        result->op_type = IS_CONST;
5235        zend_ct_eval_greater(&result->u.constant, ast->kind,
5236            &left_node.u.constant, &right_node.u.constant);
5237        zval_ptr_dtor(&left_node.u.constant);
5238        zval_ptr_dtor(&right_node.u.constant);
5239        return;
5240    }
5241
5242    zend_emit_op_tmp(result,
5243        ast->kind == ZEND_AST_GREATER ? ZEND_IS_SMALLER : ZEND_IS_SMALLER_OR_EQUAL,
5244        &right_node, &left_node);
5245}
5246/* }}} */
5247
5248void zend_compile_unary_op(znode *result, zend_ast *ast) /* {{{ */
5249{
5250    zend_ast *expr_ast = ast->child[0];
5251    uint32_t opcode = ast->attr;
5252
5253    znode expr_node;
5254    zend_compile_expr(&expr_node, expr_ast);
5255
5256    zend_emit_op_tmp(result, opcode, &expr_node, NULL);
5257}
5258/* }}} */
5259
5260void zend_compile_unary_pm(znode *result, zend_ast *ast) /* {{{ */
5261{
5262    zend_ast *expr_ast = ast->child[0];
5263    znode zero_node, expr_node;
5264
5265    ZEND_ASSERT(ast->kind == ZEND_AST_UNARY_PLUS || ast->kind == ZEND_AST_UNARY_MINUS);
5266
5267    zend_compile_expr(&expr_node, expr_ast);
5268
5269    if (expr_node.op_type == IS_CONST) {
5270        result->op_type = IS_CONST;
5271        zend_ct_eval_unary_pm(&result->u.constant, ast->kind, &expr_node.u.constant);
5272        zval_ptr_dtor(&expr_node.u.constant);
5273        return;
5274    }
5275
5276    zero_node.op_type = IS_CONST;
5277    ZVAL_LONG(&zero_node.u.constant, 0);
5278
5279    zend_emit_op_tmp(result, ast->kind == ZEND_AST_UNARY_PLUS ? ZEND_ADD : ZEND_SUB,
5280        &zero_node, &expr_node);
5281}
5282/* }}} */
5283
5284void zend_compile_short_circuiting(znode *result, zend_ast *ast) /* {{{ */
5285{
5286    zend_ast *left_ast = ast->child[0];
5287    zend_ast *right_ast = ast->child[1];
5288
5289    znode left_node, right_node;
5290    zend_op *opline_jmpz, *opline_bool;
5291    uint32_t opnum_jmpz;
5292
5293    ZEND_ASSERT(ast->kind == ZEND_AST_AND || ast->kind == ZEND_AST_OR);
5294
5295    zend_compile_expr(&left_node, left_ast);
5296
5297    opnum_jmpz = get_next_op_number(CG(active_op_array));
5298    opline_jmpz = zend_emit_op(NULL, ast->kind == ZEND_AST_AND ? ZEND_JMPZ_EX : ZEND_JMPNZ_EX,
5299        &left_node, NULL);
5300
5301    if (left_node.op_type == IS_TMP_VAR) {
5302        SET_NODE(opline_jmpz->result, &left_node);
5303    } else {
5304        opline_jmpz->result.var = get_temporary_variable(CG(active_op_array));
5305        opline_jmpz->result_type = IS_TMP_VAR;
5306    }
5307    GET_NODE(result, opline_jmpz->result);
5308
5309    zend_compile_expr(&right_node, right_ast);
5310
5311    opline_bool = zend_emit_op(NULL, ZEND_BOOL, &right_node, NULL);
5312    SET_NODE(opline_bool->result, result);
5313
5314    zend_update_jump_target_to_next(opnum_jmpz);
5315}
5316/* }}} */
5317
5318void zend_compile_post_incdec(znode *result, zend_ast *ast) /* {{{ */
5319{
5320    zend_ast *var_ast = ast->child[0];
5321    ZEND_ASSERT(ast->kind == ZEND_AST_POST_INC || ast->kind == ZEND_AST_POST_DEC);
5322
5323    if (var_ast->kind == ZEND_AST_PROP) {
5324        zend_op *opline = zend_compile_prop_common(NULL, var_ast, BP_VAR_RW);
5325        opline->opcode = ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC_OBJ : ZEND_POST_DEC_OBJ;
5326        zend_make_tmp_result(result, opline);
5327    } else {
5328        znode var_node;
5329        zend_compile_var(&var_node, var_ast, BP_VAR_RW);
5330        zend_emit_op_tmp(result, ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC : ZEND_POST_DEC,
5331            &var_node, NULL);
5332    }
5333}
5334/* }}} */
5335
5336void zend_compile_pre_incdec(znode *result, zend_ast *ast) /* {{{ */
5337{
5338    zend_ast *var_ast = ast->child[0];
5339    ZEND_ASSERT(ast->kind == ZEND_AST_PRE_INC || ast->kind == ZEND_AST_PRE_DEC);
5340
5341    if (var_ast->kind == ZEND_AST_PROP) {
5342        zend_op *opline = zend_compile_prop_common(result, var_ast, BP_VAR_RW);
5343        opline->opcode = ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC_OBJ : ZEND_PRE_DEC_OBJ;
5344    } else {
5345        znode var_node;
5346        zend_compile_var(&var_node, var_ast, BP_VAR_RW);
5347        zend_emit_op(result, ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC : ZEND_PRE_DEC,
5348            &var_node, NULL);
5349    }
5350}
5351/* }}} */
5352
5353void zend_compile_cast(znode *result, zend_ast *ast) /* {{{ */
5354{
5355    zend_ast *expr_ast = ast->child[0];
5356    znode expr_node;
5357    zend_op *opline;
5358
5359    zend_compile_expr(&expr_node, expr_ast);
5360
5361    opline = zend_emit_op_tmp(result, ZEND_CAST, &expr_node, NULL);
5362    opline->extended_value = ast->attr;
5363}
5364/* }}} */
5365
5366static void zend_compile_shorthand_conditional(znode *result, zend_ast *ast) /* {{{ */
5367{
5368    zend_ast *cond_ast = ast->child[0];
5369    zend_ast *false_ast = ast->child[2];
5370
5371    znode cond_node, false_node;
5372    zend_op *opline_jmp_set, *opline_qm_assign;
5373    uint32_t opnum_jmp_set;
5374
5375    ZEND_ASSERT(ast->child[1] == NULL);
5376
5377    zend_compile_expr(&cond_node, cond_ast);
5378
5379    opnum_jmp_set = get_next_op_number(CG(active_op_array));
5380    zend_emit_op_tmp(result, ZEND_JMP_SET, &cond_node, NULL);
5381
5382    zend_compile_expr(&false_node, false_ast);
5383
5384    opline_jmp_set = &CG(active_op_array)->opcodes[opnum_jmp_set];
5385    opline_jmp_set->op2.opline_num = get_next_op_number(CG(active_op_array)) + 1;
5386    opline_qm_assign = zend_emit_op_tmp(NULL, ZEND_QM_ASSIGN, &false_node, NULL);
5387    SET_NODE(opline_qm_assign->result, result);
5388}
5389/* }}} */
5390
5391void zend_compile_conditional(znode *result, zend_ast *ast) /* {{{ */
5392{
5393    zend_ast *cond_ast = ast->child[0];
5394    zend_ast *true_ast = ast->child[1];
5395    zend_ast *false_ast = ast->child[2];
5396
5397    znode cond_node, true_node, false_node;
5398    zend_op *opline_qm_assign1, *opline_qm_assign2;
5399    uint32_t opnum_jmpz, opnum_jmp, opnum_qm_assign1;
5400
5401    if (!true_ast) {
5402        zend_compile_shorthand_conditional(result, ast);
5403        return;
5404    }
5405
5406    zend_compile_expr(&cond_node, cond_ast);
5407
5408    opnum_jmpz = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0);
5409
5410    zend_compile_expr(&true_node, true_ast);
5411
5412    opnum_qm_assign1 = get_next_op_number(CG(active_op_array));
5413    zend_emit_op_tmp(result, ZEND_QM_ASSIGN, &true_node, NULL);
5414
5415    opnum_jmp = zend_emit_jump(0);
5416
5417    zend_update_jump_target_to_next(opnum_jmpz);
5418
5419    zend_compile_expr(&false_node, false_ast);
5420
5421    opline_qm_assign1 = &CG(active_op_array)->opcodes[opnum_qm_assign1];
5422    opline_qm_assign2 = zend_emit_op(NULL, opline_qm_assign1->opcode, &false_node, NULL);
5423    SET_NODE(opline_qm_assign2->result, result);
5424
5425    zend_update_jump_target_to_next(opnum_jmp);
5426}
5427/* }}} */
5428
5429void zend_compile_coalesce(znode *result, zend_ast *ast) /* {{{ */
5430{
5431    zend_ast *expr_ast = ast->child[0];
5432    zend_ast *default_ast = ast->child[1];
5433
5434    znode expr_node, default_node;
5435    zend_op *opline;