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