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