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