1/*
2   +----------------------------------------------------------------------+
3   | Zend Engine                                                          |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1998-2014 Zend Technologies Ltd. (http://www.zend.com) |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 2.00 of the Zend license,     |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.zend.com/license/2_00.txt.                                |
11   | If you did not receive a copy of the Zend license and are unable to  |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@zend.com so we can mail you a copy immediately.              |
14   +----------------------------------------------------------------------+
15   | Authors: Andi Gutmans <andi@zend.com>                                |
16   |          Zeev Suraski <zeev@zend.com>                                |
17   +----------------------------------------------------------------------+
18*/
19
20/* $Id$ */
21
22#include <zend_language_parser.h>
23#include "zend.h"
24#include "zend_compile.h"
25#include "zend_constants.h"
26#include "zend_llist.h"
27#include "zend_API.h"
28#include "zend_exceptions.h"
29#include "zend_virtual_cwd.h"
30#include "zend_multibyte.h"
31#include "zend_language_scanner.h"
32
33#define CONSTANT_EX(op_array, op) \
34    (op_array)->literals[op].constant
35
36#define CONSTANT(op) \
37    CONSTANT_EX(CG(active_op_array), op)
38
39#define SET_NODE(target, src) do { \
40        target ## _type = (src)->op_type; \
41        if ((src)->op_type == IS_CONST) { \
42            target.constant = zend_add_literal(CG(active_op_array), &(src)->u.constant TSRMLS_CC); \
43        } else { \
44            target = (src)->u.op; \
45        } \
46    } while (0)
47
48#define GET_NODE(target, src) do { \
49        (target)->op_type = src ## _type; \
50        if ((target)->op_type == IS_CONST) { \
51            (target)->u.constant = CONSTANT(src.constant); \
52        } else { \
53            (target)->u.op = src; \
54            (target)->EA = 0; \
55        } \
56    } while (0)
57
58#define COPY_NODE(target, src) do { \
59        target ## _type = src ## _type; \
60        target = src; \
61    } while (0)
62
63#define CALCULATE_LITERAL_HASH(num) do { \
64        zval *c = &CONSTANT(num); \
65        Z_HASH_P(c) = str_hash(Z_STRVAL_P(c), Z_STRLEN_P(c)); \
66    } while (0)
67
68#define GET_CACHE_SLOT(literal) do { \
69        CG(active_op_array)->literals[literal].cache_slot = CG(active_op_array)->last_cache_slot++; \
70        if ((CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE) && CG(active_op_array)->run_time_cache) { \
71            CG(active_op_array)->run_time_cache = erealloc(CG(active_op_array)->run_time_cache, CG(active_op_array)->last_cache_slot * sizeof(void*)); \
72            CG(active_op_array)->run_time_cache[CG(active_op_array)->last_cache_slot - 1] = NULL; \
73        } \
74    } while (0)
75
76#define POLYMORPHIC_CACHE_SLOT_SIZE 2
77
78#define GET_POLYMORPHIC_CACHE_SLOT(literal) do { \
79        CG(active_op_array)->literals[literal].cache_slot = CG(active_op_array)->last_cache_slot; \
80        CG(active_op_array)->last_cache_slot += POLYMORPHIC_CACHE_SLOT_SIZE; \
81        if ((CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE) && CG(active_op_array)->run_time_cache) { \
82            CG(active_op_array)->run_time_cache = erealloc(CG(active_op_array)->run_time_cache, CG(active_op_array)->last_cache_slot * sizeof(void*)); \
83            CG(active_op_array)->run_time_cache[CG(active_op_array)->last_cache_slot - 1] = NULL; \
84            CG(active_op_array)->run_time_cache[CG(active_op_array)->last_cache_slot - 2] = NULL; \
85        } \
86    } while (0)
87
88#define FREE_POLYMORPHIC_CACHE_SLOT(literal) do { \
89        if (CG(active_op_array)->literals[literal].cache_slot != -1 && \
90            CG(active_op_array)->literals[literal].cache_slot == \
91            CG(active_op_array)->last_cache_slot - POLYMORPHIC_CACHE_SLOT_SIZE) { \
92            CG(active_op_array)->literals[literal].cache_slot = -1; \
93            CG(active_op_array)->last_cache_slot -= POLYMORPHIC_CACHE_SLOT_SIZE; \
94        } \
95    } while (0)
96
97ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
98ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename TSRMLS_DC);
99
100#ifndef ZTS
101ZEND_API zend_compiler_globals compiler_globals;
102ZEND_API zend_executor_globals executor_globals;
103#endif
104
105static void zend_push_function_call_entry(zend_function *fbc TSRMLS_DC) /* {{{ */
106{
107    zend_function_call_entry fcall = { fbc };
108    zend_stack_push(&CG(function_call_stack), &fcall, sizeof(zend_function_call_entry));
109}
110/* }}} */
111
112static void zend_duplicate_property_info(zend_property_info *property_info) /* {{{ */
113{
114    property_info->name = str_estrndup(property_info->name, property_info->name_length);
115    if (property_info->doc_comment) {
116        property_info->doc_comment = estrndup(property_info->doc_comment, property_info->doc_comment_len);
117    }
118}
119/* }}} */
120
121static void zend_duplicate_property_info_internal(zend_property_info *property_info) /* {{{ */
122{
123    property_info->name = str_strndup(property_info->name, property_info->name_length);
124}
125/* }}} */
126
127static void zend_destroy_property_info(zend_property_info *property_info) /* {{{ */
128{
129    str_efree(property_info->name);
130    if (property_info->doc_comment) {
131        efree((char*)property_info->doc_comment);
132    }
133}
134/* }}} */
135
136static void zend_destroy_property_info_internal(zend_property_info *property_info) /* {{{ */
137{
138    str_free((char*)property_info->name);
139}
140/* }}} */
141
142static void build_runtime_defined_function_key(zval *result, const char *name, int name_length TSRMLS_DC) /* {{{ */
143{
144    char char_pos_buf[32];
145    uint char_pos_len;
146    const char *filename;
147
148    char_pos_len = zend_sprintf(char_pos_buf, "%p", LANG_SCNG(yy_text));
149    if (CG(active_op_array)->filename) {
150        filename = CG(active_op_array)->filename;
151    } else {
152        filename = "-";
153    }
154
155    /* NULL, name length, filename length, last accepting char position length */
156    Z_STRLEN_P(result) = 1+name_length+strlen(filename)+char_pos_len;
157
158    /* must be binary safe */
159    Z_STRVAL_P(result) = (char *) safe_emalloc(Z_STRLEN_P(result), 1, 1);
160    Z_STRVAL_P(result)[0] = '\0';
161    sprintf(Z_STRVAL_P(result)+1, "%s%s%s", name, filename, char_pos_buf);
162
163    result->type = IS_STRING;
164    Z_SET_REFCOUNT_P(result, 1);
165}
166/* }}} */
167
168static void init_compiler_declarables(TSRMLS_D) /* {{{ */
169{
170    Z_TYPE(CG(declarables).ticks) = IS_LONG;
171    Z_LVAL(CG(declarables).ticks) = 0;
172}
173/* }}} */
174
175void zend_init_compiler_context(TSRMLS_D) /* {{{ */
176{
177    CG(context).opcodes_size = (CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE) ? INITIAL_INTERACTIVE_OP_ARRAY_SIZE : INITIAL_OP_ARRAY_SIZE;
178    CG(context).vars_size = 0;
179    CG(context).literals_size = 0;
180    CG(context).current_brk_cont = -1;
181    CG(context).backpatch_count = 0;
182    CG(context).nested_calls = 0;
183    CG(context).used_stack = 0;
184    CG(context).in_finally = 0;
185    CG(context).labels = NULL;
186}
187/* }}} */
188
189void zend_init_compiler_data_structures(TSRMLS_D) /* {{{ */
190{
191    zend_stack_init(&CG(bp_stack));
192    zend_stack_init(&CG(function_call_stack));
193    zend_stack_init(&CG(switch_cond_stack));
194    zend_stack_init(&CG(foreach_copy_stack));
195    zend_stack_init(&CG(object_stack));
196    zend_stack_init(&CG(declare_stack));
197    CG(active_class_entry) = NULL;
198    zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0);
199    zend_llist_init(&CG(dimension_llist), sizeof(int), NULL, 0);
200    zend_stack_init(&CG(list_stack));
201    CG(in_compilation) = 0;
202    CG(start_lineno) = 0;
203    CG(current_namespace) = NULL;
204    CG(in_namespace) = 0;
205    CG(has_bracketed_namespaces) = 0;
206    CG(current_import) = NULL;
207    CG(current_import_function) = NULL;
208    CG(current_import_const) = NULL;
209    zend_hash_init(&CG(const_filenames), 0, NULL, NULL, 0);
210    init_compiler_declarables(TSRMLS_C);
211    zend_stack_init(&CG(context_stack));
212
213    CG(encoding_declared) = 0;
214}
215/* }}} */
216
217ZEND_API void file_handle_dtor(zend_file_handle *fh) /* {{{ */
218{
219    TSRMLS_FETCH();
220
221    zend_file_handle_dtor(fh TSRMLS_CC);
222}
223/* }}} */
224
225void init_compiler(TSRMLS_D) /* {{{ */
226{
227    CG(active_op_array) = NULL;
228    memset(&CG(context), 0, sizeof(CG(context)));
229    zend_init_compiler_data_structures(TSRMLS_C);
230    zend_init_rsrc_list(TSRMLS_C);
231    zend_hash_init(&CG(filenames_table), 5, NULL, (dtor_func_t) free_estring, 0);
232    zend_llist_init(&CG(open_files), sizeof(zend_file_handle), (void (*)(void *)) file_handle_dtor, 0);
233    CG(unclean_shutdown) = 0;
234}
235/* }}} */
236
237void shutdown_compiler(TSRMLS_D) /* {{{ */
238{
239    zend_stack_destroy(&CG(bp_stack));
240    zend_stack_destroy(&CG(function_call_stack));
241    zend_stack_destroy(&CG(switch_cond_stack));
242    zend_stack_destroy(&CG(foreach_copy_stack));
243    zend_stack_destroy(&CG(object_stack));
244    zend_stack_destroy(&CG(declare_stack));
245    zend_stack_destroy(&CG(list_stack));
246    zend_hash_destroy(&CG(filenames_table));
247    zend_llist_destroy(&CG(open_files));
248    zend_hash_destroy(&CG(const_filenames));
249    zend_stack_destroy(&CG(context_stack));
250}
251/* }}} */
252
253ZEND_API char *zend_set_compiled_filename(const char *new_compiled_filename TSRMLS_DC) /* {{{ */
254{
255    char **pp, *p;
256    int length = strlen(new_compiled_filename);
257
258    if (zend_hash_find(&CG(filenames_table), new_compiled_filename, length+1, (void **) &pp) == SUCCESS) {
259        CG(compiled_filename) = *pp;
260        return *pp;
261    }
262    p = estrndup(new_compiled_filename, length);
263    zend_hash_update(&CG(filenames_table), new_compiled_filename, length+1, &p, sizeof(char *), (void **) &pp);
264    CG(compiled_filename) = p;
265    return p;
266}
267/* }}} */
268
269ZEND_API void zend_restore_compiled_filename(char *original_compiled_filename TSRMLS_DC) /* {{{ */
270{
271    CG(compiled_filename) = original_compiled_filename;
272}
273/* }}} */
274
275ZEND_API char *zend_get_compiled_filename(TSRMLS_D) /* {{{ */
276{
277    return CG(compiled_filename);
278}
279/* }}} */
280
281ZEND_API int zend_get_compiled_lineno(TSRMLS_D) /* {{{ */
282{
283    return CG(zend_lineno);
284}
285/* }}} */
286
287ZEND_API zend_bool zend_is_compiling(TSRMLS_D) /* {{{ */
288{
289    return CG(in_compilation);
290}
291/* }}} */
292
293static zend_uint get_temporary_variable(zend_op_array *op_array) /* {{{ */
294{
295    return (zend_uint)(zend_uintptr_t)EX_TMP_VAR_NUM(0, (op_array->T)++);
296}
297/* }}} */
298
299static int lookup_cv(zend_op_array *op_array, char* name, int name_len, ulong hash TSRMLS_DC) /* {{{ */
300{
301    int i = 0;
302    ulong hash_value = hash ? hash : zend_inline_hash_func(name, name_len+1);
303
304    while (i < op_array->last_var) {
305        if (op_array->vars[i].name == name ||
306            (op_array->vars[i].hash_value == hash_value &&
307             op_array->vars[i].name_len == name_len &&
308             memcmp(op_array->vars[i].name, name, name_len) == 0)) {
309            str_efree(name);
310            return i;
311        }
312        i++;
313    }
314    i = op_array->last_var;
315    op_array->last_var++;
316    if (op_array->last_var > CG(context).vars_size) {
317        CG(context).vars_size += 16; /* FIXME */
318        op_array->vars = erealloc(op_array->vars, CG(context).vars_size * sizeof(zend_compiled_variable));
319    }
320    op_array->vars[i].name = zend_new_interned_string(name, name_len + 1, 1 TSRMLS_CC);
321    op_array->vars[i].name_len = name_len;
322    op_array->vars[i].hash_value = hash_value;
323    return i;
324}
325/* }}} */
326
327void zend_del_literal(zend_op_array *op_array, int n) /* {{{ */
328{
329    zval_dtor(&CONSTANT_EX(op_array, n));
330    if (n + 1 == op_array->last_literal) {
331        op_array->last_literal--;
332    } else {
333        Z_TYPE(CONSTANT_EX(op_array, n)) = IS_NULL;
334    }
335}
336/* }}} */
337
338/* Common part of zend_add_literal and zend_append_individual_literal */
339static inline void zend_insert_literal(zend_op_array *op_array, const zval *zv, int literal_position TSRMLS_DC) /* {{{ */
340{
341    if (Z_TYPE_P(zv) == IS_STRING || Z_TYPE_P(zv) == IS_CONSTANT) {
342        zval *z = (zval*)zv;
343        Z_STRVAL_P(z) = (char*)zend_new_interned_string(Z_STRVAL_P(zv), Z_STRLEN_P(zv) + 1, 1 TSRMLS_CC);
344    }
345    CONSTANT_EX(op_array, literal_position) = *zv;
346    Z_SET_REFCOUNT(CONSTANT_EX(op_array, literal_position), 2);
347    Z_SET_ISREF(CONSTANT_EX(op_array, literal_position));
348    op_array->literals[literal_position].hash_value = 0;
349    op_array->literals[literal_position].cache_slot = -1;
350}
351/* }}} */
352
353/* Is used while compiling a function, using the context to keep track
354   of an approximate size to avoid to relocate to often.
355   Literals are truncated to actual size in the second compiler pass (pass_two()). */
356int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) /* {{{ */
357{
358    int i = op_array->last_literal;
359    op_array->last_literal++;
360    if (i >= CG(context).literals_size) {
361        while (i >= CG(context).literals_size) {
362            CG(context).literals_size += 16; /* FIXME */
363        }
364        op_array->literals = (zend_literal*)erealloc(op_array->literals, CG(context).literals_size * sizeof(zend_literal));
365    }
366    zend_insert_literal(op_array, zv, i TSRMLS_CC);
367    return i;
368}
369/* }}} */
370
371/* Is used after normal compilation to append an additional literal.
372   Allocation is done precisely here. */
373int zend_append_individual_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) /* {{{ */
374{
375    int i = op_array->last_literal;
376    op_array->last_literal++;
377    op_array->literals = (zend_literal*)erealloc(op_array->literals, (i + 1) * sizeof(zend_literal));
378    zend_insert_literal(op_array, zv, i TSRMLS_CC);
379    return i;
380}
381/* }}} */
382
383int zend_add_func_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) /* {{{ */
384{
385    int ret;
386    char *lc_name;
387    zval c;
388    int lc_literal;
389
390    if (op_array->last_literal > 0 &&
391        &op_array->literals[op_array->last_literal - 1].constant == zv &&
392        op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
393        /* we already have function name as last literal (do nothing) */
394        ret = op_array->last_literal - 1;
395    } else {
396        ret = zend_add_literal(op_array, zv TSRMLS_CC);
397    }
398
399    lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
400    ZVAL_STRINGL(&c, lc_name, Z_STRLEN_P(zv), 0);
401    lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
402    CALCULATE_LITERAL_HASH(lc_literal);
403
404    return ret;
405}
406/* }}} */
407
408int zend_add_ns_func_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) /* {{{ */
409{
410    int ret;
411    char *lc_name;
412    const char *ns_separator;
413    int lc_len;
414    zval c;
415    int lc_literal;
416
417    if (op_array->last_literal > 0 &&
418        &op_array->literals[op_array->last_literal - 1].constant == zv &&
419        op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
420        /* we already have function name as last literal (do nothing) */
421        ret = op_array->last_literal - 1;
422    } else {
423        ret = zend_add_literal(op_array, zv TSRMLS_CC);
424    }
425
426    lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv), Z_STRLEN_P(zv));
427    ZVAL_STRINGL(&c, lc_name, Z_STRLEN_P(zv), 0);
428    lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
429    CALCULATE_LITERAL_HASH(lc_literal);
430
431    ns_separator = (const char*)zend_memrchr(Z_STRVAL_P(zv), '\\', Z_STRLEN_P(zv));
432
433    if (ns_separator != NULL) {
434        ns_separator += 1;
435        lc_len = Z_STRLEN_P(zv) - (ns_separator - Z_STRVAL_P(zv));
436        lc_name = zend_str_tolower_dup(ns_separator, lc_len);
437        ZVAL_STRINGL(&c, lc_name, lc_len, 0);
438        lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
439        CALCULATE_LITERAL_HASH(lc_literal);
440    }
441
442    return ret;
443}
444/* }}} */
445
446int zend_add_class_name_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC) /* {{{ */
447{
448    int ret;
449    char *lc_name;
450    int lc_len;
451    zval c;
452    int lc_literal;
453
454    if (op_array->last_literal > 0 &&
455        &op_array->literals[op_array->last_literal - 1].constant == zv &&
456        op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
457        /* we already have function name as last literal (do nothing) */
458        ret = op_array->last_literal - 1;
459    } else {
460        ret = zend_add_literal(op_array, zv TSRMLS_CC);
461    }
462
463    if (Z_STRVAL_P(zv)[0] == '\\') {
464        lc_len = Z_STRLEN_P(zv) - 1;
465        lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv) + 1, lc_len);
466    } else {
467        lc_len = Z_STRLEN_P(zv);
468        lc_name = zend_str_tolower_dup(Z_STRVAL_P(zv), lc_len);
469    }
470    ZVAL_STRINGL(&c, lc_name, lc_len, 0);
471    lc_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
472    CALCULATE_LITERAL_HASH(lc_literal);
473
474    GET_CACHE_SLOT(ret);
475
476    return ret;
477}
478/* }}} */
479
480int zend_add_const_name_literal(zend_op_array *op_array, const zval *zv, int unqualified TSRMLS_DC) /* {{{ */
481{
482    int ret, tmp_literal;
483    char *name, *tmp_name;
484    const char *ns_separator;
485    int name_len, ns_len;
486    zval c;
487
488    if (op_array->last_literal > 0 &&
489        &op_array->literals[op_array->last_literal - 1].constant == zv &&
490        op_array->literals[op_array->last_literal - 1].cache_slot == -1) {
491        /* we already have function name as last literal (do nothing) */
492        ret = op_array->last_literal - 1;
493    } else {
494        ret = zend_add_literal(op_array, zv TSRMLS_CC);
495    }
496
497    /* skip leading '\\' */
498    if (Z_STRVAL_P(zv)[0] == '\\') {
499        name_len = Z_STRLEN_P(zv) - 1;
500        name = Z_STRVAL_P(zv) + 1;
501    } else {
502        name_len = Z_STRLEN_P(zv);
503        name = Z_STRVAL_P(zv);
504    }
505    ns_separator = zend_memrchr(name, '\\', name_len);
506    if (ns_separator) {
507        ns_len = ns_separator - name;
508    } else {
509        ns_len = 0;
510    }
511
512    if (ns_len) {
513        /* lowercased namespace name & original constant name */
514        tmp_name = estrndup(name, name_len);
515        zend_str_tolower(tmp_name, ns_len);
516        ZVAL_STRINGL(&c, tmp_name, name_len, 0);
517        tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
518        CALCULATE_LITERAL_HASH(tmp_literal);
519
520        /* lowercased namespace name & lowercased constant name */
521        tmp_name = zend_str_tolower_dup(name, name_len);
522        ZVAL_STRINGL(&c, tmp_name, name_len, 0);
523        tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
524        CALCULATE_LITERAL_HASH(tmp_literal);
525    }
526
527    if (ns_len) {
528        if (!unqualified) {
529            return ret;
530        }
531        ns_len++;
532        name += ns_len;
533        name_len -= ns_len;
534    }
535
536    /* original constant name */
537    tmp_name = estrndup(name, name_len);
538    ZVAL_STRINGL(&c, tmp_name, name_len, 0);
539    tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
540    CALCULATE_LITERAL_HASH(tmp_literal);
541
542    /* lowercased constant name */
543    tmp_name = zend_str_tolower_dup(name, name_len);
544    ZVAL_STRINGL(&c, tmp_name, name_len, 0);
545    tmp_literal = zend_add_literal(CG(active_op_array), &c TSRMLS_CC);
546    CALCULATE_LITERAL_HASH(tmp_literal);
547
548    return ret;
549}
550/* }}} */
551
552#define LITERAL_STRINGL(op, str, len, copy) do { \
553        zval _c; \
554        ZVAL_STRINGL(&_c, str, len, copy); \
555        op.constant = zend_add_literal(CG(active_op_array), &_c TSRMLS_CC); \
556    } while (0)
557
558#define LITERAL_LONG(op, val) do { \
559        zval _c; \
560        ZVAL_LONG(&_c, val); \
561        op.constant = zend_add_literal(CG(active_op_array), &_c TSRMLS_CC); \
562    } while (0)
563
564#define LITERAL_LONG_EX(op_array, op, val) do { \
565        zval _c; \
566        ZVAL_LONG(&_c, val); \
567        op.constant = zend_add_literal(op_array, &_c TSRMLS_CC); \
568    } while (0)
569
570#define LITERAL_NULL(op) do { \
571        zval _c; \
572        INIT_ZVAL(  _c); \
573        op.constant = zend_add_literal(CG(active_op_array), &_c TSRMLS_CC); \
574    } while (0)
575
576static inline zend_bool zend_is_function_or_method_call(const znode *variable) /* {{{ */
577{
578    zend_uint type = variable->EA;
579
580    return  ((type & ZEND_PARSED_METHOD_CALL) || (type == ZEND_PARSED_FUNCTION_CALL));
581}
582/* }}} */
583
584void zend_do_binary_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
585{
586    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
587
588    opline->opcode = op;
589    opline->result_type = IS_TMP_VAR;
590    opline->result.var = get_temporary_variable(CG(active_op_array));
591    SET_NODE(opline->op1, op1);
592    SET_NODE(opline->op2, op2);
593    GET_NODE(result, opline->result);
594}
595/* }}} */
596
597void zend_do_unary_op(zend_uchar op, znode *result, const znode *op1 TSRMLS_DC) /* {{{ */
598{
599    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
600
601    opline->opcode = op;
602    opline->result_type = IS_TMP_VAR;
603    opline->result.var = get_temporary_variable(CG(active_op_array));
604    SET_NODE(opline->op1, op1);
605    GET_NODE(result, opline->result);
606    SET_UNUSED(opline->op2);
607}
608/* }}} */
609
610#define MAKE_NOP(opline)    { opline->opcode = ZEND_NOP;  memset(&opline->result,0,sizeof(opline->result)); memset(&opline->op1,0,sizeof(opline->op1)); memset(&opline->op2,0,sizeof(opline->op2)); opline->result_type=opline->op1_type=opline->op2_type=IS_UNUSED;  }
611
612static void zend_do_op_data(zend_op *data_op, const znode *value TSRMLS_DC) /* {{{ */
613{
614    data_op->opcode = ZEND_OP_DATA;
615    SET_NODE(data_op->op1, value);
616    SET_UNUSED(data_op->op2);
617}
618/* }}} */
619
620void zend_do_binary_assign_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
621{
622    int last_op_number = get_next_op_number(CG(active_op_array));
623    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
624
625    if (last_op_number > 0) {
626        zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
627
628        switch (last_op->opcode) {
629            case ZEND_FETCH_OBJ_RW:
630                last_op->opcode = op;
631                last_op->extended_value = ZEND_ASSIGN_OBJ;
632
633                zend_do_op_data(opline, op2 TSRMLS_CC);
634                SET_UNUSED(opline->result);
635                GET_NODE(result, last_op->result);
636                return;
637            case ZEND_FETCH_DIM_RW:
638                last_op->opcode = op;
639                last_op->extended_value = ZEND_ASSIGN_DIM;
640
641                zend_do_op_data(opline, op2 TSRMLS_CC);
642                opline->op2.var = get_temporary_variable(CG(active_op_array));
643                opline->op2_type = IS_VAR;
644                SET_UNUSED(opline->result);
645                GET_NODE(result,last_op->result);
646                return;
647            default:
648                break;
649        }
650    }
651
652    opline->opcode = op;
653    SET_NODE(opline->op1, op1);
654    SET_NODE(opline->op2, op2);
655    opline->result_type = IS_VAR;
656    opline->result.var = get_temporary_variable(CG(active_op_array));
657    GET_NODE(result, opline->result);
658}
659/* }}} */
660
661void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar op TSRMLS_DC) /* {{{ */
662{
663    zend_op opline;
664    zend_op *opline_ptr;
665    zend_llist *fetch_list_ptr;
666
667    if (varname->op_type == IS_CONST) {
668        ulong hash;
669
670        if (Z_TYPE(varname->u.constant) != IS_STRING) {
671            convert_to_string(&varname->u.constant);
672        }
673
674        hash = str_hash(Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant));
675        if (!zend_is_auto_global_quick(Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant), hash TSRMLS_CC) &&
676            !(Z_STRLEN(varname->u.constant) == (sizeof("this")-1) &&
677              !memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this") - 1)) &&
678            (CG(active_op_array)->last == 0 ||
679             CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE)) {
680            result->op_type = IS_CV;
681            result->u.op.var = lookup_cv(CG(active_op_array), Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant), hash TSRMLS_CC);
682            Z_STRVAL(varname->u.constant) = (char*)CG(active_op_array)->vars[result->u.op.var].name;
683            result->EA = 0;
684            return;
685        }
686    }
687
688    if (bp) {
689        opline_ptr = &opline;
690        init_op(opline_ptr TSRMLS_CC);
691    } else {
692        opline_ptr = get_next_op(CG(active_op_array) TSRMLS_CC);
693    }
694
695    opline_ptr->opcode = op;
696    opline_ptr->result_type = IS_VAR;
697    opline_ptr->result.var = get_temporary_variable(CG(active_op_array));
698    SET_NODE(opline_ptr->op1, varname);
699    GET_NODE(result, opline_ptr->result);
700    SET_UNUSED(opline_ptr->op2);
701    opline_ptr->extended_value = ZEND_FETCH_LOCAL;
702
703    if (varname->op_type == IS_CONST) {
704        CALCULATE_LITERAL_HASH(opline_ptr->op1.constant);
705        if (zend_is_auto_global_quick(Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant), Z_HASH_P(&CONSTANT(opline_ptr->op1.constant)) TSRMLS_CC)) {
706            opline_ptr->extended_value = ZEND_FETCH_GLOBAL;
707        }
708    }
709
710    if (bp) {
711        zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
712        zend_llist_add_element(fetch_list_ptr, opline_ptr);
713    }
714}
715/* }}} */
716
717void fetch_simple_variable(znode *result, znode *varname, int bp TSRMLS_DC) /* {{{ */
718{
719    /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
720    fetch_simple_variable_ex(result, varname, bp, ZEND_FETCH_W TSRMLS_CC);
721}
722/* }}} */
723
724void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
725{
726    znode class_node;
727    zend_llist *fetch_list_ptr;
728    zend_llist_element *le;
729    zend_op *opline_ptr;
730    zend_op opline;
731
732    if (class_name->op_type == IS_CONST &&
733        ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
734        zend_resolve_class_name(class_name TSRMLS_CC);
735        class_node = *class_name;
736    } else {
737        zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
738    }
739    zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
740    if (result->op_type == IS_CV) {
741        init_op(&opline TSRMLS_CC);
742
743        opline.opcode = ZEND_FETCH_W;
744        opline.result_type = IS_VAR;
745        opline.result.var = get_temporary_variable(CG(active_op_array));
746        opline.op1_type = IS_CONST;
747        LITERAL_STRINGL(opline.op1, estrdup(CG(active_op_array)->vars[result->u.op.var].name), CG(active_op_array)->vars[result->u.op.var].name_len, 0);
748        CALCULATE_LITERAL_HASH(opline.op1.constant);
749        GET_POLYMORPHIC_CACHE_SLOT(opline.op1.constant);
750        if (class_node.op_type == IS_CONST) {
751            opline.op2_type = IS_CONST;
752            opline.op2.constant =
753                zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
754        } else {
755            SET_NODE(opline.op2, &class_node);
756        }
757        GET_NODE(result,opline.result);
758        opline.extended_value |= ZEND_FETCH_STATIC_MEMBER;
759        opline_ptr = &opline;
760
761        zend_llist_add_element(fetch_list_ptr, &opline);
762    } else {
763        le = fetch_list_ptr->head;
764
765        opline_ptr = (zend_op *)le->data;
766        if (opline_ptr->opcode != ZEND_FETCH_W && opline_ptr->op1_type == IS_CV) {
767            init_op(&opline TSRMLS_CC);
768            opline.opcode = ZEND_FETCH_W;
769            opline.result_type = IS_VAR;
770            opline.result.var = get_temporary_variable(CG(active_op_array));
771            opline.op1_type = IS_CONST;
772            LITERAL_STRINGL(opline.op1, estrdup(CG(active_op_array)->vars[opline_ptr->op1.var].name), CG(active_op_array)->vars[opline_ptr->op1.var].name_len, 0);
773            CALCULATE_LITERAL_HASH(opline.op1.constant);
774            GET_POLYMORPHIC_CACHE_SLOT(opline.op1.constant);
775            if (class_node.op_type == IS_CONST) {
776                opline.op2_type = IS_CONST;
777                opline.op2.constant =
778                    zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
779            } else {
780                SET_NODE(opline.op2, &class_node);
781            }
782            opline.extended_value |= ZEND_FETCH_STATIC_MEMBER;
783            COPY_NODE(opline_ptr->op1, opline.result);
784
785            zend_llist_prepend_element(fetch_list_ptr, &opline);
786        } else {
787            if (opline_ptr->op1_type == IS_CONST) {
788                GET_POLYMORPHIC_CACHE_SLOT(opline_ptr->op1.constant);
789            }
790            if (class_node.op_type == IS_CONST) {
791                opline_ptr->op2_type = IS_CONST;
792                opline_ptr->op2.constant =
793                    zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
794            } else {
795                SET_NODE(opline_ptr->op2, &class_node);
796            }
797            opline_ptr->extended_value |= ZEND_FETCH_STATIC_MEMBER;
798        }
799    }
800}
801/* }}} */
802
803void fetch_array_begin(znode *result, znode *varname, znode *first_dim TSRMLS_DC) /* {{{ */
804{
805    fetch_simple_variable(result, varname, 1 TSRMLS_CC);
806
807    fetch_array_dim(result, result, first_dim TSRMLS_CC);
808}
809/* }}} */
810
811void fetch_array_dim(znode *result, const znode *parent, const znode *dim TSRMLS_DC) /* {{{ */
812{
813    zend_op opline;
814    zend_llist *fetch_list_ptr;
815
816    zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
817
818    if (zend_is_function_or_method_call(parent)) {
819        init_op(&opline TSRMLS_CC);
820        opline.opcode = ZEND_SEPARATE;
821        SET_NODE(opline.op1, parent);
822        SET_UNUSED(opline.op2);
823        opline.result_type = IS_VAR;
824        opline.result.var = opline.op1.var;
825        zend_llist_add_element(fetch_list_ptr, &opline);
826    }
827
828    init_op(&opline TSRMLS_CC);
829    opline.opcode = ZEND_FETCH_DIM_W;   /* the backpatching routine assumes W */
830    opline.result_type = IS_VAR;
831    opline.result.var = get_temporary_variable(CG(active_op_array));
832    SET_NODE(opline.op1, parent);
833    SET_NODE(opline.op2, dim);
834    if (opline.op2_type == IS_CONST && Z_TYPE(CONSTANT(opline.op2.constant)) == IS_STRING) {
835        ulong index;
836        int numeric = 0;
837
838        ZEND_HANDLE_NUMERIC_EX(Z_STRVAL(CONSTANT(opline.op2.constant)), Z_STRLEN(CONSTANT(opline.op2.constant))+1, index, numeric = 1);
839        if (numeric) {
840            zval_dtor(&CONSTANT(opline.op2.constant));
841            ZVAL_LONG(&CONSTANT(opline.op2.constant), index);
842        } else {
843            CALCULATE_LITERAL_HASH(opline.op2.constant);
844        }
845    }
846
847    GET_NODE(result, opline.result);
848
849    zend_llist_add_element(fetch_list_ptr, &opline);
850}
851/* }}} */
852
853void fetch_string_offset(znode *result, const znode *parent, const znode *offset TSRMLS_DC) /* {{{ */
854{
855    fetch_array_dim(result, parent, offset TSRMLS_CC);
856}
857/* }}} */
858
859void zend_do_print(znode *result, const znode *arg TSRMLS_DC) /* {{{ */
860{
861    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
862
863    opline->result_type = IS_TMP_VAR;
864    opline->result.var = get_temporary_variable(CG(active_op_array));
865    opline->opcode = ZEND_PRINT;
866    SET_NODE(opline->op1, arg);
867    SET_UNUSED(opline->op2);
868    GET_NODE(result, opline->result);
869}
870/* }}} */
871
872void zend_do_echo(const znode *arg TSRMLS_DC) /* {{{ */
873{
874    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
875
876    opline->opcode = ZEND_ECHO;
877    SET_NODE(opline->op1, arg);
878    SET_UNUSED(opline->op2);
879}
880/* }}} */
881
882void zend_do_abstract_method(const znode *function_name, znode *modifiers, const znode *body TSRMLS_DC) /* {{{ */
883{
884    char *method_type;
885
886    if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
887        Z_LVAL(modifiers->u.constant) |= ZEND_ACC_ABSTRACT;
888        method_type = "Interface";
889    } else {
890        method_type = "Abstract";
891    }
892
893    if (Z_LVAL(modifiers->u.constant) & ZEND_ACC_ABSTRACT) {
894        if(Z_LVAL(modifiers->u.constant) & ZEND_ACC_PRIVATE) {
895            zend_error_noreturn(E_COMPILE_ERROR, "%s function %s::%s() cannot be declared private", method_type, CG(active_class_entry)->name, Z_STRVAL(function_name->u.constant));
896        }
897        if (Z_LVAL(body->u.constant) == ZEND_ACC_ABSTRACT) {
898            zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
899
900            opline->opcode = ZEND_RAISE_ABSTRACT_ERROR;
901            SET_UNUSED(opline->op1);
902            SET_UNUSED(opline->op2);
903        } else {
904            /* we had code in the function body */
905            zend_error_noreturn(E_COMPILE_ERROR, "%s function %s::%s() cannot contain body", method_type, CG(active_class_entry)->name, Z_STRVAL(function_name->u.constant));
906        }
907    } else {
908        if (Z_LVAL(body->u.constant) == ZEND_ACC_ABSTRACT) {
909            zend_error_noreturn(E_COMPILE_ERROR, "Non-abstract method %s::%s() must contain body", CG(active_class_entry)->name, Z_STRVAL(function_name->u.constant));
910        }
911    }
912}
913/* }}} */
914
915static zend_bool opline_is_fetch_this(const zend_op *opline TSRMLS_DC) /* {{{ */
916{
917    if ((opline->opcode == ZEND_FETCH_W) && (opline->op1_type == IS_CONST)
918        && (Z_TYPE(CONSTANT(opline->op1.constant)) == IS_STRING)
919        && ((opline->extended_value & ZEND_FETCH_STATIC_MEMBER) != ZEND_FETCH_STATIC_MEMBER)
920        && (Z_HASH_P(&CONSTANT(opline->op1.constant)) == THIS_HASHVAL)
921        && (Z_STRLEN(CONSTANT(opline->op1.constant)) == (sizeof("this")-1))
922        && !memcmp(Z_STRVAL(CONSTANT(opline->op1.constant)), "this", sizeof("this") - 1)) {
923        return 1;
924    } else {
925        return 0;
926    }
927}
928/* }}} */
929
930void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC) /* {{{ */
931{
932    int last_op_number;
933    zend_op *opline;
934
935    if (value->op_type == IS_CV) {
936        zend_llist *fetch_list_ptr;
937
938        zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
939        if (fetch_list_ptr && fetch_list_ptr->head) {
940            opline = (zend_op *)fetch_list_ptr->head->data;
941
942            if (opline->opcode == ZEND_FETCH_DIM_W &&
943                opline->op1_type == IS_CV &&
944                opline->op1.var == value->u.op.var) {
945
946                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
947                opline->opcode = ZEND_FETCH_R;
948                opline->result_type = IS_VAR;
949                opline->result.var = get_temporary_variable(CG(active_op_array));
950                opline->op1_type = IS_CONST;
951                LITERAL_STRINGL(opline->op1,
952                    CG(active_op_array)->vars[value->u.op.var].name,
953                    CG(active_op_array)->vars[value->u.op.var].name_len, 1);
954                CALCULATE_LITERAL_HASH(opline->op1.constant);
955                SET_UNUSED(opline->op2);
956                opline->extended_value = ZEND_FETCH_LOCAL;
957                GET_NODE(value, opline->result);
958            }
959        }
960    }
961
962    zend_do_end_variable_parse(variable, BP_VAR_W, 0 TSRMLS_CC);
963
964    last_op_number = get_next_op_number(CG(active_op_array));
965    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
966
967    if (variable->op_type == IS_CV) {
968        if (variable->u.op.var == CG(active_op_array)->this_var) {
969            zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
970        }
971    } else if (variable->op_type == IS_VAR) {
972        int n = 0;
973
974        while (last_op_number - n > 0) {
975            zend_op *last_op;
976
977            last_op = &CG(active_op_array)->opcodes[last_op_number-n-1];
978
979            if (last_op->result_type == IS_VAR &&
980                last_op->result.var == variable->u.op.var) {
981                if (last_op->opcode == ZEND_FETCH_OBJ_W) {
982                    if (n > 0) {
983                        int opline_no = (opline-CG(active_op_array)->opcodes)/sizeof(*opline);
984                        *opline = *last_op;
985                        MAKE_NOP(last_op);
986                        /* last_op = opline; */
987                        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
988                        /* get_next_op can realloc, we need to move last_op */
989                        last_op = &CG(active_op_array)->opcodes[opline_no];
990                    }
991                    last_op->opcode = ZEND_ASSIGN_OBJ;
992                    zend_do_op_data(opline, value TSRMLS_CC);
993                    SET_UNUSED(opline->result);
994                    GET_NODE(result, last_op->result);
995                    return;
996                } else if (last_op->opcode == ZEND_FETCH_DIM_W) {
997                    if (n > 0) {
998                        int opline_no = (opline-CG(active_op_array)->opcodes)/sizeof(*opline);
999                        *opline = *last_op;
1000                        MAKE_NOP(last_op);
1001                        /* last_op = opline; */
1002                        /* TBFixed: this can realloc opcodes, leaving last_op pointing wrong */
1003                        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1004                        /* get_next_op can realloc, we need to move last_op */
1005                        last_op = &CG(active_op_array)->opcodes[opline_no];
1006                    }
1007                    last_op->opcode = ZEND_ASSIGN_DIM;
1008                    zend_do_op_data(opline, value TSRMLS_CC);
1009                    opline->op2.var = get_temporary_variable(CG(active_op_array));
1010                    opline->op2_type = IS_VAR;
1011                    SET_UNUSED(opline->result);
1012                    GET_NODE(result, last_op->result);
1013                    return;
1014                } else if (opline_is_fetch_this(last_op TSRMLS_CC)) {
1015                    zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
1016                } else {
1017                    break;
1018                }
1019            }
1020            n++;
1021        }
1022    }
1023
1024    opline->opcode = ZEND_ASSIGN;
1025    SET_NODE(opline->op1, variable);
1026    SET_NODE(opline->op2, value);
1027    opline->result_type = IS_VAR;
1028    opline->result.var = get_temporary_variable(CG(active_op_array));
1029    GET_NODE(result, opline->result);
1030}
1031/* }}} */
1032
1033void zend_do_assign_ref(znode *result, const znode *lvar, const znode *rvar TSRMLS_DC) /* {{{ */
1034{
1035    zend_op *opline;
1036
1037    if (lvar->op_type == IS_CV) {
1038        if (lvar->u.op.var == CG(active_op_array)->this_var) {
1039            zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
1040        }
1041    } else if (lvar->op_type == IS_VAR) {
1042        int last_op_number = get_next_op_number(CG(active_op_array));
1043
1044        if (last_op_number > 0) {
1045            opline = &CG(active_op_array)->opcodes[last_op_number-1];
1046            if (opline_is_fetch_this(opline TSRMLS_CC)) {
1047                zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
1048            }
1049        }
1050    }
1051
1052    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1053    opline->opcode = ZEND_ASSIGN_REF;
1054    if (zend_is_function_or_method_call(rvar)) {
1055        opline->extended_value = ZEND_RETURNS_FUNCTION;
1056    } else if (rvar->EA & ZEND_PARSED_NEW) {
1057        opline->extended_value = ZEND_RETURNS_NEW;
1058    } else {
1059        opline->extended_value = 0;
1060    }
1061    if (result) {
1062        opline->result_type = IS_VAR;
1063        opline->result.var = get_temporary_variable(CG(active_op_array));
1064        GET_NODE(result, opline->result);
1065    } else {
1066        opline->result_type = IS_UNUSED | EXT_TYPE_UNUSED;
1067    }
1068    SET_NODE(opline->op1, lvar);
1069    SET_NODE(opline->op2, rvar);
1070}
1071/* }}} */
1072
1073static inline void do_begin_loop(TSRMLS_D) /* {{{ */
1074{
1075    zend_brk_cont_element *brk_cont_element;
1076    int parent;
1077
1078    parent = CG(context).current_brk_cont;
1079    CG(context).current_brk_cont = CG(active_op_array)->last_brk_cont;
1080    brk_cont_element = get_next_brk_cont_element(CG(active_op_array));
1081    brk_cont_element->start = get_next_op_number(CG(active_op_array));
1082    brk_cont_element->parent = parent;
1083}
1084/* }}} */
1085
1086static inline void do_end_loop(int cont_addr, int has_loop_var TSRMLS_DC) /* {{{ */
1087{
1088    if (!has_loop_var) {
1089        /* The start fileld is used to free temporary variables in case of exceptions.
1090         * We won't try to free something of we don't have loop variable.
1091         */
1092        CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].start = -1;
1093    }
1094    CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].cont = cont_addr;
1095    CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].brk = get_next_op_number(CG(active_op_array));
1096    CG(context).current_brk_cont = CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].parent;
1097}
1098/* }}} */
1099
1100void zend_do_while_cond(const znode *expr, znode *close_bracket_token TSRMLS_DC) /* {{{ */
1101{
1102    int while_cond_op_number = get_next_op_number(CG(active_op_array));
1103    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1104
1105    opline->opcode = ZEND_JMPZ;
1106    SET_NODE(opline->op1, expr);
1107    close_bracket_token->u.op.opline_num = while_cond_op_number;
1108    SET_UNUSED(opline->op2);
1109
1110    do_begin_loop(TSRMLS_C);
1111    INC_BPC(CG(active_op_array));
1112}
1113/* }}} */
1114
1115void zend_do_while_end(const znode *while_token, const znode *close_bracket_token TSRMLS_DC) /* {{{ */
1116{
1117    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1118
1119    /* add unconditional jump */
1120    opline->opcode = ZEND_JMP;
1121    opline->op1.opline_num = while_token->u.op.opline_num;
1122    SET_UNUSED(opline->op1);
1123    SET_UNUSED(opline->op2);
1124
1125    /* update while's conditional jmp */
1126    CG(active_op_array)->opcodes[close_bracket_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
1127
1128    do_end_loop(while_token->u.op.opline_num, 0 TSRMLS_CC);
1129
1130    DEC_BPC(CG(active_op_array));
1131}
1132/* }}} */
1133
1134void zend_do_for_cond(const znode *expr, znode *second_semicolon_token TSRMLS_DC) /* {{{ */
1135{
1136    int for_cond_op_number = get_next_op_number(CG(active_op_array));
1137    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1138
1139    opline->opcode = ZEND_JMPZNZ;
1140    SET_NODE(opline->op1, expr);  /* the conditional expression */
1141    second_semicolon_token->u.op.opline_num = for_cond_op_number;
1142    SET_UNUSED(opline->op2);
1143}
1144/* }}} */
1145
1146void zend_do_for_before_statement(const znode *cond_start, const znode *second_semicolon_token TSRMLS_DC) /* {{{ */
1147{
1148    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1149
1150    opline->opcode = ZEND_JMP;
1151    opline->op1.opline_num = cond_start->u.op.opline_num;
1152    CG(active_op_array)->opcodes[second_semicolon_token->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
1153    SET_UNUSED(opline->op1);
1154    SET_UNUSED(opline->op2);
1155
1156    do_begin_loop(TSRMLS_C);
1157
1158    INC_BPC(CG(active_op_array));
1159}
1160/* }}} */
1161
1162void zend_do_for_end(const znode *second_semicolon_token TSRMLS_DC) /* {{{ */
1163{
1164    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1165
1166    opline->opcode = ZEND_JMP;
1167    opline->op1.opline_num = second_semicolon_token->u.op.opline_num+1;
1168    CG(active_op_array)->opcodes[second_semicolon_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
1169    SET_UNUSED(opline->op1);
1170    SET_UNUSED(opline->op2);
1171
1172    do_end_loop(second_semicolon_token->u.op.opline_num+1, 0 TSRMLS_CC);
1173
1174    DEC_BPC(CG(active_op_array));
1175}
1176/* }}} */
1177
1178void zend_do_pre_incdec(znode *result, const znode *op1, zend_uchar op TSRMLS_DC) /* {{{ */
1179{
1180    int last_op_number = get_next_op_number(CG(active_op_array));
1181    zend_op *opline;
1182
1183    if (last_op_number > 0) {
1184        zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
1185
1186        if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
1187            last_op->opcode = (op==ZEND_PRE_INC)?ZEND_PRE_INC_OBJ:ZEND_PRE_DEC_OBJ;
1188            last_op->result_type = IS_VAR;
1189            last_op->result.var = get_temporary_variable(CG(active_op_array));
1190            GET_NODE(result, last_op->result);
1191            return;
1192        }
1193    }
1194
1195    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1196    opline->opcode = op;
1197    SET_NODE(opline->op1, op1);
1198    SET_UNUSED(opline->op2);
1199    opline->result_type = IS_VAR;
1200    opline->result.var = get_temporary_variable(CG(active_op_array));
1201    GET_NODE(result, opline->result);
1202}
1203/* }}} */
1204
1205void zend_do_post_incdec(znode *result, const znode *op1, zend_uchar op TSRMLS_DC) /* {{{ */
1206{
1207    int last_op_number = get_next_op_number(CG(active_op_array));
1208    zend_op *opline;
1209
1210    if (last_op_number > 0) {
1211        zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
1212
1213        if (last_op->opcode == ZEND_FETCH_OBJ_RW) {
1214            last_op->opcode = (op==ZEND_POST_INC)?ZEND_POST_INC_OBJ:ZEND_POST_DEC_OBJ;
1215            last_op->result_type = IS_TMP_VAR;
1216            last_op->result.var = get_temporary_variable(CG(active_op_array));
1217            GET_NODE(result, last_op->result);
1218            return;
1219        }
1220    }
1221
1222    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1223    opline->opcode = op;
1224    SET_NODE(opline->op1, op1);
1225    SET_UNUSED(opline->op2);
1226    opline->result_type = IS_TMP_VAR;
1227    opline->result.var = get_temporary_variable(CG(active_op_array));
1228    GET_NODE(result, opline->result);
1229}
1230/* }}} */
1231
1232void zend_do_if_cond(const znode *cond, znode *closing_bracket_token TSRMLS_DC) /* {{{ */
1233{
1234    int if_cond_op_number = get_next_op_number(CG(active_op_array));
1235    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1236
1237    opline->opcode = ZEND_JMPZ;
1238    SET_NODE(opline->op1, cond);
1239    closing_bracket_token->u.op.opline_num = if_cond_op_number;
1240    SET_UNUSED(opline->op2);
1241    INC_BPC(CG(active_op_array));
1242}
1243/* }}} */
1244
1245void zend_do_if_after_statement(const znode *closing_bracket_token, unsigned char initialize TSRMLS_DC) /* {{{ */
1246{
1247    int if_end_op_number = get_next_op_number(CG(active_op_array));
1248    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1249    zend_llist *jmp_list_ptr;
1250
1251    opline->opcode = ZEND_JMP;
1252    /* save for backpatching */
1253    if (initialize) {
1254        zend_llist jmp_list;
1255
1256        zend_llist_init(&jmp_list, sizeof(int), NULL, 0);
1257        zend_stack_push(&CG(bp_stack), (void *) &jmp_list, sizeof(zend_llist));
1258    }
1259    zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
1260    zend_llist_add_element(jmp_list_ptr, &if_end_op_number);
1261
1262    CG(active_op_array)->opcodes[closing_bracket_token->u.op.opline_num].op2.opline_num = if_end_op_number+1;
1263    SET_UNUSED(opline->op1);
1264    SET_UNUSED(opline->op2);
1265}
1266/* }}} */
1267
1268void zend_do_if_end(TSRMLS_D) /* {{{ */
1269{
1270    int next_op_number = get_next_op_number(CG(active_op_array));
1271    zend_llist *jmp_list_ptr;
1272    zend_llist_element *le;
1273
1274    zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
1275    for (le=jmp_list_ptr->head; le; le = le->next) {
1276        CG(active_op_array)->opcodes[*((int *) le->data)].op1.opline_num = next_op_number;
1277    }
1278    zend_llist_destroy(jmp_list_ptr);
1279    zend_stack_del_top(&CG(bp_stack));
1280    DEC_BPC(CG(active_op_array));
1281}
1282/* }}} */
1283
1284void zend_check_writable_variable(const znode *variable) /* {{{ */
1285{
1286    zend_uint type = variable->EA;
1287
1288    if (type & ZEND_PARSED_METHOD_CALL) {
1289        zend_error_noreturn(E_COMPILE_ERROR, "Can't use method return value in write context");
1290    }
1291    if (type == ZEND_PARSED_FUNCTION_CALL) {
1292        zend_error_noreturn(E_COMPILE_ERROR, "Can't use function return value in write context");
1293    }
1294}
1295/* }}} */
1296
1297void zend_do_begin_variable_parse(TSRMLS_D) /* {{{ */
1298{
1299    zend_llist fetch_list;
1300
1301    zend_llist_init(&fetch_list, sizeof(zend_op), NULL, 0);
1302    zend_stack_push(&CG(bp_stack), (void *) &fetch_list, sizeof(zend_llist));
1303}
1304/* }}} */
1305
1306void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS_DC) /* {{{ */
1307{
1308    zend_llist *fetch_list_ptr;
1309    zend_llist_element *le;
1310    zend_op *opline = NULL;
1311    zend_op *opline_ptr;
1312    zend_uint this_var = -1;
1313
1314    zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
1315
1316    le = fetch_list_ptr->head;
1317
1318    /* TODO: $foo->x->y->z = 1 should fetch "x" and "y" for R or RW, not just W */
1319
1320    if (le) {
1321        opline_ptr = (zend_op *)le->data;
1322        if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
1323            /* convert to FETCH_?(this) into IS_CV */
1324            if (CG(active_op_array)->last == 0 ||
1325                CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE) {
1326
1327                this_var = opline_ptr->result.var;
1328                if (CG(active_op_array)->this_var == -1) {
1329                    CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), Z_STRVAL(CONSTANT(opline_ptr->op1.constant)), Z_STRLEN(CONSTANT(opline_ptr->op1.constant)), Z_HASH_P(&CONSTANT(opline_ptr->op1.constant)) TSRMLS_CC);
1330                    Z_TYPE(CONSTANT(opline_ptr->op1.constant)) = IS_NULL;
1331                } else {
1332                    zend_del_literal(CG(active_op_array), opline_ptr->op1.constant);
1333                }
1334                le = le->next;
1335                if (variable->op_type == IS_VAR &&
1336                    variable->u.op.var == this_var) {
1337                    variable->op_type = IS_CV;
1338                    variable->u.op.var = CG(active_op_array)->this_var;
1339                }
1340            } else if (CG(active_op_array)->this_var == -1) {
1341                CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), estrndup("this", sizeof("this")-1), sizeof("this")-1, THIS_HASHVAL TSRMLS_CC);
1342            }
1343        }
1344
1345        while (le) {
1346            opline_ptr = (zend_op *)le->data;
1347            if (opline_ptr->opcode == ZEND_SEPARATE) {
1348                if (type != BP_VAR_R && type != BP_VAR_IS) {
1349                    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1350                    memcpy(opline, opline_ptr, sizeof(zend_op));
1351                }
1352                le = le->next;
1353                continue;
1354            }
1355            opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1356            memcpy(opline, opline_ptr, sizeof(zend_op));
1357            if (opline->op1_type == IS_VAR &&
1358                opline->op1.var == this_var) {
1359                opline->op1_type = IS_CV;
1360                opline->op1.var = CG(active_op_array)->this_var;
1361            }
1362            switch (type) {
1363                case BP_VAR_R:
1364                    if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2_type == IS_UNUSED) {
1365                        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
1366                    }
1367                    opline->opcode -= 3;
1368                    break;
1369                case BP_VAR_W:
1370                    break;
1371                case BP_VAR_RW:
1372                    opline->opcode += 3;
1373                    break;
1374                case BP_VAR_IS:
1375                    if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2_type == IS_UNUSED) {
1376                        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
1377                    }
1378                    opline->opcode += 6; /* 3+3 */
1379                    break;
1380                case BP_VAR_FUNC_ARG:
1381                    opline->opcode += 9; /* 3+3+3 */
1382                    opline->extended_value |= arg_offset;
1383                    break;
1384                case BP_VAR_UNSET:
1385                    if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2_type == IS_UNUSED) {
1386                        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for unsetting");
1387                    }
1388                    opline->opcode += 12; /* 3+3+3+3 */
1389                    break;
1390            }
1391            le = le->next;
1392        }
1393        if (opline && type == BP_VAR_W && arg_offset) {
1394            opline->extended_value |= ZEND_FETCH_MAKE_REF;
1395        }
1396    }
1397    zend_llist_destroy(fetch_list_ptr);
1398    zend_stack_del_top(&CG(bp_stack));
1399}
1400/* }}} */
1401
1402void zend_do_add_string(znode *result, const znode *op1, znode *op2 TSRMLS_DC) /* {{{ */
1403{
1404    zend_op *opline;
1405
1406    if (Z_STRLEN(op2->u.constant) > 1) {
1407        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1408        opline->opcode = ZEND_ADD_STRING;
1409    } else if (Z_STRLEN(op2->u.constant) == 1) {
1410        int ch = *Z_STRVAL(op2->u.constant);
1411
1412        /* Free memory and use ZEND_ADD_CHAR in case of 1 character strings */
1413        efree(Z_STRVAL(op2->u.constant));
1414        ZVAL_LONG(&op2->u.constant, ch);
1415        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1416        opline->opcode = ZEND_ADD_CHAR;
1417    } else { /* String can be empty after a variable at the end of a heredoc */
1418        efree(Z_STRVAL(op2->u.constant));
1419        return;
1420    }
1421
1422    if (op1) {
1423        SET_NODE(opline->op1, op1);
1424        SET_NODE(opline->result, op1);
1425    } else {
1426        SET_UNUSED(opline->op1);
1427        opline->result_type = IS_TMP_VAR;
1428        opline->result.var = get_temporary_variable(CG(active_op_array));
1429    }
1430    SET_NODE(opline->op2, op2);
1431    GET_NODE(result, opline->result);
1432}
1433/* }}} */
1434
1435void zend_do_add_variable(znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
1436{
1437    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1438
1439    opline->opcode = ZEND_ADD_VAR;
1440
1441    if (op1) {
1442        SET_NODE(opline->op1, op1);
1443        SET_NODE(opline->result, op1);
1444    } else {
1445        SET_UNUSED(opline->op1);
1446        opline->result_type = IS_TMP_VAR;
1447        opline->result.var = get_temporary_variable(CG(active_op_array));
1448    }
1449    SET_NODE(opline->op2, op2);
1450    GET_NODE(result, opline->result);
1451}
1452/* }}} */
1453
1454void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */
1455{
1456    if (op1->op_type==IS_TMP_VAR) {
1457        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1458
1459        opline->opcode = ZEND_FREE;
1460        SET_NODE(opline->op1, op1);
1461        SET_UNUSED(opline->op2);
1462    } else if (op1->op_type==IS_VAR) {
1463        zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
1464
1465        while (opline->opcode == ZEND_END_SILENCE || opline->opcode == ZEND_EXT_FCALL_END || opline->opcode == ZEND_OP_DATA) {
1466            opline--;
1467        }
1468        if (opline->result_type == IS_VAR
1469            && opline->result.var == op1->u.op.var) {
1470            if (opline->opcode == ZEND_FETCH_R ||
1471                opline->opcode == ZEND_FETCH_DIM_R ||
1472                opline->opcode == ZEND_FETCH_OBJ_R ||
1473                opline->opcode == ZEND_QM_ASSIGN_VAR) {
1474                /* It's very rare and useless case. It's better to use
1475                   additional FREE opcode and simplify the FETCH handlers
1476                   their selves */
1477                opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1478                opline->opcode = ZEND_FREE;
1479                SET_NODE(opline->op1, op1);
1480                SET_UNUSED(opline->op2);
1481            } else {
1482                opline->result_type |= EXT_TYPE_UNUSED;
1483            }
1484        } else {
1485            while (opline>CG(active_op_array)->opcodes) {
1486                if (opline->opcode == ZEND_FETCH_DIM_R
1487                    && opline->op1_type == IS_VAR
1488                    && opline->op1.var == op1->u.op.var) {
1489                    /* This should the end of a list() construct
1490                     * Mark its result as unused
1491                     */
1492                    opline->extended_value = ZEND_FETCH_STANDARD;
1493                    break;
1494                } else if (opline->result_type==IS_VAR
1495                    && opline->result.var == op1->u.op.var) {
1496                    if (opline->opcode == ZEND_NEW) {
1497                        opline->result_type |= EXT_TYPE_UNUSED;
1498                    }
1499                    break;
1500                }
1501                opline--;
1502            }
1503        }
1504    } else if (op1->op_type == IS_CONST) {
1505        zval_dtor(&op1->u.constant);
1506    }
1507}
1508/* }}} */
1509
1510int zend_do_verify_access_types(const znode *current_access_type, const znode *new_modifier) /* {{{ */
1511{
1512    if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_PPP_MASK)
1513        && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_PPP_MASK)) {
1514        zend_error_noreturn(E_COMPILE_ERROR, "Multiple access type modifiers are not allowed");
1515    }
1516    if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_ABSTRACT)
1517        && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_ABSTRACT)) {
1518        zend_error_noreturn(E_COMPILE_ERROR, "Multiple abstract modifiers are not allowed");
1519    }
1520    if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_STATIC)
1521        && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_STATIC)) {
1522        zend_error_noreturn(E_COMPILE_ERROR, "Multiple static modifiers are not allowed");
1523    }
1524    if ((Z_LVAL(current_access_type->u.constant) & ZEND_ACC_FINAL)
1525        && (Z_LVAL(new_modifier->u.constant) & ZEND_ACC_FINAL)) {
1526        zend_error_noreturn(E_COMPILE_ERROR, "Multiple final modifiers are not allowed");
1527    }
1528    if (((Z_LVAL(current_access_type->u.constant) | Z_LVAL(new_modifier->u.constant)) & (ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL)) == (ZEND_ACC_ABSTRACT | ZEND_ACC_FINAL)) {
1529        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use the final modifier on an abstract class member");
1530    }
1531    return (Z_LVAL(current_access_type->u.constant) | Z_LVAL(new_modifier->u.constant));
1532}
1533/* }}} */
1534
1535void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC) /* {{{ */
1536{
1537    zend_op_array op_array;
1538    char *name = Z_STRVAL(function_name->u.constant);
1539    int name_len = Z_STRLEN(function_name->u.constant);
1540    int function_begin_line = function_token->u.op.opline_num;
1541    zend_uint fn_flags;
1542    const char *lcname;
1543    zend_bool orig_interactive;
1544    ALLOCA_FLAG(use_heap)
1545
1546    if (is_method) {
1547        if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
1548            if ((Z_LVAL(fn_flags_znode->u.constant) & ~(ZEND_ACC_STATIC|ZEND_ACC_PUBLIC))) {
1549                zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface method %s::%s() must be omitted", CG(active_class_entry)->name, Z_STRVAL(function_name->u.constant));
1550            }
1551            Z_LVAL(fn_flags_znode->u.constant) |= ZEND_ACC_ABSTRACT; /* propagates to the rest of the parser */
1552        }
1553        fn_flags = Z_LVAL(fn_flags_znode->u.constant); /* must be done *after* the above check */
1554    } else {
1555        fn_flags = 0;
1556    }
1557    if ((fn_flags & ZEND_ACC_STATIC) && (fn_flags & ZEND_ACC_ABSTRACT) && !(CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) {
1558        zend_error(E_STRICT, "Static function %s%s%s() should not be abstract", is_method ? CG(active_class_entry)->name : "", is_method ? "::" : "", Z_STRVAL(function_name->u.constant));
1559    }
1560
1561    function_token->u.op_array = CG(active_op_array);
1562
1563    orig_interactive = CG(interactive);
1564    CG(interactive) = 0;
1565    init_op_array(&op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
1566    CG(interactive) = orig_interactive;
1567
1568    op_array.function_name = name;
1569    if (return_reference) {
1570        op_array.fn_flags |= ZEND_ACC_RETURN_REFERENCE;
1571    }
1572    op_array.fn_flags |= fn_flags;
1573
1574    op_array.scope = is_method?CG(active_class_entry):NULL;
1575    op_array.prototype = NULL;
1576
1577    op_array.line_start = zend_get_compiled_lineno(TSRMLS_C);
1578
1579    if (is_method) {
1580        zend_ulong hash;
1581
1582        lcname = zend_new_interned_string(zend_str_tolower_dup(name, name_len), name_len + 1, 1 TSRMLS_CC);
1583        hash = str_hash(lcname, name_len);
1584        if (zend_hash_quick_add(&CG(active_class_entry)->function_table, lcname, name_len+1, hash, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)) == FAILURE) {
1585            zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::%s()", CG(active_class_entry)->name, name);
1586        }
1587
1588        zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context)));
1589        zend_init_compiler_context(TSRMLS_C);
1590
1591        if (fn_flags & ZEND_ACC_ABSTRACT) {
1592            CG(active_class_entry)->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
1593        }
1594
1595        if (!(fn_flags & ZEND_ACC_PPP_MASK)) {
1596            fn_flags |= ZEND_ACC_PUBLIC;
1597        }
1598
1599        if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
1600            if ((name_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
1601                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1602                    zend_error(E_WARNING, "The magic method __call() must have public visibility and cannot be static");
1603                }
1604            } else if ((name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1))) {
1605                if ((fn_flags & (ZEND_ACC_PPP_MASK ^ ZEND_ACC_PUBLIC)) || (fn_flags & ZEND_ACC_STATIC) == 0) {
1606                    zend_error(E_WARNING, "The magic method __callStatic() must have public visibility and be static");
1607                }
1608            } else if ((name_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1))) {
1609                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1610                    zend_error(E_WARNING, "The magic method __get() must have public visibility and cannot be static");
1611                }
1612            } else if ((name_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1))) {
1613                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1614                    zend_error(E_WARNING, "The magic method __set() must have public visibility and cannot be static");
1615                }
1616            } else if ((name_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1))) {
1617                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1618                    zend_error(E_WARNING, "The magic method __unset() must have public visibility and cannot be static");
1619                }
1620            } else if ((name_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
1621                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1622                    zend_error(E_WARNING, "The magic method __isset() must have public visibility and cannot be static");
1623                }
1624            } else if ((name_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
1625                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1626                    zend_error(E_WARNING, "The magic method __toString() must have public visibility and cannot be static");
1627                }
1628            } else if ((name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1))) {
1629                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1630                    zend_error(E_WARNING, "The magic method __invoke() must have public visibility and cannot be static");
1631                }
1632
1633            } else if ((name_len == sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_DEBUGINFO_FUNC_NAME, sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1))) {
1634                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1635                    zend_error(E_WARNING, "The magic method __debugInfo() must have public visibility and cannot be static");
1636                }
1637            }
1638        } else {
1639            char *class_lcname;
1640
1641            class_lcname = do_alloca(CG(active_class_entry)->name_length + 1, use_heap);
1642            zend_str_tolower_copy(class_lcname, CG(active_class_entry)->name, CG(active_class_entry)->name_length);
1643            /* Improve after RC: cache the lowercase class name */
1644
1645            if ((CG(active_class_entry)->name_length == name_len) && ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) != ZEND_ACC_TRAIT) && (!memcmp(class_lcname, lcname, name_len))) {
1646                if (!CG(active_class_entry)->constructor) {
1647                    CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
1648                }
1649            } else if ((name_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)))) {
1650                if (CG(active_class_entry)->constructor) {
1651                    zend_error(E_STRICT, "Redefining already defined constructor for class %s", CG(active_class_entry)->name);
1652                }
1653                CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
1654            } else if ((name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1))) {
1655                CG(active_class_entry)->destructor = (zend_function *) CG(active_op_array);
1656            } else if ((name_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)-1))) {
1657                CG(active_class_entry)->clone = (zend_function *) CG(active_op_array);
1658            } else if ((name_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
1659                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1660                    zend_error(E_WARNING, "The magic method __call() must have public visibility and cannot be static");
1661                }
1662                CG(active_class_entry)->__call = (zend_function *) CG(active_op_array);
1663            } else if ((name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1))) {
1664                if ((fn_flags & (ZEND_ACC_PPP_MASK ^ ZEND_ACC_PUBLIC)) || (fn_flags & ZEND_ACC_STATIC) == 0) {
1665                    zend_error(E_WARNING, "The magic method __callStatic() must have public visibility and be static");
1666                }
1667                CG(active_class_entry)->__callstatic = (zend_function *) CG(active_op_array);
1668            } else if ((name_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1))) {
1669                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1670                    zend_error(E_WARNING, "The magic method __get() must have public visibility and cannot be static");
1671                }
1672                CG(active_class_entry)->__get = (zend_function *) CG(active_op_array);
1673            } else if ((name_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1))) {
1674                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1675                    zend_error(E_WARNING, "The magic method __set() must have public visibility and cannot be static");
1676                }
1677                CG(active_class_entry)->__set = (zend_function *) CG(active_op_array);
1678            } else if ((name_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1))) {
1679                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1680                    zend_error(E_WARNING, "The magic method __unset() must have public visibility and cannot be static");
1681                }
1682                CG(active_class_entry)->__unset = (zend_function *) CG(active_op_array);
1683            } else if ((name_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
1684                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1685                    zend_error(E_WARNING, "The magic method __isset() must have public visibility and cannot be static");
1686                }
1687                CG(active_class_entry)->__isset = (zend_function *) CG(active_op_array);
1688            } else if ((name_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
1689                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1690                    zend_error(E_WARNING, "The magic method __toString() must have public visibility and cannot be static");
1691                }
1692                CG(active_class_entry)->__tostring = (zend_function *) CG(active_op_array);
1693            } else if ((name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1))) {
1694                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1695                    zend_error(E_WARNING, "The magic method __invoke() must have public visibility and cannot be static");
1696                }
1697            } else if ((name_len == sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_DEBUGINFO_FUNC_NAME, sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1))) {
1698                if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
1699                    zend_error(E_WARNING, "The magic method __debugInfo() must have public visibility and cannot be static");
1700                }
1701                CG(active_class_entry)->__debugInfo = (zend_function *) CG(active_op_array);
1702            } else if (!(fn_flags & ZEND_ACC_STATIC)) {
1703                CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC;
1704            }
1705            free_alloca(class_lcname, use_heap);
1706        }
1707
1708        str_efree(lcname);
1709    } else {
1710        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1711        zval key;
1712        zval **ns_name;
1713
1714        if (CG(current_namespace)) {
1715            /* Prefix function name with current namespace name */
1716            znode tmp;
1717
1718            tmp.u.constant = *CG(current_namespace);
1719            zval_copy_ctor(&tmp.u.constant);
1720            zend_do_build_namespace_name(&tmp, &tmp, function_name TSRMLS_CC);
1721            op_array.function_name = Z_STRVAL(tmp.u.constant);
1722            name_len = Z_STRLEN(tmp.u.constant);
1723            lcname = zend_str_tolower_dup(Z_STRVAL(tmp.u.constant), name_len);
1724        } else {
1725            lcname = zend_str_tolower_dup(name, name_len);
1726        }
1727
1728        /* Function name must not conflict with import names */
1729        if (CG(current_import_function) &&
1730            zend_hash_find(CG(current_import_function), lcname, Z_STRLEN(function_name->u.constant)+1, (void**)&ns_name) == SUCCESS) {
1731
1732            char *tmp = zend_str_tolower_dup(Z_STRVAL_PP(ns_name), Z_STRLEN_PP(ns_name));
1733
1734            if (Z_STRLEN_PP(ns_name) != Z_STRLEN(function_name->u.constant) ||
1735                memcmp(tmp, lcname, Z_STRLEN(function_name->u.constant))) {
1736                zend_error(E_COMPILE_ERROR, "Cannot declare function %s because the name is already in use", Z_STRVAL(function_name->u.constant));
1737            }
1738            efree(tmp);
1739        }
1740
1741        opline->opcode = ZEND_DECLARE_FUNCTION;
1742        opline->op1_type = IS_CONST;
1743        build_runtime_defined_function_key(&key, lcname, name_len TSRMLS_CC);
1744        opline->op1.constant = zend_add_literal(CG(active_op_array), &key TSRMLS_CC);
1745        Z_HASH_P(&CONSTANT(opline->op1.constant)) = zend_hash_func(Z_STRVAL(CONSTANT(opline->op1.constant)), Z_STRLEN(CONSTANT(opline->op1.constant)));
1746        opline->op2_type = IS_CONST;
1747        LITERAL_STRINGL(opline->op2, lcname, name_len, 1);
1748        CALCULATE_LITERAL_HASH(opline->op2.constant);
1749        opline->extended_value = ZEND_DECLARE_FUNCTION;
1750        zend_hash_quick_update(CG(function_table), Z_STRVAL(key), Z_STRLEN(key), Z_HASH_P(&CONSTANT(opline->op1.constant)), &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
1751        zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context)));
1752        zend_init_compiler_context(TSRMLS_C);
1753        str_efree(lcname);
1754    }
1755
1756    if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
1757        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1758
1759        opline->opcode = ZEND_EXT_NOP;
1760        opline->lineno = function_begin_line;
1761        SET_UNUSED(opline->op1);
1762        SET_UNUSED(opline->op2);
1763    }
1764
1765    {
1766        /* Push a separator to the switch stack */
1767        zend_switch_entry switch_entry;
1768
1769        switch_entry.cond.op_type = IS_UNUSED;
1770        switch_entry.default_case = 0;
1771        switch_entry.control_var = 0;
1772
1773        zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry, sizeof(switch_entry));
1774    }
1775
1776    {
1777        /* Push a separator to the foreach stack */
1778        zend_op dummy_opline;
1779
1780        dummy_opline.result_type = IS_UNUSED;
1781
1782        zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op));
1783    }
1784
1785    if (CG(doc_comment)) {
1786        CG(active_op_array)->doc_comment = CG(doc_comment);
1787        CG(active_op_array)->doc_comment_len = CG(doc_comment_len);
1788        CG(doc_comment) = NULL;
1789        CG(doc_comment_len) = 0;
1790    }
1791}
1792/* }}} */
1793
1794void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference, int is_static TSRMLS_DC) /* {{{ */
1795{
1796    znode          function_name;
1797    zend_op_array *current_op_array = CG(active_op_array);
1798    int            current_op_number = get_next_op_number(CG(active_op_array));
1799    zend_op       *current_op;
1800
1801    function_name.op_type = IS_CONST;
1802    ZVAL_STRINGL(&function_name.u.constant, "{closure}", sizeof("{closure}")-1, 1);
1803
1804    zend_do_begin_function_declaration(function_token, &function_name, 0, return_reference, NULL TSRMLS_CC);
1805
1806    result->op_type = IS_TMP_VAR;
1807    result->u.op.var = get_temporary_variable(current_op_array);
1808
1809    current_op = &current_op_array->opcodes[current_op_number];
1810    current_op->opcode = ZEND_DECLARE_LAMBDA_FUNCTION;
1811    zend_del_literal(current_op_array, current_op->op2.constant);
1812    SET_UNUSED(current_op->op2);
1813    SET_NODE(current_op->result, result);
1814    if (is_static) {
1815        CG(active_op_array)->fn_flags |= ZEND_ACC_STATIC;
1816    }
1817    CG(active_op_array)->fn_flags |= ZEND_ACC_CLOSURE;
1818}
1819/* }}} */
1820
1821void zend_do_handle_exception(TSRMLS_D) /* {{{ */
1822{
1823    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1824
1825    opline->opcode = ZEND_HANDLE_EXCEPTION;
1826    SET_UNUSED(opline->op1);
1827    SET_UNUSED(opline->op2);
1828}
1829/* }}} */
1830
1831void zend_do_end_function_declaration(const znode *function_token TSRMLS_DC) /* {{{ */
1832{
1833    char lcname[16];
1834    int name_len;
1835
1836    zend_do_extended_info(TSRMLS_C);
1837    zend_do_return(NULL, 0 TSRMLS_CC);
1838
1839    pass_two(CG(active_op_array) TSRMLS_CC);
1840    zend_release_labels(0 TSRMLS_CC);
1841
1842    if (CG(active_class_entry)) {
1843        zend_check_magic_method_implementation(CG(active_class_entry), (zend_function*)CG(active_op_array), E_COMPILE_ERROR TSRMLS_CC);
1844    } else {
1845        /* we don't care if the function name is longer, in fact lowercasing only
1846         * the beginning of the name speeds up the check process */
1847        name_len = strlen(CG(active_op_array)->function_name);
1848        zend_str_tolower_copy(lcname, CG(active_op_array)->function_name, MIN(name_len, sizeof(lcname)-1));
1849        lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
1850        if (name_len == sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)) && CG(active_op_array)->num_args != 1) {
1851            zend_error_noreturn(E_COMPILE_ERROR, "%s() must take exactly 1 argument", ZEND_AUTOLOAD_FUNC_NAME);
1852        }
1853    }
1854
1855    CG(active_op_array)->line_end = zend_get_compiled_lineno(TSRMLS_C);
1856    CG(active_op_array) = function_token->u.op_array;
1857
1858
1859    /* Pop the switch and foreach separators */
1860    zend_stack_del_top(&CG(switch_cond_stack));
1861    zend_stack_del_top(&CG(foreach_copy_stack));
1862}
1863/* }}} */
1864
1865void zend_do_receive_param(zend_uchar op, znode *varname, const znode *initialization, znode *class_type, zend_uchar pass_by_reference, zend_bool is_variadic TSRMLS_DC) /* {{{ */
1866{
1867    zend_op *opline;
1868    zend_arg_info *cur_arg_info;
1869    znode var;
1870
1871    if (zend_is_auto_global(Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant) TSRMLS_CC)) {
1872        zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign auto-global variable %s", Z_STRVAL(varname->u.constant));
1873    } else {
1874        var.op_type = IS_CV;
1875        var.u.op.var = lookup_cv(CG(active_op_array), Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant), 0 TSRMLS_CC);
1876        Z_STRVAL(varname->u.constant) = (char*)CG(active_op_array)->vars[var.u.op.var].name;
1877        var.EA = 0;
1878        if (CG(active_op_array)->vars[var.u.op.var].hash_value == THIS_HASHVAL &&
1879            Z_STRLEN(varname->u.constant) == sizeof("this")-1 &&
1880            !memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this")-1)) {
1881            if (CG(active_op_array)->scope &&
1882                (CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) {
1883                zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
1884            }
1885            CG(active_op_array)->this_var = var.u.op.var;
1886        }
1887    }
1888
1889    if (CG(active_op_array)->fn_flags & ZEND_ACC_VARIADIC) {
1890        zend_error_noreturn(E_COMPILE_ERROR, "Only the last parameter can be variadic");
1891    }
1892
1893    if (is_variadic) {
1894        if (op == ZEND_RECV_INIT) {
1895            zend_error_noreturn(E_COMPILE_ERROR, "Variadic parameter cannot have a default value");
1896        }
1897
1898        op = ZEND_RECV_VARIADIC;
1899        CG(active_op_array)->fn_flags |= ZEND_ACC_VARIADIC;
1900    }
1901
1902    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
1903    CG(active_op_array)->num_args++;
1904    opline->opcode = op;
1905    SET_NODE(opline->result, &var);
1906    opline->op1_type = IS_UNUSED;
1907    opline->op1.num = CG(active_op_array)->num_args;
1908    if (op == ZEND_RECV_INIT) {
1909        SET_NODE(opline->op2, initialization);
1910    } else {
1911        SET_UNUSED(opline->op2);
1912        if (!is_variadic) {
1913            CG(active_op_array)->required_num_args = CG(active_op_array)->num_args;
1914        }
1915    }
1916    CG(active_op_array)->arg_info = erealloc(CG(active_op_array)->arg_info, sizeof(zend_arg_info)*(CG(active_op_array)->num_args));
1917    cur_arg_info = &CG(active_op_array)->arg_info[CG(active_op_array)->num_args-1];
1918    cur_arg_info->name = zend_new_interned_string(estrndup(Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant)), Z_STRLEN(varname->u.constant) + 1, 1 TSRMLS_CC);
1919    cur_arg_info->name_len = Z_STRLEN(varname->u.constant);
1920    cur_arg_info->type_hint = 0;
1921    cur_arg_info->pass_by_reference = pass_by_reference;
1922    cur_arg_info->allow_null = 1;
1923    cur_arg_info->is_variadic = is_variadic;
1924    cur_arg_info->class_name = NULL;
1925    cur_arg_info->class_name_len = 0;
1926
1927    if (class_type->op_type != IS_UNUSED) {
1928        cur_arg_info->allow_null = 0;
1929
1930        if (class_type->u.constant.type != IS_NULL) {
1931            if (class_type->u.constant.type == IS_ARRAY) {
1932                cur_arg_info->type_hint = IS_ARRAY;
1933                if (op == ZEND_RECV_INIT) {
1934                    if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL")) || Z_TYPE(initialization->u.constant) == IS_CONSTANT_AST) {
1935                        cur_arg_info->allow_null = 1;
1936                    } else if (Z_TYPE(initialization->u.constant) != IS_ARRAY) {
1937                        zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with array type hint can only be an array or NULL");
1938                    }
1939                }
1940            } else if (class_type->u.constant.type == IS_CALLABLE) {
1941                cur_arg_info->type_hint = IS_CALLABLE;
1942                if (op == ZEND_RECV_INIT) {
1943                    if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL")) || Z_TYPE(initialization->u.constant) == IS_CONSTANT_AST) {
1944                        cur_arg_info->allow_null = 1;
1945                    } else {
1946                        zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with callable type hint can only be NULL");
1947                    }
1948                }
1949            } else {
1950                cur_arg_info->type_hint = IS_OBJECT;
1951                if (ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_type->u.constant), Z_STRLEN(class_type->u.constant))) {
1952                    zend_resolve_class_name(class_type TSRMLS_CC);
1953                }
1954                Z_STRVAL(class_type->u.constant) = (char*)zend_new_interned_string(Z_STRVAL(class_type->u.constant), Z_STRLEN(class_type->u.constant) + 1, 1 TSRMLS_CC);
1955                cur_arg_info->class_name = Z_STRVAL(class_type->u.constant);
1956                cur_arg_info->class_name_len = Z_STRLEN(class_type->u.constant);
1957                if (op == ZEND_RECV_INIT) {
1958                    if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL")) || Z_TYPE(initialization->u.constant) == IS_CONSTANT_AST) {
1959                        cur_arg_info->allow_null = 1;
1960                    } else {
1961                        zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with a class type hint can only be NULL");
1962                    }
1963                }
1964            }
1965        }
1966    }
1967}
1968/* }}} */
1969
1970int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace TSRMLS_DC) /* {{{ */
1971{
1972    zend_function *function;
1973    char *lcname;
1974    char *is_compound = memchr(Z_STRVAL(function_name->u.constant), '\\', Z_STRLEN(function_name->u.constant));
1975
1976    zend_resolve_function_name(function_name, &check_namespace TSRMLS_CC);
1977
1978    if (check_namespace && CG(current_namespace) && !is_compound) {
1979            /* We assume we call function from the current namespace
1980            if it is not prefixed. */
1981
1982            /* In run-time PHP will check for function with full name and
1983            internal function with short name */
1984            zend_do_begin_dynamic_function_call(function_name, 1 TSRMLS_CC);
1985            return 1;
1986    }
1987
1988    lcname = zend_str_tolower_dup(Z_STRVAL(function_name->u.constant), Z_STRLEN(function_name->u.constant));
1989    if ((zend_hash_find(CG(function_table), lcname, Z_STRLEN(function_name->u.constant)+1, (void **) &function)==FAILURE) ||
1990        ((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS) &&
1991        (function->type == ZEND_INTERNAL_FUNCTION))) {
1992            zend_do_begin_dynamic_function_call(function_name, 0 TSRMLS_CC);
1993            efree(lcname);
1994            return 1; /* Dynamic */
1995    }
1996    efree(Z_STRVAL(function_name->u.constant));
1997    Z_STRVAL(function_name->u.constant) = lcname;
1998
1999    zend_push_function_call_entry(function TSRMLS_CC);
2000    if (CG(context).nested_calls + 1 > CG(active_op_array)->nested_calls) {
2001        CG(active_op_array)->nested_calls = CG(context).nested_calls + 1;
2002    }
2003    zend_do_extended_fcall_begin(TSRMLS_C);
2004    return 0;
2005}
2006/* }}} */
2007
2008void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
2009{
2010    zend_op *last_op;
2011    int last_op_number;
2012
2013    zend_do_end_variable_parse(left_bracket, BP_VAR_R, 0 TSRMLS_CC);
2014    zend_do_begin_variable_parse(TSRMLS_C);
2015
2016    last_op_number = get_next_op_number(CG(active_op_array))-1;
2017    last_op = &CG(active_op_array)->opcodes[last_op_number];
2018
2019    if ((last_op->op2_type == IS_CONST) && (Z_TYPE(CONSTANT(last_op->op2.constant)) == IS_STRING) && (Z_STRLEN(CONSTANT(last_op->op2.constant)) == sizeof(ZEND_CLONE_FUNC_NAME)-1)
2020        && !zend_binary_strcasecmp(Z_STRVAL(CONSTANT(last_op->op2.constant)), Z_STRLEN(CONSTANT(last_op->op2.constant)), ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)-1)) {
2021        zend_error_noreturn(E_COMPILE_ERROR, "Cannot call __clone() method on objects - use 'clone $obj' instead");
2022    }
2023
2024    if (last_op->opcode == ZEND_FETCH_OBJ_R) {
2025        if (last_op->op2_type == IS_CONST) {
2026            zval name;
2027            name = CONSTANT(last_op->op2.constant);
2028            if (Z_TYPE(name) != IS_STRING) {
2029                zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string");
2030            }
2031            Z_STRVAL(name) = str_estrndup(Z_STRVAL(name), Z_STRLEN(name));
2032            FREE_POLYMORPHIC_CACHE_SLOT(last_op->op2.constant);
2033            last_op->op2.constant =
2034                zend_add_func_name_literal(CG(active_op_array), &name TSRMLS_CC);
2035            GET_POLYMORPHIC_CACHE_SLOT(last_op->op2.constant);
2036        }
2037        last_op->opcode = ZEND_INIT_METHOD_CALL;
2038        last_op->result_type = IS_UNUSED;
2039        last_op->result.num = CG(context).nested_calls;
2040        Z_LVAL(left_bracket->u.constant) = ZEND_INIT_FCALL_BY_NAME;
2041    } else {
2042        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2043        opline->opcode = ZEND_INIT_FCALL_BY_NAME;
2044        opline->result.num = CG(context).nested_calls;
2045        SET_UNUSED(opline->op1);
2046        if (left_bracket->op_type == IS_CONST) {
2047            opline->op2_type = IS_CONST;
2048            opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &left_bracket->u.constant TSRMLS_CC);
2049            GET_CACHE_SLOT(opline->op2.constant);
2050        } else {
2051            SET_NODE(opline->op2, left_bracket);
2052        }
2053    }
2054
2055    zend_push_function_call_entry(NULL TSRMLS_CC);
2056    if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
2057        CG(active_op_array)->nested_calls = CG(context).nested_calls;
2058    }
2059    zend_do_extended_fcall_begin(TSRMLS_C);
2060}
2061/* }}} */
2062
2063void zend_do_clone(znode *result, const znode *expr TSRMLS_DC) /* {{{ */
2064{
2065    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2066
2067    opline->opcode = ZEND_CLONE;
2068    SET_NODE(opline->op1, expr);
2069    SET_UNUSED(opline->op2);
2070    opline->result_type = IS_VAR;
2071    opline->result.var = get_temporary_variable(CG(active_op_array));
2072    GET_NODE(result, opline->result);
2073}
2074/* }}} */
2075
2076void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRMLS_DC) /* {{{ */
2077{
2078    zend_op *opline;
2079
2080    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2081    if (ns_call) {
2082        /* In run-time PHP will check for function with full name and
2083           internal function with short name */
2084        opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
2085        opline->result.num = CG(context).nested_calls;
2086        SET_UNUSED(opline->op1);
2087        opline->op2_type = IS_CONST;
2088        opline->op2.constant = zend_add_ns_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC);
2089        GET_CACHE_SLOT(opline->op2.constant);
2090    } else {
2091        opline->opcode = ZEND_INIT_FCALL_BY_NAME;
2092        opline->result.num = CG(context).nested_calls;
2093        SET_UNUSED(opline->op1);
2094        if (function_name->op_type == IS_CONST) {
2095            opline->op2_type = IS_CONST;
2096            opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC);
2097            GET_CACHE_SLOT(opline->op2.constant);
2098        } else {
2099            SET_NODE(opline->op2, function_name);
2100        }
2101    }
2102
2103    zend_push_function_call_entry(NULL TSRMLS_CC);
2104    if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
2105        CG(active_op_array)->nested_calls = CG(context).nested_calls;
2106    }
2107    zend_do_extended_fcall_begin(TSRMLS_C);
2108}
2109/* }}} */
2110
2111void zend_resolve_non_class_name(znode *element_name, zend_bool *check_namespace, zend_bool case_sensitive, HashTable *current_import_sub TSRMLS_DC) /* {{{ */
2112{
2113    znode tmp;
2114    int len;
2115    zval **ns;
2116    char *lookup_name, *compound = memchr(Z_STRVAL(element_name->u.constant), '\\', Z_STRLEN(element_name->u.constant));
2117
2118    if (Z_STRVAL(element_name->u.constant)[0] == '\\') {
2119        /* name starts with \ so it is known and unambiguos, nothing to do here but shorten it */
2120        memmove(Z_STRVAL(element_name->u.constant), Z_STRVAL(element_name->u.constant)+1, Z_STRLEN(element_name->u.constant));
2121        --Z_STRLEN(element_name->u.constant);
2122        return;
2123    }
2124
2125    if(!*check_namespace) {
2126        return;
2127    }
2128
2129    if (current_import_sub) {
2130        len = Z_STRLEN(element_name->u.constant)+1;
2131        if (case_sensitive) {
2132            lookup_name = estrndup(Z_STRVAL(element_name->u.constant), len);
2133        } else {
2134            lookup_name = zend_str_tolower_dup(Z_STRVAL(element_name->u.constant), len);
2135        }
2136        /* Check if function/const matches imported name */
2137        if (zend_hash_find(current_import_sub, lookup_name, len, (void**)&ns) == SUCCESS) {
2138            zval_dtor(&element_name->u.constant);
2139            element_name->u.constant = **ns;
2140            zval_copy_ctor(&element_name->u.constant);
2141            efree(lookup_name);
2142            *check_namespace = 0;
2143            return;
2144        }
2145        efree(lookup_name);
2146    }
2147
2148    if (compound && CG(current_import)) {
2149        len = compound - Z_STRVAL(element_name->u.constant);
2150        /* namespace is always lowercase */
2151        lookup_name = zend_str_tolower_dup(Z_STRVAL(element_name->u.constant), len);
2152        /* Check if first part of compound name is an import name */
2153        if (zend_hash_find(CG(current_import), lookup_name, len+1, (void**)&ns) == SUCCESS) {
2154            /* Substitute import name */
2155            tmp.op_type = IS_CONST;
2156            tmp.u.constant = **ns;
2157            zval_copy_ctor(&tmp.u.constant);
2158            len += 1;
2159            Z_STRLEN(element_name->u.constant) -= len;
2160            memmove(Z_STRVAL(element_name->u.constant), Z_STRVAL(element_name->u.constant)+len, Z_STRLEN(element_name->u.constant)+1);
2161            zend_do_build_namespace_name(&tmp, &tmp, element_name TSRMLS_CC);
2162            *element_name = tmp;
2163            efree(lookup_name);
2164            *check_namespace = 0;
2165            return;
2166        }
2167        efree(lookup_name);
2168    }
2169
2170    if (CG(current_namespace)) {
2171        tmp = *element_name;
2172        Z_STRLEN(tmp.u.constant) = sizeof("\\")-1 + Z_STRLEN(element_name->u.constant) + Z_STRLEN_P(CG(current_namespace));
2173        Z_STRVAL(tmp.u.constant) = (char *) emalloc(Z_STRLEN(tmp.u.constant)+1);
2174        memcpy(Z_STRVAL(tmp.u.constant), Z_STRVAL_P(CG(current_namespace)), Z_STRLEN_P(CG(current_namespace)));
2175        memcpy(&(Z_STRVAL(tmp.u.constant)[Z_STRLEN_P(CG(current_namespace))]), "\\", sizeof("\\")-1);
2176        memcpy(&(Z_STRVAL(tmp.u.constant)[Z_STRLEN_P(CG(current_namespace)) + sizeof("\\")-1]), Z_STRVAL(element_name->u.constant), Z_STRLEN(element_name->u.constant)+1);
2177        str_efree(Z_STRVAL(element_name->u.constant));
2178        *element_name = tmp;
2179    }
2180}
2181/* }}} */
2182
2183void zend_resolve_function_name(znode *element_name, zend_bool *check_namespace TSRMLS_DC) /* {{{ */
2184{
2185    zend_resolve_non_class_name(element_name, check_namespace, 0, CG(current_import_function) TSRMLS_CC);
2186}
2187/* }}} */
2188
2189void zend_resolve_const_name(znode *element_name, zend_bool *check_namespace TSRMLS_DC) /* {{{ */
2190{
2191    zend_resolve_non_class_name(element_name, check_namespace, 1, CG(current_import_const) TSRMLS_CC);
2192}
2193/* }}} */
2194
2195void zend_do_resolve_class_name(znode *result, znode *class_name, int is_static TSRMLS_DC) /* {{{ */
2196{
2197    char *lcname;
2198    int lctype;
2199    znode constant_name;
2200
2201    lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
2202    lctype = zend_get_class_fetch_type(lcname, strlen(lcname));
2203    switch (lctype) {
2204        case ZEND_FETCH_CLASS_SELF:
2205            if (!CG(active_class_entry)) {
2206                zend_error_noreturn(E_COMPILE_ERROR, "Cannot access self::class when no class scope is active");
2207            }
2208            zval_dtor(&class_name->u.constant);
2209            class_name->op_type = IS_CONST;
2210            ZVAL_STRINGL(&class_name->u.constant, CG(active_class_entry)->name, CG(active_class_entry)->name_length, 1);
2211            *result = *class_name;
2212            break;
2213        case ZEND_FETCH_CLASS_STATIC:
2214        case ZEND_FETCH_CLASS_PARENT:
2215            if (is_static) {
2216                zend_error_noreturn(E_COMPILE_ERROR,
2217                    "%s::class cannot be used for compile-time class name resolution",
2218                    lctype == ZEND_FETCH_CLASS_STATIC ? "static" : "parent"
2219                    );
2220            }
2221            if (!CG(active_class_entry)) {
2222                zend_error_noreturn(E_COMPILE_ERROR,
2223                    "Cannot access %s::class when no class scope is active",
2224                    lctype == ZEND_FETCH_CLASS_STATIC ? "static" : "parent"
2225                    );
2226            }
2227            constant_name.op_type = IS_CONST;
2228            ZVAL_STRINGL(&constant_name.u.constant, "class", sizeof("class")-1, 1);
2229            zend_do_fetch_constant(result, class_name, &constant_name, ZEND_RT, 1 TSRMLS_CC);
2230            break;
2231        case ZEND_FETCH_CLASS_DEFAULT:
2232            zend_resolve_class_name(class_name TSRMLS_CC);
2233            *result = *class_name;
2234            break;
2235    }
2236
2237    efree(lcname);
2238
2239}
2240/* }}} */
2241
2242void zend_resolve_class_name(znode *class_name TSRMLS_DC) /* {{{ */
2243{
2244    char *compound;
2245    char *lcname;
2246    zval **ns;
2247    znode tmp;
2248    int len;
2249
2250    compound = memchr(Z_STRVAL(class_name->u.constant), '\\', Z_STRLEN(class_name->u.constant));
2251    if (compound) {
2252        /* This is a compound class name that contains namespace prefix */
2253        if (Z_STRVAL(class_name->u.constant)[0] == '\\') {
2254            /* The STRING name has "\" prefix */
2255            Z_STRLEN(class_name->u.constant) -= 1;
2256            memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+1, Z_STRLEN(class_name->u.constant)+1);
2257            Z_STRVAL(class_name->u.constant) = erealloc(
2258            Z_STRVAL(class_name->u.constant),
2259            Z_STRLEN(class_name->u.constant) + 1);
2260
2261            if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
2262                zend_error_noreturn(E_COMPILE_ERROR, "'\\%s' is an invalid class name", Z_STRVAL(class_name->u.constant));
2263            }
2264        } else {
2265            if (CG(current_import)) {
2266                len = compound - Z_STRVAL(class_name->u.constant);
2267                lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), len);
2268                /* Check if first part of compound name is an import name */
2269                if (zend_hash_find(CG(current_import), lcname, len+1, (void**)&ns) == SUCCESS) {
2270                    /* Substitute import name */
2271                    tmp.op_type = IS_CONST;
2272                    tmp.u.constant = **ns;
2273                    zval_copy_ctor(&tmp.u.constant);
2274                    len += 1;
2275                    Z_STRLEN(class_name->u.constant) -= len;
2276                    memmove(Z_STRVAL(class_name->u.constant), Z_STRVAL(class_name->u.constant)+len, Z_STRLEN(class_name->u.constant)+1);
2277                    zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
2278                    *class_name = tmp;
2279                    efree(lcname);
2280                    return;
2281                }
2282                efree(lcname);
2283            }
2284            /* Here name is not prefixed with \ and not imported */
2285            if (CG(current_namespace)) {
2286                tmp.op_type = IS_CONST;
2287                tmp.u.constant = *CG(current_namespace);
2288                zval_copy_ctor(&tmp.u.constant);
2289                zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
2290                *class_name = tmp;
2291            }
2292        }
2293    } else if (CG(current_import) || CG(current_namespace)) {
2294        /* this is a plain name (without \) */
2295        lcname = zend_str_tolower_dup(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
2296
2297        if (CG(current_import) &&
2298            zend_hash_find(CG(current_import), lcname, Z_STRLEN(class_name->u.constant)+1, (void**)&ns) == SUCCESS) {
2299            /* The given name is an import name. Substitute it. */
2300            zval_dtor(&class_name->u.constant);
2301            class_name->u.constant = **ns;
2302            zval_copy_ctor(&class_name->u.constant);
2303        } else if (CG(current_namespace)) {
2304            /* plain name, no import - prepend current namespace to it */
2305            tmp.op_type = IS_CONST;
2306            tmp.u.constant = *CG(current_namespace);
2307            zval_copy_ctor(&tmp.u.constant);
2308            zend_do_build_namespace_name(&tmp, &tmp, class_name TSRMLS_CC);
2309            *class_name = tmp;
2310        }
2311        efree(lcname);
2312    }
2313}
2314/* }}} */
2315
2316void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC) /* {{{ */
2317{
2318    long fetch_class_op_number;
2319    zend_op *opline;
2320
2321    fetch_class_op_number = get_next_op_number(CG(active_op_array));
2322    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2323
2324    opline->opcode = ZEND_FETCH_CLASS;
2325    SET_UNUSED(opline->op1);
2326    opline->extended_value = ZEND_FETCH_CLASS_DEFAULT;
2327    CG(catch_begin) = fetch_class_op_number;
2328    if (class_name->op_type == IS_CONST) {
2329        int fetch_type;
2330
2331        fetch_type = zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant));
2332        switch (fetch_type) {
2333            case ZEND_FETCH_CLASS_SELF:
2334            case ZEND_FETCH_CLASS_PARENT:
2335            case ZEND_FETCH_CLASS_STATIC:
2336                SET_UNUSED(opline->op2);
2337                opline->extended_value = fetch_type;
2338                zval_dtor(&class_name->u.constant);
2339                break;
2340            default:
2341                zend_resolve_class_name(class_name TSRMLS_CC);
2342                opline->op2_type = IS_CONST;
2343                opline->op2.constant =
2344                    zend_add_class_name_literal(CG(active_op_array), &class_name->u.constant TSRMLS_CC);
2345                break;
2346        }
2347    } else {
2348        SET_NODE(opline->op2, class_name);
2349    }
2350    opline->result.var = get_temporary_variable(CG(active_op_array));
2351    opline->result_type = IS_VAR; /* FIXME: Hack so that INIT_FCALL_BY_NAME still knows this is a class */
2352    GET_NODE(result, opline->result);
2353    result->EA = opline->extended_value;
2354}
2355/* }}} */
2356
2357void zend_do_label(znode *label TSRMLS_DC) /* {{{ */
2358{
2359    zend_label dest;
2360
2361    if (!CG(context).labels) {
2362        ALLOC_HASHTABLE(CG(context).labels);
2363        zend_hash_init(CG(context).labels, 4, NULL, NULL, 0);
2364    }
2365
2366    dest.brk_cont = CG(context).current_brk_cont;
2367    dest.opline_num = get_next_op_number(CG(active_op_array));
2368
2369    if (zend_hash_add(CG(context).labels, Z_STRVAL(label->u.constant), Z_STRLEN(label->u.constant) + 1, (void**)&dest, sizeof(zend_label), NULL) == FAILURE) {
2370        zend_error_noreturn(E_COMPILE_ERROR, "Label '%s' already defined", Z_STRVAL(label->u.constant));
2371    }
2372
2373    /* Done with label now */
2374    zval_dtor(&label->u.constant);
2375}
2376/* }}} */
2377
2378void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2 TSRMLS_DC) /* {{{ */
2379{
2380    zend_label *dest;
2381    long current, distance;
2382    zval *label;
2383
2384    if (pass2) {
2385        label = opline->op2.zv;
2386    } else {
2387        label = &CONSTANT_EX(op_array, opline->op2.constant);
2388    }
2389    if (CG(context).labels == NULL ||
2390        zend_hash_find(CG(context).labels, Z_STRVAL_P(label), Z_STRLEN_P(label)+1, (void**)&dest) == FAILURE) {
2391
2392        if (pass2) {
2393            CG(in_compilation) = 1;
2394            CG(active_op_array) = op_array;
2395            CG(zend_lineno) = opline->lineno;
2396            zend_error_noreturn(E_COMPILE_ERROR, "'goto' to undefined label '%s'", Z_STRVAL_P(label));
2397        } else {
2398            /* Label is not defined. Delay to pass 2. */
2399            INC_BPC(op_array);
2400            return;
2401        }
2402    }
2403
2404    opline->op1.opline_num = dest->opline_num;
2405    zval_dtor(label);
2406    Z_TYPE_P(label) = IS_NULL;
2407
2408    /* Check that we are not moving into loop or switch */
2409    current = opline->extended_value;
2410    for (distance = 0; current != dest->brk_cont; distance++) {
2411        if (current == -1) {
2412            if (pass2) {
2413                CG(in_compilation) = 1;
2414                CG(active_op_array) = op_array;
2415                CG(zend_lineno) = opline->lineno;
2416            }
2417            zend_error_noreturn(E_COMPILE_ERROR, "'goto' into loop or switch statement is disallowed");
2418        }
2419        current = op_array->brk_cont_array[current].parent;
2420    }
2421
2422    if (distance == 0) {
2423        /* Nothing to break out of, optimize to ZEND_JMP */
2424        opline->opcode = ZEND_JMP;
2425        opline->extended_value = 0;
2426        SET_UNUSED(opline->op2);
2427    } else {
2428        /* Set real break distance */
2429        ZVAL_LONG(label, distance);
2430    }
2431
2432    if (pass2) {
2433        DEC_BPC(op_array);
2434    }
2435}
2436/* }}} */
2437
2438void zend_do_goto(const znode *label TSRMLS_DC) /* {{{ */
2439{
2440    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2441
2442    opline->opcode = ZEND_GOTO;
2443    opline->extended_value = CG(context).current_brk_cont;
2444    SET_UNUSED(opline->op1);
2445    SET_NODE(opline->op2, label);
2446    zend_resolve_goto_label(CG(active_op_array), opline, 0 TSRMLS_CC);
2447}
2448/* }}} */
2449
2450void zend_release_labels(int temporary TSRMLS_DC) /* {{{ */
2451{
2452    if (CG(context).labels) {
2453        zend_hash_destroy(CG(context).labels);
2454        FREE_HASHTABLE(CG(context).labels);
2455        CG(context).labels = NULL;
2456    }
2457    if (!temporary && !zend_stack_is_empty(&CG(context_stack))) {
2458        zend_compiler_context *ctx;
2459
2460        zend_stack_top(&CG(context_stack), (void**)&ctx);
2461        CG(context) = *ctx;
2462        zend_stack_del_top(&CG(context_stack));
2463    }
2464}
2465/* }}} */
2466
2467void zend_do_build_full_name(znode *result, znode *prefix, znode *name, int is_class_member TSRMLS_DC) /* {{{ */
2468{
2469    zend_uint length;
2470
2471    if (!result) {
2472        result = prefix;
2473    } else {
2474        *result = *prefix;
2475    }
2476
2477    if (is_class_member) {
2478        length = sizeof("::")-1 + Z_STRLEN(result->u.constant) + Z_STRLEN(name->u.constant);
2479        Z_STRVAL(result->u.constant) = str_erealloc(Z_STRVAL(result->u.constant), length+1);
2480        memcpy(&Z_STRVAL(result->u.constant)[Z_STRLEN(result->u.constant)], "::", sizeof("::")-1);
2481        memcpy(&Z_STRVAL(result->u.constant)[Z_STRLEN(result->u.constant) + sizeof("::")-1], Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant)+1);
2482        str_efree(Z_STRVAL(name->u.constant));
2483        Z_STRLEN(result->u.constant) = length;
2484    } else {
2485        length = sizeof("\\")-1 + Z_STRLEN(result->u.constant) + Z_STRLEN(name->u.constant);
2486        Z_STRVAL(result->u.constant) = str_erealloc(Z_STRVAL(result->u.constant), length+1);
2487        memcpy(&Z_STRVAL(result->u.constant)[Z_STRLEN(result->u.constant)], "\\", sizeof("\\")-1);
2488        memcpy(&Z_STRVAL(result->u.constant)[Z_STRLEN(result->u.constant) + sizeof("\\")-1], Z_STRVAL(name->u.constant), Z_STRLEN(name->u.constant)+1);
2489        str_efree(Z_STRVAL(name->u.constant));
2490        Z_STRLEN(result->u.constant) = length;
2491    }
2492}
2493/* }}} */
2494
2495int zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC) /* {{{ */
2496{
2497    znode class_node;
2498    zend_op *opline;
2499
2500    if (method_name->op_type == IS_CONST) {
2501        char *lcname;
2502        if (Z_TYPE(method_name->u.constant) != IS_STRING) {
2503            zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string");
2504        }
2505        lcname = zend_str_tolower_dup(Z_STRVAL(method_name->u.constant), Z_STRLEN(method_name->u.constant));
2506        if ((sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == Z_STRLEN(method_name->u.constant) &&
2507            memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == 0) {
2508            zval_dtor(&method_name->u.constant);
2509            method_name->op_type = IS_UNUSED;
2510        }
2511        efree(lcname);
2512    }
2513
2514    if (class_name->op_type == IS_CONST &&
2515        ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
2516        zend_resolve_class_name(class_name TSRMLS_CC);
2517        class_node = *class_name;
2518        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2519    } else {
2520        zend_do_fetch_class(&class_node, class_name TSRMLS_CC);
2521        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2522        opline->extended_value = class_node.EA  ;
2523    }
2524    opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
2525    opline->result.num = CG(context).nested_calls;
2526    if (class_node.op_type == IS_CONST) {
2527        opline->op1_type = IS_CONST;
2528        opline->op1.constant =
2529            zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC);
2530    } else {
2531        SET_NODE(opline->op1, &class_node);
2532    }
2533    if (method_name->op_type == IS_CONST) {
2534        opline->op2_type = IS_CONST;
2535        opline->op2.constant =
2536            zend_add_func_name_literal(CG(active_op_array), &method_name->u.constant TSRMLS_CC);
2537        if (opline->op1_type == IS_CONST) {
2538            GET_CACHE_SLOT(opline->op2.constant);
2539        } else {
2540            GET_POLYMORPHIC_CACHE_SLOT(opline->op2.constant);
2541        }
2542    } else {
2543        SET_NODE(opline->op2, method_name);
2544    }
2545
2546    zend_push_function_call_entry(NULL TSRMLS_CC);
2547    if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) {
2548        CG(active_op_array)->nested_calls = CG(context).nested_calls;
2549    }
2550    zend_do_extended_fcall_begin(TSRMLS_C);
2551    return 1; /* Dynamic */
2552}
2553/* }}} */
2554
2555void zend_do_end_function_call(znode *function_name, znode *result, int is_method, int is_dynamic_fcall TSRMLS_DC) /* {{{ */
2556{
2557    zend_op *opline;
2558    zend_function_call_entry *fcall;
2559    zend_stack_top(&CG(function_call_stack), (void **) &fcall);
2560
2561    if (is_method && function_name && function_name->op_type == IS_UNUSED) {
2562        /* clone */
2563        if (fcall->arg_num != 0) {
2564            zend_error(E_WARNING, "Clone method does not require arguments");
2565        }
2566        opline = &CG(active_op_array)->opcodes[Z_LVAL(function_name->u.constant)];
2567    } else {
2568        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2569        if (fcall->fbc) {
2570            opline->opcode = ZEND_DO_FCALL;
2571            SET_NODE(opline->op1, function_name);
2572            SET_UNUSED(opline->op2);
2573            opline->op2.num = CG(context).nested_calls;
2574            CALCULATE_LITERAL_HASH(opline->op1.constant);
2575            GET_CACHE_SLOT(opline->op1.constant);
2576        } else {
2577            opline->opcode = ZEND_DO_FCALL_BY_NAME;
2578            SET_UNUSED(opline->op1);
2579            SET_UNUSED(opline->op2);
2580            opline->op2.num = --CG(context).nested_calls;
2581
2582            /* This would normally be a ZEND_DO_FCALL, but was forced to use
2583             * ZEND_DO_FCALL_BY_NAME due to a ... argument. In this case we need to
2584             * free the function_name */
2585            if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) {
2586                zval_dtor(&function_name->u.constant);
2587            }
2588        }
2589    }
2590
2591    opline->result.var = get_temporary_variable(CG(active_op_array));
2592    opline->result_type = IS_VAR;
2593    GET_NODE(result, opline->result);
2594    opline->extended_value = fcall->arg_num;
2595
2596    if (CG(context).used_stack + 1 > CG(active_op_array)->used_stack) {
2597        CG(active_op_array)->used_stack = CG(context).used_stack + 1;
2598    }
2599    CG(context).used_stack -= fcall->arg_num;
2600    zend_stack_del_top(&CG(function_call_stack));
2601}
2602/* }}} */
2603
2604void zend_do_pass_param(znode *param, zend_uchar op TSRMLS_DC) /* {{{ */
2605{
2606    zend_op *opline;
2607    int original_op = op;
2608    zend_function_call_entry *fcall;
2609    zend_function *function_ptr;
2610    int send_by_reference = 0;
2611    int send_function = 0;
2612
2613    zend_stack_top(&CG(function_call_stack), (void **) &fcall);
2614    function_ptr = fcall->fbc;
2615    fcall->arg_num++;
2616
2617    if (fcall->uses_argument_unpacking) {
2618        zend_error_noreturn(E_COMPILE_ERROR,
2619            "Cannot use positional argument after argument unpacking");
2620    }
2621
2622    if (original_op == ZEND_SEND_REF) {
2623        if (function_ptr &&
2624            function_ptr->common.function_name &&
2625            function_ptr->common.type == ZEND_USER_FUNCTION &&
2626            !ARG_SHOULD_BE_SENT_BY_REF(function_ptr, fcall->arg_num)) {
2627            zend_error_noreturn(E_COMPILE_ERROR,
2628                        "Call-time pass-by-reference has been removed; "
2629                        "If you would like to pass argument by reference, modify the declaration of %s().",
2630                        function_ptr->common.function_name);
2631        } else {
2632            zend_error_noreturn(E_COMPILE_ERROR, "Call-time pass-by-reference has been removed");
2633        }
2634        return;
2635    }
2636
2637    if (function_ptr) {
2638        if (ARG_MAY_BE_SENT_BY_REF(function_ptr, fcall->arg_num)) {
2639            if (op == ZEND_SEND_VAR && param->op_type & (IS_VAR|IS_CV)) {
2640                send_by_reference = ZEND_ARG_SEND_BY_REF;
2641                if (zend_is_function_or_method_call(param)) {
2642                    /* Method call */
2643                    op = ZEND_SEND_VAR_NO_REF;
2644                    send_function = ZEND_ARG_SEND_FUNCTION | ZEND_ARG_SEND_SILENT;
2645                }
2646            } else {
2647                op = ZEND_SEND_VAL;
2648            }
2649        } else if (ARG_SHOULD_BE_SENT_BY_REF(function_ptr, fcall->arg_num)) {
2650            send_by_reference = ZEND_ARG_SEND_BY_REF;
2651        }
2652    }
2653
2654    if (op == ZEND_SEND_VAR && zend_is_function_or_method_call(param)) {
2655        /* Method call */
2656        op = ZEND_SEND_VAR_NO_REF;
2657        send_function = ZEND_ARG_SEND_FUNCTION;
2658    } else if (op == ZEND_SEND_VAL && (param->op_type & (IS_VAR|IS_CV))) {
2659        op = ZEND_SEND_VAR_NO_REF;
2660    }
2661
2662    if (op!=ZEND_SEND_VAR_NO_REF && send_by_reference==ZEND_ARG_SEND_BY_REF) {
2663        /* change to passing by reference */
2664        switch (param->op_type) {
2665            case IS_VAR:
2666            case IS_CV:
2667                op = ZEND_SEND_REF;
2668                break;
2669            default:
2670                zend_error_noreturn(E_COMPILE_ERROR, "Only variables can be passed by reference");
2671                break;
2672        }
2673    }
2674
2675    if (original_op == ZEND_SEND_VAR) {
2676        switch (op) {
2677            case ZEND_SEND_VAR_NO_REF:
2678                zend_do_end_variable_parse(param, BP_VAR_R, 0 TSRMLS_CC);
2679                break;
2680            case ZEND_SEND_VAR:
2681                if (function_ptr) {
2682                    zend_do_end_variable_parse(param, BP_VAR_R, 0 TSRMLS_CC);
2683                } else {
2684                    zend_do_end_variable_parse(param, BP_VAR_FUNC_ARG, fcall->arg_num TSRMLS_CC);
2685                }
2686                break;
2687            case ZEND_SEND_REF:
2688                zend_do_end_variable_parse(param, BP_VAR_W, 0 TSRMLS_CC);
2689                break;
2690        }
2691    }
2692
2693    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2694
2695    if (op == ZEND_SEND_VAR_NO_REF) {
2696        if (function_ptr) {
2697            opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND | send_by_reference | send_function;
2698        } else {
2699            opline->extended_value = send_function;
2700        }
2701    } else {
2702        if (function_ptr) {
2703            opline->extended_value = ZEND_DO_FCALL;
2704        } else {
2705            opline->extended_value = ZEND_DO_FCALL_BY_NAME;
2706        }
2707    }
2708    opline->opcode = op;
2709    SET_NODE(opline->op1, param);
2710    opline->op2.opline_num = fcall->arg_num;
2711    SET_UNUSED(opline->op2);
2712
2713    if (++CG(context).used_stack > CG(active_op_array)->used_stack) {
2714        CG(active_op_array)->used_stack = CG(context).used_stack;
2715    }
2716}
2717/* }}} */
2718
2719void zend_do_unpack_params(znode *params TSRMLS_DC) /* {{{ */
2720{
2721    zend_op *opline;
2722    zend_function_call_entry *fcall;
2723
2724    zend_stack_top(&CG(function_call_stack), (void **) &fcall);
2725    fcall->uses_argument_unpacking = 1;
2726
2727    if (fcall->fbc) {
2728        /* If argument unpacking is used argument numbers and sending modes can no longer be
2729         * computed at compile time, thus we need access to EX(call). In order to have it we
2730         * retroactively emit a ZEND_INIT_FCALL_BY_NAME opcode. */
2731        zval func_name;
2732        ZVAL_STRING(&func_name, fcall->fbc->common.function_name, 1);
2733
2734        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2735        opline->opcode = ZEND_INIT_FCALL_BY_NAME;
2736        opline->result.num = CG(context).nested_calls;
2737        SET_UNUSED(opline->op1);
2738        opline->op2_type = IS_CONST;
2739        opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &func_name TSRMLS_CC);
2740        GET_CACHE_SLOT(opline->op2.constant);
2741
2742        ++CG(context).nested_calls;
2743        fcall->fbc = NULL;
2744    }
2745
2746    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2747    opline->opcode = ZEND_SEND_UNPACK;
2748    SET_NODE(opline->op1, params);
2749    SET_UNUSED(opline->op2);
2750    opline->op2.num = fcall->arg_num;
2751}
2752/* }}} */
2753
2754static int generate_free_switch_expr(const zend_switch_entry *switch_entry TSRMLS_DC) /* {{{ */
2755{
2756    zend_op *opline;
2757
2758    if (switch_entry->cond.op_type != IS_VAR && switch_entry->cond.op_type != IS_TMP_VAR) {
2759        return (switch_entry->cond.op_type == IS_UNUSED);
2760    }
2761
2762    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2763
2764    opline->opcode = (switch_entry->cond.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
2765    SET_NODE(opline->op1, &switch_entry->cond);
2766    SET_UNUSED(opline->op2);
2767
2768    return 0;
2769}
2770/* }}} */
2771
2772static int generate_free_foreach_copy(const zend_op *foreach_copy TSRMLS_DC) /* {{{ */
2773{
2774    zend_op *opline;
2775
2776    /* If we reach the separator then stop applying the stack */
2777    if (foreach_copy->result_type == IS_UNUSED) {
2778        return 1;
2779    }
2780
2781    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2782
2783    opline->opcode = (foreach_copy->result_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
2784    COPY_NODE(opline->op1, foreach_copy->result);
2785    SET_UNUSED(opline->op2);
2786
2787    return 0;
2788}
2789/* }}} */
2790
2791void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */
2792{
2793    zend_op *opline;
2794    int start_op_number, end_op_number;
2795    zend_bool returns_reference = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
2796
2797    /* The error for use of return inside a generator is thrown in pass_two. */
2798
2799    if (do_end_vparse) {
2800        if (returns_reference && !zend_is_function_or_method_call(expr)) {
2801            zend_do_end_variable_parse(expr, BP_VAR_W, 0 TSRMLS_CC);
2802        } else {
2803            zend_do_end_variable_parse(expr, BP_VAR_R, 0 TSRMLS_CC);
2804        }
2805    }
2806
2807    start_op_number = get_next_op_number(CG(active_op_array));
2808
2809#ifdef ZTS
2810    zend_stack_apply_with_argument(&CG(switch_cond_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element, void *)) generate_free_switch_expr TSRMLS_CC);
2811    zend_stack_apply_with_argument(&CG(foreach_copy_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element, void *)) generate_free_foreach_copy TSRMLS_CC);
2812#else
2813    zend_stack_apply(&CG(switch_cond_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_switch_expr);
2814    zend_stack_apply(&CG(foreach_copy_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_foreach_copy);
2815#endif
2816
2817    end_op_number = get_next_op_number(CG(active_op_array));
2818    while (start_op_number < end_op_number) {
2819        CG(active_op_array)->opcodes[start_op_number].extended_value |= EXT_TYPE_FREE_ON_RETURN;
2820        start_op_number++;
2821    }
2822
2823    if (CG(context).in_finally) {
2824        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2825        opline->opcode = ZEND_DISCARD_EXCEPTION;
2826        SET_UNUSED(opline->op1);
2827        SET_UNUSED(opline->op2);
2828    }
2829
2830    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2831
2832    opline->opcode = returns_reference ? ZEND_RETURN_BY_REF : ZEND_RETURN;
2833
2834    if (expr) {
2835        SET_NODE(opline->op1, expr);
2836
2837        if (!do_end_vparse) {
2838            opline->extended_value = ZEND_RETURNS_VALUE;
2839        } else if (zend_is_function_or_method_call(expr)) {
2840            opline->extended_value = ZEND_RETURNS_FUNCTION;
2841        }
2842    } else {
2843        opline->op1_type = IS_CONST;
2844        LITERAL_NULL(opline->op1);
2845    }
2846
2847    SET_UNUSED(opline->op2);
2848}
2849/* }}} */
2850
2851void zend_do_yield(znode *result, znode *value, const znode *key, zend_bool is_variable TSRMLS_DC) /* {{{ */
2852{
2853    zend_op *opline;
2854
2855    if (!CG(active_op_array)->function_name) {
2856        zend_error_noreturn(E_COMPILE_ERROR, "The \"yield\" expression can only be used inside a function");
2857    }
2858
2859    CG(active_op_array)->fn_flags |= ZEND_ACC_GENERATOR;
2860
2861    if (is_variable) {
2862        if ((CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) && !zend_is_function_or_method_call(value)) {
2863            zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC);
2864        } else {
2865            zend_do_end_variable_parse(value, BP_VAR_R, 0 TSRMLS_CC);
2866        }
2867    }
2868
2869    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2870
2871    opline->opcode = ZEND_YIELD;
2872
2873    if (value) {
2874        SET_NODE(opline->op1, value);
2875
2876        if (is_variable && zend_is_function_or_method_call(value)) {
2877            opline->extended_value = ZEND_RETURNS_FUNCTION;
2878        }
2879    } else {
2880        SET_UNUSED(opline->op1);
2881    }
2882
2883    if (key) {
2884        SET_NODE(opline->op2, key);
2885    } else {
2886        SET_UNUSED(opline->op2);
2887    }
2888
2889    opline->result_type = IS_VAR;
2890    opline->result.var = get_temporary_variable(CG(active_op_array));
2891    GET_NODE(result, opline->result);
2892}
2893/* }}} */
2894
2895static int zend_add_try_element(zend_uint try_op TSRMLS_DC) /* {{{ */
2896{
2897    int try_catch_offset = CG(active_op_array)->last_try_catch++;
2898
2899    CG(active_op_array)->try_catch_array = erealloc(CG(active_op_array)->try_catch_array, sizeof(zend_try_catch_element)*CG(active_op_array)->last_try_catch);
2900    CG(active_op_array)->try_catch_array[try_catch_offset].try_op = try_op;
2901    CG(active_op_array)->try_catch_array[try_catch_offset].catch_op = 0;
2902    CG(active_op_array)->try_catch_array[try_catch_offset].finally_op = 0;
2903    CG(active_op_array)->try_catch_array[try_catch_offset].finally_end = 0;
2904    return try_catch_offset;
2905}
2906/* }}} */
2907
2908static void zend_add_catch_element(int offset, zend_uint catch_op TSRMLS_DC) /* {{{ */
2909{
2910    CG(active_op_array)->try_catch_array[offset].catch_op = catch_op;
2911}
2912/* }}} */
2913
2914void zend_do_first_catch(znode *open_parentheses TSRMLS_DC) /* {{{ */
2915{
2916    open_parentheses->u.op.opline_num = get_next_op_number(CG(active_op_array));
2917}
2918/* }}} */
2919
2920void zend_initialize_try_catch_element(znode *catch_token TSRMLS_DC) /* {{{ */
2921{
2922    int jmp_op_number = get_next_op_number(CG(active_op_array));
2923    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2924    zend_llist jmp_list;
2925    zend_llist *jmp_list_ptr;
2926
2927    opline->opcode = ZEND_JMP;
2928    SET_UNUSED(opline->op1);
2929    SET_UNUSED(opline->op2);
2930    /* save for backpatching */
2931
2932    zend_llist_init(&jmp_list, sizeof(int), NULL, 0);
2933    zend_stack_push(&CG(bp_stack), (void *) &jmp_list, sizeof(zend_llist));
2934    zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
2935    zend_llist_add_element(jmp_list_ptr, &jmp_op_number);
2936
2937    catch_token->EA = get_next_op_number(CG(active_op_array));
2938}
2939/* }}} */
2940
2941void zend_do_mark_last_catch(const znode *first_catch, const znode *last_additional_catch TSRMLS_DC) /* {{{ */
2942{
2943    CG(active_op_array)->last--;
2944    zend_do_if_end(TSRMLS_C);
2945    if (last_additional_catch->u.op.opline_num == -1) {
2946        CG(active_op_array)->opcodes[first_catch->u.op.opline_num].result.num = 1;
2947        CG(active_op_array)->opcodes[first_catch->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
2948    } else {
2949        CG(active_op_array)->opcodes[last_additional_catch->u.op.opline_num].result.num = 1;
2950        CG(active_op_array)->opcodes[last_additional_catch->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
2951    }
2952    DEC_BPC(CG(active_op_array));
2953}
2954/* }}} */
2955
2956void zend_do_try(znode *try_token TSRMLS_DC) /* {{{ */
2957{
2958    try_token->u.op.opline_num = zend_add_try_element(get_next_op_number(CG(active_op_array)) TSRMLS_CC);
2959    INC_BPC(CG(active_op_array));
2960}
2961/* }}} */
2962
2963void zend_do_finally(znode *finally_token TSRMLS_DC) /* {{{ */
2964{
2965    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2966
2967    finally_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
2968    /* call the the "finally" block */
2969    opline->opcode = ZEND_FAST_CALL;
2970    SET_UNUSED(opline->op1);
2971    opline->op1.opline_num = finally_token->u.op.opline_num + 1;
2972    SET_UNUSED(opline->op2);
2973    /* jump to code after the "finally" block,
2974     * the actual jump address is going to be set in zend_do_end_finally()
2975     */
2976    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
2977    opline->opcode = ZEND_JMP;
2978    SET_UNUSED(opline->op1);
2979    SET_UNUSED(opline->op2);
2980
2981    CG(context).in_finally++;
2982}
2983/* }}} */
2984
2985void zend_do_begin_catch(znode *catch_token, znode *class_name, znode *catch_var, znode *first_catch TSRMLS_DC) /* {{{ */
2986{
2987    long catch_op_number;
2988    zend_op *opline;
2989    znode catch_class;
2990
2991    if (class_name->op_type == IS_CONST &&
2992        ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_name->u.constant), Z_STRLEN(class_name->u.constant))) {
2993        zend_resolve_class_name(class_name TSRMLS_CC);
2994        catch_class = *class_name;
2995    } else {
2996        zend_error_noreturn(E_COMPILE_ERROR, "Bad class name in the catch statement");
2997    }
2998
2999    catch_op_number = get_next_op_number(CG(active_op_array));
3000    if (first_catch) {
3001        first_catch->u.op.opline_num = catch_op_number;
3002    }
3003
3004    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3005    opline->opcode = ZEND_CATCH;
3006    opline->op1_type = IS_CONST;
3007    opline->op1.constant = zend_add_class_name_literal(CG(active_op_array), &catch_class.u.constant TSRMLS_CC);
3008    opline->op2_type = IS_CV;
3009    opline->op2.var = lookup_cv(CG(active_op_array), Z_STRVAL(catch_var->u.constant), Z_STRLEN(catch_var->u.constant), 0 TSRMLS_CC);
3010    Z_STRVAL(catch_var->u.constant) = (char*)CG(active_op_array)->vars[opline->op2.var].name;
3011    opline->result.num = 0; /* 1 means it's the last catch in the block */
3012
3013    catch_token->u.op.opline_num = catch_op_number;
3014}
3015/* }}} */
3016
3017void zend_do_end_catch(znode *catch_token TSRMLS_DC) /* {{{ */
3018{
3019    int jmp_op_number = get_next_op_number(CG(active_op_array));
3020    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3021    zend_llist *jmp_list_ptr;
3022
3023    opline->opcode = ZEND_JMP;
3024    SET_UNUSED(opline->op1);
3025    SET_UNUSED(opline->op2);
3026    /* save for backpatching */
3027
3028    zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr);
3029    zend_llist_add_element(jmp_list_ptr, &jmp_op_number);
3030
3031    CG(active_op_array)->opcodes[catch_token->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array));
3032}
3033/* }}} */
3034
3035void zend_do_bind_catch(znode *try_token, znode *catch_token TSRMLS_DC) /* {{{ */ {
3036    if (catch_token->op_type != IS_UNUSED) {
3037        zend_add_catch_element(try_token->u.op.opline_num, catch_token->EA TSRMLS_CC);
3038    }
3039}
3040/* }}} */
3041
3042void zend_do_end_finally(znode *try_token, znode* catch_token, znode *finally_token TSRMLS_DC) /* {{{ */
3043{
3044    if (catch_token->op_type == IS_UNUSED && finally_token->op_type == IS_UNUSED) {
3045        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use try without catch or finally");
3046    }
3047    if (finally_token->op_type != IS_UNUSED) {
3048        zend_op *opline;
3049
3050        CG(active_op_array)->try_catch_array[try_token->u.op.opline_num].finally_op = finally_token->u.op.opline_num + 1;
3051        CG(active_op_array)->try_catch_array[try_token->u.op.opline_num].finally_end = get_next_op_number(CG(active_op_array));
3052        CG(active_op_array)->has_finally_block = 1;
3053
3054        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3055        opline->opcode = ZEND_FAST_RET;
3056        SET_UNUSED(opline->op1);
3057        SET_UNUSED(opline->op2);
3058
3059        CG(active_op_array)->opcodes[finally_token->u.op.opline_num].op1.opline_num = get_next_op_number(CG(active_op_array));
3060
3061        CG(context).in_finally--;
3062    }
3063}
3064/* }}} */
3065
3066void zend_do_throw(const znode *expr TSRMLS_DC) /* {{{ */
3067{
3068    zend_op *opline;
3069
3070    opline = get_next_op(CG(active_op_array) TSRMLS_CC);
3071    opline->opcode = ZEND_THROW;
3072    SET_NODE(opline->op1, expr);
3073    SET_UNUSED(opline->op2);
3074}
3075/* }}} */
3076
3077ZEND_API void function_add_ref(zend_function *function) /* {{{ */
3078{
3079    if (function->type == ZEND_USER_FUNCTION) {
3080        zend_op_array *op_array = &function->op_array;
3081
3082        (*op_array->refcount)++;
3083        if (op_array->static_variables) {
3084            HashTable *static_variables = op_array->static_variables;
3085            zval *tmp_zval;
3086
3087            ALLOC_HASHTABLE(op_array->static_variables);
3088            zend_hash_init(op_array->static_variables, zend_hash_num_elements(static_variables), NULL, ZVAL_PTR_DTOR, 0);
3089            zend_hash_copy(op_array->static_variables, static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *));
3090        }
3091        op_array->run_time_cache = NULL;
3092    }
3093}
3094/* }}} */
3095
3096static void do_inherit_parent_constructor(zend_class_entry *ce) /* {{{ */
3097{
3098    zend_function *function, *new_function;
3099
3100    if (!ce->parent) {
3101        return;
3102    }
3103
3104    /* You cannot change create_object */
3105    ce->create_object = ce->parent->create_object;
3106
3107    /* Inherit special functions if needed */
3108    if (!ce->get_iterator) {
3109        ce->get_iterator = ce->parent->get_iterator;
3110    }
3111    if (!ce->iterator_funcs.funcs) {
3112        ce->iterator_funcs.funcs = ce->parent->iterator_funcs.funcs;
3113    }
3114    if (!ce->__get) {
3115        ce->__get   = ce->parent->__get;
3116    }
3117    if (!ce->__set) {
3118        ce->__set = ce->parent->__set;
3119    }
3120    if (!ce->__unset) {
3121        ce->__unset = ce->parent->__unset;
3122    }
3123    if (!ce->__isset) {
3124        ce->__isset = ce->parent->__isset;
3125    }
3126    if (!ce->__call) {
3127        ce->__call = ce->parent->__call;
3128    }
3129    if (!ce->__callstatic) {
3130        ce->__callstatic = ce->parent->__callstatic;
3131    }
3132    if (!ce->__tostring) {
3133        ce->__tostring = ce->parent->__tostring;
3134    }
3135    if (!ce->clone) {
3136        ce->clone = ce->parent->clone;
3137    }
3138    if(!ce->serialize) {
3139        ce->serialize = ce->parent->serialize;
3140    }
3141    if(!ce->unserialize) {
3142        ce->unserialize = ce->parent->unserialize;
3143    }
3144    if (!ce->destructor) {
3145        ce->destructor   = ce->parent->destructor;
3146    }
3147    if (!ce->__debugInfo) {
3148        ce->__debugInfo = ce->parent->__debugInfo;
3149    }
3150    if (ce->constructor) {
3151        if (ce->parent->constructor && ce->parent->constructor->common.fn_flags & ZEND_ACC_FINAL) {
3152            zend_error(E_ERROR, "Cannot override final %s::%s() with %s::%s()",
3153                ce->parent->name, ce->parent->constructor->common.function_name,
3154                ce->name, ce->constructor->common.function_name
3155                );
3156        }
3157        return;
3158    }
3159
3160    if (zend_hash_find(&ce->parent->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), (void **)&function)==SUCCESS) {
3161        /* inherit parent's constructor */
3162        zend_hash_update(&ce->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), function, sizeof(zend_function), (void**)&new_function);
3163        function_add_ref(new_function);
3164    } else {
3165        /* Don't inherit the old style constructor if we already have the new style constructor */
3166        char *lc_class_name;
3167        char *lc_parent_class_name;
3168
3169        lc_class_name = zend_str_tolower_dup(ce->name, ce->name_length);
3170        if (!zend_hash_exists(&ce->function_table, lc_class_name, ce->name_length+1)) {
3171            lc_parent_class_name = zend_str_tolower_dup(ce->parent->name, ce->parent->name_length);
3172            if (!zend_hash_exists(&ce->function_table, lc_parent_class_name, ce->parent->name_length+1) &&
3173                    zend_hash_find(&ce->parent->function_table, lc_parent_class_name, ce->parent->name_length+1, (void **)&function)==SUCCESS) {
3174                if (function->common.fn_flags & ZEND_ACC_CTOR) {
3175                    /* inherit parent's constructor */
3176                    zend_hash_update(&ce->function_table, lc_parent_class_name, ce->parent->name_length+1, function, sizeof(zend_function), (void**)&new_function);
3177                    function_add_ref(new_function);
3178                }
3179            }
3180            efree(lc_parent_class_name);
3181        }
3182        efree(lc_class_name);
3183    }
3184    ce->constructor = ce->parent->constructor;
3185}
3186/* }}} */
3187
3188char *zend_visibility_string(zend_uint fn_flags) /* {{{ */
3189{
3190    if (fn_flags & ZEND_ACC_PRIVATE) {
3191        return "private";
3192    }
3193    if (fn_flags & ZEND_ACC_PROTECTED) {
3194        return "protected";
3195    }
3196    if (fn_flags & ZEND_ACC_PUBLIC) {
3197        return "public";
3198    }
3199    return "";
3200}
3201/* }}} */
3202
3203static void do_inherit_method(zend_function *function) /* {{{ */
3204{
3205    /* The class entry of the derived function intentionally remains the same
3206     * as that of the parent class.  That allows us to know in which context
3207     * we're running, and handle private method calls properly.
3208     */
3209    function_add_ref(function);
3210}
3211/* }}} */
3212
3213static zend_bool zend_do_perform_implementation_check(const zend_function *fe, const zend_function *proto TSRMLS_DC) /* {{{ */
3214{
3215    zend_uint i, num_args;
3216
3217    /* If it's a user function then arg_info == NULL means we don't have any parameters but
3218     * we still need to do the arg number checks.  We are only willing to ignore this for internal
3219     * functions because extensions don't always define arg_info.
3220     */
3221    if (!proto || (!proto->common.arg_info && proto->common.type != ZEND_USER_FUNCTION)) {
3222        return 1;
3223    }
3224
3225    /* Checks for constructors only if they are declared in an interface,
3226     * or explicitly marked as abstract
3227     */
3228    if ((fe->common.fn_flags & ZEND_ACC_CTOR)
3229        && ((proto->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0
3230            && (proto->common.fn_flags & ZEND_ACC_ABSTRACT) == 0)) {
3231        return 1;
3232    }
3233
3234    /* If both methods are private do not enforce a signature */
3235    if ((fe->common.fn_flags & ZEND_ACC_PRIVATE) && (proto->common.fn_flags & ZEND_ACC_PRIVATE)) {
3236        return 1;
3237    }
3238
3239    /* check number of arguments */
3240    if (proto->common.required_num_args < fe->common.required_num_args
3241        || proto->common.num_args > fe->common.num_args) {
3242        return 0;
3243    }
3244
3245    /* by-ref constraints on return values are covariant */
3246    if ((proto->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
3247        && !(fe->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
3248        return 0;
3249    }
3250
3251    if ((proto->common.fn_flags & ZEND_ACC_VARIADIC)
3252        && !(fe->common.fn_flags & ZEND_ACC_VARIADIC)) {
3253        return 0;
3254    }
3255
3256    /* For variadic functions any additional (optional) arguments that were added must be
3257     * checked against the signature of the variadic argument, so in this case we have to
3258     * go through all the parameters of the function and not just those present in the
3259     * prototype. */
3260    num_args = proto->common.num_args;
3261    if ((fe->common.fn_flags & ZEND_ACC_VARIADIC)
3262        && fe->common.num_args > proto->common.num_args) {
3263        num_args = fe->common.num_args;
3264    }
3265
3266    for (i = 0; i < num_args; i++) {
3267        zend_arg_info *fe_arg_info = &fe->common.arg_info[i];
3268
3269        zend_arg_info *proto_arg_info;
3270        if (i < proto->common.num_args) {
3271            proto_arg_info = &proto->common.arg_info[i];
3272        } else {
3273            proto_arg_info = &proto->common.arg_info[proto->common.num_args-1];
3274        }
3275
3276        if (ZEND_LOG_XOR(fe_arg_info->class_name, proto_arg_info->class_name)) {
3277            /* Only one has a type hint and the other one doesn't */
3278            return 0;
3279        }
3280
3281        if (fe_arg_info->class_name) {
3282            const char *fe_class_name, *proto_class_name;
3283            zend_uint fe_class_name_len, proto_class_name_len;
3284
3285            if (!strcasecmp(fe_arg_info->class_name, "parent") && proto->common.scope) {
3286                fe_class_name = proto->common.scope->name;
3287                fe_class_name_len = proto->common.scope->name_length;
3288            } else if (!strcasecmp(fe_arg_info->class_name, "self") && fe->common.scope) {
3289                fe_class_name = fe->common.scope->name;
3290                fe_class_name_len = fe->common.scope->name_length;
3291            } else {
3292                fe_class_name = fe_arg_info->class_name;
3293                fe_class_name_len = fe_arg_info->class_name_len;
3294            }
3295
3296            if (!strcasecmp(proto_arg_info->class_name, "parent") && proto->common.scope && proto->common.scope->parent) {
3297                proto_class_name = proto->common.scope->parent->name;
3298                proto_class_name_len = proto->common.scope->parent->name_length;
3299            } else if (!strcasecmp(proto_arg_info->class_name, "self") && proto->common.scope) {
3300                proto_class_name = proto->common.scope->name;
3301                proto_class_name_len = proto->common.scope->name_length;
3302            } else {
3303                proto_class_name = proto_arg_info->class_name;
3304                proto_class_name_len = proto_arg_info->class_name_len;
3305            }
3306
3307            if (strcasecmp(fe_class_name, proto_class_name)!=0) {
3308                const char *colon;
3309
3310                if (fe->common.type != ZEND_USER_FUNCTION) {
3311                    return 0;
3312                } else if (strchr(proto_class_name, '\\') != NULL ||
3313                        (colon = zend_memrchr(fe_class_name, '\\', fe_class_name_len)) == NULL ||
3314                        strcasecmp(colon+1, proto_class_name) != 0) {
3315                    zend_class_entry **fe_ce, **proto_ce;
3316                    int found, found2;
3317
3318                    found = zend_lookup_class(fe_class_name, fe_class_name_len, &fe_ce TSRMLS_CC);
3319                    found2 = zend_lookup_class(proto_class_name, proto_class_name_len, &proto_ce TSRMLS_CC);
3320
3321                    /* Check for class alias */
3322                    if (found != SUCCESS || found2 != SUCCESS ||
3323                            (*fe_ce)->type == ZEND_INTERNAL_CLASS ||
3324                            (*proto_ce)->type == ZEND_INTERNAL_CLASS ||
3325                            *fe_ce != *proto_ce) {
3326                        return 0;
3327                    }
3328                }
3329            }
3330        }
3331        if (fe_arg_info->type_hint != proto_arg_info->type_hint) {
3332            /* Incompatible type hint */
3333            return 0;
3334        }
3335
3336        /* by-ref constraints on arguments are invariant */
3337        if (fe_arg_info->pass_by_reference != proto_arg_info->pass_by_reference) {
3338            return 0;
3339        }
3340    }
3341
3342    return 1;
3343}
3344/* }}} */
3345
3346#define REALLOC_BUF_IF_EXCEED(buf, offset, length, size) \
3347    if (UNEXPECTED(offset - buf + size >= length)) {    \
3348        length += size + 1;                 \
3349        buf = erealloc(buf, length);        \
3350    }
3351
3352static char * zend_get_function_declaration(zend_function *fptr TSRMLS_DC) /* {{{ */
3353{
3354    char *offset, *buf;
3355    zend_uint length = 1024;
3356
3357    offset = buf = (char *)emalloc(length * sizeof(char));
3358    if (fptr->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
3359        *(offset++) = '&';
3360        *(offset++) = ' ';
3361    }
3362
3363    if (fptr->common.scope) {
3364        memcpy(offset, fptr->common.scope->name, fptr->common.scope->name_length);
3365        offset += fptr->common.scope->name_length;
3366        *(offset++) = ':';
3367        *(offset++) = ':';
3368    }
3369
3370    {
3371        size_t name_len = strlen(fptr->common.function_name);
3372        REALLOC_BUF_IF_EXCEED(buf, offset, length, name_len);
3373        memcpy(offset, fptr->common.function_name, name_len);
3374        offset += name_len;
3375    }
3376
3377    *(offset++) = '(';
3378    if (fptr->common.arg_info) {
3379        zend_uint i, required;
3380        zend_arg_info *arg_info = fptr->common.arg_info;
3381
3382        required = fptr->common.required_num_args;
3383        for (i = 0; i < fptr->common.num_args;) {
3384            if (arg_info->class_name) {
3385                const char *class_name;
3386                zend_uint class_name_len;
3387                if (!strcasecmp(arg_info->class_name, "self") && fptr->common.scope ) {
3388                    class_name = fptr->common.scope->name;
3389                    class_name_len = fptr->common.scope->name_length;
3390                } else if (!strcasecmp(arg_info->class_name, "parent") && fptr->common.scope->parent) {
3391                    class_name = fptr->common.scope->parent->name;
3392                    class_name_len = fptr->common.scope->parent->name_length;
3393                } else {
3394                    class_name = arg_info->class_name;
3395                    class_name_len = arg_info->class_name_len;
3396                }
3397                REALLOC_BUF_IF_EXCEED(buf, offset, length, class_name_len);
3398                memcpy(offset, class_name, class_name_len);
3399                offset += class_name_len;
3400                *(offset++) = ' ';
3401            } else if (arg_info->type_hint) {
3402                zend_uint type_name_len;
3403                char *type_name = zend_get_type_by_const(arg_info->type_hint);
3404                type_name_len = strlen(type_name);
3405                REALLOC_BUF_IF_EXCEED(buf, offset, length, type_name_len);
3406                memcpy(offset, type_name, type_name_len);
3407                offset += type_name_len;
3408                *(offset++) = ' ';
3409            }
3410
3411            if (arg_info->pass_by_reference) {
3412                *(offset++) = '&';
3413            }
3414
3415            if (arg_info->is_variadic) {
3416                *(offset++) = '.';
3417                *(offset++) = '.';
3418                *(offset++) = '.';
3419            }
3420
3421            *(offset++) = '$';
3422
3423            if (arg_info->name) {
3424                REALLOC_BUF_IF_EXCEED(buf, offset, length, arg_info->name_len);
3425                memcpy(offset, arg_info->name, arg_info->name_len);
3426                offset += arg_info->name_len;
3427            } else {
3428                zend_uint idx = i;
3429                memcpy(offset, "param", 5);
3430                offset += 5;
3431                do {
3432                    *(offset++) = (char) (idx % 10) + '0';
3433                    idx /= 10;
3434                } while (idx > 0);
3435            }
3436            if (i >= required && !arg_info->is_variadic) {
3437                *(offset++) = ' ';
3438                *(offset++) = '=';
3439                *(offset++) = ' ';
3440                if (fptr->type == ZEND_USER_FUNCTION) {
3441                    zend_op *precv = NULL;
3442                    {
3443                        zend_uint idx  = i;
3444                        zend_op *op = ((zend_op_array *)fptr)->opcodes;
3445                        zend_op *end = op + ((zend_op_array *)fptr)->last;
3446
3447                        ++idx;
3448                        while (op < end) {
3449                            if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT)
3450                                    && op->op1.num == (long)idx)
3451                            {
3452                                precv = op;
3453                            }
3454                            ++op;
3455                        }
3456                    }
3457                    if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2_type != IS_UNUSED) {
3458                        zval *zv, zv_copy;
3459                        int use_copy;
3460                        ALLOC_ZVAL(zv);
3461                        *zv = *precv->op2.zv;
3462                        zval_copy_ctor(zv);
3463                        INIT_PZVAL(zv);
3464                        zval_update_constant_ex(&zv, 1, fptr->common.scope TSRMLS_CC);
3465                        if (Z_TYPE_P(zv) == IS_BOOL) {
3466                            if (Z_LVAL_P(zv)) {
3467                                memcpy(offset, "true", 4);
3468                                offset += 4;
3469                            } else {
3470                                memcpy(offset, "false", 5);
3471                                offset += 5;
3472                            }
3473                        } else if (Z_TYPE_P(zv) == IS_NULL) {
3474                            memcpy(offset, "NULL", 4);
3475                            offset += 4;
3476                        } else if (Z_TYPE_P(zv) == IS_STRING) {
3477                            *(offset++) = '\'';
3478                            REALLOC_BUF_IF_EXCEED(buf, offset, length, MIN(Z_STRLEN_P(zv), 10));
3479                            memcpy(offset, Z_STRVAL_P(zv), MIN(Z_STRLEN_P(zv), 10));
3480                            offset += MIN(Z_STRLEN_P(zv), 10);
3481                            if (Z_STRLEN_P(zv) > 10) {
3482                                *(offset++) = '.';
3483                                *(offset++) = '.';
3484                                *(offset++) = '.';
3485                            }
3486                            *(offset++) = '\'';
3487                        } else if (Z_TYPE_P(zv) == IS_ARRAY) {
3488                            memcpy(offset, "Array", 5);
3489                            offset += 5;
3490                        } else {
3491                            zend_make_printable_zval(zv, &zv_copy, &use_copy);
3492                            REALLOC_BUF_IF_EXCEED(buf, offset, length, Z_STRLEN(zv_copy));
3493                            memcpy(offset, Z_STRVAL(zv_copy), Z_STRLEN(zv_copy));
3494                            offset += Z_STRLEN(zv_copy);
3495                            if (use_copy) {
3496                                zval_dtor(&zv_copy);
3497                            }
3498                        }
3499                        zval_ptr_dtor(&zv);
3500                    }
3501                } else {
3502                    memcpy(offset, "NULL", 4);
3503                    offset += 4;
3504                }
3505            }
3506
3507            if (++i < fptr->common.num_args) {
3508                *(offset++) = ',';
3509                *(offset++) = ' ';
3510            }
3511            arg_info++;
3512            REALLOC_BUF_IF_EXCEED(buf, offset, length, 32);
3513        }
3514    }
3515    *(offset++) = ')';
3516    *offset = '\0';
3517
3518    return buf;
3519}
3520/* }}} */
3521
3522static void do_inheritance_check_on_method(zend_function *child, zend_function *parent TSRMLS_DC) /* {{{ */
3523{
3524    zend_uint child_flags;
3525    zend_uint parent_flags = parent->common.fn_flags;
3526
3527    if ((parent->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0
3528        && parent->common.fn_flags & ZEND_ACC_ABSTRACT
3529        && parent->common.scope != (child->common.prototype ? child->common.prototype->common.scope : child->common.scope)
3530        && child->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_IMPLEMENTED_ABSTRACT)) {
3531        zend_error_noreturn(E_COMPILE_ERROR, "Can't inherit abstract function %s::%s() (previously declared abstract in %s)",
3532            parent->common.scope->name,
3533            child->common.function_name,
3534            child->common.prototype ? child->common.prototype->common.scope->name : child->common.scope->name);
3535    }
3536
3537    if (parent_flags & ZEND_ACC_FINAL) {
3538        zend_error_noreturn(E_COMPILE_ERROR, "Cannot override final method %s::%s()", ZEND_FN_SCOPE_NAME(parent), child->common.function_name);
3539    }
3540
3541    child_flags = child->common.fn_flags;
3542    /* You cannot change from static to non static and vice versa.
3543     */
3544    if ((child_flags & ZEND_ACC_STATIC) != (parent_flags & ZEND_ACC_STATIC)) {
3545        if (child->common.fn_flags & ZEND_ACC_STATIC) {
3546            zend_error_noreturn(E_COMPILE_ERROR, "Cannot make non static method %s::%s() static in class %s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
3547        } else {
3548            zend_error_noreturn(E_COMPILE_ERROR, "Cannot make static method %s::%s() non static in class %s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
3549        }
3550    }
3551
3552    /* Disallow making an inherited method abstract. */
3553    if ((child_flags & ZEND_ACC_ABSTRACT) && !(parent_flags & ZEND_ACC_ABSTRACT)) {
3554        zend_error_noreturn(E_COMPILE_ERROR, "Cannot make non abstract method %s::%s() abstract in class %s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
3555    }
3556
3557    if (parent_flags & ZEND_ACC_CHANGED) {
3558        child->common.fn_flags |= ZEND_ACC_CHANGED;
3559    } else {
3560        /* Prevent derived classes from restricting access that was available in parent classes
3561         */
3562        if ((child_flags & ZEND_ACC_PPP_MASK) > (parent_flags & ZEND_ACC_PPP_MASK)) {
3563            zend_error_noreturn(E_COMPILE_ERROR, "Access level to %s::%s() must be %s (as in class %s)%s", ZEND_FN_SCOPE_NAME(child), child->common.function_name, zend_visibility_string(parent_flags), ZEND_FN_SCOPE_NAME(parent), (parent_flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
3564        } else if (((child_flags & ZEND_ACC_PPP_MASK) < (parent_flags & ZEND_ACC_PPP_MASK))
3565            && ((parent_flags & ZEND_ACC_PPP_MASK) & ZEND_ACC_PRIVATE)) {
3566            child->common.fn_flags |= ZEND_ACC_CHANGED;
3567        }
3568    }
3569
3570    if (parent_flags & ZEND_ACC_PRIVATE) {
3571        child->common.prototype = NULL;
3572    } else if (parent_flags & ZEND_ACC_ABSTRACT) {
3573        child->common.fn_flags |= ZEND_ACC_IMPLEMENTED_ABSTRACT;
3574        child->common.prototype = parent;
3575    } else if (!(parent->common.fn_flags & ZEND_ACC_CTOR) || (parent->common.prototype && (parent->common.prototype->common.scope->ce_flags & ZEND_ACC_INTERFACE))) {
3576        /* ctors only have a prototype if it comes from an interface */
3577        child->common.prototype = parent->common.prototype ? parent->common.prototype : parent;
3578    }
3579
3580    if (child->common.prototype && (child->common.prototype->common.fn_flags & ZEND_ACC_ABSTRACT)) {
3581        if (!zend_do_perform_implementation_check(child, child->common.prototype TSRMLS_CC)) {
3582            zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s::%s() must be compatible with %s", ZEND_FN_SCOPE_NAME(child), child->common.function_name, zend_get_function_declaration(child->common.prototype TSRMLS_CC));
3583        }
3584    } else if (EG(error_reporting) & E_STRICT || EG(user_error_handler)) { /* Check E_STRICT (or custom error handler) before the check so that we save some time */
3585        if (!zend_do_perform_implementation_check(child, parent TSRMLS_CC)) {
3586            char *method_prototype = zend_get_function_declaration(parent TSRMLS_CC);
3587            zend_error(E_STRICT, "Declaration of %s::%s() should be compatible with %s", ZEND_FN_SCOPE_NAME(child), child->common.function_name, method_prototype);
3588            efree(method_prototype);
3589        }
3590    }
3591}
3592/* }}} */
3593
3594static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_function *parent, const zend_hash_key *hash_key, zend_class_entry *child_ce) /* {{{ */
3595{
3596    zend_uint parent_flags = parent->common.fn_flags;
3597    zend_function *child;
3598    TSRMLS_FETCH();
3599
3600    if (zend_hash_quick_find(child_function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child)==FAILURE) {
3601        if (parent_flags & (ZEND_ACC_ABSTRACT)) {
3602            child_ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
3603        }
3604        return 1; /* method doesn't exist in child, copy from parent */
3605    }
3606
3607    do_inheritance_check_on_method(child, parent TSRMLS_CC);
3608
3609    return 0;
3610}
3611/* }}} */
3612
3613static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_property_info *parent_info, const zend_hash_key *hash_key, zend_class_entry *ce) /* {{{ */
3614{
3615    zend_property_info *child_info;
3616    zend_class_entry *parent_ce = ce->parent;
3617
3618    if (parent_info->flags & (ZEND_ACC_PRIVATE|ZEND_ACC_SHADOW)) {
3619        if (zend_hash_quick_find(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
3620            child_info->flags |= ZEND_ACC_CHANGED;
3621        } else {
3622            zend_hash_quick_update(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, parent_info, sizeof(zend_property_info), (void **) &child_info);
3623            if(ce->type & ZEND_INTERNAL_CLASS) {
3624                zend_duplicate_property_info_internal(child_info);
3625            } else {
3626                zend_duplicate_property_info(child_info);
3627            }
3628            child_info->flags &= ~ZEND_ACC_PRIVATE; /* it's not private anymore */
3629            child_info->flags |= ZEND_ACC_SHADOW; /* but it's a shadow of private */
3630        }
3631        return 0; /* don't copy access information to child */
3632    }
3633
3634    if (zend_hash_quick_find(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
3635        if ((parent_info->flags & ZEND_ACC_STATIC) != (child_info->flags & ZEND_ACC_STATIC)) {
3636            zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s%s::$%s as %s%s::$%s",
3637                (parent_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", parent_ce->name, hash_key->arKey,
3638                (child_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", ce->name, hash_key->arKey);
3639
3640        }
3641
3642        if(parent_info->flags & ZEND_ACC_CHANGED) {
3643            child_info->flags |= ZEND_ACC_CHANGED;
3644        }
3645
3646        if ((child_info->flags & ZEND_ACC_PPP_MASK) > (parent_info->flags & ZEND_ACC_PPP_MASK)) {
3647            zend_error_noreturn(E_COMPILE_ERROR, "Access level to %s::$%s must be %s (as in class %s)%s", ce->name, hash_key->arKey, zend_visibility_string(parent_info->flags), parent_ce->name, (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
3648        } else if ((child_info->flags & ZEND_ACC_STATIC) == 0) {
3649            zval_ptr_dtor(&(ce->default_properties_table[parent_info->offset]));
3650            ce->default_properties_table[parent_info->offset] = ce->default_properties_table[child_info->offset];
3651            ce->default_properties_table[child_info->offset] = NULL;
3652            child_info->offset = parent_info->offset;
3653        }
3654        return 0;   /* Don't copy from parent */
3655    } else {
3656        return 1;   /* Copy from parent */
3657    }
3658}
3659/* }}} */
3660
3661static inline void do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC) /* {{{ */
3662{
3663    if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && iface->interface_gets_implemented && iface->interface_gets_implemented(iface, ce TSRMLS_CC) == FAILURE) {
3664        zend_error(E_CORE_ERROR, "Class %s could not implement interface %s", ce->name, iface->name);
3665    }
3666    if (ce == iface) {
3667        zend_error(E_ERROR, "Interface %s cannot implement itself", ce->name);
3668    }
3669}
3670/* }}} */
3671
3672ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_entry *iface TSRMLS_DC) /* {{{ */
3673{
3674    /* expects interface to be contained in ce's interface list already */
3675    zend_uint i, ce_num, if_num = iface->num_interfaces;
3676    zend_class_entry *entry;
3677
3678    if (if_num==0) {
3679        return;
3680    }
3681    ce_num = ce->num_interfaces;
3682
3683    if (ce->type == ZEND_INTERNAL_CLASS) {
3684        ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num));
3685    } else {
3686        ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num));
3687    }
3688
3689    /* Inherit the interfaces, only if they're not already inherited by the class */
3690    while (if_num--) {
3691        entry = iface->interfaces[if_num];
3692        for (i = 0; i < ce_num; i++) {
3693            if (ce->interfaces[i] == entry) {
3694                break;
3695            }
3696        }
3697        if (i == ce_num) {
3698            ce->interfaces[ce->num_interfaces++] = entry;
3699        }
3700    }
3701
3702    /* and now call the implementing handlers */
3703    while (ce_num < ce->num_interfaces) {
3704        do_implement_interface(ce, ce->interfaces[ce_num++] TSRMLS_CC);
3705    }
3706}
3707/* }}} */
3708
3709#ifdef ZTS
3710static void zval_internal_ctor(zval **p) /* {{{ */
3711{
3712    zval *orig_ptr = *p;
3713
3714    ALLOC_ZVAL(*p);
3715    MAKE_COPY_ZVAL(&orig_ptr, *p);
3716}
3717/* }}} */
3718
3719# define zval_property_ctor(parent_ce, ce) \
3720    ((void (*)(void *)) (((parent_ce)->type != (ce)->type) ? zval_internal_ctor : zval_add_ref))
3721#else
3722# define zval_property_ctor(parent_ce, ce) \
3723    ((void (*)(void *)) zval_add_ref)
3724#endif
3725
3726ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce TSRMLS_DC) /* {{{ */
3727{
3728    zend_property_info *property_info;
3729
3730    if ((ce->ce_flags & ZEND_ACC_INTERFACE)
3731        && !(parent_ce->ce_flags & ZEND_ACC_INTERFACE)) {
3732        zend_error_noreturn(E_COMPILE_ERROR, "Interface %s may not inherit from class (%s)", ce->name, parent_ce->name);
3733    }
3734    if (parent_ce->ce_flags & ZEND_ACC_FINAL_CLASS) {
3735        zend_error_noreturn(E_COMPILE_ERROR, "Class %s may not inherit from final class (%s)", ce->name, parent_ce->name);
3736    }
3737
3738    ce->parent = parent_ce;
3739    /* Copy serialize/unserialize callbacks */
3740    if (!ce->serialize) {
3741        ce->serialize   = parent_ce->serialize;
3742    }
3743    if (!ce->unserialize) {
3744        ce->unserialize = parent_ce->unserialize;
3745    }
3746
3747    /* Inherit interfaces */
3748    zend_do_inherit_interfaces(ce, parent_ce TSRMLS_CC);
3749
3750    /* Inherit properties */
3751    if (parent_ce->default_properties_count) {
3752        int i = ce->default_properties_count + parent_ce->default_properties_count;
3753
3754        ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(void*) * i, ce->type == ZEND_INTERNAL_CLASS);
3755        if (ce->default_properties_count) {
3756            while (i-- > parent_ce->default_properties_count) {
3757                ce->default_properties_table[i] = ce->default_properties_table[i - parent_ce->default_properties_count];
3758            }
3759        }
3760        for (i = 0; i < parent_ce->default_properties_count; i++) {
3761            ce->default_properties_table[i] = parent_ce->default_properties_table[i];
3762            if (ce->default_properties_table[i]) {
3763#ifdef ZTS
3764                if (parent_ce->type != ce->type) {
3765                    zval *p;
3766
3767                    ALLOC_ZVAL(p);
3768                    MAKE_COPY_ZVAL(&ce->default_properties_table[i], p);
3769                    ce->default_properties_table[i] = p;
3770                } else {
3771                    Z_ADDREF_P(ce->default_properties_table[i]);
3772                }
3773#else
3774                Z_ADDREF_P(ce->default_properties_table[i]);
3775#endif
3776            }
3777        }
3778        ce->default_properties_count += parent_ce->default_properties_count;
3779    }
3780
3781    if (parent_ce->type != ce->type) {
3782        /* User class extends internal class */
3783        zend_update_class_constants(parent_ce  TSRMLS_CC);
3784        if (parent_ce->default_static_members_count) {
3785            int i = ce->default_static_members_count + parent_ce->default_static_members_count;
3786
3787            ce->default_static_members_table = erealloc(ce->default_static_members_table, sizeof(void*) * i);
3788            if (ce->default_static_members_count) {
3789                while (i-- > parent_ce->default_static_members_count) {
3790                    ce->default_static_members_table[i] = ce->default_static_members_table[i - parent_ce->default_static_members_count];
3791                }
3792            }
3793            for (i = 0; i < parent_ce->default_static_members_count; i++) {
3794                SEPARATE_ZVAL_TO_MAKE_IS_REF(&CE_STATIC_MEMBERS(parent_ce)[i]);
3795                ce->default_static_members_table[i] = CE_STATIC_MEMBERS(parent_ce)[i];
3796                Z_ADDREF_P(ce->default_static_members_table[i]);
3797            }
3798            ce->default_static_members_count += parent_ce->default_static_members_count;
3799            ce->static_members_table = ce->default_static_members_table;
3800        }
3801    } else {
3802        if (parent_ce->default_static_members_count) {
3803            int i = ce->default_static_members_count + parent_ce->default_static_members_count;
3804
3805            ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(void*) * i, ce->type == ZEND_INTERNAL_CLASS);
3806            if (ce->default_static_members_count) {
3807                while (i-- > parent_ce->default_static_members_count) {
3808                    ce->default_static_members_table[i] = ce->default_static_members_table[i - parent_ce->default_static_members_count];
3809                }
3810            }
3811            for (i = 0; i < parent_ce->default_static_members_count; i++) {
3812                SEPARATE_ZVAL_TO_MAKE_IS_REF(&parent_ce->default_static_members_table[i]);
3813                ce->default_static_members_table[i] = parent_ce->default_static_members_table[i];
3814                Z_ADDREF_P(ce->default_static_members_table[i]);
3815            }
3816            ce->default_static_members_count += parent_ce->default_static_members_count;
3817            if (ce->type == ZEND_USER_CLASS) {
3818                ce->static_members_table = ce->default_static_members_table;
3819            }
3820        }
3821    }
3822
3823    for (zend_hash_internal_pointer_reset(&ce->properties_info);
3824    zend_hash_get_current_data(&ce->properties_info, (void *) &property_info) == SUCCESS;
3825    zend_hash_move_forward(&ce->properties_info)) {
3826        if (property_info->ce == ce) {
3827            if (property_info->flags & ZEND_ACC_STATIC) {
3828                property_info->offset += parent_ce->default_static_members_count;
3829            } else {
3830                property_info->offset += parent_ce->default_properties_count;
3831            }
3832        }
3833    }
3834
3835    zend_hash_merge_ex(&ce->properties_info, &parent_ce->properties_info, (copy_ctor_func_t) (ce->type & ZEND_INTERNAL_CLASS ? zend_duplicate_property_info_internal : zend_duplicate_property_info), sizeof(zend_property_info), (merge_checker_func_t) do_inherit_property_access_check, ce);
3836
3837    zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, zval_property_ctor(parent_ce, ce), NULL, sizeof(zval *), 0);
3838    zend_hash_merge_ex(&ce->function_table, &parent_ce->function_table, (copy_ctor_func_t) do_inherit_method, sizeof(zend_function), (merge_checker_func_t) do_inherit_method_check, ce);
3839    do_inherit_parent_constructor(ce);
3840
3841    if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS && ce->type == ZEND_INTERNAL_CLASS) {
3842        ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
3843    } else if (!(ce->ce_flags & (ZEND_ACC_IMPLEMENT_INTERFACES|ZEND_ACC_IMPLEMENT_TRAITS))) {
3844        /* The verification will be done in runtime by ZEND_VERIFY_ABSTRACT_CLASS */
3845        zend_verify_abstract_class(ce TSRMLS_CC);
3846    }
3847    ce->ce_flags |= parent_ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS;
3848}
3849/* }}} */
3850
3851static zend_bool do_inherit_constant_check(HashTable *child_constants_table, const zval **parent_constant, const zend_hash_key *hash_key, const zend_class_entry *iface) /* {{{ */
3852{
3853    zval **old_constant;
3854
3855    if (zend_hash_quick_find(child_constants_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void**)&old_constant) == SUCCESS) {
3856        if (*old_constant != *parent_constant) {
3857            zend_error_noreturn(E_COMPILE_ERROR, "Cannot inherit previously-inherited or override constant %s from interface %s", hash_key->arKey, iface->name);
3858        }
3859        return 0;
3860    }
3861    return 1;
3862}
3863/* }}} */
3864
3865static int do_interface_constant_check(zval **val TSRMLS_DC, int num_args, va_list args, const zend_hash_key *key) /* {{{ */
3866{
3867    zend_class_entry **iface = va_arg(args, zend_class_entry**);
3868
3869    do_inherit_constant_check(&(*iface)->constants_table, (const zval **) val, key, *iface);
3870
3871    return ZEND_HASH_APPLY_KEEP;
3872}
3873/* }}} */
3874
3875ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC) /* {{{ */
3876{
3877    zend_uint i, ignore = 0;
3878    zend_uint current_iface_num = ce->num_interfaces;
3879    zend_uint parent_iface_num  = ce->parent ? ce->parent->num_interfaces : 0;
3880
3881    for (i = 0; i < ce->num_interfaces; i++) {
3882        if (ce->interfaces[i] == NULL) {
3883            memmove(ce->interfaces + i, ce->interfaces + i + 1, sizeof(zend_class_entry*) * (--ce->num_interfaces - i));
3884            i--;
3885        } else if (ce->interfaces[i] == iface) {
3886            if (i < parent_iface_num) {
3887                ignore = 1;
3888            } else {
3889                zend_error_noreturn(E_COMPILE_ERROR, "Class %s cannot implement previously implemented interface %s", ce->name, iface->name);
3890            }
3891        }
3892    }
3893    if (ignore) {
3894        /* Check for attempt to redeclare interface constants */
3895        zend_hash_apply_with_arguments(&ce->constants_table TSRMLS_CC, (apply_func_args_t) do_interface_constant_check, 1, &iface);
3896    } else {
3897        if (ce->num_interfaces >= current_iface_num) {
3898            if (ce->type == ZEND_INTERNAL_CLASS) {
3899                ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
3900            } else {
3901                ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
3902            }
3903        }
3904        ce->interfaces[ce->num_interfaces++] = iface;
3905
3906        zend_hash_merge_ex(&ce->constants_table, &iface->constants_table, (copy_ctor_func_t) zval_add_ref, sizeof(zval *), (merge_checker_func_t) do_inherit_constant_check, iface);
3907        zend_hash_merge_ex(&ce->function_table, &iface->function_table, (copy_ctor_func_t) do_inherit_method, sizeof(zend_function), (merge_checker_func_t) do_inherit_method_check, ce);
3908
3909        do_implement_interface(ce, iface TSRMLS_CC);
3910        zend_do_inherit_interfaces(ce, iface TSRMLS_CC);
3911    }
3912}
3913/* }}} */
3914
3915ZEND_API void zend_do_implement_trait(zend_class_entry *ce, zend_class_entry *trait TSRMLS_DC) /* {{{ */
3916{
3917    zend_uint i, ignore = 0;
3918    zend_uint current_trait_num = ce->num_traits;
3919    zend_uint parent_trait_num  = ce->parent ? ce->parent->num_traits : 0;
3920
3921    for (i = 0; i < ce->num_traits; i++) {
3922        if (ce->traits[i] == NULL) {
3923            memmove(ce->traits + i, ce->traits + i + 1, sizeof(zend_class_entry*) * (--ce->num_traits - i));
3924            i--;
3925        } else if (ce->traits[i] == trait) {
3926            if (i < parent_trait_num) {
3927                ignore = 1;
3928            }
3929        }
3930    }
3931    if (!ignore) {
3932        if (ce->num_traits >= current_trait_num) {
3933            if (ce->type == ZEND_INTERNAL_CLASS) {
3934                ce->traits = (zend_class_entry **) realloc(ce->traits, sizeof(zend_class_entry *) * (++current_trait_num));
3935            } else {
3936                ce->traits = (zend_class_entry **) erealloc(ce->traits, sizeof(zend_class_entry *) * (++current_trait_num));
3937            }
3938        }
3939        ce->traits[ce->num_traits++] = trait;
3940    }
3941}
3942/* }}} */
3943
3944static zend_bool zend_traits_method_compatibility_check(zend_function *fn, zend_function *other_fn TSRMLS_DC) /* {{{ */
3945{
3946    zend_uint    fn_flags = fn->common.scope->ce_flags;
3947    zend_uint other_flags = other_fn->common.scope->ce_flags;
3948
3949    return zend_do_perform_implementation_check(fn, other_fn TSRMLS_CC)
3950        && ((other_fn->common.scope->ce_flags & ZEND_ACC_INTERFACE) || zend_do_perform_implementation_check(other_fn, fn TSRMLS_CC))
3951        && ((fn_flags & (ZEND_ACC_FINAL|ZEND_ACC_STATIC)) ==
3952            (other_flags & (ZEND_ACC_FINAL|ZEND_ACC_STATIC))); /* equal final and static qualifier */
3953}
3954/* }}} */
3955
3956static void zend_add_magic_methods(zend_class_entry* ce, const char* mname, uint mname_len, zend_function* fe TSRMLS_DC) /* {{{ */
3957{
3958    if (!strncmp(mname, ZEND_CLONE_FUNC_NAME, mname_len)) {
3959        ce->clone = fe; fe->common.fn_flags |= ZEND_ACC_CLONE;
3960    } else if (!strncmp(mname, ZEND_CONSTRUCTOR_FUNC_NAME, mname_len)) {
3961        if (ce->constructor) {
3962            zend_error_noreturn(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ce->name);
3963        }
3964        ce->constructor = fe; fe->common.fn_flags |= ZEND_ACC_CTOR;
3965    } else if (!strncmp(mname, ZEND_DESTRUCTOR_FUNC_NAME,  mname_len)) {
3966        ce->destructor = fe; fe->common.fn_flags |= ZEND_ACC_DTOR;
3967    } else if (!strncmp(mname, ZEND_GET_FUNC_NAME, mname_len)) {
3968        ce->__get = fe;
3969    } else if (!strncmp(mname, ZEND_SET_FUNC_NAME, mname_len)) {
3970        ce->__set = fe;
3971    } else if (!strncmp(mname, ZEND_CALL_FUNC_NAME, mname_len)) {
3972        ce->__call = fe;
3973    } else if (!strncmp(mname, ZEND_UNSET_FUNC_NAME, mname_len)) {
3974        ce->__unset = fe;
3975    } else if (!strncmp(mname, ZEND_ISSET_FUNC_NAME, mname_len)) {
3976        ce->__isset = fe;
3977    } else if (!strncmp(mname, ZEND_CALLSTATIC_FUNC_NAME, mname_len)) {
3978        ce->__callstatic = fe;
3979    } else if (!strncmp(mname, ZEND_TOSTRING_FUNC_NAME, mname_len)) {
3980        ce->__tostring = fe;
3981    } else if (!strncmp(mname, ZEND_DEBUGINFO_FUNC_NAME, mname_len)) {
3982        ce->__debugInfo = fe;
3983    } else if (ce->name_length + 1 == mname_len) {
3984        char *lowercase_name = emalloc(ce->name_length + 1);
3985        zend_str_tolower_copy(lowercase_name, ce->name, ce->name_length);
3986        lowercase_name = (char*)zend_new_interned_string(lowercase_name, ce->name_length + 1, 1 TSRMLS_CC);
3987        if (!memcmp(mname, lowercase_name, mname_len)) {
3988            if (ce->constructor) {
3989                zend_error_noreturn(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ce->name);
3990            }
3991            ce->constructor = fe;
3992            fe->common.fn_flags |= ZEND_ACC_CTOR;
3993        }
3994        str_efree(lowercase_name);
3995    }
3996}
3997/* }}} */
3998
3999static void zend_add_trait_method(zend_class_entry *ce, const char *name, const char *arKey, uint nKeyLength, zend_function *fn, HashTable **overriden TSRMLS_DC) /* {{{ */
4000{
4001    zend_function *existing_fn = NULL;
4002    ulong h = zend_hash_func(arKey, nKeyLength);
4003
4004    if (zend_hash_quick_find(&ce->function_table, arKey, nKeyLength, h, (void**) &existing_fn) == SUCCESS) {
4005        if (existing_fn->common.scope == ce) {
4006            /* members from the current class override trait methods */
4007            /* use temporary *overriden HashTable to detect hidden conflict */
4008            if (*overriden) {
4009                if (zend_hash_quick_find(*overriden, arKey, nKeyLength, h, (void**) &existing_fn) == SUCCESS) {
4010                    if (existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
4011                        /* Make sure the trait method is compatible with previosly declared abstract method */
4012                        if (!zend_traits_method_compatibility_check(fn, existing_fn TSRMLS_CC)) {
4013                            zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
4014                                zend_get_function_declaration(fn TSRMLS_CC),
4015                                zend_get_function_declaration(existing_fn TSRMLS_CC));
4016                        }
4017                    } else if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
4018                        /* Make sure the abstract declaration is compatible with previous declaration */
4019                        if (!zend_traits_method_compatibility_check(existing_fn, fn TSRMLS_CC)) {
4020                            zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
4021                                zend_get_function_declaration(fn TSRMLS_CC),
4022                                zend_get_function_declaration(existing_fn TSRMLS_CC));
4023                        }
4024                        return;
4025                    }
4026                }
4027            } else {
4028                ALLOC_HASHTABLE(*overriden);
4029                zend_hash_init_ex(*overriden, 2, NULL, NULL, 0, 0);
4030            }
4031            zend_hash_quick_update(*overriden, arKey, nKeyLength, h, fn, sizeof(zend_function), (void**)&fn);
4032            return;
4033        } else if (existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
4034            /* Make sure the trait method is compatible with previosly declared abstract method */
4035            if (!zend_traits_method_compatibility_check(fn, existing_fn TSRMLS_CC)) {
4036                zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
4037                    zend_get_function_declaration(fn TSRMLS_CC),
4038                    zend_get_function_declaration(existing_fn TSRMLS_CC));
4039            }
4040        } else if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
4041            /* Make sure the abstract declaration is compatible with previous declaration */
4042            if (!zend_traits_method_compatibility_check(existing_fn, fn TSRMLS_CC)) {
4043                zend_error_noreturn(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
4044                    zend_get_function_declaration(fn TSRMLS_CC),
4045                    zend_get_function_declaration(existing_fn TSRMLS_CC));
4046            }
4047            return;
4048        } else if ((existing_fn->common.scope->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
4049            /* two traits can't define the same non-abstract method */
4050#if 1
4051            zend_error_noreturn(E_COMPILE_ERROR, "Trait method %s has not been applied, because there are collisions with other trait methods on %s",
4052                name, ce->name);
4053#else       /* TODO: better error message */
4054            zend_error_noreturn(E_COMPILE_ERROR, "Trait method %s::%s has not been applied as %s::%s, because of collision with %s::%s",
4055                fn->common.scope->name, fn->common.function_name,
4056                ce->name, name,
4057                existing_fn->common.scope->name, existing_fn->common.function_name);
4058#endif
4059        } else {
4060            /* inherited members are overridden by members inserted by traits */
4061            /* check whether the trait method fulfills the inheritance requirements */
4062            do_inheritance_check_on_method(fn, existing_fn TSRMLS_CC);
4063        }
4064    }
4065
4066    function_add_ref(fn);
4067    zend_hash_quick_update(&ce->function_table, arKey, nKeyLength, h, fn, sizeof(zend_function), (void**)&fn);
4068    zend_add_magic_methods(ce, arKey, nKeyLength, fn TSRMLS_CC);
4069}
4070/* }}} */
4071
4072static int zend_fixup_trait_method(zend_function *fn, zend_class_entry *ce TSRMLS_DC) /* {{{ */
4073{
4074    if ((fn->common.scope->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
4075
4076        fn->common.scope = ce;
4077
4078        if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
4079            ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
4080        }
4081        if (fn->op_array.static_variables) {
4082            ce->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
4083        }
4084    }
4085    return ZEND_HASH_APPLY_KEEP;
4086}
4087/* }}} */
4088
4089static int zend_traits_copy_functions(zend_function *fn TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
4090{
4091    zend_class_entry  *ce;
4092    HashTable         **overriden;
4093    zend_trait_alias  *alias, **alias_ptr;
4094    HashTable         *exclude_table;
4095    char              *lcname;
4096    unsigned int       fnname_len;
4097    zend_function      fn_copy;
4098    void              *dummy;
4099
4100    ce            = va_arg(args, zend_class_entry*);
4101    overriden     = va_arg(args, HashTable**);
4102    exclude_table = va_arg(args, HashTable*);
4103
4104    fnname_len = hash_key->nKeyLength - 1;
4105
4106    /* apply aliases which are qualified with a class name, there should not be any ambiguity */
4107    if (ce->trait_aliases) {
4108        alias_ptr = ce->trait_aliases;
4109        alias = *alias_ptr;
4110        while (alias) {
4111            /* Scope unset or equal to the function we compare to, and the alias applies to fn */
4112            if (alias->alias != NULL
4113                && (!alias->trait_method->ce || fn->common.scope == alias->trait_method->ce)
4114                && alias->trait_method->mname_len == fnname_len
4115                && (zend_binary_strcasecmp(alias->trait_method->method_name, alias->trait_method->mname_len, hash_key->arKey, fnname_len) == 0)) {
4116                fn_copy = *fn;
4117
4118                /* if it is 0, no modifieres has been changed */
4119                if (alias->modifiers) {
4120                    fn_copy.common.fn_flags = alias->modifiers | (fn->common.fn_flags ^ (fn->common.fn_flags & ZEND_ACC_PPP_MASK));
4121                }
4122
4123                lcname = zend_str_tolower_dup(alias->alias, alias->alias_len);
4124                zend_add_trait_method(ce, alias->alias, lcname, alias->alias_len+1, &fn_copy, overriden TSRMLS_CC);
4125                efree(lcname);
4126
4127                /* Record the trait from which this alias was resolved. */
4128                if (!alias->trait_method->ce) {
4129                    alias->trait_method->ce = fn->common.scope;
4130                }
4131            }
4132            alias_ptr++;
4133            alias = *alias_ptr;
4134        }
4135    }
4136
4137    lcname = (char *) hash_key->arKey;
4138
4139    if (exclude_table == NULL || zend_hash_find(exclude_table, lcname, fnname_len, &dummy) == FAILURE) {
4140        /* is not in hashtable, thus, function is not to be excluded */
4141        fn_copy = *fn;
4142
4143        /* apply aliases which have not alias name, just setting visibility */
4144        if (ce->trait_aliases) {
4145            alias_ptr = ce->trait_aliases;
4146            alias = *alias_ptr;
4147            while (alias) {
4148                /* Scope unset or equal to the function we compare to, and the alias applies to fn */
4149                if (alias->alias == NULL && alias->modifiers != 0
4150                    && (!alias->trait_method->ce || fn->common.scope == alias->trait_method->ce)
4151                    && (alias->trait_method->mname_len == fnname_len)
4152                    && (zend_binary_strcasecmp(alias->trait_method->method_name, alias->trait_method->mname_len, lcname, fnname_len) == 0)) {
4153
4154                    fn_copy.common.fn_flags = alias->modifiers | (fn->common.fn_flags ^ (fn->common.fn_flags & ZEND_ACC_PPP_MASK));
4155
4156                    /** Record the trait from which this alias was resolved. */
4157                    if (!alias->trait_method->ce) {
4158                        alias->trait_method->ce = fn->common.scope;
4159                    }
4160                }
4161                alias_ptr++;
4162                alias = *alias_ptr;
4163            }
4164        }
4165
4166        zend_add_trait_method(ce, fn->common.function_name, lcname, fnname_len+1, &fn_copy, overriden TSRMLS_CC);
4167    }
4168
4169    return ZEND_HASH_APPLY_KEEP;
4170}
4171/* }}} */
4172
4173static void zend_check_trait_usage(zend_class_entry *ce, zend_class_entry *trait TSRMLS_DC) /* {{{ */
4174{
4175    zend_uint i;
4176
4177    if ((trait->ce_flags & ZEND_ACC_TRAIT) != ZEND_ACC_TRAIT) {
4178        zend_error_noreturn(E_COMPILE_ERROR, "Class %s is not a trait, Only traits may be used in 'as' and 'insteadof' statements", trait->name);
4179    }
4180
4181    for (i = 0; i < ce->num_traits; i++) {
4182        if (ce->traits[i] == trait) {
4183            return;
4184        }
4185    }
4186    zend_error_noreturn(E_COMPILE_ERROR, "Required Trait %s wasn't added to %s", trait->name, ce->name);
4187}
4188/* }}} */
4189
4190static void zend_traits_init_trait_structures(zend_class_entry *ce TSRMLS_DC) /* {{{ */
4191{
4192    size_t i, j = 0;
4193    zend_trait_precedence *cur_precedence;
4194    zend_trait_method_reference *cur_method_ref;
4195    char *lcname;
4196    zend_bool method_exists;
4197
4198    /* resolve class references */
4199    if (ce->trait_precedences) {
4200        i = 0;
4201        while ((cur_precedence = ce->trait_precedences[i])) {
4202            /** Resolve classes for all precedence operations. */
4203            if (cur_precedence->exclude_from_classes) {
4204                cur_method_ref = cur_precedence->trait_method;
4205                if (!(cur_precedence->trait_method->ce = zend_fetch_class(cur_method_ref->class_name, cur_method_ref->cname_len,
4206                                ZEND_FETCH_CLASS_TRAIT|ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC))) {
4207                    zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", cur_method_ref->class_name);
4208                }
4209                zend_check_trait_usage(ce, cur_precedence->trait_method->ce TSRMLS_CC);
4210
4211                /** Ensure that the prefered method is actually available. */
4212                lcname = zend_str_tolower_dup(cur_method_ref->method_name,
4213                                              cur_method_ref->mname_len);
4214                method_exists = zend_hash_exists(&cur_method_ref->ce->function_table,
4215                                                 lcname,
4216                                                 cur_method_ref->mname_len + 1);
4217                efree(lcname);
4218                if (!method_exists) {
4219                    zend_error_noreturn(E_COMPILE_ERROR,
4220                               "A precedence rule was defined for %s::%s but this method does not exist",
4221                               cur_method_ref->ce->name,
4222                               cur_method_ref->method_name);
4223                }
4224
4225                /** With the other traits, we are more permissive.
4226                    We do not give errors for those. This allows to be more
4227                    defensive in such definitions.
4228                    However, we want to make sure that the insteadof declaration
4229                    is consistent in itself.
4230                 */
4231                j = 0;
4232                while (cur_precedence->exclude_from_classes[j]) {
4233                    char* class_name = (char*)cur_precedence->exclude_from_classes[j];
4234                    zend_uint name_length = strlen(class_name);
4235
4236                    if (!(cur_precedence->exclude_from_classes[j] = zend_fetch_class(class_name, name_length, ZEND_FETCH_CLASS_TRAIT |ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC))) {
4237                        zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", class_name);
4238                    }
4239                    zend_check_trait_usage(ce, cur_precedence->exclude_from_classes[j] TSRMLS_CC);
4240
4241                    /* make sure that the trait method is not from a class mentioned in
4242                     exclude_from_classes, for consistency */
4243                    if (cur_precedence->trait_method->ce == cur_precedence->exclude_from_classes[i]) {
4244                        zend_error_noreturn(E_COMPILE_ERROR,
4245                                   "Inconsistent insteadof definition. "
4246                                   "The method %s is to be used from %s, but %s is also on the exclude list",
4247                                   cur_method_ref->method_name,
4248                                   cur_precedence->trait_method->ce->name,
4249                                   cur_precedence->trait_method->ce->name);
4250                    }
4251
4252                    efree(class_name);
4253                    j++;
4254                }
4255            }
4256            i++;
4257        }
4258    }
4259
4260    if (ce->trait_aliases) {
4261        i = 0;
4262        while (ce->trait_aliases[i]) {
4263            /** For all aliases with an explicit class name, resolve the class now. */
4264            if (ce->trait_aliases[i]->trait_method->class_name) {
4265                cur_method_ref = ce->trait_aliases[i]->trait_method;
4266                if (!(cur_method_ref->ce = zend_fetch_class(cur_method_ref->class_name, cur_method_ref->cname_len, ZEND_FETCH_CLASS_TRAIT|ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC))) {
4267                    zend_error_noreturn(E_COMPILE_ERROR, "Could not find trait %s", cur_method_ref->class_name);
4268                }
4269                zend_check_trait_usage(ce, cur_method_ref->ce TSRMLS_CC);
4270
4271                /** And, ensure that the referenced method is resolvable, too. */
4272                lcname = zend_str_tolower_dup(cur_method_ref->method_name,
4273                        cur_method_ref->mname_len);
4274                method_exists = zend_hash_exists(&cur_method_ref->ce->function_table,
4275                        lcname, cur_method_ref->mname_len + 1);
4276                efree(lcname);
4277
4278                if (!method_exists) {
4279                    zend_error_noreturn(E_COMPILE_ERROR, "An alias was defined for %s::%s but this method does not exist", cur_method_ref->ce->name, cur_method_ref->method_name);
4280                }
4281            }
4282            i++;
4283        }
4284    }
4285}
4286/* }}} */
4287
4288static void zend_traits_compile_exclude_table(HashTable* exclude_table, zend_trait_precedence **precedences, zend_class_entry *trait) /* {{{ */
4289{
4290    size_t i = 0, j;
4291
4292    if (!precedences) {
4293        return;
4294    }
4295    while (precedences[i]) {
4296        if (precedences[i]->exclude_from_classes) {
4297            j = 0;
4298            while (precedences[i]->exclude_from_classes[j]) {
4299                if (precedences[i]->exclude_from_classes[j] == trait) {
4300                    zend_uint lcname_len = precedences[i]->trait_method->mname_len;
4301                    char *lcname = zend_str_tolower_dup(precedences[i]->trait_method->method_name, lcname_len);
4302
4303                    if (zend_hash_add(exclude_table, lcname, lcname_len, NULL, 0, NULL) == FAILURE) {
4304                        efree(lcname);
4305                        zend_error_noreturn(E_COMPILE_ERROR, "Failed to evaluate a trait precedence (%s). Method of trait %s was defined to be excluded multiple times", precedences[i]->trait_method->method_name, trait->name);
4306                    }
4307                    efree(lcname);
4308                }
4309                ++j;
4310            }
4311        }
4312        ++i;
4313    }
4314}
4315/* }}} */
4316
4317static void zend_do_traits_method_binding(zend_class_entry *ce TSRMLS_DC) /* {{{ */
4318{
4319    zend_uint i;
4320    HashTable *overriden = NULL;
4321
4322    for (i = 0; i < ce->num_traits; i++) {
4323        if (ce->trait_precedences) {
4324            HashTable exclude_table;
4325
4326            /* TODO: revisit this start size, may be its not optimal */
4327            zend_hash_init_ex(&exclude_table, 2, NULL, NULL, 0, 0);
4328
4329            zend_traits_compile_exclude_table(&exclude_table, ce->trait_precedences, ce->traits[i]);
4330
4331            /* copies functions, applies defined aliasing, and excludes unused trait methods */
4332            zend_hash_apply_with_arguments(&ce->traits[i]->function_table TSRMLS_CC, (apply_func_args_t)zend_traits_copy_functions, 3, ce, &overriden, &exclude_table);
4333
4334            zend_hash_destroy(&exclude_table);
4335        } else {
4336            zend_hash_apply_with_arguments(&ce->traits[i]->function_table TSRMLS_CC, (apply_func_args_t)zend_traits_copy_functions, 3, ce, &overriden, NULL);
4337        }
4338    }
4339
4340    zend_hash_apply_with_argument(&ce->function_table, (apply_func_arg_t)zend_fixup_trait_method, ce TSRMLS_CC);
4341
4342    if (overriden) {
4343        zend_hash_destroy(overriden);
4344        FREE_HASHTABLE(overriden);
4345    }
4346}
4347/* }}} */
4348
4349static zend_class_entry* find_first_definition(zend_class_entry *ce, size_t current_trait, const char* prop_name, int prop_name_length, ulong prop_hash, zend_class_entry *coliding_ce) /* {{{ */
4350{
4351    size_t i;
4352
4353    if (coliding_ce == ce) {
4354        for (i = 0; i < current_trait; i++) {
4355            if (zend_hash_quick_exists(&ce->traits[i]->properties_info, prop_name, prop_name_length+1, prop_hash)) {
4356                return ce->traits[i];
4357            }
4358        }
4359    }
4360
4361    return coliding_ce;
4362}
4363/* }}} */
4364
4365static void zend_do_traits_property_binding(zend_class_entry *ce TSRMLS_DC) /* {{{ */
4366{
4367    size_t i;
4368    zend_property_info *property_info;
4369    zend_property_info *coliding_prop;
4370    zval compare_result;
4371    const char* prop_name;
4372    int   prop_name_length;
4373    ulong prop_hash;
4374    const char* class_name_unused;
4375    zend_bool not_compatible;
4376    zval* prop_value;
4377    char* doc_comment;
4378    zend_uint flags;
4379
4380    /* In the following steps the properties are inserted into the property table
4381     * for that, a very strict approach is applied:
4382     * - check for compatibility, if not compatible with any property in class -> fatal
4383     * - if compatible, then strict notice
4384     */
4385    for (i = 0; i < ce->num_traits; i++) {
4386        for (zend_hash_internal_pointer_reset(&ce->traits[i]->properties_info);
4387             zend_hash_get_current_data(&ce->traits[i]->properties_info, (void *) &property_info) == SUCCESS;
4388             zend_hash_move_forward(&ce->traits[i]->properties_info)) {
4389            /* first get the unmangeld name if necessary,
4390             * then check whether the property is already there
4391             */
4392            flags = property_info->flags;
4393            if ((flags & ZEND_ACC_PPP_MASK) == ZEND_ACC_PUBLIC) {
4394                prop_hash = property_info->h;
4395                prop_name = property_info->name;
4396                prop_name_length = property_info->name_length;
4397            } else {
4398                /* for private and protected we need to unmangle the names */
4399                zend_unmangle_property_name_ex(property_info->name, property_info->name_length,
4400                                            &class_name_unused, &prop_name, &prop_name_length);
4401                prop_hash = zend_get_hash_value(prop_name, prop_name_length + 1);
4402            }
4403
4404            /* next: check for conflicts with current class */
4405            if (zend_hash_quick_find(&ce->properties_info, prop_name, prop_name_length+1, prop_hash, (void **) &coliding_prop) == SUCCESS) {
4406                if (coliding_prop->flags & ZEND_ACC_SHADOW) {
4407                    zend_hash_quick_del(&ce->properties_info, prop_name, prop_name_length+1, prop_hash);
4408                    flags |= ZEND_ACC_CHANGED;
4409                } else {
4410                    if ((coliding_prop->flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))
4411                        == (flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))) {
4412                        /* flags are identical, now the value needs to be checked */
4413                        if (flags & ZEND_ACC_STATIC) {
4414                            not_compatible = (FAILURE == compare_function(&compare_result,
4415                                              ce->default_static_members_table[coliding_prop->offset],
4416                                              ce->traits[i]->default_static_members_table[property_info->offset] TSRMLS_CC))
4417                                  || (Z_LVAL(compare_result) != 0);
4418                        } else {
4419                            not_compatible = (FAILURE == compare_function(&compare_result,
4420                                              ce->default_properties_table[coliding_prop->offset],
4421                                              ce->traits[i]->default_properties_table[property_info->offset] TSRMLS_CC))
4422                                  || (Z_LVAL(compare_result) != 0);
4423                        }
4424                    } else {
4425                        /* the flags are not identical, thus, we assume properties are not compatible */
4426                        not_compatible = 1;
4427                    }
4428
4429                    if (not_compatible) {
4430                        zend_error_noreturn(E_COMPILE_ERROR,
4431                               "%s and %s define the same property ($%s) in the composition of %s. However, the definition differs and is considered incompatible. Class was composed",
4432                                find_first_definition(ce, i, prop_name, prop_name_length, prop_hash, coliding_prop->ce)->name,
4433                                property_info->ce->name,
4434                                prop_name,
4435                                ce->name);
4436                    } else {
4437                        zend_error(E_STRICT,
4438                               "%s and %s define the same property ($%s) in the composition of %s. This might be incompatible, to improve maintainability consider using accessor methods in traits instead. Class was composed",
4439                                find_first_definition(ce, i, prop_name, prop_name_length, prop_hash, coliding_prop->ce)->name,
4440                                property_info->ce->name,
4441                                prop_name,
4442                                ce->name);
4443                        continue;
4444                    }
4445                }
4446            }
4447
4448            /* property not found, so lets add it */
4449            if (flags & ZEND_ACC_STATIC) {
4450                prop_value = ce->traits[i]->default_static_members_table[property_info->offset];
4451            } else {
4452                prop_value = ce->traits[i]->default_properties_table[property_info->offset];
4453            }
4454            Z_ADDREF_P(prop_value);
4455
4456            doc_comment = property_info->doc_comment ? estrndup(property_info->doc_comment, property_info->doc_comment_len) : NULL;
4457            zend_declare_property_ex(ce, prop_name, prop_name_length,
4458                                     prop_value, flags,
4459                                     doc_comment, property_info->doc_comment_len TSRMLS_CC);
4460        }
4461    }
4462}
4463/* }}} */
4464
4465static void zend_do_check_for_inconsistent_traits_aliasing(zend_class_entry *ce TSRMLS_DC) /* {{{ */
4466{
4467    int i = 0;
4468    zend_trait_alias* cur_alias;
4469    char* lc_method_name;
4470
4471    if (ce->trait_aliases) {
4472        while (ce->trait_aliases[i]) {
4473            cur_alias = ce->trait_aliases[i];
4474            /** The trait for this alias has not been resolved, this means, this
4475                alias was not applied. Abort with an error. */
4476            if (!cur_alias->trait_method->ce) {
4477                if (cur_alias->alias) {
4478                    /** Plain old inconsistency/typo/bug */
4479                    zend_error_noreturn(E_COMPILE_ERROR,
4480                               "An alias (%s) was defined for method %s(), but this method does not exist",
4481                               cur_alias->alias,
4482                               cur_alias->trait_method->method_name);
4483                } else {
4484                    /** Here are two possible cases:
4485                        1) this is an attempt to modifiy the visibility
4486                           of a method introduce as part of another alias.
4487                           Since that seems to violate the DRY principle,
4488                           we check against it and abort.
4489                        2) it is just a plain old inconsitency/typo/bug
4490                           as in the case where alias is set. */
4491
4492                    lc_method_name = zend_str_tolower_dup(cur_alias->trait_method->method_name,
4493                                                          cur_alias->trait_method->mname_len);
4494                    if (zend_hash_exists(&ce->function_table,
4495                                         lc_method_name,
4496                                         cur_alias->trait_method->mname_len+1)) {
4497                        efree(lc_method_name);
4498                        zend_error_noreturn(E_COMPILE_ERROR,
4499                                   "The modifiers for the trait alias %s() need to be changed in the same statment in which the alias is defined. Error",
4500                                   cur_alias->trait_method->method_name);
4501                    } else {
4502                        efree(lc_method_name);
4503                        zend_error_noreturn(E_COMPILE_ERROR,
4504                                   "The modifiers of the trait method %s() are changed, but this method does not exist. Error",
4505                                   cur_alias->trait_method->method_name);
4506
4507                    }
4508                }
4509            }
4510            i++;
4511        }
4512    }
4513}
4514/* }}} */
4515
4516ZEND_API void zend_do_bind_traits(zend_class_entry *ce TSRMLS_DC) /* {{{ */
4517{
4518
4519    if (ce->num_traits <= 0) {
4520        return;
4521    }
4522
4523    /* complete initialization of trait strutures in ce */
4524    zend_traits_init_trait_structures(ce TSRMLS_CC);
4525
4526    /* first care about all methods to be flattened into the class */
4527    zend_do_traits_method_binding(ce TSRMLS_CC);
4528
4529    /* Aliases which have not been applied indicate typos/bugs. */
4530    zend_do_check_for_inconsistent_traits_aliasing(ce TSRMLS_CC);
4531
4532    /* then flatten the properties into it, to, mostly to notfiy developer about problems */
4533    zend_do_traits_property_binding(ce TSRMLS_CC);
4534
4535    /* verify that all abstract methods from traits have been implemented */
4536    zend_verify_abstract_class(ce TSRMLS_CC);
4537
4538    /* now everything should be fine and an added ZEND_ACC_IMPLICIT_ABSTRACT_CLASS should be removed */
4539    if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) {
4540        ce->ce_flags -= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
4541    }
4542}
4543/* }}} */
4544
4545ZEND_API int do_bind_function(const zend_op_array *op_array, zend_op *opline, HashTable *function_table, zend_bool compile_time) /* {{{ */
4546{
4547    zend_function *function;
4548    zval *op1, *op2;
4549
4550    if (compile_time) {
4551        op1 = &CONSTANT_EX(op_array, opline->op1.constant);
4552        op2 = &CONSTANT_EX(op_array, opline->op2.constant);
4553    } else {
4554        op1 = opline->op1.zv;
4555        op2 = opline->op2.zv;
4556    }
4557
4558    zend_hash_quick_find(function_table, Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_HASH_P(op1), (void *) &function);
4559    if (zend_hash_quick_add(function_table, Z_STRVAL_P(op2), Z_STRLEN_P(op2)+1, Z_HASH_P(op2), function, sizeof(zend_function), NULL)==FAILURE) {
4560        int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR;
4561        zend_function *old_function;
4562
4563        if (zend_hash_quick_find(function_table, Z_STRVAL_P(op2), Z_STRLEN_P(op2)+1, Z_HASH_P(op2), (void *) &old_function)==SUCCESS
4564            && old_function->type == ZEND_USER_FUNCTION
4565            && old_function->op_array.last > 0) {
4566            zend_error(error_level, "Cannot redeclare %s() (previously declared in %s:%d)",
4567                        function->common.function_name,
4568                        old_function->op_array.filename,
4569                        old_function->op_array.opcodes[0].lineno);
4570        } else {
4571            zend_error(error_level, "Cannot redeclare %s()", function->common.function_name);
4572        }
4573        return FAILURE;
4574    } else {
4575        (*function->op_array.refcount)++;
4576        function->op_array.static_variables = NULL; /* NULL out the unbound function */
4577        return SUCCESS;
4578    }
4579}
4580/* }}} */
4581
4582void zend_prepare_reference(znode *result, znode *class_name, znode *method_name TSRMLS_DC) /* {{{ */
4583{
4584    zend_trait_method_reference *method_ref = emalloc(sizeof(zend_trait_method_reference));
4585    method_ref->ce = NULL;
4586
4587    /* REM: There should not be a need for copying,
4588       zend_do_begin_class_declaration is also just using that string */
4589    if (class_name) {
4590        zend_resolve_class_name(class_name TSRMLS_CC);
4591        method_ref->class_name = Z_STRVAL(class_name->u.constant);
4592        method_ref->cname_len  = Z_STRLEN(class_name->u.constant);
4593    } else {
4594        method_ref->class_name = NULL;
4595        method_ref->cname_len  = 0;
4596    }
4597
4598    method_ref->method_name = Z_STRVAL(method_name->u.constant);
4599    method_ref->mname_len   = Z_STRLEN(method_name->u.constant);
4600
4601    result->u.op.ptr = method_ref;
4602    result->op_type = IS_TMP_VAR;
4603}
4604/* }}} */
4605
4606void zend_add_trait_alias(znode *method_reference, znode *modifiers, znode *alias TSRMLS_DC) /* {{{ */
4607{
4608    zend_class_entry *ce = CG(active_class_entry);
4609    zend_trait_alias *trait_alias;
4610
4611    if (Z_LVAL(modifiers->u.constant) == ZEND_ACC_STATIC) {
4612        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as method modifier");
4613        return;
4614    } else if (Z_LVAL(modifiers->u.constant) == ZEND_ACC_ABSTRACT) {
4615        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as method modifier");
4616        return;
4617    } else if (Z_LVAL(modifiers->u.constant) == ZEND_ACC_FINAL) {
4618        zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as method modifier");
4619        return;
4620    }
4621
4622    trait_alias = emalloc(sizeof(zend_trait_alias));
4623    trait_alias->trait_method = (zend_trait_method_reference*)method_reference->u.op.ptr;
4624    trait_alias->modifiers = Z_LVAL(modifiers->u.constant);
4625    if (alias) {
4626        trait_alias->alias = Z_STRVAL(alias->u.constant);
4627        trait_alias->alias_len = Z_STRLEN(alias->u.constant);
4628    } else {
4629        trait_alias->alias = NULL;
4630    }
4631    zend_add_to_list(&ce->trait_aliases, trait_alias TSRMLS_CC);
4632}
4633/* }}} */
4634
4635void zend_add_trait_precedence(znode *method_reference, znode *trait_list TSRMLS_DC) /* {{{ */
4636{
4637    zend_class_entry *ce = CG(active_class_entry);
4638    zend_trait_precedence *trait_precedence = emalloc(sizeof(zend_trait_precedence));
4639
4640    trait_precedence->trait_method = (zend_trait_method_reference*)method_reference->u.op.ptr;
4641    trait_precedence->exclude_from_classes = (zend_class_entry**) trait_list->u.op.ptr;
4642
4643    zend_add_to_list(&ce->trait_precedences, trait_precedence TSRMLS_CC);
4644}
4645/* }}} */
4646
4647ZEND_API zend_class_entry *do_bind_class(const zend_op_array* op_array, const zend_op *opline, HashTable *class_table, zend_bool compile_time TSRMLS_DC) /* {{{ */
4648{
4649    zend_class_entry *ce, **pce;
4650    zval *op1, *op2;
4651
4652    if (compile_time) {