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