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