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