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