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