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