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                        zval_update_constant_ex(&zv, (void*)1, fptr->common.scope TSRMLS_CC);
3154                        if (Z_TYPE_P(zv) == IS_BOOL) {
3155                            if (Z_LVAL_P(zv)) {
3156                                memcpy(offset, "true", 4);
3157                                offset += 4;
3158                            } else {
3159                                memcpy(offset, "false", 5);
3160                                offset += 5;
3161                            }
3162                        } else if (Z_TYPE_P(zv) == IS_NULL) {
3163                            memcpy(offset, "NULL", 4);
3164                            offset += 4;
3165                        } else if (Z_TYPE_P(zv) == IS_STRING) {
3166                            *(offset++) = '\'';
3167                            REALLOC_BUF_IF_EXCEED(buf, offset, length, MIN(Z_STRLEN_P(zv), 10));
3168                            memcpy(offset, Z_STRVAL_P(zv), MIN(Z_STRLEN_P(zv), 10));
3169                            offset += MIN(Z_STRLEN_P(zv), 10);
3170                            if (Z_STRLEN_P(zv) > 10) {
3171                                *(offset++) = '.';
3172                                *(offset++) = '.';
3173                                *(offset++) = '.';
3174                            }
3175                            *(offset++) = '\'';
3176                        } else if (Z_TYPE_P(zv) == IS_ARRAY) {
3177                            memcpy(offset, "Array", 5);
3178                            offset += 5;
3179                        } else {
3180                            zend_make_printable_zval(zv, &zv_copy, &use_copy);
3181                            REALLOC_BUF_IF_EXCEED(buf, offset, length, Z_STRLEN(zv_copy));
3182                            memcpy(offset, Z_STRVAL(zv_copy), Z_STRLEN(zv_copy));
3183                            offset += Z_STRLEN(zv_copy);
3184                            if (use_copy) {
3185                                zval_dtor(&zv_copy);
3186                            }
3187                        }
3188                        zval_ptr_dtor(&zv);
3189                    }
3190                } else {
3191                    memcpy(offset, "NULL", 4);
3192                    offset += 4;
3193                }
3194            }
3195
3196            if (++i < fptr->common.num_args) {
3197                *(offset++) = ',';
3198                *(offset++) = ' ';
3199            }
3200            arg_info++;
3201            REALLOC_BUF_IF_EXCEED(buf, offset, length, 32);
3202        }
3203    }
3204    *(offset++) = ')';
3205    *offset = '\0';
3206
3207    return buf;
3208}
3209/* }}} */
3210
3211static void do_inheritance_check_on_method(zend_function *child, zend_function *parent TSRMLS_DC) /* {{{ */
3212{
3213    zend_uint child_flags;
3214    zend_uint parent_flags = parent->common.fn_flags;
3215
3216    if ((parent->common.scope->ce_flags & ZEND_ACC_INTERFACE) == 0
3217        && parent->common.fn_flags & ZEND_ACC_ABSTRACT
3218        && parent->common.scope != (child->common.prototype ? child->common.prototype->common.scope : child->common.scope)
3219        && child->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_IMPLEMENTED_ABSTRACT)) {
3220        zend_error(E_COMPILE_ERROR, "Can't inherit abstract function %s::%s() (previously declared abstract in %s)",
3221            parent->common.scope->name,
3222            child->common.function_name,
3223            child->common.prototype ? child->common.prototype->common.scope->name : child->common.scope->name);
3224    }
3225
3226    if (parent_flags & ZEND_ACC_FINAL) {
3227        zend_error(E_COMPILE_ERROR, "Cannot override final method %s::%s()", ZEND_FN_SCOPE_NAME(parent), child->common.function_name);
3228    }
3229
3230    child_flags = child->common.fn_flags;
3231    /* You cannot change from static to non static and vice versa.
3232     */
3233    if ((child_flags & ZEND_ACC_STATIC) != (parent_flags & ZEND_ACC_STATIC)) {
3234        if (child->common.fn_flags & ZEND_ACC_STATIC) {
3235            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));
3236        } else {
3237            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));
3238        }
3239    }
3240
3241    /* Disallow making an inherited method abstract. */
3242    if ((child_flags & ZEND_ACC_ABSTRACT) && !(parent_flags & ZEND_ACC_ABSTRACT)) {
3243        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));
3244    }
3245
3246    if (parent_flags & ZEND_ACC_CHANGED) {
3247        child->common.fn_flags |= ZEND_ACC_CHANGED;
3248    } else {
3249        /* Prevent derived classes from restricting access that was available in parent classes
3250         */
3251        if ((child_flags & ZEND_ACC_PPP_MASK) > (parent_flags & ZEND_ACC_PPP_MASK)) {
3252            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");
3253        } else if (((child_flags & ZEND_ACC_PPP_MASK) < (parent_flags & ZEND_ACC_PPP_MASK))
3254            && ((parent_flags & ZEND_ACC_PPP_MASK) & ZEND_ACC_PRIVATE)) {
3255            child->common.fn_flags |= ZEND_ACC_CHANGED;
3256        }
3257    }
3258
3259    if (parent_flags & ZEND_ACC_PRIVATE) {
3260        child->common.prototype = NULL;
3261    } else if (parent_flags & ZEND_ACC_ABSTRACT) {
3262        child->common.fn_flags |= ZEND_ACC_IMPLEMENTED_ABSTRACT;
3263        child->common.prototype = parent;
3264    } else if (!(parent->common.fn_flags & ZEND_ACC_CTOR) || (parent->common.prototype && (parent->common.prototype->common.scope->ce_flags & ZEND_ACC_INTERFACE))) {
3265        /* ctors only have a prototype if it comes from an interface */
3266        child->common.prototype = parent->common.prototype ? parent->common.prototype : parent;
3267    }
3268
3269    if (child->common.prototype && (child->common.prototype->common.fn_flags & ZEND_ACC_ABSTRACT)) {
3270        if (!zend_do_perform_implementation_check(child, child->common.prototype TSRMLS_CC)) {
3271            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));
3272        }
3273    } 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 */
3274        if (!zend_do_perform_implementation_check(child, parent TSRMLS_CC)) {
3275            char *method_prototype = zend_get_function_declaration(parent TSRMLS_CC);
3276            zend_error(E_STRICT, "Declaration of %s::%s() should be compatible with %s", ZEND_FN_SCOPE_NAME(child), child->common.function_name, method_prototype);
3277            efree(method_prototype);
3278        }
3279    }
3280}
3281/* }}} */
3282
3283static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_function *parent, const zend_hash_key *hash_key, zend_class_entry *child_ce) /* {{{ */
3284{
3285    zend_uint parent_flags = parent->common.fn_flags;
3286    zend_function *child;
3287    TSRMLS_FETCH();
3288
3289    if (zend_hash_quick_find(child_function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child)==FAILURE) {
3290        if (parent_flags & (ZEND_ACC_ABSTRACT)) {
3291            child_ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
3292        }
3293        return 1; /* method doesn't exist in child, copy from parent */
3294    }
3295
3296    do_inheritance_check_on_method(child, parent TSRMLS_CC);
3297
3298    return 0;
3299}
3300/* }}} */
3301
3302static 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) /* {{{ */
3303{
3304    zend_property_info *child_info;
3305    zend_class_entry *parent_ce = ce->parent;
3306
3307    if (parent_info->flags & (ZEND_ACC_PRIVATE|ZEND_ACC_SHADOW)) {
3308        if (zend_hash_quick_find(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
3309            child_info->flags |= ZEND_ACC_CHANGED;
3310        } else {
3311            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);
3312            if(ce->type & ZEND_INTERNAL_CLASS) {
3313                zend_duplicate_property_info_internal(child_info);
3314            } else {
3315                zend_duplicate_property_info(child_info);
3316            }
3317            child_info->flags &= ~ZEND_ACC_PRIVATE; /* it's not private anymore */
3318            child_info->flags |= ZEND_ACC_SHADOW; /* but it's a shadow of private */
3319        }
3320        return 0; /* don't copy access information to child */
3321    }
3322
3323    if (zend_hash_quick_find(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
3324        if ((parent_info->flags & ZEND_ACC_STATIC) != (child_info->flags & ZEND_ACC_STATIC)) {
3325            zend_error(E_COMPILE_ERROR, "Cannot redeclare %s%s::$%s as %s%s::$%s",
3326                (parent_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", parent_ce->name, hash_key->arKey,
3327                (child_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", ce->name, hash_key->arKey);
3328
3329        }
3330
3331        if(parent_info->flags & ZEND_ACC_CHANGED) {
3332            child_info->flags |= ZEND_ACC_CHANGED;
3333        }
3334
3335        if ((child_info->flags & ZEND_ACC_PPP_MASK) > (parent_info->flags & ZEND_ACC_PPP_MASK)) {
3336            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");
3337        } else if ((child_info->flags & ZEND_ACC_STATIC) == 0) {
3338            zval_ptr_dtor(&(ce->default_properties_table[parent_info->offset]));
3339            ce->default_properties_table[parent_info->offset] = ce->default_properties_table[child_info->offset];
3340            ce->default_properties_table[child_info->offset] = NULL;
3341            child_info->offset = parent_info->offset;
3342        }
3343        return 0;   /* Don't copy from parent */
3344    } else {
3345        return 1;   /* Copy from parent */
3346    }
3347}
3348/* }}} */
3349
3350static inline void do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC) /* {{{ */
3351{
3352    if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && iface->interface_gets_implemented && iface->interface_gets_implemented(iface, ce TSRMLS_CC) == FAILURE) {
3353        zend_error(E_CORE_ERROR, "Class %s could not implement interface %s", ce->name, iface->name);
3354    }
3355    if (ce == iface) {
3356        zend_error(E_ERROR, "Interface %s cannot implement itself", ce->name);
3357    }
3358}
3359/* }}} */
3360
3361ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_entry *iface TSRMLS_DC) /* {{{ */
3362{
3363    /* expects interface to be contained in ce's interface list already */
3364    zend_uint i, ce_num, if_num = iface->num_interfaces;
3365    zend_class_entry *entry;
3366
3367    if (if_num==0) {
3368        return;
3369    }
3370    ce_num = ce->num_interfaces;
3371
3372    if (ce->type == ZEND_INTERNAL_CLASS) {
3373        ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num));
3374    } else {
3375        ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num));
3376    }
3377
3378    /* Inherit the interfaces, only if they're not already inherited by the class */
3379    while (if_num--) {
3380        entry = iface->interfaces[if_num];
3381        for (i = 0; i < ce_num; i++) {
3382            if (ce->interfaces[i] == entry) {
3383                break;
3384            }
3385        }
3386        if (i == ce_num) {
3387            ce->interfaces[ce->num_interfaces++] = entry;
3388        }
3389    }
3390
3391    /* and now call the implementing handlers */
3392    while (ce_num < ce->num_interfaces) {
3393        do_implement_interface(ce, ce->interfaces[ce_num++] TSRMLS_CC);
3394    }
3395}
3396/* }}} */
3397
3398#ifdef ZTS
3399static void zval_internal_ctor(zval **p) /* {{{ */
3400{
3401    zval *orig_ptr = *p;
3402
3403    ALLOC_ZVAL(*p);
3404    MAKE_COPY_ZVAL(&orig_ptr, *p);
3405}
3406/* }}} */
3407
3408# define zval_property_ctor(parent_ce, ce) \
3409    ((void (*)(void *)) (((parent_ce)->type != (ce)->type) ? zval_internal_ctor : zval_add_ref))
3410#else
3411# define zval_property_ctor(parent_ce, ce) \
3412    ((void (*)(void *)) zval_add_ref)
3413#endif
3414
3415ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce TSRMLS_DC) /* {{{ */
3416{
3417    zend_property_info *property_info;
3418
3419    if ((ce->ce_flags & ZEND_ACC_INTERFACE)
3420        && !(parent_ce->ce_flags & ZEND_ACC_INTERFACE)) {
3421        zend_error(E_COMPILE_ERROR, "Interface %s may not inherit from class (%s)", ce->name, parent_ce->name);
3422    }
3423    if (parent_ce->ce_flags & ZEND_ACC_FINAL_CLASS) {
3424        zend_error(E_COMPILE_ERROR, "Class %s may not inherit from final class (%s)", ce->name, parent_ce->name);
3425    }
3426
3427    ce->parent = parent_ce;
3428    /* Copy serialize/unserialize callbacks */
3429    if (!ce->serialize) {
3430        ce->serialize   = parent_ce->serialize;
3431    }
3432    if (!ce->unserialize) {
3433        ce->unserialize = parent_ce->unserialize;
3434    }
3435
3436    /* Inherit interfaces */
3437    zend_do_inherit_interfaces(ce, parent_ce TSRMLS_CC);
3438
3439    /* Inherit properties */
3440    if (parent_ce->default_properties_count) {
3441        int i = ce->default_properties_count + parent_ce->default_properties_count;
3442
3443        ce->default_properties_table = perealloc(ce->default_properties_table, sizeof(void*) * i, ce->type == ZEND_INTERNAL_CLASS);
3444        if (ce->default_properties_count) {
3445            while (i-- > parent_ce->default_properties_count) {
3446                ce->default_properties_table[i] = ce->default_properties_table[i - parent_ce->default_properties_count];
3447            }
3448        }
3449        for (i = 0; i < parent_ce->default_properties_count; i++) {
3450            ce->default_properties_table[i] = parent_ce->default_properties_table[i];
3451            if (ce->default_properties_table[i]) {
3452#ifdef ZTS
3453                if (parent_ce->type != ce->type) {
3454                    zval *p;
3455
3456                    ALLOC_ZVAL(p);
3457                    MAKE_COPY_ZVAL(&ce->default_properties_table[i], p);
3458                    ce->default_properties_table[i] = p;
3459                } else {
3460                    Z_ADDREF_P(ce->default_properties_table[i]);
3461                }
3462#else
3463                Z_ADDREF_P(ce->default_properties_table[i]);
3464#endif
3465            }
3466        }
3467        ce->default_properties_count += parent_ce->default_properties_count;
3468    }
3469
3470    if (parent_ce->type != ce->type) {
3471        /* User class extends internal class */
3472        zend_update_class_constants(parent_ce  TSRMLS_CC);
3473        if (parent_ce->default_static_members_count) {
3474            int i = ce->default_static_members_count + parent_ce->default_static_members_count;
3475
3476            ce->default_static_members_table = erealloc(ce->default_static_members_table, sizeof(void*) * i);
3477            if (ce->default_static_members_count) {
3478                while (i-- > parent_ce->default_static_members_count) {
3479                    ce->default_static_members_table[i] = ce->default_static_members_table[i - parent_ce->default_static_members_count];
3480                }
3481            }
3482            for (i = 0; i < parent_ce->default_static_members_count; i++) {
3483                SEPARATE_ZVAL_TO_MAKE_IS_REF(&CE_STATIC_MEMBERS(parent_ce)[i]);
3484                ce->default_static_members_table[i] = CE_STATIC_MEMBERS(parent_ce)[i];
3485                Z_ADDREF_P(ce->default_static_members_table[i]);
3486            }
3487            ce->default_static_members_count += parent_ce->default_static_members_count;
3488            ce->static_members_table = ce->default_static_members_table;
3489        }
3490    } else {
3491        if (parent_ce->default_static_members_count) {
3492            int i = ce->default_static_members_count + parent_ce->default_static_members_count;
3493
3494            ce->default_static_members_table = perealloc(ce->default_static_members_table, sizeof(void*) * i, ce->type == ZEND_INTERNAL_CLASS);
3495            if (ce->default_static_members_count) {
3496                while (i-- > parent_ce->default_static_members_count) {
3497                    ce->default_static_members_table[i] = ce->default_static_members_table[i - parent_ce->default_static_members_count];
3498                }
3499            }
3500            for (i = 0; i < parent_ce->default_static_members_count; i++) {
3501                SEPARATE_ZVAL_TO_MAKE_IS_REF(&parent_ce->default_static_members_table[i]);
3502                ce->default_static_members_table[i] = parent_ce->default_static_members_table[i];
3503                Z_ADDREF_P(ce->default_static_members_table[i]);
3504            }
3505            ce->default_static_members_count += parent_ce->default_static_members_count;
3506            if (ce->type == ZEND_USER_CLASS) {
3507                ce->static_members_table = ce->default_static_members_table;
3508            }
3509        }
3510    }
3511
3512    for (zend_hash_internal_pointer_reset(&ce->properties_info);
3513    zend_hash_get_current_data(&ce->properties_info, (void *) &property_info) == SUCCESS;
3514    zend_hash_move_forward(&ce->properties_info)) {
3515        if (property_info->ce == ce) {
3516            if (property_info->flags & ZEND_ACC_STATIC) {
3517                property_info->offset += parent_ce->default_static_members_count;
3518            } else {
3519                property_info->offset += parent_ce->default_properties_count;
3520            }
3521        }
3522    }
3523
3524    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);
3525
3526    zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, zval_property_ctor(parent_ce, ce), NULL, sizeof(zval *), 0);
3527    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);
3528    do_inherit_parent_constructor(ce);
3529
3530    if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS && ce->type == ZEND_INTERNAL_CLASS) {
3531        ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
3532    } else if (!(ce->ce_flags & (ZEND_ACC_IMPLEMENT_INTERFACES|ZEND_ACC_IMPLEMENT_TRAITS))) {
3533        /* The verification will be done in runtime by ZEND_VERIFY_ABSTRACT_CLASS */
3534        zend_verify_abstract_class(ce TSRMLS_CC);
3535    }
3536    ce->ce_flags |= parent_ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS;
3537}
3538/* }}} */
3539
3540static 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) /* {{{ */
3541{
3542    zval **old_constant;
3543
3544    if (zend_hash_quick_find(child_constants_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void**)&old_constant) == SUCCESS) {
3545        if (*old_constant != *parent_constant) {
3546            zend_error(E_COMPILE_ERROR, "Cannot inherit previously-inherited or override constant %s from interface %s", hash_key->arKey, iface->name);
3547        }
3548        return 0;
3549    }
3550    return 1;
3551}
3552/* }}} */
3553
3554static int do_interface_constant_check(zval **val TSRMLS_DC, int num_args, va_list args, const zend_hash_key *key) /* {{{ */
3555{
3556    zend_class_entry **iface = va_arg(args, zend_class_entry**);
3557
3558    do_inherit_constant_check(&(*iface)->constants_table, (const zval **) val, key, *iface);
3559
3560    return ZEND_HASH_APPLY_KEEP;
3561}
3562/* }}} */
3563
3564ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC) /* {{{ */
3565{
3566    zend_uint i, ignore = 0;
3567    zend_uint current_iface_num = ce->num_interfaces;
3568    zend_uint parent_iface_num  = ce->parent ? ce->parent->num_interfaces : 0;
3569
3570    for (i = 0; i < ce->num_interfaces; i++) {
3571        if (ce->interfaces[i] == NULL) {
3572            memmove(ce->interfaces + i, ce->interfaces + i + 1, sizeof(zend_class_entry*) * (--ce->num_interfaces - i));
3573            i--;
3574        } else if (ce->interfaces[i] == iface) {
3575            if (i < parent_iface_num) {
3576                ignore = 1;
3577            } else {
3578                zend_error(E_COMPILE_ERROR, "Class %s cannot implement previously implemented interface %s", ce->name, iface->name);
3579            }
3580        }
3581    }
3582    if (ignore) {
3583        /* Check for attempt to redeclare interface constants */
3584        zend_hash_apply_with_arguments(&ce->constants_table TSRMLS_CC, (apply_func_args_t) do_interface_constant_check, 1, &iface);
3585    } else {
3586        if (ce->num_interfaces >= current_iface_num) {
3587            if (ce->type == ZEND_INTERNAL_CLASS) {
3588                ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
3589            } else {
3590                ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num));
3591            }
3592        }
3593        ce->interfaces[ce->num_interfaces++] = iface;
3594
3595        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);
3596        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);
3597
3598        do_implement_interface(ce, iface TSRMLS_CC);
3599        zend_do_inherit_interfaces(ce, iface TSRMLS_CC);
3600    }
3601}
3602/* }}} */
3603
3604ZEND_API void zend_do_implement_trait(zend_class_entry *ce, zend_class_entry *trait TSRMLS_DC) /* {{{ */
3605{
3606    zend_uint i, ignore = 0;
3607    zend_uint current_trait_num = ce->num_traits;
3608    zend_uint parent_trait_num  = ce->parent ? ce->parent->num_traits : 0;
3609
3610    for (i = 0; i < ce->num_traits; i++) {
3611        if (ce->traits[i] == NULL) {
3612            memmove(ce->traits + i, ce->traits + i + 1, sizeof(zend_class_entry*) * (--ce->num_traits - i));
3613            i--;
3614        } else if (ce->traits[i] == trait) {
3615            if (i < parent_trait_num) {
3616                ignore = 1;
3617            }
3618        }
3619    }
3620    if (!ignore) {
3621        if (ce->num_traits >= current_trait_num) {
3622            if (ce->type == ZEND_INTERNAL_CLASS) {
3623                ce->traits = (zend_class_entry **) realloc(ce->traits, sizeof(zend_class_entry *) * (++current_trait_num));
3624            } else {
3625                ce->traits = (zend_class_entry **) erealloc(ce->traits, sizeof(zend_class_entry *) * (++current_trait_num));
3626            }
3627        }
3628        ce->traits[ce->num_traits++] = trait;
3629    }
3630}
3631/* }}} */
3632
3633static zend_bool zend_traits_method_compatibility_check(zend_function *fn, zend_function *other_fn TSRMLS_DC) /* {{{ */
3634{
3635    zend_uint    fn_flags = fn->common.scope->ce_flags;
3636    zend_uint other_flags = other_fn->common.scope->ce_flags;
3637
3638    return zend_do_perform_implementation_check(fn, other_fn TSRMLS_CC)
3639        && ((other_fn->common.scope->ce_flags & ZEND_ACC_INTERFACE) || zend_do_perform_implementation_check(other_fn, fn TSRMLS_CC))
3640        && ((fn_flags & (ZEND_ACC_FINAL|ZEND_ACC_STATIC)) ==
3641            (other_flags & (ZEND_ACC_FINAL|ZEND_ACC_STATIC))); /* equal final and static qualifier */
3642}
3643/* }}} */
3644
3645static void zend_add_magic_methods(zend_class_entry* ce, const char* mname, uint mname_len, zend_function* fe TSRMLS_DC) /* {{{ */
3646{
3647    if (!strncmp(mname, ZEND_CLONE_FUNC_NAME, mname_len)) {
3648        ce->clone = fe; fe->common.fn_flags |= ZEND_ACC_CLONE;
3649    } else if (!strncmp(mname, ZEND_CONSTRUCTOR_FUNC_NAME, mname_len)) {
3650        if (ce->constructor) {
3651            zend_error(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ce->name);
3652        }
3653        ce->constructor = fe; fe->common.fn_flags |= ZEND_ACC_CTOR;
3654    } else if (!strncmp(mname, ZEND_DESTRUCTOR_FUNC_NAME,  mname_len)) {
3655        ce->destructor = fe; fe->common.fn_flags |= ZEND_ACC_DTOR;
3656    } else if (!strncmp(mname, ZEND_GET_FUNC_NAME, mname_len)) {
3657        ce->__get = fe;
3658    } else if (!strncmp(mname, ZEND_SET_FUNC_NAME, mname_len)) {
3659        ce->__set = fe;
3660    } else if (!strncmp(mname, ZEND_CALL_FUNC_NAME, mname_len)) {
3661        ce->__call = fe;
3662    } else if (!strncmp(mname, ZEND_UNSET_FUNC_NAME, mname_len)) {
3663        ce->__unset = fe;
3664    } else if (!strncmp(mname, ZEND_ISSET_FUNC_NAME, mname_len)) {
3665        ce->__isset = fe;
3666    } else if (!strncmp(mname, ZEND_CALLSTATIC_FUNC_NAME, mname_len)) {
3667        ce->__callstatic = fe;
3668    } else if (!strncmp(mname, ZEND_TOSTRING_FUNC_NAME, mname_len)) {
3669        ce->__tostring = fe;
3670    } else if (ce->name_length + 1 == mname_len) {
3671        char *lowercase_name = emalloc(ce->name_length + 1);
3672        zend_str_tolower_copy(lowercase_name, ce->name, ce->name_length);
3673        lowercase_name = (char*)zend_new_interned_string(lowercase_name, ce->name_length + 1, 1 TSRMLS_CC);
3674        if (!memcmp(mname, lowercase_name, mname_len)) {
3675            if (ce->constructor) {
3676                zend_error(E_COMPILE_ERROR, "%s has colliding constructor definitions coming from traits", ce->name);
3677            }
3678            ce->constructor = fe;
3679            fe->common.fn_flags |= ZEND_ACC_CTOR;
3680        }
3681        str_efree(lowercase_name);
3682    }
3683}
3684/* }}} */
3685
3686static void zend_add_trait_method(zend_class_entry *ce, const char *name, const char *arKey, uint nKeyLength, zend_function *fn, HashTable **overriden TSRMLS_DC) /* {{{ */
3687{
3688    zend_function *existing_fn = NULL;
3689    ulong h = zend_hash_func(arKey, nKeyLength);
3690
3691    if (zend_hash_quick_find(&ce->function_table, arKey, nKeyLength, h, (void**) &existing_fn) == SUCCESS) {
3692        if (existing_fn->common.scope == ce) {
3693            /* members from the current class override trait methods */
3694            /* use temporary *overriden HashTable to detect hidden conflict */
3695            if (*overriden) {
3696                if (zend_hash_quick_find(*overriden, arKey, nKeyLength, h, (void**) &existing_fn) == SUCCESS) {
3697                    if (existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
3698                        /* Make sure the trait method is compatible with previosly declared abstract method */
3699                        if (!zend_traits_method_compatibility_check(fn, existing_fn TSRMLS_CC)) {
3700                            zend_error(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
3701                                zend_get_function_declaration(fn TSRMLS_CC),
3702                                zend_get_function_declaration(existing_fn TSRMLS_CC));
3703                        }
3704                    } else if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
3705                        /* Make sure the abstract declaration is compatible with previous declaration */
3706                        if (!zend_traits_method_compatibility_check(existing_fn, fn TSRMLS_CC)) {
3707                            zend_error(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
3708                                zend_get_function_declaration(fn TSRMLS_CC),
3709                                zend_get_function_declaration(existing_fn TSRMLS_CC));
3710                        }
3711                        return;
3712                    }
3713                }
3714            } else {
3715                ALLOC_HASHTABLE(*overriden);
3716                zend_hash_init_ex(*overriden, 2, NULL, NULL, 0, 0);
3717            }
3718            zend_hash_quick_update(*overriden, arKey, nKeyLength, h, fn, sizeof(zend_function), (void**)&fn);
3719            return;
3720        } else if (existing_fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
3721            /* Make sure the trait method is compatible with previosly declared abstract method */
3722            if (!zend_traits_method_compatibility_check(fn, existing_fn TSRMLS_CC)) {
3723                zend_error(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
3724                    zend_get_function_declaration(fn TSRMLS_CC),
3725                    zend_get_function_declaration(existing_fn TSRMLS_CC));
3726            }
3727        } else if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
3728            /* Make sure the abstract declaration is compatible with previous declaration */
3729            if (!zend_traits_method_compatibility_check(existing_fn, fn TSRMLS_CC)) {
3730                zend_error(E_COMPILE_ERROR, "Declaration of %s must be compatible with %s",
3731                    zend_get_function_declaration(fn TSRMLS_CC),
3732                    zend_get_function_declaration(existing_fn TSRMLS_CC));
3733            }
3734            return;
3735        } else if ((existing_fn->common.scope->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
3736            /* two trais can't define the same non-abstract method */
3737#if 1
3738            zend_error(E_COMPILE_ERROR, "Trait method %s has not been applied, because there are collisions with other trait methods on %s",
3739                name, ce->name);
3740#else       /* TODO: better errot message */
3741            zend_error(E_COMPILE_ERROR, "Trait method %s::%s has not been applied as %s::%s, because of collision with %s::%s",
3742                fn->common.scope->name, fn->common.function_name,
3743                ce->name, name,
3744                existing_fn->common.scope->name, existing_fn->common.function_name);
3745#endif
3746        } else {
3747            /* inherited members are overridden by members inserted by traits */
3748            /* check whether the trait method fulfills the inheritance requirements */
3749            do_inheritance_check_on_method(fn, existing_fn TSRMLS_CC);
3750        }
3751    }
3752
3753    function_add_ref(fn);
3754    zend_hash_quick_update(&ce->function_table, arKey, nKeyLength, h, fn, sizeof(zend_function), (void**)&fn);
3755    zend_add_magic_methods(ce, arKey, nKeyLength, fn TSRMLS_CC);
3756}
3757/* }}} */
3758
3759static int zend_fixup_trait_method(zend_function *fn, zend_class_entry *ce TSRMLS_DC) /* {{{ */
3760{
3761    if ((fn->common.scope->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
3762
3763        fn->common.scope = ce;
3764
3765        if (fn->common.fn_flags & ZEND_ACC_ABSTRACT) {
3766            ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
3767        }
3768        if (fn->op_array.static_variables) {
3769            ce->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
3770        }
3771    }
3772    return ZEND_HASH_APPLY_KEEP;
3773}
3774/* }}} */
3775
3776static int zend_traits_copy_functions(zend_function *fn TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
3777{
3778    zend_class_entry  *ce;
3779    HashTable         **overriden;
3780    zend_trait_alias  *alias, **alias_ptr;
3781    HashTable         *exclude_table;
3782    char              *lcname;
3783    unsigned int       fnname_len;
3784    zend_function      fn_copy;
3785    void              *dummy;
3786
3787    ce            = va_arg(args, zend_class_entry*);
3788    overriden     = va_arg(args, HashTable**);
3789    exclude_table = va_arg(args, HashTable*);
3790
3791    fnname_len = hash_key->nKeyLength - 1;
3792
3793    /* apply aliases which are qualified with a class name, there should not be any ambiguity */
3794    if (ce->trait_aliases) {
3795        alias_ptr = ce->trait_aliases;
3796        alias = *alias_ptr;
3797        while (alias) {
3798            /* Scope unset or equal to the function we compare to, and the alias applies to fn */
3799            if (alias->alias != NULL
3800                && (!alias->trait_method->ce || fn->common.scope == alias->trait_method->ce)
3801                && alias->trait_method->mname_len == fnname_len
3802                && (zend_binary_strcasecmp(alias->trait_method->method_name, alias->trait_method->mname_len, hash_key->arKey, fnname_len) == 0)) {
3803                fn_copy = *fn;
3804
3805                /* if it is 0, no modifieres has been changed */
3806                if (alias->modifiers) {
3807                    fn_copy.common.fn_flags = alias->modifiers | (fn->common.fn_flags ^ (fn->common.fn_flags & ZEND_ACC_PPP_MASK));
3808                }
3809
3810                lcname = zend_str_tolower_dup(alias->alias, alias->alias_len);
3811                zend_add_trait_method(ce, alias->alias, lcname, alias->alias_len+1, &fn_copy, overriden TSRMLS_CC);
3812                efree(lcname);
3813
3814                /* Record the trait from which this alias was resolved. */
3815                if (!alias->trait_method->ce) {
3816                    alias->trait_method->ce = fn->common.scope;
3817                }
3818            }
3819            alias_ptr++;
3820            alias = *alias_ptr;
3821        }
3822    }
3823
3824    lcname = hash_key->arKey;
3825
3826    if (exclude_table == NULL || zend_hash_find(exclude_table, lcname, fnname_len, &dummy) == FAILURE) {
3827        /* is not in hashtable, thus, function is not to be excluded */
3828        fn_copy = *fn;
3829
3830        /* apply aliases which have not alias name, just setting visibility */
3831        if (ce->trait_aliases) {
3832            alias_ptr = ce->trait_aliases;
3833            alias = *alias_ptr;
3834            while (alias) {
3835                /* Scope unset or equal to the function we compare to, and the alias applies to fn */
3836                if (alias->alias == NULL && alias->modifiers != 0
3837                    && (!alias->trait_method->ce || fn->common.scope == alias->trait_method->ce)
3838                    && (alias->trait_method->mname_len == fnname_len)
3839                    && (zend_binary_strcasecmp(alias->trait_method->method_name, alias->trait_method->mname_len, lcname, fnname_len) == 0)) {
3840
3841                    fn_copy.common.fn_flags = alias->modifiers | (fn->common.fn_flags ^ (fn->common.fn_flags & ZEND_ACC_PPP_MASK));
3842
3843                    /** Record the trait from which this alias was resolved. */
3844                    if (!alias->trait_method->ce) {
3845                        alias->trait_method->ce = fn->common.scope;
3846                    }
3847                }
3848                alias_ptr++;
3849                alias = *alias_ptr;
3850            }
3851        }
3852
3853        zend_add_trait_method(ce, fn->common.function_name, lcname, fnname_len+1, &fn_copy, overriden TSRMLS_CC);
3854    }
3855
3856    return ZEND_HASH_APPLY_KEEP;
3857}
3858/* }}} */
3859
3860static void zend_check_trait_usage(zend_class_entry *ce, zend_class_entry *trait TSRMLS_DC) /* {{{ */
3861{
3862    zend_uint i;
3863
3864    if ((trait->ce_flags & ZEND_ACC_TRAIT) != ZEND_ACC_TRAIT) {
3865        zend_error(E_COMPILE_ERROR, "Class %s is not a trait, Only traits may be used in 'as' and 'insteadof' statements", trait->name);
3866    }
3867
3868    for (i = 0; i < ce->num_traits; i++) {
3869        if (ce->traits[i] == trait) {
3870            return;
3871        }
3872    }
3873    zend_error(E_COMPILE_ERROR, "Required Trait %s wasn't added to %s", trait->name, ce->name);
3874}
3875/* }}} */
3876
3877static void zend_traits_init_trait_structures(zend_class_entry *ce TSRMLS_DC) /* {{{ */
3878{
3879    size_t i, j = 0;
3880    zend_trait_precedence *cur_precedence;
3881    zend_trait_method_reference *cur_method_ref;
3882    char *lcname;
3883    zend_bool method_exists;
3884
3885    /* resolve class references */
3886    if (ce->trait_precedences) {
3887        i = 0;
3888        while ((cur_precedence = ce->trait_precedences[i])) {
3889            /** Resolve classes for all precedence operations. */
3890            if (cur_precedence->exclude_from_classes) {
3891                cur_method_ref = cur_precedence->trait_method;
3892                if (!(cur_precedence->trait_method->ce = zend_fetch_class(cur_method_ref->class_name, cur_method_ref->cname_len,
3893                                ZEND_FETCH_CLASS_TRAIT|ZEND_FETCH_CLASS_NO_AUTOLOAD TSRMLS_CC))) {
3894                    zend_error(E_COMPILE_ERROR, "Could not find trait %s", cur_method_ref->class_name);
3895                }
3896                zend_check_trait_usage(ce, cur_precedence->trait_method->ce TSRMLS_CC);
3897
3898                /** Ensure that the prefered method is actually available. */
3899                lcname = zend_str_tolower_dup(cur_method_ref->method_name,
3900                                              cur_method_ref->mname_len);
3901                method_exists = zend_hash_exists(&cur_method_ref->ce->function_table,
3902                                                 lcname,
3903                                                 cur_method_ref->mname_len + 1);
3904                efree(lcname);
3905                if (!method_exists) {
3906                    zend_error(E_COMPILE_ERROR,
3907                               "A precedence rule was defined for %s::%s but this method does not exist",
3908                               cur_method_ref->ce->name,
3909                               cur_method_ref->method_name);
3910                }
3911
3912                /** With the other traits, we are more permissive.
3913                    We do not give errors for those. This allows to be more
3914                    defensive in such definitions.
3915                    However, we want to make sure that the insteadof declaration
3916                    is consistent in itself.
3917                 */
3918                j = 0;
3919                while (cur_precedence->exclude_from_classes[j]) {
3920                    char* class_name = (char*)cur_precedence->exclude_from_classes[j];
3921                    zend_uint name_length = strlen(class_name);
3922
3923                    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))) {
3924                        zend_error(E_COMPILE_ERROR, "Could not find trait %s", class_name);
3925                    }
3926                    zend_check_trait_usage(ce, cur_precedence->exclude_from_classes[j] TSRMLS_CC);
3927
3928                    /* make sure that the trait method is not from a class mentioned in
3929                     exclude_from_classes, for consistency */
3930                    if (cur_precedence->trait_method->ce == cur_precedence->exclude_from_classes[i]) {
3931                        zend_error(E_COMPILE_ERROR,
3932                                   "Inconsistent insteadof definition. "
3933                                   "The method %s is to be used from %s, but %s is also on the exclude list",
3934                                   cur_method_ref->method_name,
3935                                   cur_precedence->trait_method->ce->name,
3936                                   cur_precedence->trait_method->ce->name);
3937                    }
3938
3939                    efree(class_name);
3940                    j++;
3941                }
3942            }
3943            i++;
3944        }
3945    }
3946
3947    if (ce->trait_aliases) {
3948        i = 0;
3949        while (ce->trait_aliases[i]) {
3950            /** For all aliases with an explicit class name, resolve the class now. */
3951            if (ce->trait_aliases[i]->trait_method->class_name) {
3952                cur_method_ref = ce->trait_aliases[i]->trait_method;
3953                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))) {
3954                    zend_error(E_COMPILE_ERROR, "Could not find trait %s", cur_method_ref->class_name);
3955                }
3956                zend_check_trait_usage(ce, cur_method_ref->ce TSRMLS_CC);
3957
3958                /** And, ensure that the referenced method is resolvable, too. */
3959                lcname = zend_str_tolower_dup(cur_method_ref->method_name,
3960                        cur_method_ref->mname_len);
3961                method_exists = zend_hash_exists(&cur_method_ref->ce->function_table,
3962                        lcname, cur_method_ref->mname_len + 1);
3963                efree(lcname);
3964
3965                if (!method_exists) {
3966                    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);
3967                }
3968            }
3969            i++;
3970        }
3971    }
3972}
3973/* }}} */
3974
3975static void zend_traits_compile_exclude_table(HashTable* exclude_table, zend_trait_precedence **precedences, zend_class_entry *trait) /* {{{ */
3976{
3977    size_t i = 0, j;
3978
3979    if (!precedences) {
3980        return;
3981    }
3982    while (precedences[i]) {
3983        if (precedences[i]->exclude_from_classes) {
3984            j = 0;
3985            while (precedences[i]->exclude_from_classes[j]) {
3986                if (precedences[i]->exclude_from_classes[j] == trait) {
3987                    zend_uint lcname_len = precedences[i]->trait_method->mname_len;
3988                    char *lcname = zend_str_tolower_dup(precedences[i]->trait_method->method_name, lcname_len);
3989
3990                    if (zend_hash_add(exclude_table, lcname, lcname_len, NULL, 0, NULL) == FAILURE) {
3991                        efree(lcname);
3992                        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);
3993                    }
3994                    efree(lcname);
3995                }
3996                ++j;
3997            }
3998        }
3999        ++i;
4000    }
4001}
4002/* }}} */
4003
4004static void zend_do_traits_method_binding(zend_class_entry *ce TSRMLS_DC) /* {{{ */
4005{
4006    zend_uint i;
4007    HashTable *overriden = NULL;
4008
4009    for (i = 0; i < ce->num_traits; i++) {
4010        if (ce->trait_precedences) {
4011            HashTable exclude_table;
4012
4013            /* TODO: revisit this start size, may be its not optimal */
4014            zend_hash_init_ex(&exclude_table, 2, NULL, NULL, 0, 0);
4015
4016            zend_traits_compile_exclude_table(&exclude_table, ce->trait_precedences, ce->traits[i]);
4017
4018            /* copies functions, applies defined aliasing, and excludes unused trait methods */
4019            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);
4020
4021            zend_hash_destroy(&exclude_table);
4022        } else {
4023            zend_hash_apply_with_arguments(&ce->traits[i]->function_table TSRMLS_CC, (apply_func_args_t)zend_traits_copy_functions, 3, ce, &overriden, NULL);
4024        }
4025    }
4026
4027    zend_hash_apply_with_argument(&ce->function_table, (apply_func_arg_t)zend_fixup_trait_method, ce TSRMLS_CC);
4028
4029    if (overriden) {
4030        zend_hash_destroy(overriden);
4031        FREE_HASHTABLE(overriden);
4032    }
4033}
4034/* }}} */
4035
4036static 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) /* {{{ */
4037{
4038    size_t i;
4039
4040    if (coliding_ce == ce) {
4041        for (i = 0; i < current_trait; i++) {
4042            if (zend_hash_quick_exists(&ce->traits[i]->properties_info, prop_name, prop_name_length+1, prop_hash)) {
4043                return ce->traits[i];
4044            }
4045        }
4046    }
4047
4048    return coliding_ce;
4049}
4050/* }}} */
4051
4052static void zend_do_traits_property_binding(zend_class_entry *ce TSRMLS_DC) /* {{{ */
4053{
4054    size_t i;
4055    zend_property_info *property_info;
4056    zend_property_info *coliding_prop;
4057    zval compare_result;
4058    const char* prop_name;
4059    int   prop_name_length;
4060    ulong prop_hash;
4061    const char* class_name_unused;
4062    zend_bool not_compatible;
4063    zval* prop_value;
4064    char* doc_comment;
4065    zend_uint flags;
4066
4067    /* In the following steps the properties are inserted into the property table
4068     * for that, a very strict approach is applied:
4069     * - check for compatibility, if not compatible with any property in class -> fatal
4070     * - if compatible, then strict notice
4071     */
4072    for (i = 0; i < ce->num_traits; i++) {
4073        for (zend_hash_internal_pointer_reset(&ce->traits[i]->properties_info);
4074             zend_hash_get_current_data(&ce->traits[i]->properties_info, (void *) &property_info) == SUCCESS;
4075             zend_hash_move_forward(&ce->traits[i]->properties_info)) {
4076            /* first get the unmangeld name if necessary,
4077             * then check whether the property is already there
4078             */
4079            flags = property_info->flags;
4080            if ((flags & ZEND_ACC_PPP_MASK) == ZEND_ACC_PUBLIC) {
4081                prop_hash = property_info->h;
4082                prop_name = property_info->name;
4083                prop_name_length = property_info->name_length;
4084            } else {
4085                /* for private and protected we need to unmangle the names */
4086                zend_unmangle_property_name(property_info->name, property_info->name_length,
4087                                            &class_name_unused, &prop_name);
4088                prop_name_length = strlen(prop_name);
4089                prop_hash = zend_get_hash_value(prop_name, prop_name_length + 1);
4090            }
4091
4092            /* next: check for conflicts with current class */
4093            if (zend_hash_quick_find(&ce->properties_info, prop_name, prop_name_length+1, prop_hash, (void **) &coliding_prop) == SUCCESS) {
4094                if (coliding_prop->flags & ZEND_ACC_SHADOW) {
4095                    zend_hash_quick_del(&ce->properties_info, prop_name, prop_name_length+1, prop_hash);
4096                    flags |= ZEND_ACC_CHANGED;
4097                } else {
4098                    if ((coliding_prop->flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))
4099                        == (flags & (ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC))) {
4100                        /* flags are identical, now the value needs to be checked */
4101                        if (flags & ZEND_ACC_STATIC) {
4102                            not_compatible = (FAILURE == compare_function(&compare_result,
4103                                              ce->default_static_members_table[coliding_prop->offset],
4104                                              ce->traits[i]->default_static_members_table[property_info->offset] TSRMLS_CC))
4105                                  || (Z_LVAL(compare_result) != 0);
4106                        } else {
4107                            not_compatible = (FAILURE == compare_function(&compare_result,
4108                                              ce->default_properties_table[coliding_prop->offset],
4109                                              ce->traits[i]->default_properties_table[property_info->offset] TSRMLS_CC))
4110                                  || (Z_LVAL(compare_result) != 0);
4111                        }
4112                    } else {
4113                        /* the flags are not identical, thus, we assume properties are not compatible */
4114                        not_compatible = 1;
4115                    }
4116
4117                    if (not_compatible) {
4118                        zend_error(E_COMPILE_ERROR,
4119                               "%s and %s define the same property ($%s) in the composition of %s. However, the definition differs and is considered incompatible. Class was composed",
4120                                find_first_definition(ce, i, prop_name, prop_name_length, prop_hash, coliding_prop->ce)->name,
4121                                property_info->ce->name,
4122                                prop_name,
4123                                ce->name);
4124                    } else {
4125                        zend_error(E_STRICT,
4126                               "%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",
4127                                find_first_definition(ce, i, prop_name, prop_name_length, prop_hash, coliding_prop->ce)->name,
4128                                property_info->ce->name,
4129                                prop_name,
4130                                ce->name);
4131                        continue;
4132                    }
4133                }
4134            }
4135
4136            /* property not found, so lets add it */
4137            if (flags & ZEND_ACC_STATIC) {
4138                prop_value = ce->traits[i]->default_static_members_table[property_info->offset];
4139            } else {
4140                prop_value = ce->traits[i]->default_properties_table[property_info->offset];
4141            }
4142            Z_ADDREF_P(prop_value);
4143
4144            doc_comment = property_info->doc_comment ? estrndup(property_info->doc_comment, property_info->doc_comment_len) : NULL;
4145            zend_declare_property_ex(ce, prop_name, prop_name_length,
4146                                     prop_value, flags,
4147                                     doc_comment, property_info->doc_comment_len TSRMLS_CC);
4148        }
4149    }
4150}
4151/* }}} */
4152
4153static void zend_do_check_for_inconsistent_traits_aliasing(zend_class_entry *ce TSRMLS_DC) /* {{{ */
4154{
4155    int i = 0;
4156    zend_trait_alias* cur_alias;
4157    char* lc_method_name;
4158
4159    if (ce->trait_aliases) {
4160        while (ce->trait_aliases[i]) {
4161            cur_alias = ce->trait_aliases[i];
4162            /** The trait for this alias has not been resolved, this means, this
4163                alias was not applied. Abort with an error. */
4164            if (!cur_alias->trait_method->ce) {
4165                if (cur_alias->alias) {
4166                    /** Plain old inconsistency/typo/bug */
4167                    zend_error(E_COMPILE_ERROR,
4168                               "An alias (%s) was defined for method %s(), but this method does not exist",
4169                               cur_alias->alias,
4170                               cur_alias->trait_method->method_name);
4171                } else {
4172                    /** Here are two possible cases:
4173                        1) this is an attempt to modifiy the visibility
4174                           of a method introduce as part of another alias.
4175                           Since that seems to violate the DRY principle,
4176                           we check against it and abort.
4177                        2) it is just a plain old inconsitency/typo/bug
4178                           as in the case where alias is set. */
4179
4180                    lc_method_name = zend_str_tolower_dup(cur_alias->trait_method->method_name,
4181                                                          cur_alias->trait_method->mname_len);
4182                    if (zend_hash_exists(&ce->function_table,
4183                                         lc_method_name,
4184                                         cur_alias->trait_method->mname_len+1)) {
4185                        efree(lc_method_name);
4186                        zend_error(E_COMPILE_ERROR,
4187                                   "The modifiers for the trait alias %s() need to be changed in the same statment in which the alias is defined. Error",
4188                                   cur_alias->trait_method->method_name);
4189                    } else {
4190                        efree(lc_method_name);
4191                        zend_error(E_COMPILE_ERROR,
4192                                   "The modifiers of the trait method %s() are changed, but this method does not exist. Error",
4193                                   cur_alias->trait_method->method_name);
4194
4195                    }
4196                }
4197            }
4198            i++;
4199        }
4200    }
4201}
4202/* }}} */
4203
4204ZEND_API void zend_do_bind_traits(zend_class_entry *ce TSRMLS_DC) /* {{{ */
4205{
4206
4207    if (ce->num_traits <= 0) {
4208        return;
4209    }
4210
4211    /* complete initialization of trait strutures in ce */
4212    zend_traits_init_trait_structures(ce TSRMLS_CC);
4213
4214    /* first care about all methods to be flattened into the class */
4215    zend_do_traits_method_binding(ce TSRMLS_CC);
4216
4217    /* Aliases which have not been applied indicate typos/bugs. */
4218    zend_do_check_for_inconsistent_traits_aliasing(ce TSRMLS_CC);
4219
4220    /* then flatten the properties into it, to, mostly to notfiy developer about problems */
4221    zend_do_traits_property_binding(ce TSRMLS_CC);
4222
4223    /* verify that all abstract methods from traits have been implemented */
4224    zend_verify_abstract_class(ce TSRMLS_CC);
4225
4226    /* now everything should be fine and an added ZEND_ACC_IMPLICIT_ABSTRACT_CLASS should be removed */
4227    if (ce->ce_flags & ZEND_ACC_IMPLICIT_ABSTRACT_CLASS) {
4228        ce->ce_flags -= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
4229    }
4230}
4231/* }}} */
4232
4233ZEND_API int do_bind_function(const zend_op_array *op_array, zend_op *opline, HashTable *function_table, zend_bool compile_time) /* {{{ */
4234{
4235    zend_function *function;
4236    zval *op1, *op2;
4237
4238    if (compile_time) {
4239        op1 = &CONSTANT_EX(op_array, opline->op1.constant);
4240        op2 = &CONSTANT_EX(op_array, opline->op2.constant);
4241    } else {
4242        op1 = opline->op1.zv;
4243        op2 = opline->op2.zv;
4244    }
4245
4246    zend_hash_quick_find(function_table, Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_HASH_P(op1), (void *) &function);
4247    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) {
4248        int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR;
4249        zend_function *old_function;
4250
4251        if (zend_hash_quick_find(function_table, Z_STRVAL_P(op2), Z_STRLEN_P(op2)+1, Z_HASH_P(op2), (void *) &old_function)==SUCCESS
4252            && old_function->type == ZEND_USER_FUNCTION
4253            && old_function->op_array.last > 0) {
4254            zend_error(error_level, "Cannot redeclare %s() (previously declared in %s:%d)",
4255                        function->common.function_name,
4256                        old_function->op_array.filename,
4257                        old_function->op_array.opcodes[0].lineno);
4258        } else {
4259            zend_error(error_level, "Cannot redeclare %s()", function->common.function_name);
4260        }
4261        return FAILURE;
4262    } else {
4263        (*function->op_array.refcount)++;
4264        function->op_array.static_variables = NULL; /* NULL out the unbound function */
4265        return SUCCESS;
4266    }
4267}
4268/* }}} */
4269
4270void zend_prepare_reference(znode *result, znode *class_name, znode *method_name TSRMLS_DC) /* {{{ */
4271{
4272    zend_trait_method_reference *method_ref = emalloc(sizeof(zend_trait_method_reference));
4273    method_ref->ce = NULL;
4274
4275    /* REM: There should not be a need for copying,
4276       zend_do_begin_class_declaration is also just using that string */
4277    if (class_name) {
4278        zend_resolve_class_name(class_name, ZEND_FETCH_CLASS_GLOBAL, 1 TSRMLS_CC);
4279        method_ref->class_name = Z_STRVAL(class_name->u.constant);
4280        method_ref->cname_len  = Z_STRLEN(class_name->u.constant);
4281    } else {
4282        method_ref->class_name = NULL;
4283        method_ref->cname_len  = 0;
4284    }
4285
4286    method_ref->method_name = Z_STRVAL(method_name->u.constant);
4287    method_ref->mname_len   = Z_STRLEN(method_name->u.constant);
4288
4289    result->u.op.ptr = method_ref;
4290    result->op_type = IS_TMP_VAR;
4291}
4292/* }}} */
4293
4294void zend_add_trait_alias(znode *method_reference, znode *modifiers, znode *alias TSRMLS_DC) /* {{{ */
4295{
4296    zend_class_entry *ce = CG(active_class_entry);
4297    zend_trait_alias *trait_alias;
4298
4299    if (Z_LVAL(modifiers->u.constant) == ZEND_ACC_STATIC) {
4300        zend_error(E_COMPILE_ERROR, "Cannot use 'static' as method modifier");
4301        return;
4302    } else if (Z_LVAL(modifiers->u.constant) == ZEND_ACC_ABSTRACT) {
4303        zend_error(E_COMPILE_ERROR, "Cannot use 'abstract' as method modifier");
4304        return;
4305    } else if (Z_LVAL(modifiers->u.constant) == ZEND_ACC_FINAL) {
4306        zend_error(E_COMPILE_ERROR, "Cannot use 'final' as method modifier");
4307        return;
4308    }
4309
4310    trait_alias = emalloc(sizeof(zend_trait_alias));
4311    trait_alias->trait_method = (zend_trait_method_reference*)method_reference->u.op.ptr;
4312    trait_alias->modifiers = Z_LVAL(modifiers->u.constant);
4313    if (alias) {
4314        trait_alias->alias = Z_STRVAL(alias->u.constant);
4315        trait_alias->alias_len = Z_STRLEN(alias->u.constant);
4316    } else {
4317        trait_alias->alias = NULL;
4318    }
4319    trait_alias->function = NULL;
4320
4321    zend_add_to_list(&ce->trait_aliases, trait_alias TSRMLS_CC);
4322}
4323/* }}} */
4324
4325void zend_add_trait_precedence(znode *method_reference, znode *trait_list TSRMLS_DC) /* {{{ */
4326{
4327    zend_class_entry *ce = CG(active_class_entry);
4328    zend_trait_precedence *trait_precedence = emalloc(sizeof(zend_trait_precedence));
4329
4330    trait_precedence->trait_method = (zend_trait_method_reference*)method_reference->u.op.ptr;
4331    trait_precedence->exclude_from_classes = (zend_class_entry**) trait_list->u.op.ptr;
4332
4333    trait_precedence->function = NULL;
4334
4335    zend_add_to_list(&ce->trait_precedences, trait_precedence TSRMLS_CC);
4336}
4337/* }}} */
4338
4339ZEND_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) /* {{{ */
4340{
4341    zend_class_entry *ce, **pce;
4342    zval *op1, *op2;
4343
4344    if (compile_time) {
4345        op1 = &CONSTANT_EX(op_array, opline->op1.constant);
4346        op2 = &CONSTANT_EX(op_array, opline->op2.constant);
4347    } else {
4348        op1 = opline->op1.zv;
4349        op2 = opline->op2.zv;
4350    }
4351    if (zend_hash_quick_find(class_table, Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_HASH_P(op1), (void **) &pce)==FAILURE) {
4352        zend_error(E_COMPILE_ERROR, "Internal Zend error - Missing class information for %s", Z_STRVAL_P(op1));
4353        return NULL;
4354    } else {
4355        ce = *pce;
4356    }
4357    ce->refcount++;
4358    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) {
4359        ce->refcount--;
4360        if (!compile_time) {
4361            /* If we're in compile time, in practice, it's quite possible
4362             * that we'll never reach this class declaration at runtime,
4363             * so we shut up about it.  This allows the if (!defined('FOO')) { return; }
4364             * approach to work.
4365             */
4366            zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", ce->name);
4367        }
4368        return NULL;
4369    } else {
4370        if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLEMENT_INTERFACES|ZEND_ACC_IMPLEMENT_TRAITS))) {
4371            zend_verify_abstract_class(ce TSRMLS_CC);
4372        }
4373        return ce;
4374    }
4375}
4376/* }}} */
4377
4378ZEND_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) /* {{{ */
4379{
4380    zend_class_entry *ce, **pce;
4381    int found_ce;
4382    zval *op1, *op2;
4383
4384    if (compile_time) {
4385        op1 = &CONSTANT_EX(op_array, opline->op1.constant);
4386        op2 = &CONSTANT_EX(op_array, opline->op2.constant);
4387    } else {
4388        op1 = opline->op1.zv;
4389        op2 = opline->op2.zv;
4390    }
4391
4392    found_ce = zend_hash_quick_find(class_table, Z_STRVAL_P(op1), Z_STRLEN_P(op1), Z_HASH_P(op1), (void **) &pce);
4393
4394    if (found_ce == FAILURE) {
4395        if (!compile_time) {
4396            /* If we're in compile time, in practice, it's quite possible
4397             * that we'll never reach this class declaration at runtime,
4398             * so we shut up about it.  This allows the if (!defined('FOO')) { return; }
4399             * approach to work.
4400             */
4401            zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", Z_STRVAL_P(op2));
4402        }
4403        return NULL;
4404    } else {
4405        ce = *pce;
4406    }
4407
4408    if (parent_ce->ce_flags & ZEND_ACC_INTERFACE) {
4409        zend_error(E_COMPILE_ERROR, "Class %s cannot extend from interface %s", ce->name, parent_ce->name);
4410    } else if ((parent_ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
4411        zend_error(E_COMPILE_ERROR, "Class %s cannot extend from trait %s", ce->name, parent_ce->name);
4412    }
4413
4414    zend_do_inheritance(ce, parent_ce TSRMLS_CC);
4415
4416    ce->refcount++;
4417
4418    /* Register the derived class */
4419    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) {
4420        zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", ce->name);
4421    }
4422    return ce;
4423}
4424/* }}} */
4425
4426void zend_do_early_binding(TSRMLS_D) /* {{{ */
4427{
4428    zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
4429    HashTable *table;
4430
4431    while (opline->opcode == ZEND_TICKS && opline > CG(active_op_array)->opcodes) {
4432        opline--;
4433    }
4434
4435    switch (opline->opcode) {
4436        case ZEND_DECLARE_FUNCTION:
4437            if (do_bind_function(CG(active_op_array), opline, CG(function_table), 1) == FAILURE) {
4438                return;
4439            }
4440            table = CG(function_table);
4441            break;
4442        case ZEND_DECLARE_CLASS:
4443            if (do_bind_class(CG(active_op_array), opline, CG(class_table), 1 TSRMLS_CC) == NULL) {
4444                return;
4445            }
4446            table = CG(class_table);
4447            break;
4448        case ZEND_DECLARE_INHERITED_CLASS:
4449            {
4450                zend_op *fetch_class_opline = opline-1;
4451                zval *parent_name;
4452                zend_class_entry **pce;
4453
4454                parent_name = &CONSTANT(fetch_class_opline->op2.constant);
4455                if ((zend_lookup_class(Z_STRVAL_P(parent_name), Z_STRLEN_P(parent_name), &pce TSRMLS_CC) == FAILURE) ||
4456                    ((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES) &&
4457                     ((*pce)->type == ZEND_INTERNAL_CLASS))) {
4458                    if (CG(compiler_options) & ZEND_COMPILE_DELAYED_BINDING) {
4459                        zend_uint *opline_num = &CG(active_op_array)->early_binding;
4460
4461                        while (*opline_num != -1) {
4462                            opline_num = &CG(active_op_array)->opcodes[*opline_num].result.opline_num;
4463                        }
4464                        *opline_num = opline - CG(active_op_array)->opcodes;
4465                        opline->opcode = ZEND_DECLARE_INHERITED_CLASS_DELAYED;
4466                        opline->result_type = IS_UNUSED;
4467                        opline->result.opline_num = -1;
4468                    }
4469                    return;
4470                }
4471                if (do_bind_inherited_class(CG(active_op_array), opline, CG(class_table), *pce, 1 TSRMLS_CC) == NULL) {
4472                    return;
4473                }
4474                /* clear unnecessary ZEND_FETCH_CLASS opcode */
4475                zend_del_literal(CG(active_op_array), fetch_class_opline->op2.constant);
4476                MAKE_NOP(fetch_class_opline);
4477
4478                table = CG(class_table);
4479                break;
4480            }
4481        case ZEND_VERIFY_ABSTRACT_CLASS:
4482        case ZEND_ADD_INTERFACE:
4483        case ZEND_ADD_TRAIT:
4484        case ZEND_BIND_TRAITS:
4485            /* We currently don't early-bind classes that implement interfaces */
4486            /* Classes with traits are handled exactly the same, no early-bind here */
4487            return;
4488        default:
4489            zend_error(E_COMPILE_ERROR, "Invalid binding type");
4490            return;
4491    }
4492
4493    zend_hash_quick_del(table, Z_STRVAL(CONSTANT(opline->op1.constant)), Z_STRLEN(CONSTANT(opline->op1.constant)), Z_HASH_P(&CONSTANT(opline->op1.constant)));
4494    zend_del_literal(CG(active_op_array), opline->op1.constant);
4495    zend_del_literal(CG(active_op_array), opline->op2.constant);
4496    MAKE_NOP(opline);
4497}
4498/* }}} */
4499
4500ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array TSRMLS_DC) /* {{{ */
4501{
4502    if (op_array->early_binding != -1) {
4503        zend_bool orig_in_compilation = CG(in_compilation);
4504        zend_uint opline_num = op_array->early_binding;
4505        zend_class_entry **pce;
4506
4507        CG(in_compilation) = 1;
4508        while (opline_num != -1) {
4509            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) {
4510                do_bind_inherited_class(op_array, &op_array->opcodes[opline_num], EG(class_table), *pce, 0 TSRMLS_CC);
4511            }
4512            opline_num = op_array->opcodes[opline_num].result.opline_num;
4513        }
4514        CG(in_compilation) = orig_in_compilation;
4515    }
4516}
4517/* }}} */
4518
4519void zend_do_boolean_or_begin(znode *expr1, znode *op_token TSRMLS_DC) /* {{{ */
4520{
4521    int next_op_number = get_next_op_number(CG(active_op_array));
4522    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4523
4524    opline->opcode = ZEND_JMPNZ_EX;
4525    if (expr1->op_type == IS_TMP_VAR) {
4526        SET_NODE(opline->result, expr1);
4527    } else {
4528        opline->result.var = get_temporary_variable(CG(active_op_array));
4529        opline->result_type = IS_TMP_VAR;
4530    }
4531    SET_NODE(opline->op1, expr1);
4532    SET_UNUSED(opline->op2);
4533
4534    op_token->u.op.opline_num = next_op_number;
4535
4536    GET_NODE(expr1, opline->result);
4537}
4538/* }}} */
4539
4540void zend_do_boolean_or_end(znode *result, const znode *expr1, const znode *expr2, znode *op_token TSRMLS_DC) /* {{{ */
4541{
4542    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4543
4544    *result = *expr1; /* we saved the original result in expr1 */
4545    opline->opcode = ZEND_BOOL;
4546    SET_NODE(opline->result, result);
4547    SET_NODE(opline->op1, expr2);
4548    SET_UNUSED(opline->op2);
4549
4550    CG(active_op_array)->opcodes[op_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
4551}
4552/* }}} */
4553
4554void zend_do_boolean_and_begin(znode *expr1, znode *op_token TSRMLS_DC) /* {{{ */
4555{
4556    int next_op_number = get_next_op_number(CG(active_op_array));
4557    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4558
4559    opline->opcode = ZEND_JMPZ_EX;
4560    if (expr1->op_type == IS_TMP_VAR) {
4561        SET_NODE(opline->result, expr1);
4562    } else {
4563        opline->result.var = get_temporary_variable(CG(active_op_array));
4564        opline->result_type = IS_TMP_VAR;
4565    }
4566    SET_NODE(opline->op1, expr1);
4567    SET_UNUSED(opline->op2);
4568
4569    op_token->u.op.opline_num = next_op_number;
4570
4571    GET_NODE(expr1, opline->result);
4572}
4573/* }}} */
4574
4575void zend_do_boolean_and_end(znode *result, const znode *expr1, const znode *expr2, const znode *op_token TSRMLS_DC) /* {{{ */
4576{
4577    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4578
4579    *result = *expr1; /* we saved the original result in expr1 */
4580    opline->opcode = ZEND_BOOL;
4581    SET_NODE(opline->result, result);
4582    SET_NODE(opline->op1, expr2);
4583    SET_UNUSED(opline->op2);
4584
4585    CG(active_op_array)->opcodes[op_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array));
4586}
4587/* }}} */
4588
4589void zend_do_do_while_begin(TSRMLS_D) /* {{{ */
4590{
4591    do_begin_loop(TSRMLS_C);
4592    INC_BPC(CG(active_op_array));
4593}
4594/* }}} */
4595
4596void zend_do_do_while_end(const znode *do_token, const znode *expr_open_bracket, const znode *expr TSRMLS_DC) /* {{{ */
4597{
4598    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4599
4600    opline->opcode = ZEND_JMPNZ;
4601    SET_NODE(opline->op1, expr);
4602    opline->op2.opline_num = do_token->u.op.opline_num;
4603    SET_UNUSED(opline->op2);
4604
4605    do_end_loop(expr_open_bracket->u.op.opline_num, 0 TSRMLS_CC);
4606
4607    DEC_BPC(CG(active_op_array));
4608}
4609/* }}} */
4610
4611void zend_do_brk_cont(zend_uchar op, const znode *expr TSRMLS_DC) /* {{{ */
4612{
4613    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4614
4615    opline->opcode = op;
4616    opline->op1.opline_num = CG(context).current_brk_cont;
4617    SET_UNUSED(opline->op1);
4618    if (expr) {
4619        if (expr->op_type != IS_CONST) {
4620            zend_error(E_COMPILE_ERROR, "'%s' operator with non-constant operand is no longer supported", op == ZEND_BRK ? "break" : "continue");
4621        } else if (Z_TYPE(expr->u.constant) != IS_LONG || Z_LVAL(expr->u.constant) < 1) {
4622            zend_error(E_COMPILE_ERROR, "'%s' operator accepts only positive numbers", op == ZEND_BRK ? "break" : "continue");
4623        }
4624        SET_NODE(opline->op2, expr);
4625    } else {
4626        LITERAL_LONG(opline->op2, 1);
4627        opline->op2_type = IS_CONST;
4628    }
4629}
4630/* }}} */
4631
4632void zend_do_switch_cond(const znode *cond TSRMLS_DC) /* {{{ */
4633{
4634    zend_switch_entry switch_entry;
4635
4636    switch_entry.cond = *cond;
4637    switch_entry.default_case = -1;
4638    switch_entry.control_var = -1;
4639    zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry, sizeof(switch_entry));
4640
4641    do_begin_loop(TSRMLS_C);
4642
4643    INC_BPC(CG(active_op_array));
4644}
4645/* }}} */
4646
4647void zend_do_switch_end(const znode *case_list TSRMLS_DC) /* {{{ */
4648{
4649    zend_op *opline;
4650    zend_switch_entry *switch_entry_ptr;
4651
4652    zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
4653
4654    /* add code to jmp to default case */
4655    if (switch_entry_ptr->default_case != -1) {
4656        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4657        opline->opcode = ZEND_JMP;
4658        SET_UNUSED(opline->op1);
4659        SET_UNUSED(opline->op2);
4660        opline->op1.opline_num = switch_entry_ptr->default_case;
4661    }
4662
4663    if (case_list->op_type != IS_UNUSED) { /* non-empty switch */
4664        int next_op_number = get_next_op_number(CG(active_op_array));
4665
4666        CG(active_op_array)->opcodes[case_list->u.op.opline_num].op1.opline_num = next_op_number;
4667    }
4668
4669    /* remember break/continue loop information */
4670    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));
4671    CG(context).current_brk_cont = CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].parent;
4672
4673    if (switch_entry_ptr->cond.op_type==IS_VAR || switch_entry_ptr->cond.op_type==IS_TMP_VAR) {
4674        /* emit free for the switch condition*/
4675        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4676        opline->opcode = (switch_entry_ptr->cond.op_type == IS_TMP_VAR) ? ZEND_FREE : ZEND_SWITCH_FREE;
4677        SET_NODE(opline->op1, &switch_entry_ptr->cond);
4678        SET_UNUSED(opline->op2);
4679    }
4680    if (switch_entry_ptr->cond.op_type == IS_CONST) {
4681        zval_dtor(&switch_entry_ptr->cond.u.constant);
4682    }
4683
4684    zend_stack_del_top(&CG(switch_cond_stack));
4685
4686    DEC_BPC(CG(active_op_array));
4687}
4688/* }}} */
4689
4690void zend_do_case_before_statement(const znode *case_list, znode *case_token, const znode *case_expr TSRMLS_DC) /* {{{ */
4691{
4692    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4693    int next_op_number;
4694    zend_switch_entry *switch_entry_ptr;
4695    znode result;
4696
4697    zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
4698
4699    if (switch_entry_ptr->control_var == -1) {
4700        switch_entry_ptr->control_var = get_temporary_variable(CG(active_op_array));
4701    }
4702    opline->opcode = ZEND_CASE;
4703    opline->result.var = switch_entry_ptr->control_var;
4704    opline->result_type = IS_TMP_VAR;
4705    SET_NODE(opline->op1, &switch_entry_ptr->cond);
4706    SET_NODE(opline->op2, case_expr);