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