1/*
2   +----------------------------------------------------------------------+
3   | Zend Engine                                                          |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1998-2016 Zend Technologies Ltd. (http://www.zend.com) |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 2.00 of the Zend license,     |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.zend.com/license/2_00.txt.                                |
11   | If you did not receive a copy of the Zend license and are unable to  |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@zend.com so we can mail you a copy immediately.              |
14   +----------------------------------------------------------------------+
15   | Authors: Andi Gutmans <andi@zend.com>                                |
16   |          Zeev Suraski <zeev@zend.com>                                |
17   |          Nikita Popov <nikic@php.net>                                |
18   +----------------------------------------------------------------------+
19*/
20
21/* $Id$ */
22
23#include <zend_language_parser.h>
24#include "zend.h"
25#include "zend_compile.h"
26#include "zend_constants.h"
27#include "zend_llist.h"
28#include "zend_API.h"
29#include "zend_exceptions.h"
30#include "zend_interfaces.h"
31#include "zend_virtual_cwd.h"
32#include "zend_multibyte.h"
33#include "zend_language_scanner.h"
34#include "zend_inheritance.h"
35#include "zend_vm.h"
36
37#define SET_NODE(target, src) do { \
38		target ## _type = (src)->op_type; \
39		if ((src)->op_type == IS_CONST) { \
40			target.constant = zend_add_literal(CG(active_op_array), &(src)->u.constant); \
41		} else { \
42			target = (src)->u.op; \
43		} \
44	} while (0)
45
46#define GET_NODE(target, src) do { \
47		(target)->op_type = src ## _type; \
48		if ((target)->op_type == IS_CONST) { \
49			ZVAL_COPY_VALUE(&(target)->u.constant, CT_CONSTANT(src)); \
50		} else { \
51			(target)->u.op = src; \
52		} \
53	} while (0)
54
55#define FC(member) (CG(file_context).member)
56
57typedef struct _zend_loop_var {
58	zend_uchar opcode;
59	zend_uchar var_type;
60	uint32_t   var_num;
61	union {
62		uint32_t try_catch_offset;
63		uint32_t live_range_offset;
64	} u;
65} zend_loop_var;
66
67static inline void zend_alloc_cache_slot(uint32_t literal) {
68	zend_op_array *op_array = CG(active_op_array);
69	Z_CACHE_SLOT(op_array->literals[literal]) = op_array->cache_size;
70	op_array->cache_size += sizeof(void*);
71}
72
73#define POLYMORPHIC_CACHE_SLOT_SIZE 2
74
75static inline void zend_alloc_polymorphic_cache_slot(uint32_t literal) {
76	zend_op_array *op_array = CG(active_op_array);
77	Z_CACHE_SLOT(op_array->literals[literal]) = op_array->cache_size;
78	op_array->cache_size += POLYMORPHIC_CACHE_SLOT_SIZE * sizeof(void*);
79}
80
81ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type);
82ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename);
83
84#ifndef ZTS
85ZEND_API zend_compiler_globals compiler_globals;
86ZEND_API zend_executor_globals executor_globals;
87#endif
88
89static zend_op *zend_emit_op(znode *result, zend_uchar opcode, znode *op1, znode *op2);
90
91static void zend_destroy_property_info_internal(zval *zv) /* {{{ */
92{
93	zend_property_info *property_info = Z_PTR_P(zv);
94
95	zend_string_release(property_info->name);
96	free(property_info);
97}
98/* }}} */
99
100static void zend_destroy_class_constant_internal(zval *zv) /* {{{ */
101{
102	free(Z_PTR_P(zv));
103}
104/* }}} */
105
106static zend_string *zend_new_interned_string_safe(zend_string *str) /* {{{ */ {
107	zend_string *interned_str;
108
109	zend_string_addref(str);
110	interned_str = zend_new_interned_string(str);
111	if (str != interned_str) {
112		return interned_str;
113	} else {
114		zend_string_release(str);
115		return str;
116	}
117}
118/* }}} */
119
120static zend_string *zend_build_runtime_definition_key(zend_string *name, unsigned char *lex_pos) /* {{{ */
121{
122	zend_string *result;
123	char char_pos_buf[32];
124	size_t char_pos_len = zend_sprintf(char_pos_buf, "%p", lex_pos);
125	zend_string *filename = CG(active_op_array)->filename;
126
127	/* NULL, name length, filename length, last accepting char position length */
128	result = zend_string_alloc(1 + ZSTR_LEN(name) + ZSTR_LEN(filename) + char_pos_len, 0);
129 	sprintf(ZSTR_VAL(result), "%c%s%s%s", '\0', ZSTR_VAL(name), ZSTR_VAL(filename), char_pos_buf);
130	return zend_new_interned_string(result);
131}
132/* }}} */
133
134static zend_bool zend_get_unqualified_name(const zend_string *name, const char **result, size_t *result_len) /* {{{ */
135{
136	const char *ns_separator = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
137	if (ns_separator != NULL) {
138		*result = ns_separator + 1;
139		*result_len = ZSTR_VAL(name) + ZSTR_LEN(name) - *result;
140		return 1;
141	}
142
143	return 0;
144}
145/* }}} */
146
147struct reserved_class_name {
148	const char *name;
149	size_t len;
150};
151static const struct reserved_class_name reserved_class_names[] = {
152	{ZEND_STRL("bool")},
153	{ZEND_STRL("false")},
154	{ZEND_STRL("float")},
155	{ZEND_STRL("int")},
156	{ZEND_STRL("null")},
157	{ZEND_STRL("parent")},
158	{ZEND_STRL("self")},
159	{ZEND_STRL("static")},
160	{ZEND_STRL("string")},
161	{ZEND_STRL("true")},
162	{ZEND_STRL("void")},
163	{NULL, 0}
164};
165
166static zend_bool zend_is_reserved_class_name(const zend_string *name) /* {{{ */
167{
168	const struct reserved_class_name *reserved = reserved_class_names;
169
170	const char *uqname = ZSTR_VAL(name);
171	size_t uqname_len = ZSTR_LEN(name);
172	zend_get_unqualified_name(name, &uqname, &uqname_len);
173
174	for (; reserved->name; ++reserved) {
175		if (uqname_len == reserved->len
176			&& zend_binary_strcasecmp(uqname, uqname_len, reserved->name, reserved->len) == 0
177		) {
178			return 1;
179		}
180	}
181
182	return 0;
183}
184/* }}} */
185
186ZEND_API void zend_assert_valid_class_name(const zend_string *name) /* {{{ */
187{
188	if (zend_is_reserved_class_name(name)) {
189		zend_error_noreturn(E_COMPILE_ERROR,
190			"Cannot use '%s' as class name as it is reserved", ZSTR_VAL(name));
191	}
192}
193/* }}} */
194
195typedef struct _builtin_type_info {
196	const char* name;
197	const size_t name_len;
198	const zend_uchar type;
199} builtin_type_info;
200
201static const builtin_type_info builtin_types[] = {
202	{ZEND_STRL("int"), IS_LONG},
203	{ZEND_STRL("float"), IS_DOUBLE},
204	{ZEND_STRL("string"), IS_STRING},
205	{ZEND_STRL("bool"), _IS_BOOL},
206	{ZEND_STRL("void"), IS_VOID},
207	{NULL, 0, IS_UNDEF}
208};
209
210
211static zend_always_inline zend_uchar zend_lookup_builtin_type_by_name(const zend_string *name) /* {{{ */
212{
213	const builtin_type_info *info = &builtin_types[0];
214
215	for (; info->name; ++info) {
216		if (ZSTR_LEN(name) == info->name_len
217			&& zend_binary_strcasecmp(ZSTR_VAL(name), ZSTR_LEN(name), info->name, info->name_len) == 0
218		) {
219			return info->type;
220		}
221	}
222
223	return 0;
224}
225/* }}} */
226
227
228void zend_oparray_context_begin(zend_oparray_context *prev_context) /* {{{ */
229{
230	*prev_context = CG(context);
231	CG(context).opcodes_size = INITIAL_OP_ARRAY_SIZE;
232	CG(context).vars_size = 0;
233	CG(context).literals_size = 0;
234	CG(context).backpatch_count = 0;
235	CG(context).in_finally = 0;
236	CG(context).fast_call_var = -1;
237	CG(context).current_brk_cont = -1;
238	CG(context).last_brk_cont = 0;
239	CG(context).brk_cont_array = NULL;
240	CG(context).labels = NULL;
241}
242/* }}} */
243
244void zend_oparray_context_end(zend_oparray_context *prev_context) /* {{{ */
245{
246	if (CG(context).brk_cont_array) {
247		efree(CG(context).brk_cont_array);
248		CG(context).brk_cont_array = NULL;
249	}
250	if (CG(context).labels) {
251		zend_hash_destroy(CG(context).labels);
252		FREE_HASHTABLE(CG(context).labels);
253		CG(context).labels = NULL;
254	}
255	CG(context) = *prev_context;
256}
257/* }}} */
258
259static void zend_reset_import_tables(void) /* {{{ */
260{
261	if (FC(imports)) {
262		zend_hash_destroy(FC(imports));
263		efree(FC(imports));
264		FC(imports) = NULL;
265	}
266
267	if (FC(imports_function)) {
268		zend_hash_destroy(FC(imports_function));
269		efree(FC(imports_function));
270		FC(imports_function) = NULL;
271	}
272
273	if (FC(imports_const)) {
274		zend_hash_destroy(FC(imports_const));
275		efree(FC(imports_const));
276		FC(imports_const) = NULL;
277	}
278}
279/* }}} */
280
281static void zend_end_namespace(void) /* {{{ */ {
282	FC(in_namespace) = 0;
283	zend_reset_import_tables();
284	if (FC(current_namespace)) {
285		zend_string_release(FC(current_namespace));
286		FC(current_namespace) = NULL;
287	}
288}
289/* }}} */
290
291void zend_file_context_begin(zend_file_context *prev_context) /* {{{ */
292{
293	*prev_context = CG(file_context);
294	FC(imports) = NULL;
295	FC(imports_function) = NULL;
296	FC(imports_const) = NULL;
297	FC(current_namespace) = NULL;
298	FC(in_namespace) = 0;
299	FC(has_bracketed_namespaces) = 0;
300	FC(declarables).ticks = 0;
301}
302/* }}} */
303
304void zend_file_context_end(zend_file_context *prev_context) /* {{{ */
305{
306	zend_end_namespace();
307	CG(file_context) = *prev_context;
308}
309/* }}} */
310
311void zend_init_compiler_data_structures(void) /* {{{ */
312{
313	zend_stack_init(&CG(loop_var_stack), sizeof(zend_loop_var));
314	zend_stack_init(&CG(delayed_oplines_stack), sizeof(zend_op));
315	CG(active_class_entry) = NULL;
316	CG(in_compilation) = 0;
317	CG(start_lineno) = 0;
318	zend_hash_init(&CG(const_filenames), 8, NULL, NULL, 0);
319
320	CG(encoding_declared) = 0;
321}
322/* }}} */
323
324ZEND_API void file_handle_dtor(zend_file_handle *fh) /* {{{ */
325{
326
327	zend_file_handle_dtor(fh);
328}
329/* }}} */
330
331void init_compiler(void) /* {{{ */
332{
333	CG(arena) = zend_arena_create(64 * 1024);
334	CG(active_op_array) = NULL;
335	memset(&CG(context), 0, sizeof(CG(context)));
336	zend_init_compiler_data_structures();
337	zend_init_rsrc_list();
338	zend_hash_init(&CG(filenames_table), 8, NULL, ZVAL_PTR_DTOR, 0);
339	zend_llist_init(&CG(open_files), sizeof(zend_file_handle), (void (*)(void *)) file_handle_dtor, 0);
340	CG(unclean_shutdown) = 0;
341}
342/* }}} */
343
344void shutdown_compiler(void) /* {{{ */
345{
346	zend_stack_destroy(&CG(loop_var_stack));
347	zend_stack_destroy(&CG(delayed_oplines_stack));
348	zend_hash_destroy(&CG(filenames_table));
349	zend_hash_destroy(&CG(const_filenames));
350	zend_arena_destroy(CG(arena));
351}
352/* }}} */
353
354ZEND_API zend_string *zend_set_compiled_filename(zend_string *new_compiled_filename) /* {{{ */
355{
356	zval *p, rv;
357
358	if ((p = zend_hash_find(&CG(filenames_table), new_compiled_filename))) {
359		ZEND_ASSERT(Z_TYPE_P(p) == IS_STRING);
360		CG(compiled_filename) = Z_STR_P(p);
361		return Z_STR_P(p);
362	}
363
364	ZVAL_STR_COPY(&rv, new_compiled_filename);
365	zend_hash_update(&CG(filenames_table), new_compiled_filename, &rv);
366
367	CG(compiled_filename) = new_compiled_filename;
368	return new_compiled_filename;
369}
370/* }}} */
371
372ZEND_API void zend_restore_compiled_filename(zend_string *original_compiled_filename) /* {{{ */
373{
374	CG(compiled_filename) = original_compiled_filename;
375}
376/* }}} */
377
378ZEND_API zend_string *zend_get_compiled_filename(void) /* {{{ */
379{
380	return CG(compiled_filename);
381}
382/* }}} */
383
384ZEND_API int zend_get_compiled_lineno(void) /* {{{ */
385{
386	return CG(zend_lineno);
387}
388/* }}} */
389
390ZEND_API zend_bool zend_is_compiling(void) /* {{{ */
391{
392	return CG(in_compilation);
393}
394/* }}} */
395
396static uint32_t get_temporary_variable(zend_op_array *op_array) /* {{{ */
397{
398	return (uint32_t)op_array->T++;
399}
400/* }}} */
401
402static int lookup_cv(zend_op_array *op_array, zend_string* name) /* {{{ */{
403	int i = 0;
404	zend_ulong hash_value = zend_string_hash_val(name);
405
406	while (i < op_array->last_var) {
407		if (ZSTR_VAL(op_array->vars[i]) == ZSTR_VAL(name) ||
408		    (ZSTR_H(op_array->vars[i]) == hash_value &&
409		     ZSTR_LEN(op_array->vars[i]) == ZSTR_LEN(name) &&
410		     memcmp(ZSTR_VAL(op_array->vars[i]), ZSTR_VAL(name), ZSTR_LEN(name)) == 0)) {
411			zend_string_release(name);
412			return (int)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, i);
413		}
414		i++;
415	}
416	i = op_array->last_var;
417	op_array->last_var++;
418	if (op_array->last_var > CG(context).vars_size) {
419		CG(context).vars_size += 16; /* FIXME */
420		op_array->vars = erealloc(op_array->vars, CG(context).vars_size * sizeof(zend_string*));
421	}
422
423	op_array->vars[i] = zend_new_interned_string(name);
424	return (int)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, i);
425}
426/* }}} */
427
428void zend_del_literal(zend_op_array *op_array, int n) /* {{{ */
429{
430	zval_dtor(CT_CONSTANT_EX(op_array, n));
431	if (n + 1 == op_array->last_literal) {
432		op_array->last_literal--;
433	} else {
434		ZVAL_UNDEF(CT_CONSTANT_EX(op_array, n));
435	}
436}
437/* }}} */
438
439/* Common part of zend_add_literal and zend_append_individual_literal */
440static inline void zend_insert_literal(zend_op_array *op_array, zval *zv, int literal_position) /* {{{ */
441{
442	if (Z_TYPE_P(zv) == IS_STRING || Z_TYPE_P(zv) == IS_CONSTANT) {
443		zend_string_hash_val(Z_STR_P(zv));
444		Z_STR_P(zv) = zend_new_interned_string(Z_STR_P(zv));
445		if (ZSTR_IS_INTERNED(Z_STR_P(zv))) {
446			Z_TYPE_FLAGS_P(zv) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
447		}
448	}
449	ZVAL_COPY_VALUE(CT_CONSTANT_EX(op_array, literal_position), zv);
450	Z_CACHE_SLOT(op_array->literals[literal_position]) = -1;
451}
452/* }}} */
453
454/* Is used while compiling a function, using the context to keep track
455   of an approximate size to avoid to relocate to often.
456   Literals are truncated to actual size in the second compiler pass (pass_two()). */
457int zend_add_literal(zend_op_array *op_array, zval *zv) /* {{{ */
458{
459	int i = op_array->last_literal;
460	op_array->last_literal++;
461	if (i >= CG(context).literals_size) {
462		while (i >= CG(context).literals_size) {
463			CG(context).literals_size += 16; /* FIXME */
464		}
465		op_array->literals = (zval*)erealloc(op_array->literals, CG(context).literals_size * sizeof(zval));
466	}
467	zend_insert_literal(op_array, zv, i);
468	return i;
469}
470/* }}} */
471
472static inline int zend_add_literal_string(zend_op_array *op_array, zend_string **str) /* {{{ */
473{
474	int ret;
475	zval zv;
476	ZVAL_STR(&zv, *str);
477	ret = zend_add_literal(op_array, &zv);
478	*str = Z_STR(zv);
479	return ret;
480}
481/* }}} */
482
483static int zend_add_func_name_literal(zend_op_array *op_array, zend_string *name) /* {{{ */
484{
485	/* Original name */
486	int ret = zend_add_literal_string(op_array, &name);
487
488	/* Lowercased name */
489	zend_string *lc_name = zend_string_tolower(name);
490	zend_add_literal_string(op_array, &lc_name);
491
492	return ret;
493}
494/* }}} */
495
496static int zend_add_ns_func_name_literal(zend_op_array *op_array, zend_string *name) /* {{{ */
497{
498	const char *unqualified_name;
499	size_t unqualified_name_len;
500
501	/* Original name */
502	int ret = zend_add_literal_string(op_array, &name);
503
504	/* Lowercased name */
505	zend_string *lc_name = zend_string_tolower(name);
506	zend_add_literal_string(op_array, &lc_name);
507
508	/* Lowercased unqualfied name */
509	if (zend_get_unqualified_name(name, &unqualified_name, &unqualified_name_len)) {
510		lc_name = zend_string_alloc(unqualified_name_len, 0);
511		zend_str_tolower_copy(ZSTR_VAL(lc_name), unqualified_name, unqualified_name_len);
512		zend_add_literal_string(op_array, &lc_name);
513	}
514
515	return ret;
516}
517/* }}} */
518
519static int zend_add_class_name_literal(zend_op_array *op_array, zend_string *name) /* {{{ */
520{
521	/* Original name */
522	int ret = zend_add_literal_string(op_array, &name);
523
524	/* Lowercased name */
525	zend_string *lc_name = zend_string_tolower(name);
526	zend_add_literal_string(op_array, &lc_name);
527
528	zend_alloc_cache_slot(ret);
529
530	return ret;
531}
532/* }}} */
533
534static int zend_add_const_name_literal(zend_op_array *op_array, zend_string *name, zend_bool unqualified) /* {{{ */
535{
536	zend_string *tmp_name;
537
538	int ret = zend_add_literal_string(op_array, &name);
539
540	size_t ns_len = 0, after_ns_len = ZSTR_LEN(name);
541	const char *after_ns = zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
542	if (after_ns) {
543		after_ns += 1;
544		ns_len = after_ns - ZSTR_VAL(name) - 1;
545		after_ns_len = ZSTR_LEN(name) - ns_len - 1;
546
547		/* lowercased namespace name & original constant name */
548		tmp_name = zend_string_init(ZSTR_VAL(name), ZSTR_LEN(name), 0);
549		zend_str_tolower(ZSTR_VAL(tmp_name), ns_len);
550		zend_add_literal_string(op_array, &tmp_name);
551
552		/* lowercased namespace name & lowercased constant name */
553		tmp_name = zend_string_tolower(name);
554		zend_add_literal_string(op_array, &tmp_name);
555
556		if (!unqualified) {
557			return ret;
558		}
559	} else {
560		after_ns = ZSTR_VAL(name);
561	}
562
563	/* original unqualified constant name */
564	tmp_name = zend_string_init(after_ns, after_ns_len, 0);
565	zend_add_literal_string(op_array, &tmp_name);
566
567	/* lowercased unqualified constant name */
568	tmp_name = zend_string_alloc(after_ns_len, 0);
569	zend_str_tolower_copy(ZSTR_VAL(tmp_name), after_ns, after_ns_len);
570	zend_add_literal_string(op_array, &tmp_name);
571
572	return ret;
573}
574/* }}} */
575
576#define LITERAL_STR(op, str) do { \
577		zval _c; \
578		ZVAL_STR(&_c, str); \
579		op.constant = zend_add_literal(CG(active_op_array), &_c); \
580	} while (0)
581
582void zend_stop_lexing(void)
583{
584	if(LANG_SCNG(on_event)) LANG_SCNG(on_event)(ON_STOP, END, 0);
585
586	LANG_SCNG(yy_cursor) = LANG_SCNG(yy_limit);
587}
588
589static uint32_t zend_start_live_range(zend_op_array *op_array, uint32_t start) /* {{{ */
590{
591	zend_live_range *range;
592
593	op_array->last_live_range++;
594	op_array->live_range = erealloc(op_array->live_range, sizeof(zend_live_range) * op_array->last_live_range);
595	range = op_array->live_range + op_array->last_live_range - 1;
596	range->start = start;
597	return op_array->last_live_range - 1;
598}
599/* }}} */
600
601static uint32_t zend_start_live_range_ex(zend_op_array *op_array, uint32_t start) /* {{{ */
602{
603	if (op_array->last_live_range == 0 ||
604	    op_array->live_range[op_array->last_live_range - 1].start <= start) {
605		return zend_start_live_range(op_array, start);
606	} else {
607		/* Live ranges have to be sorted by "start" field */
608		uint32_t n = op_array->last_live_range;
609
610		/* move early ranges to make a room */
611		op_array->last_live_range = n + 1;
612		op_array->live_range = erealloc(op_array->live_range, sizeof(zend_live_range) * op_array->last_live_range);
613		do {
614			op_array->live_range[n] = op_array->live_range[n-1];
615			n--;
616		} while (n != 0 && op_array->live_range[n-1].start > start);
617
618	    /* initialize new range */
619		op_array->live_range[n].start = start;
620
621		/* update referens to live-ranges from stack */
622		if (!zend_stack_is_empty(&CG(loop_var_stack))) {
623			zend_loop_var *loop_var = zend_stack_top(&CG(loop_var_stack));
624			zend_loop_var *base = zend_stack_base(&CG(loop_var_stack));
625			int check_opcodes = 0;
626
627			for (; loop_var >= base; loop_var--) {
628				if (loop_var->opcode == ZEND_RETURN) {
629					/* Stack separator */
630					break;
631				} else if (loop_var->opcode == ZEND_FREE ||
632			           loop_var->opcode == ZEND_FE_FREE) {
633					if (loop_var->u.live_range_offset >= n) {
634						loop_var->u.live_range_offset++;
635						check_opcodes = 1;
636					} else {
637						break;
638					}
639				}
640			}
641
642			/* update previously generated FREE/FE_FREE opcodes */
643			if (check_opcodes) {
644				zend_op *opline = op_array->opcodes + op_array->live_range[n+1].start;
645				zend_op *end = op_array->opcodes + op_array->last;
646
647				while (opline < end) {
648					if ((opline->opcode == ZEND_FREE ||
649					     opline->opcode == ZEND_FE_FREE) &&
650					    (opline->extended_value & ZEND_FREE_ON_RETURN) &&
651					    opline->op2.num >= n) {
652						opline->op2.num++;
653					}
654					opline++;
655				}
656			}
657		}
658		return n;
659	}
660}
661/* }}} */
662
663static void zend_end_live_range(zend_op_array *op_array, uint32_t offset, uint32_t end, uint32_t kind, uint32_t var) /* {{{ */
664{
665	zend_live_range *range = op_array->live_range + offset;
666
667	if (range->start == end && offset == op_array->last_live_range - 1) {
668		op_array->last_live_range--;
669	} else {
670		range->end = end;
671		range->var = (var * sizeof(zval)) | kind;
672	}
673}
674/* }}} */
675
676static inline void zend_begin_loop(zend_uchar free_opcode, const znode *loop_var) /* {{{ */
677{
678	zend_brk_cont_element *brk_cont_element;
679	int parent = CG(context).current_brk_cont;
680	zend_loop_var info = {0};
681
682	CG(context).current_brk_cont = CG(context).last_brk_cont;
683	brk_cont_element = get_next_brk_cont_element();
684	brk_cont_element->parent = parent;
685
686	if (loop_var && (loop_var->op_type & (IS_VAR|IS_TMP_VAR))) {
687		uint32_t start = get_next_op_number(CG(active_op_array));
688
689		info.opcode = free_opcode;
690		info.var_type = loop_var->op_type;
691		info.var_num = loop_var->u.op.var;
692		info.u.live_range_offset = zend_start_live_range(CG(active_op_array), start);
693		brk_cont_element->start = start;
694	} else {
695		info.opcode = ZEND_NOP;
696		/* The start field is used to free temporary variables in case of exceptions.
697		 * We won't try to free something of we don't have loop variable.  */
698		brk_cont_element->start = -1;
699	}
700
701	zend_stack_push(&CG(loop_var_stack), &info);
702}
703/* }}} */
704
705static inline void zend_end_loop(int cont_addr, const znode *var_node) /* {{{ */
706{
707	uint32_t end = get_next_op_number(CG(active_op_array));
708	zend_brk_cont_element *brk_cont_element
709		= &CG(context).brk_cont_array[CG(context).current_brk_cont];
710	brk_cont_element->cont = cont_addr;
711	brk_cont_element->brk = end;
712	CG(context).current_brk_cont = brk_cont_element->parent;
713
714	if (brk_cont_element->start != -1) {
715		zend_loop_var *loop_var = zend_stack_top(&CG(loop_var_stack));
716		zend_end_live_range(CG(active_op_array), loop_var->u.live_range_offset, end,
717			loop_var->opcode == ZEND_FE_FREE ? ZEND_LIVE_LOOP : ZEND_LIVE_TMPVAR,
718			var_node->u.op.var);
719	}
720
721	zend_stack_del_top(&CG(loop_var_stack));
722}
723/* }}} */
724
725void zend_do_free(znode *op1) /* {{{ */
726{
727	if (op1->op_type==IS_TMP_VAR) {
728		zend_emit_op(NULL, ZEND_FREE, op1, NULL);
729	} else if (op1->op_type==IS_VAR) {
730		zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
731
732		while (opline->opcode == ZEND_END_SILENCE || opline->opcode == ZEND_EXT_FCALL_END || opline->opcode == ZEND_OP_DATA) {
733			opline--;
734		}
735		if (opline->result_type == IS_VAR
736			&& opline->result.var == op1->u.op.var) {
737			if (opline->opcode == ZEND_FETCH_R ||
738			    opline->opcode == ZEND_FETCH_DIM_R ||
739			    opline->opcode == ZEND_FETCH_OBJ_R ||
740			    opline->opcode == ZEND_FETCH_STATIC_PROP_R) {
741				/* It's very rare and useless case. It's better to use
742				   additional FREE opcode and simplify the FETCH handlers
743				   their selves */
744				zend_emit_op(NULL, ZEND_FREE, op1, NULL);
745			} else {
746				opline->result_type |= EXT_TYPE_UNUSED;
747			}
748		} else {
749			while (opline >= CG(active_op_array)->opcodes) {
750				if (opline->opcode == ZEND_FETCH_LIST &&
751				    opline->op1_type == IS_VAR &&
752				    opline->op1.var == op1->u.op.var) {
753					zend_emit_op(NULL, ZEND_FREE, op1, NULL);
754					return;
755				}
756				if (opline->result_type==IS_VAR
757					&& opline->result.var == op1->u.op.var) {
758					if (opline->opcode == ZEND_NEW) {
759						opline->result_type |= EXT_TYPE_UNUSED;
760						opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
761						while (opline->opcode != ZEND_DO_FCALL || opline->op1.num != ZEND_CALL_CTOR) {
762							opline--;
763						}
764						opline->op1.num |= ZEND_CALL_CTOR_RESULT_UNUSED;
765					}
766					break;
767				}
768				opline--;
769			}
770		}
771	} else if (op1->op_type == IS_CONST) {
772		/* Destroy value without using GC: When opcache moves arrays into SHM it will
773		 * free the zend_array structure, so references to it from outside the op array
774		 * become invalid. GC would cause such a reference in the root buffer. */
775		zval_ptr_dtor_nogc(&op1->u.constant);
776	}
777}
778/* }}} */
779
780uint32_t zend_add_class_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */
781{
782	uint32_t new_flags = flags | new_flag;
783	if ((flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) && (new_flag & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
784		zend_error_noreturn(E_COMPILE_ERROR, "Multiple abstract modifiers are not allowed");
785	}
786	if ((flags & ZEND_ACC_FINAL) && (new_flag & ZEND_ACC_FINAL)) {
787		zend_error_noreturn(E_COMPILE_ERROR, "Multiple final modifiers are not allowed");
788	}
789	if ((new_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) && (new_flags & ZEND_ACC_FINAL)) {
790		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use the final modifier on an abstract class");
791	}
792	return new_flags;
793}
794/* }}} */
795
796uint32_t zend_add_member_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */
797{
798	uint32_t new_flags = flags | new_flag;
799	if ((flags & ZEND_ACC_PPP_MASK) && (new_flag & ZEND_ACC_PPP_MASK)) {
800		zend_error_noreturn(E_COMPILE_ERROR, "Multiple access type modifiers are not allowed");
801	}
802	if ((flags & ZEND_ACC_ABSTRACT) && (new_flag & ZEND_ACC_ABSTRACT)) {
803		zend_error_noreturn(E_COMPILE_ERROR, "Multiple abstract modifiers are not allowed");
804	}
805	if ((flags & ZEND_ACC_STATIC) && (new_flag & ZEND_ACC_STATIC)) {
806		zend_error_noreturn(E_COMPILE_ERROR, "Multiple static modifiers are not allowed");
807	}
808	if ((flags & ZEND_ACC_FINAL) && (new_flag & ZEND_ACC_FINAL)) {
809		zend_error_noreturn(E_COMPILE_ERROR, "Multiple final modifiers are not allowed");
810	}
811	if ((new_flags & ZEND_ACC_ABSTRACT) && (new_flags & ZEND_ACC_FINAL)) {
812		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use the final modifier on an abstract class member");
813	}
814	return new_flags;
815}
816/* }}} */
817
818zend_string *zend_concat3(char *str1, size_t str1_len, char *str2, size_t str2_len, char *str3, size_t str3_len) /* {{{ */
819{
820	size_t len = str1_len + str2_len + str3_len;
821	zend_string *res = zend_string_alloc(len, 0);
822
823	memcpy(ZSTR_VAL(res), str1, str1_len);
824	memcpy(ZSTR_VAL(res) + str1_len, str2, str2_len);
825	memcpy(ZSTR_VAL(res) + str1_len + str2_len, str3, str3_len);
826	ZSTR_VAL(res)[len] = '\0';
827
828	return res;
829}
830
831zend_string *zend_concat_names(char *name1, size_t name1_len, char *name2, size_t name2_len) {
832	return zend_concat3(name1, name1_len, "\\", 1, name2, name2_len);
833}
834
835zend_string *zend_prefix_with_ns(zend_string *name) {
836	if (FC(current_namespace)) {
837		zend_string *ns = FC(current_namespace);
838		return zend_concat_names(ZSTR_VAL(ns), ZSTR_LEN(ns), ZSTR_VAL(name), ZSTR_LEN(name));
839	} else {
840		return zend_string_copy(name);
841	}
842}
843
844void *zend_hash_find_ptr_lc(HashTable *ht, const char *str, size_t len) {
845	void *result;
846	zend_string *lcname;
847	ALLOCA_FLAG(use_heap);
848
849	ZSTR_ALLOCA_ALLOC(lcname, len, use_heap);
850	zend_str_tolower_copy(ZSTR_VAL(lcname), str, len);
851	result = zend_hash_find_ptr(ht, lcname);
852	ZSTR_ALLOCA_FREE(lcname, use_heap);
853
854	return result;
855}
856
857zend_string *zend_resolve_non_class_name(
858	zend_string *name, uint32_t type, zend_bool *is_fully_qualified,
859	zend_bool case_sensitive, HashTable *current_import_sub
860) {
861	char *compound;
862	*is_fully_qualified = 0;
863
864	if (ZSTR_VAL(name)[0] == '\\') {
865		/* Remove \ prefix (only relevant if this is a string rather than a label) */
866		return zend_string_init(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1, 0);
867	}
868
869	if (type == ZEND_NAME_FQ) {
870		*is_fully_qualified = 1;
871		return zend_string_copy(name);
872	}
873
874	if (type == ZEND_NAME_RELATIVE) {
875		*is_fully_qualified = 1;
876		return zend_prefix_with_ns(name);
877	}
878
879	if (current_import_sub) {
880		/* If an unqualified name is a function/const alias, replace it. */
881		zend_string *import_name;
882		if (case_sensitive) {
883			import_name = zend_hash_find_ptr(current_import_sub, name);
884		} else {
885			import_name = zend_hash_find_ptr_lc(current_import_sub, ZSTR_VAL(name), ZSTR_LEN(name));
886		}
887
888		if (import_name) {
889			*is_fully_qualified = 1;
890			return zend_string_copy(import_name);
891		}
892	}
893
894	compound = memchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
895	if (compound) {
896		*is_fully_qualified = 1;
897	}
898
899	if (compound && FC(imports)) {
900		/* If the first part of a qualified name is an alias, substitute it. */
901		size_t len = compound - ZSTR_VAL(name);
902		zend_string *import_name = zend_hash_find_ptr_lc(FC(imports), ZSTR_VAL(name), len);
903
904		if (import_name) {
905			return zend_concat_names(
906				ZSTR_VAL(import_name), ZSTR_LEN(import_name), ZSTR_VAL(name) + len + 1, ZSTR_LEN(name) - len - 1);
907		}
908	}
909
910	return zend_prefix_with_ns(name);
911}
912/* }}} */
913
914zend_string *zend_resolve_function_name(zend_string *name, uint32_t type, zend_bool *is_fully_qualified) /* {{{ */
915{
916	return zend_resolve_non_class_name(
917		name, type, is_fully_qualified, 0, FC(imports_function));
918}
919/* }}} */
920
921zend_string *zend_resolve_const_name(zend_string *name, uint32_t type, zend_bool *is_fully_qualified) /* {{{ */ {
922	return zend_resolve_non_class_name(
923		name, type, is_fully_qualified, 1, FC(imports_const));
924}
925/* }}} */
926
927zend_string *zend_resolve_class_name(zend_string *name, uint32_t type) /* {{{ */
928{
929	char *compound;
930
931	if (type == ZEND_NAME_RELATIVE) {
932		return zend_prefix_with_ns(name);
933	}
934
935	if (type == ZEND_NAME_FQ || ZSTR_VAL(name)[0] == '\\') {
936		/* Remove \ prefix (only relevant if this is a string rather than a label) */
937		if (ZSTR_VAL(name)[0] == '\\') {
938			name = zend_string_init(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1, 0);
939		} else {
940			zend_string_addref(name);
941		}
942		/* Ensure that \self, \parent and \static are not used */
943		if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
944			zend_error_noreturn(E_COMPILE_ERROR, "'\\%s' is an invalid class name", ZSTR_VAL(name));
945		}
946		return name;
947	}
948
949	if (FC(imports)) {
950		compound = memchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
951		if (compound) {
952			/* If the first part of a qualified name is an alias, substitute it. */
953			size_t len = compound - ZSTR_VAL(name);
954			zend_string *import_name =
955				zend_hash_find_ptr_lc(FC(imports), ZSTR_VAL(name), len);
956
957			if (import_name) {
958				return zend_concat_names(
959					ZSTR_VAL(import_name), ZSTR_LEN(import_name), ZSTR_VAL(name) + len + 1, ZSTR_LEN(name) - len - 1);
960			}
961		} else {
962			/* If an unqualified name is an alias, replace it. */
963			zend_string *import_name
964				= zend_hash_find_ptr_lc(FC(imports), ZSTR_VAL(name), ZSTR_LEN(name));
965
966			if (import_name) {
967				return zend_string_copy(import_name);
968			}
969		}
970	}
971
972	/* If not fully qualified and not an alias, prepend the current namespace */
973	return zend_prefix_with_ns(name);
974}
975/* }}} */
976
977zend_string *zend_resolve_class_name_ast(zend_ast *ast) /* {{{ */
978{
979	zval *class_name = zend_ast_get_zval(ast);
980	if (Z_TYPE_P(class_name) != IS_STRING) {
981		zend_error_noreturn(E_COMPILE_ERROR, "Illegal class name");
982	}
983	return zend_resolve_class_name(Z_STR_P(class_name), ast->attr);
984}
985/* }}} */
986
987static void label_ptr_dtor(zval *zv) /* {{{ */
988{
989	efree_size(Z_PTR_P(zv), sizeof(zend_label));
990}
991/* }}} */
992
993static void str_dtor(zval *zv)  /* {{{ */ {
994	zend_string_release(Z_STR_P(zv));
995}
996/* }}} */
997
998static zend_bool zend_is_call(zend_ast *ast);
999
1000static uint32_t zend_add_try_element(uint32_t try_op) /* {{{ */
1001{
1002	zend_op_array *op_array = CG(active_op_array);
1003	uint32_t try_catch_offset = op_array->last_try_catch++;
1004	zend_try_catch_element *elem;
1005
1006	op_array->try_catch_array = safe_erealloc(
1007		op_array->try_catch_array, sizeof(zend_try_catch_element), op_array->last_try_catch, 0);
1008
1009	elem = &op_array->try_catch_array[try_catch_offset];
1010	elem->try_op = try_op;
1011	elem->catch_op = 0;
1012	elem->finally_op = 0;
1013	elem->finally_end = 0;
1014
1015	return try_catch_offset;
1016}
1017/* }}} */
1018
1019ZEND_API void function_add_ref(zend_function *function) /* {{{ */
1020{
1021	if (function->type == ZEND_USER_FUNCTION) {
1022		zend_op_array *op_array = &function->op_array;
1023
1024		if (op_array->refcount) {
1025			(*op_array->refcount)++;
1026		}
1027		if (op_array->static_variables) {
1028			if (!(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
1029				GC_REFCOUNT(op_array->static_variables)++;
1030			}
1031		}
1032		op_array->run_time_cache = NULL;
1033	} else if (function->type == ZEND_INTERNAL_FUNCTION) {
1034		if (function->common.function_name) {
1035			zend_string_addref(function->common.function_name);
1036		}
1037	}
1038}
1039/* }}} */
1040
1041ZEND_API int do_bind_function(const zend_op_array *op_array, const zend_op *opline, HashTable *function_table, zend_bool compile_time) /* {{{ */
1042{
1043	zend_function *function, *new_function;
1044	zval *lcname, *rtd_key;
1045
1046	if (compile_time) {
1047		lcname = CT_CONSTANT_EX(op_array, opline->op1.constant);
1048		rtd_key = lcname + 1;
1049	} else {
1050		lcname = RT_CONSTANT(op_array, opline->op1);
1051		rtd_key = lcname + 1;
1052	}
1053
1054	function = zend_hash_find_ptr(function_table, Z_STR_P(rtd_key));
1055	new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
1056	memcpy(new_function, function, sizeof(zend_op_array));
1057	if (zend_hash_add_ptr(function_table, Z_STR_P(lcname), new_function) == NULL) {
1058		int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR;
1059		zend_function *old_function;
1060
1061		if ((old_function = zend_hash_find_ptr(function_table, Z_STR_P(lcname))) != NULL
1062			&& old_function->type == ZEND_USER_FUNCTION
1063			&& old_function->op_array.last > 0) {
1064			zend_error_noreturn(error_level, "Cannot redeclare %s() (previously declared in %s:%d)",
1065						ZSTR_VAL(function->common.function_name),
1066						ZSTR_VAL(old_function->op_array.filename),
1067						old_function->op_array.opcodes[0].lineno);
1068		} else {
1069			zend_error_noreturn(error_level, "Cannot redeclare %s()", ZSTR_VAL(function->common.function_name));
1070		}
1071		return FAILURE;
1072	} else {
1073		if (function->op_array.refcount) {
1074			(*function->op_array.refcount)++;
1075		}
1076		function->op_array.static_variables = NULL; /* NULL out the unbound function */
1077		return SUCCESS;
1078	}
1079}
1080/* }}} */
1081
1082ZEND_API zend_class_entry *do_bind_class(const zend_op_array* op_array, const zend_op *opline, HashTable *class_table, zend_bool compile_time) /* {{{ */
1083{
1084	zend_class_entry *ce;
1085	zval *lcname, *rtd_key;
1086
1087	if (compile_time) {
1088		lcname = CT_CONSTANT_EX(op_array, opline->op1.constant);
1089		rtd_key = lcname + 1;
1090	} else {
1091		lcname = RT_CONSTANT(op_array, opline->op1);
1092		rtd_key = lcname + 1;
1093	}
1094	if ((ce = zend_hash_find_ptr(class_table, Z_STR_P(rtd_key))) == NULL) {
1095		zend_error_noreturn(E_COMPILE_ERROR, "Internal Zend error - Missing class information for %s", Z_STRVAL_P(rtd_key));
1096		return NULL;
1097	}
1098	ce->refcount++;
1099	if (zend_hash_add_ptr(class_table, Z_STR_P(lcname), ce) == NULL) {
1100		ce->refcount--;
1101		if (!compile_time) {
1102			/* If we're in compile time, in practice, it's quite possible
1103			 * that we'll never reach this class declaration at runtime,
1104			 * so we shut up about it.  This allows the if (!defined('FOO')) { return; }
1105			 * approach to work.
1106			 */
1107			zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
1108		}
1109		return NULL;
1110	} else {
1111		if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLEMENT_INTERFACES|ZEND_ACC_IMPLEMENT_TRAITS))) {
1112			zend_verify_abstract_class(ce);
1113		}
1114		return ce;
1115	}
1116}
1117/* }}} */
1118
1119ZEND_API zend_class_entry *do_bind_inherited_class(const zend_op_array *op_array, const zend_op *opline, HashTable *class_table, zend_class_entry *parent_ce, zend_bool compile_time) /* {{{ */
1120{
1121	zend_class_entry *ce;
1122	zval *lcname, *rtd_key;
1123
1124	if (compile_time) {
1125		lcname = CT_CONSTANT_EX(op_array, opline->op1.constant);
1126		rtd_key = lcname + 1;
1127	} else {
1128		lcname = RT_CONSTANT(op_array, opline->op1);
1129		rtd_key = lcname + 1;
1130	}
1131
1132	ce = zend_hash_find_ptr(class_table, Z_STR_P(rtd_key));
1133
1134	if (!ce) {
1135		if (!compile_time) {
1136			/* If we're in compile time, in practice, it's quite possible
1137			 * that we'll never reach this class declaration at runtime,
1138			 * so we shut up about it.  This allows the if (!defined('FOO')) { return; }
1139			 * approach to work.
1140			 */
1141			zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare  %s, because the name is already in use", zend_get_object_type(Z_OBJCE_P(lcname)), Z_STRVAL_P(lcname));
1142		}
1143		return NULL;
1144	}
1145
1146	if (zend_hash_exists(class_table, Z_STR_P(lcname))) {
1147		zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
1148	}
1149
1150	zend_do_inheritance(ce, parent_ce);
1151
1152	ce->refcount++;
1153
1154	/* Register the derived class */
1155	if (zend_hash_add_ptr(class_table, Z_STR_P(lcname), ce) == NULL) {
1156		zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
1157	}
1158	return ce;
1159}
1160/* }}} */
1161
1162void zend_do_early_binding(void) /* {{{ */
1163{
1164	zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
1165	HashTable *table;
1166
1167	while (opline->opcode == ZEND_TICKS && opline > CG(active_op_array)->opcodes) {
1168		opline--;
1169	}
1170
1171	switch (opline->opcode) {
1172		case ZEND_DECLARE_FUNCTION:
1173			if (do_bind_function(CG(active_op_array), opline, CG(function_table), 1) == FAILURE) {
1174				return;
1175			}
1176			table = CG(function_table);
1177			break;
1178		case ZEND_DECLARE_CLASS:
1179			if (do_bind_class(CG(active_op_array), opline, CG(class_table), 1) == NULL) {
1180				return;
1181			}
1182			table = CG(class_table);
1183			break;
1184		case ZEND_DECLARE_INHERITED_CLASS:
1185			{
1186				zend_op *fetch_class_opline = opline-1;
1187				zval *parent_name;
1188				zend_class_entry *ce;
1189
1190				parent_name = CT_CONSTANT(fetch_class_opline->op2);
1191				if (((ce = zend_lookup_class_ex(Z_STR_P(parent_name), parent_name + 1, 0)) == NULL) ||
1192				    ((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES) &&
1193				     (ce->type == ZEND_INTERNAL_CLASS))) {
1194					if (CG(compiler_options) & ZEND_COMPILE_DELAYED_BINDING) {
1195						uint32_t *opline_num = &CG(active_op_array)->early_binding;
1196
1197						while (*opline_num != (uint32_t)-1) {
1198							opline_num = &CG(active_op_array)->opcodes[*opline_num].result.opline_num;
1199						}
1200						*opline_num = opline - CG(active_op_array)->opcodes;
1201						opline->opcode = ZEND_DECLARE_INHERITED_CLASS_DELAYED;
1202						opline->result_type = IS_UNUSED;
1203						opline->result.opline_num = -1;
1204					}
1205					return;
1206				}
1207				if (do_bind_inherited_class(CG(active_op_array), opline, CG(class_table), ce, 1) == NULL) {
1208					return;
1209				}
1210				/* clear unnecessary ZEND_FETCH_CLASS opcode */
1211				zend_del_literal(CG(active_op_array), fetch_class_opline->op2.constant);
1212				MAKE_NOP(fetch_class_opline);
1213
1214				table = CG(class_table);
1215				break;
1216			}
1217		case ZEND_VERIFY_ABSTRACT_CLASS:
1218		case ZEND_ADD_INTERFACE:
1219		case ZEND_ADD_TRAIT:
1220		case ZEND_BIND_TRAITS:
1221			/* We currently don't early-bind classes that implement interfaces */
1222			/* Classes with traits are handled exactly the same, no early-bind here */
1223			return;
1224		default:
1225			zend_error_noreturn(E_COMPILE_ERROR, "Invalid binding type");
1226			return;
1227	}
1228
1229	zend_hash_del(table, Z_STR_P(CT_CONSTANT(opline->op1)+1));
1230	zend_del_literal(CG(active_op_array), opline->op1.constant+1);
1231	zend_del_literal(CG(active_op_array), opline->op1.constant);
1232	MAKE_NOP(opline);
1233}
1234/* }}} */
1235
1236static void zend_mark_function_as_generator() /* {{{ */
1237{
1238	if (!CG(active_op_array)->function_name) {
1239		zend_error_noreturn(E_COMPILE_ERROR,
1240			"The \"yield\" expression can only be used inside a function");
1241	}
1242
1243	if (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
1244		const char *msg = "Generators may only declare a return type of Generator, Iterator or Traversable, %s is not permitted";
1245		zend_arg_info return_info = CG(active_op_array)->arg_info[-1];
1246
1247		if (!return_info.class_name) {
1248			zend_error_noreturn(E_COMPILE_ERROR, msg, zend_get_type_by_const(return_info.type_hint));
1249		}
1250
1251		if (!zend_string_equals_literal_ci(return_info.class_name, "Traversable")
1252			&& !zend_string_equals_literal_ci(return_info.class_name, "Iterator")
1253			&& !zend_string_equals_literal_ci(return_info.class_name, "Generator")) {
1254			zend_error_noreturn(E_COMPILE_ERROR, msg, ZSTR_VAL(return_info.class_name));
1255		}
1256	}
1257
1258	CG(active_op_array)->fn_flags |= ZEND_ACC_GENERATOR;
1259}
1260/* }}} */
1261
1262ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array) /* {{{ */
1263{
1264	if (op_array->early_binding != (uint32_t)-1) {
1265		zend_bool orig_in_compilation = CG(in_compilation);
1266		uint32_t opline_num = op_array->early_binding;
1267		zend_class_entry *ce;
1268
1269		CG(in_compilation) = 1;
1270		while (opline_num != (uint32_t)-1) {
1271			zval *parent_name = RT_CONSTANT(op_array, op_array->opcodes[opline_num-1].op2);
1272			if ((ce = zend_lookup_class_ex(Z_STR_P(parent_name), parent_name + 1, 0)) != NULL) {
1273				do_bind_inherited_class(op_array, &op_array->opcodes[opline_num], EG(class_table), ce, 0);
1274			}
1275			opline_num = op_array->opcodes[opline_num].result.opline_num;
1276		}
1277		CG(in_compilation) = orig_in_compilation;
1278	}
1279}
1280/* }}} */
1281
1282ZEND_API zend_string *zend_mangle_property_name(const char *src1, size_t src1_length, const char *src2, size_t src2_length, int internal) /* {{{ */
1283{
1284	size_t prop_name_length = 1 + src1_length + 1 + src2_length;
1285	zend_string *prop_name = zend_string_alloc(prop_name_length, internal);
1286
1287	ZSTR_VAL(prop_name)[0] = '\0';
1288	memcpy(ZSTR_VAL(prop_name) + 1, src1, src1_length+1);
1289	memcpy(ZSTR_VAL(prop_name) + 1 + src1_length + 1, src2, src2_length+1);
1290	return prop_name;
1291}
1292/* }}} */
1293
1294static zend_always_inline size_t zend_strnlen(const char* s, size_t maxlen) /* {{{ */
1295{
1296	size_t len = 0;
1297	while (*s++ && maxlen--) len++;
1298	return len;
1299}
1300/* }}} */
1301
1302ZEND_API int zend_unmangle_property_name_ex(const zend_string *name, const char **class_name, const char **prop_name, size_t *prop_len) /* {{{ */
1303{
1304	size_t class_name_len;
1305	size_t anonclass_src_len;
1306
1307	*class_name = NULL;
1308
1309	if (ZSTR_VAL(name)[0] != '\0') {
1310		*prop_name = ZSTR_VAL(name);
1311		if (prop_len) {
1312			*prop_len = ZSTR_LEN(name);
1313		}
1314		return SUCCESS;
1315	}
1316	if (ZSTR_LEN(name) < 3 || ZSTR_VAL(name)[1] == '\0') {
1317		zend_error(E_NOTICE, "Illegal member variable name");
1318		*prop_name = ZSTR_VAL(name);
1319		if (prop_len) {
1320			*prop_len = ZSTR_LEN(name);
1321		}
1322		return FAILURE;
1323	}
1324
1325	class_name_len = zend_strnlen(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 2);
1326	if (class_name_len >= ZSTR_LEN(name) - 2 || ZSTR_VAL(name)[class_name_len + 1] != '\0') {
1327		zend_error(E_NOTICE, "Corrupt member variable name");
1328		*prop_name = ZSTR_VAL(name);
1329		if (prop_len) {
1330			*prop_len = ZSTR_LEN(name);
1331		}
1332		return FAILURE;
1333	}
1334
1335	*class_name = ZSTR_VAL(name) + 1;
1336	anonclass_src_len = zend_strnlen(*class_name + class_name_len + 1, ZSTR_LEN(name) - class_name_len - 2);
1337	if (class_name_len + anonclass_src_len + 2 != ZSTR_LEN(name)) {
1338		class_name_len += anonclass_src_len + 1;
1339	}
1340	*prop_name = ZSTR_VAL(name) + class_name_len + 2;
1341	if (prop_len) {
1342		*prop_len = ZSTR_LEN(name) - class_name_len - 2;
1343	}
1344	return SUCCESS;
1345}
1346/* }}} */
1347
1348static zend_constant *zend_lookup_reserved_const(const char *name, size_t len) /* {{{ */
1349{
1350	zend_constant *c = zend_hash_find_ptr_lc(EG(zend_constants), name, len);
1351	if (c && !(c->flags & CONST_CS) && (c->flags & CONST_CT_SUBST)) {
1352		return c;
1353	}
1354	return NULL;
1355}
1356/* }}} */
1357
1358static zend_bool zend_try_ct_eval_const(zval *zv, zend_string *name, zend_bool is_fully_qualified) /* {{{ */
1359{
1360	zend_constant *c;
1361
1362	/* Substitute case-sensitive (or lowercase) constants */
1363	c = zend_hash_find_ptr(EG(zend_constants), name);
1364	if (c && (
1365	      ((c->flags & CONST_PERSISTENT) && !(CG(compiler_options) & ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION))
1366	   || (Z_TYPE(c->value) < IS_OBJECT && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION))
1367	)) {
1368		ZVAL_DUP(zv, &c->value);
1369		return 1;
1370	}
1371
1372	{
1373		/* Substitute true, false and null (including unqualified usage in namespaces) */
1374		const char *lookup_name = ZSTR_VAL(name);
1375		size_t lookup_len = ZSTR_LEN(name);
1376
1377		if (!is_fully_qualified) {
1378			zend_get_unqualified_name(name, &lookup_name, &lookup_len);
1379		}
1380
1381		c = zend_lookup_reserved_const(lookup_name, lookup_len);
1382		if (c) {
1383			ZVAL_DUP(zv, &c->value);
1384			return 1;
1385		}
1386	}
1387
1388	return 0;
1389}
1390/* }}} */
1391
1392static inline zend_bool zend_is_scope_known() /* {{{ */
1393{
1394	if (CG(active_op_array)->fn_flags & ZEND_ACC_CLOSURE) {
1395		/* Closures can be rebound to a different scope */
1396		return 0;
1397	}
1398
1399	if (!CG(active_class_entry)) {
1400		/* The scope is known if we're in a free function (no scope), but not if we're in
1401		 * a file/eval (which inherits including/eval'ing scope). */
1402		return CG(active_op_array)->function_name != NULL;
1403	}
1404
1405	/* For traits self etc refers to the using class, not the trait itself */
1406	return (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) == 0;
1407}
1408/* }}} */
1409
1410static inline zend_bool class_name_refers_to_active_ce(zend_string *class_name, uint32_t fetch_type) /* {{{ */
1411{
1412	if (!CG(active_class_entry)) {
1413		return 0;
1414	}
1415	if (fetch_type == ZEND_FETCH_CLASS_SELF && zend_is_scope_known()) {
1416		return 1;
1417	}
1418	return fetch_type == ZEND_FETCH_CLASS_DEFAULT
1419		&& zend_string_equals_ci(class_name, CG(active_class_entry)->name);
1420}
1421/* }}} */
1422
1423uint32_t zend_get_class_fetch_type(zend_string *name) /* {{{ */
1424{
1425	if (zend_string_equals_literal_ci(name, "self")) {
1426		return ZEND_FETCH_CLASS_SELF;
1427	} else if (zend_string_equals_literal_ci(name, "parent")) {
1428		return ZEND_FETCH_CLASS_PARENT;
1429	} else if (zend_string_equals_literal_ci(name, "static")) {
1430		return ZEND_FETCH_CLASS_STATIC;
1431	} else {
1432		return ZEND_FETCH_CLASS_DEFAULT;
1433	}
1434}
1435/* }}} */
1436
1437static uint32_t zend_get_class_fetch_type_ast(zend_ast *name_ast) /* {{{ */
1438{
1439	/* Fully qualified names are always default refs */
1440	if (name_ast->attr == ZEND_NAME_FQ) {
1441		return ZEND_FETCH_CLASS_DEFAULT;
1442	}
1443
1444	return zend_get_class_fetch_type(zend_ast_get_str(name_ast));
1445}
1446/* }}} */
1447
1448static void zend_ensure_valid_class_fetch_type(uint32_t fetch_type) /* {{{ */
1449{
1450	if (fetch_type != ZEND_FETCH_CLASS_DEFAULT && !CG(active_class_entry) && zend_is_scope_known()) {
1451		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"%s\" when no class scope is active",
1452			fetch_type == ZEND_FETCH_CLASS_SELF ? "self" :
1453			fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static");
1454	}
1455}
1456/* }}} */
1457
1458static zend_bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_ast *class_ast, zend_ast *name_ast, zend_bool constant) /* {{{ */
1459{
1460	uint32_t fetch_type;
1461
1462	if (name_ast->kind != ZEND_AST_ZVAL) {
1463		return 0;
1464	}
1465
1466	if (!zend_string_equals_literal_ci(zend_ast_get_str(name_ast), "class")) {
1467		return 0;
1468	}
1469
1470	if (class_ast->kind != ZEND_AST_ZVAL) {
1471		zend_error_noreturn(E_COMPILE_ERROR,
1472			"Dynamic class names are not allowed in compile-time ::class fetch");
1473	}
1474
1475	fetch_type = zend_get_class_fetch_type(zend_ast_get_str(class_ast));
1476	zend_ensure_valid_class_fetch_type(fetch_type);
1477
1478	switch (fetch_type) {
1479		case ZEND_FETCH_CLASS_SELF:
1480			if (constant || (CG(active_class_entry) && zend_is_scope_known())) {
1481				ZVAL_STR_COPY(zv, CG(active_class_entry)->name);
1482			} else {
1483				ZVAL_NULL(zv);
1484			}
1485			return 1;
1486		case ZEND_FETCH_CLASS_STATIC:
1487		case ZEND_FETCH_CLASS_PARENT:
1488			if (constant) {
1489				zend_error_noreturn(E_COMPILE_ERROR,
1490					"%s::class cannot be used for compile-time class name resolution",
1491					fetch_type == ZEND_FETCH_CLASS_STATIC ? "static" : "parent"
1492				);
1493			} else {
1494				ZVAL_NULL(zv);
1495			}
1496			return 1;
1497		case ZEND_FETCH_CLASS_DEFAULT:
1498			ZVAL_STR(zv, zend_resolve_class_name_ast(class_ast));
1499			return 1;
1500		EMPTY_SWITCH_DEFAULT_CASE()
1501	}
1502}
1503/* }}} */
1504
1505static zend_bool zend_try_ct_eval_class_const(zval *zv, zend_string *class_name, zend_string *name) /* {{{ */
1506{
1507	uint32_t fetch_type = zend_get_class_fetch_type(class_name);
1508	zend_class_constant *cc;
1509	zval *c;
1510
1511	if (class_name_refers_to_active_ce(class_name, fetch_type)) {
1512		cc = zend_hash_find_ptr(&CG(active_class_entry)->constants_table, name);
1513	} else if (fetch_type == ZEND_FETCH_CLASS_DEFAULT && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) {
1514		zend_class_entry *ce = zend_hash_find_ptr_lc(CG(class_table), ZSTR_VAL(class_name), ZSTR_LEN(class_name));
1515		if (ce) {
1516			cc = zend_hash_find_ptr(&ce->constants_table, name);
1517		} else {
1518			return 0;
1519		}
1520	} else {
1521		return 0;
1522	}
1523
1524	if (CG(compiler_options) & ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION) {
1525		return 0;
1526	}
1527
1528	if (!cc || !zend_verify_const_access(cc, CG(active_class_entry))) {
1529		return 0;
1530	}
1531
1532	c = &cc->value;
1533
1534	/* Substitute case-sensitive (or lowercase) persistent class constants */
1535	if (Z_TYPE_P(c) < IS_OBJECT) {
1536		ZVAL_DUP(zv, c);
1537		return 1;
1538	}
1539
1540	return 0;
1541}
1542/* }}} */
1543
1544static void zend_add_to_list(void *result, void *item) /* {{{ */
1545{
1546	void** list = *(void**)result;
1547	size_t n = 0;
1548
1549	if (list) {
1550		while (list[n]) {
1551			n++;
1552		}
1553	}
1554
1555	list = erealloc(list, sizeof(void*) * (n+2));
1556
1557	list[n]   = item;
1558	list[n+1] = NULL;
1559
1560	*(void**)result = list;
1561}
1562/* }}} */
1563
1564void zend_do_extended_info(void) /* {{{ */
1565{
1566	zend_op *opline;
1567
1568	if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
1569		return;
1570	}
1571
1572	opline = get_next_op(CG(active_op_array));
1573
1574	opline->opcode = ZEND_EXT_STMT;
1575	SET_UNUSED(opline->op1);
1576	SET_UNUSED(opline->op2);
1577}
1578/* }}} */
1579
1580void zend_do_extended_fcall_begin(void) /* {{{ */
1581{
1582	zend_op *opline;
1583
1584	if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
1585		return;
1586	}
1587
1588	opline = get_next_op(CG(active_op_array));
1589
1590	opline->opcode = ZEND_EXT_FCALL_BEGIN;
1591	SET_UNUSED(opline->op1);
1592	SET_UNUSED(opline->op2);
1593}
1594/* }}} */
1595
1596void zend_do_extended_fcall_end(void) /* {{{ */
1597{
1598	zend_op *opline;
1599
1600	if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
1601		return;
1602	}
1603
1604	opline = get_next_op(CG(active_op_array));
1605
1606	opline->opcode = ZEND_EXT_FCALL_END;
1607	SET_UNUSED(opline->op1);
1608	SET_UNUSED(opline->op2);
1609}
1610/* }}} */
1611
1612zend_bool zend_is_auto_global_str(char *name, size_t len) /* {{{ */ {
1613	zend_auto_global *auto_global;
1614
1615	if ((auto_global = zend_hash_str_find_ptr(CG(auto_globals), name, len)) != NULL) {
1616		if (auto_global->armed) {
1617			auto_global->armed = auto_global->auto_global_callback(auto_global->name);
1618		}
1619		return 1;
1620	}
1621	return 0;
1622}
1623/* }}} */
1624
1625zend_bool zend_is_auto_global(zend_string *name) /* {{{ */
1626{
1627	zend_auto_global *auto_global;
1628
1629	if ((auto_global = zend_hash_find_ptr(CG(auto_globals), name)) != NULL) {
1630		if (auto_global->armed) {
1631			auto_global->armed = auto_global->auto_global_callback(auto_global->name);
1632		}
1633		return 1;
1634	}
1635	return 0;
1636}
1637/* }}} */
1638
1639int zend_register_auto_global(zend_string *name, zend_bool jit, zend_auto_global_callback auto_global_callback) /* {{{ */
1640{
1641	zend_auto_global auto_global;
1642	int retval;
1643
1644	auto_global.name = zend_new_interned_string(name);
1645	auto_global.auto_global_callback = auto_global_callback;
1646	auto_global.jit = jit;
1647
1648	retval = zend_hash_add_mem(CG(auto_globals), auto_global.name, &auto_global, sizeof(zend_auto_global)) != NULL ? SUCCESS : FAILURE;
1649
1650	zend_string_release(name);
1651	return retval;
1652}
1653/* }}} */
1654
1655ZEND_API void zend_activate_auto_globals(void) /* {{{ */
1656{
1657	zend_auto_global *auto_global;
1658
1659	ZEND_HASH_FOREACH_PTR(CG(auto_globals), auto_global) {
1660		if (auto_global->jit) {
1661			auto_global->armed = 1;
1662		} else if (auto_global->auto_global_callback) {
1663			auto_global->armed = auto_global->auto_global_callback(auto_global->name);
1664		} else {
1665			auto_global->armed = 0;
1666		}
1667	} ZEND_HASH_FOREACH_END();
1668}
1669/* }}} */
1670
1671int zendlex(zend_parser_stack_elem *elem) /* {{{ */
1672{
1673	zval zv;
1674	int retval;
1675
1676	if (CG(increment_lineno)) {
1677		CG(zend_lineno)++;
1678		CG(increment_lineno) = 0;
1679	}
1680
1681again:
1682	ZVAL_UNDEF(&zv);
1683	retval = lex_scan(&zv);
1684	if (EG(exception)) {
1685		return T_ERROR;
1686	}
1687
1688	switch (retval) {
1689		case T_COMMENT:
1690		case T_DOC_COMMENT:
1691		case T_OPEN_TAG:
1692		case T_WHITESPACE:
1693			goto again;
1694
1695		case T_CLOSE_TAG:
1696			if (LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-1] != '>') {
1697				CG(increment_lineno) = 1;
1698			}
1699			retval = ';'; /* implicit ; */
1700			break;
1701		case T_OPEN_TAG_WITH_ECHO:
1702			retval = T_ECHO;
1703			break;
1704	}
1705	if (Z_TYPE(zv) != IS_UNDEF) {
1706		elem->ast = zend_ast_create_zval(&zv);
1707	}
1708
1709	return retval;
1710}
1711/* }}} */
1712
1713ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers) /* {{{ */
1714{
1715	zend_bool persistent_hashes = (ce->type == ZEND_INTERNAL_CLASS) ? 1 : 0;
1716
1717	ce->refcount = 1;
1718	ce->ce_flags = ZEND_ACC_CONSTANTS_UPDATED;
1719
1720	if (CG(compiler_options) & ZEND_COMPILE_GUARDS) {
1721		ce->ce_flags |= ZEND_ACC_USE_GUARDS;
1722	}
1723
1724	ce->default_properties_table = NULL;
1725	ce->default_static_members_table = NULL;
1726	zend_hash_init_ex(&ce->properties_info, 8, NULL, (persistent_hashes ? zend_destroy_property_info_internal : NULL), persistent_hashes, 0);
1727	zend_hash_init_ex(&ce->constants_table, 8, NULL, (persistent_hashes ? zend_destroy_class_constant_internal : NULL), persistent_hashes, 0);
1728	zend_hash_init_ex(&ce->function_table, 8, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0);
1729
1730	if (ce->type == ZEND_INTERNAL_CLASS) {
1731#ifdef ZTS
1732		int n = zend_hash_num_elements(CG(class_table));
1733
1734		if (CG(static_members_table) && n >= CG(last_static_member)) {
1735			/* Support for run-time declaration: dl() */
1736			CG(last_static_member) = n+1;
1737			CG(static_members_table) = realloc(CG(static_members_table), (n+1)*sizeof(zval*));
1738			CG(static_members_table)[n] = NULL;
1739		}
1740		ce->static_members_table = (zval*)(zend_intptr_t)n;
1741#else
1742		ce->static_members_table = NULL;
1743#endif
1744	} else {
1745		ce->static_members_table = ce->default_static_members_table;
1746		ce->info.user.doc_comment = NULL;
1747	}
1748
1749	ce->default_properties_count = 0;
1750	ce->default_static_members_count = 0;
1751
1752	if (nullify_handlers) {
1753		ce->constructor = NULL;
1754		ce->destructor = NULL;
1755		ce->clone = NULL;
1756		ce->__get = NULL;
1757		ce->__set = NULL;
1758		ce->__unset = NULL;
1759		ce->__isset = NULL;
1760		ce->__call = NULL;
1761		ce->__callstatic = NULL;
1762		ce->__tostring = NULL;
1763		ce->create_object = NULL;
1764		ce->get_iterator = NULL;
1765		ce->iterator_funcs.funcs = NULL;
1766		ce->interface_gets_implemented = NULL;
1767		ce->get_static_method = NULL;
1768		ce->parent = NULL;
1769		ce->num_interfaces = 0;
1770		ce->interfaces = NULL;
1771		ce->num_traits = 0;
1772		ce->traits = NULL;
1773		ce->trait_aliases = NULL;
1774		ce->trait_precedences = NULL;
1775		ce->serialize = NULL;
1776		ce->unserialize = NULL;
1777		ce->serialize_func = NULL;
1778		ce->unserialize_func = NULL;
1779		ce->__debugInfo = NULL;
1780		if (ce->type == ZEND_INTERNAL_CLASS) {
1781			ce->info.internal.module = NULL;
1782			ce->info.internal.builtin_functions = NULL;
1783		}
1784	}
1785}
1786/* }}} */
1787
1788ZEND_API zend_string *zend_get_compiled_variable_name(const zend_op_array *op_array, uint32_t var) /* {{{ */
1789{
1790	return op_array->vars[EX_VAR_TO_NUM(var)];
1791}
1792/* }}} */
1793
1794zend_ast *zend_ast_append_str(zend_ast *left_ast, zend_ast *right_ast) /* {{{ */
1795{
1796	zval *left_zv = zend_ast_get_zval(left_ast);
1797	zend_string *left = Z_STR_P(left_zv);
1798	zend_string *right = zend_ast_get_str(right_ast);
1799
1800	zend_string *result;
1801	size_t left_len = ZSTR_LEN(left);
1802	size_t len = left_len + ZSTR_LEN(right) + 1; /* left\right */
1803
1804	result = zend_string_extend(left, len, 0);
1805	ZSTR_VAL(result)[left_len] = '\\';
1806	memcpy(&ZSTR_VAL(result)[left_len + 1], ZSTR_VAL(right), ZSTR_LEN(right));
1807	ZSTR_VAL(result)[len] = '\0';
1808	zend_string_release(right);
1809
1810	ZVAL_STR(left_zv, result);
1811	return left_ast;
1812}
1813/* }}} */
1814
1815void zend_verify_namespace(void) /* {{{ */
1816{
1817	if (FC(has_bracketed_namespaces) && !FC(in_namespace)) {
1818		zend_error_noreturn(E_COMPILE_ERROR, "No code may exist outside of namespace {}");
1819	}
1820}
1821/* }}} */
1822
1823/* {{{ zend_dirname
1824   Returns directory name component of path */
1825ZEND_API size_t zend_dirname(char *path, size_t len)
1826{
1827	register char *end = path + len - 1;
1828	unsigned int len_adjust = 0;
1829
1830#ifdef ZEND_WIN32
1831	/* Note that on Win32 CWD is per drive (heritage from CP/M).
1832	 * This means dirname("c:foo") maps to "c:." or "c:" - which means CWD on C: drive.
1833	 */
1834	if ((2 <= len) && isalpha((int)((unsigned char *)path)[0]) && (':' == path[1])) {
1835		/* Skip over the drive spec (if any) so as not to change */
1836		path += 2;
1837		len_adjust += 2;
1838		if (2 == len) {
1839			/* Return "c:" on Win32 for dirname("c:").
1840			 * It would be more consistent to return "c:."
1841			 * but that would require making the string *longer*.
1842			 */
1843			return len;
1844		}
1845	}
1846#elif defined(NETWARE)
1847	/*
1848	 * Find the first occurrence of : from the left
1849	 * move the path pointer to the position just after :
1850	 * increment the len_adjust to the length of path till colon character(inclusive)
1851	 * If there is no character beyond : simple return len
1852	 */
1853	char *colonpos = NULL;
1854	colonpos = strchr(path, ':');
1855	if (colonpos != NULL) {
1856		len_adjust = ((colonpos - path) + 1);
1857		path += len_adjust;
1858		if (len_adjust == len) {
1859			return len;
1860		}
1861	}
1862#endif
1863
1864	if (len == 0) {
1865		/* Illegal use of this function */
1866		return 0;
1867	}
1868
1869	/* Strip trailing slashes */
1870	while (end >= path && IS_SLASH_P(end)) {
1871		end--;
1872	}
1873	if (end < path) {
1874		/* The path only contained slashes */
1875		path[0] = DEFAULT_SLASH;
1876		path[1] = '\0';
1877		return 1 + len_adjust;
1878	}
1879
1880	/* Strip filename */
1881	while (end >= path && !IS_SLASH_P(end)) {
1882		end--;
1883	}
1884	if (end < path) {
1885		/* No slash found, therefore return '.' */
1886#ifdef NETWARE
1887		if (len_adjust == 0) {
1888			path[0] = '.';
1889			path[1] = '\0';
1890			return 1; /* only one character */
1891		} else {
1892			path[0] = '\0';
1893			return len_adjust;
1894		}
1895#else
1896		path[0] = '.';
1897		path[1] = '\0';
1898		return 1 + len_adjust;
1899#endif
1900	}
1901
1902	/* Strip slashes which came before the file name */
1903	while (end >= path && IS_SLASH_P(end)) {
1904		end--;
1905	}
1906	if (end < path) {
1907		path[0] = DEFAULT_SLASH;
1908		path[1] = '\0';
1909		return 1 + len_adjust;
1910	}
1911	*(end+1) = '\0';
1912
1913	return (size_t)(end + 1 - path) + len_adjust;
1914}
1915/* }}} */
1916
1917static void zend_adjust_for_fetch_type(zend_op *opline, uint32_t type) /* {{{ */
1918{
1919	zend_uchar factor = (opline->opcode == ZEND_FETCH_STATIC_PROP_R) ? 1 : 3;
1920
1921	switch (type & BP_VAR_MASK) {
1922		case BP_VAR_R:
1923			return;
1924		case BP_VAR_W:
1925			opline->opcode += 1 * factor;
1926			return;
1927		case BP_VAR_RW:
1928			opline->opcode += 2 * factor;
1929			return;
1930		case BP_VAR_IS:
1931			opline->opcode += 3 * factor;
1932			return;
1933		case BP_VAR_FUNC_ARG:
1934			opline->opcode += 4 * factor;
1935			opline->extended_value |= type >> BP_VAR_SHIFT;
1936			return;
1937		case BP_VAR_UNSET:
1938			opline->opcode += 5 * factor;
1939			return;
1940		EMPTY_SWITCH_DEFAULT_CASE()
1941	}
1942}
1943/* }}} */
1944
1945static inline void zend_make_var_result(znode *result, zend_op *opline) /* {{{ */
1946{
1947	opline->result_type = IS_VAR;
1948	opline->result.var = get_temporary_variable(CG(active_op_array));
1949	GET_NODE(result, opline->result);
1950}
1951/* }}} */
1952
1953static inline void zend_make_tmp_result(znode *result, zend_op *opline) /* {{{ */
1954{
1955	opline->result_type = IS_TMP_VAR;
1956	opline->result.var = get_temporary_variable(CG(active_op_array));
1957	GET_NODE(result, opline->result);
1958}
1959/* }}} */
1960
1961static void zend_find_live_range(zend_op *opline, zend_uchar type, uint32_t var) /* {{{ */
1962{
1963	zend_op *def = opline;
1964
1965	while (def != CG(active_op_array)->opcodes) {
1966		def--;
1967		if (def->result_type == type && def->result.var == var) {
1968			if (def->opcode == ZEND_ADD_ARRAY_ELEMENT ||
1969			    def->opcode == ZEND_ROPE_ADD) {
1970			    /* not a real definition */
1971				continue;
1972			} else if (def->opcode == ZEND_JMPZ_EX ||
1973			           def->opcode == ZEND_JMPNZ_EX ||
1974			           def->opcode == ZEND_BOOL ||
1975			           def->opcode == ZEND_BOOL_NOT) {
1976				/* result IS_BOOL, it does't have to be destroyed */
1977				break;
1978			} else if (def->opcode == ZEND_DECLARE_CLASS ||
1979			           def->opcode == ZEND_DECLARE_INHERITED_CLASS ||
1980			           def->opcode == ZEND_DECLARE_INHERITED_CLASS_DELAYED ||
1981			           def->opcode == ZEND_DECLARE_ANON_CLASS ||
1982			           def->opcode == ZEND_DECLARE_ANON_INHERITED_CLASS) {
1983				/* classes don't have to be destroyed */
1984				break;
1985			} else if (def->opcode == ZEND_FAST_CALL) {
1986				/* fast_calls don't have to be destroyed */
1987				break;
1988			} else if (def->opcode == ZEND_NEW) {
1989				/* Objects created via ZEND_NEW are only fully initialized
1990				 * after the DO_FCALL (constructor call) */
1991				def = CG(active_op_array)->opcodes + def->op2.opline_num - 1;
1992				if (def + 1 == opline) {
1993					break;
1994				}
1995			}
1996	        zend_end_live_range(CG(active_op_array),
1997				zend_start_live_range_ex(CG(active_op_array),
1998					def + 1 - CG(active_op_array)->opcodes),
1999				opline - CG(active_op_array)->opcodes,
2000				ZEND_LIVE_TMPVAR, def->result.var);
2001		    break;
2002		}
2003	}
2004}
2005/* }}} */
2006
2007static zend_always_inline int zend_is_def_range(zend_op *opline, zend_uchar type, uint32_t var) /* {{{ */
2008{
2009	while (1) {
2010		if (opline->result_type == type && opline->result.var == var) {
2011			return opline->opcode != ZEND_ADD_ARRAY_ELEMENT &&
2012				opline->opcode != ZEND_ROPE_ADD;
2013		} else if (opline->opcode == ZEND_OP_DATA) {
2014			return (opline-1)->result_type == type &&
2015				(opline-1)->result.var == var;
2016		} else if (opline->opcode == ZEND_END_SILENCE ||
2017		           opline->opcode == ZEND_NOP ||
2018	    	       opline->opcode == ZEND_EXT_NOP ||
2019	        	   opline->opcode == ZEND_EXT_STMT ||
2020	        	   opline->opcode == ZEND_EXT_FCALL_BEGIN ||
2021	        	   opline->opcode == ZEND_EXT_FCALL_END ||
2022	        	   opline->opcode == ZEND_TICKS) {
2023			opline--;
2024		} else {
2025			return 0;
2026		}
2027	}
2028}
2029/* }}} */
2030
2031static void zend_check_live_ranges(zend_op *opline) /* {{{ */
2032{
2033	if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) &&
2034		!zend_is_def_range(opline - 1, opline->op1_type, opline->op1.var)) {
2035
2036		if (opline->opcode == ZEND_OP_DATA) {
2037			if (!zend_is_def_range(opline - 2, opline->op1_type, opline->op1.var)) {
2038				zend_find_live_range(opline - 1, opline->op1_type, opline->op1.var);
2039			}
2040		} else if (opline->opcode == ZEND_INIT_STATIC_METHOD_CALL ||
2041		           opline->opcode == ZEND_NEW ||
2042		           opline->opcode == ZEND_FETCH_CLASS_CONSTANT ||
2043		           opline->opcode == ZEND_ADD_INTERFACE ||
2044		           opline->opcode == ZEND_ADD_TRAIT ||
2045		           opline->opcode == ZEND_BIND_TRAITS ||
2046		           opline->opcode == ZEND_VERIFY_ABSTRACT_CLASS) {
2047			/* classes don't have to be destroyed */
2048		} else if (opline->opcode == ZEND_FAST_RET) {
2049			/* fast_calls don't have to be destroyed */
2050		} else if (opline->opcode == ZEND_CASE ||
2051		           opline->opcode == ZEND_FE_FETCH_R ||
2052		           opline->opcode == ZEND_FE_FETCH_RW ||
2053			       opline->opcode == ZEND_FE_FREE ||
2054			       opline->opcode == ZEND_ROPE_ADD ||
2055			       opline->opcode == ZEND_ROPE_END ||
2056			       opline->opcode == ZEND_END_SILENCE ||
2057			       opline->opcode == ZEND_FETCH_LIST ||
2058			       opline->opcode == ZEND_VERIFY_RETURN_TYPE ||
2059			       opline->opcode == ZEND_BIND_LEXICAL) {
2060			/* these opcodes are handled separately */
2061		} else {
2062			zend_find_live_range(opline, opline->op1_type, opline->op1.var);
2063		}
2064	}
2065
2066	if ((opline->op2_type & (IS_VAR|IS_TMP_VAR)) &&
2067		!zend_is_def_range(opline - 1, opline->op2_type, opline->op2.var)) {
2068
2069		if (opline->opcode == ZEND_OP_DATA) {
2070			if (!zend_is_def_range(opline - 2, opline->op2_type, opline->op2.var)) {
2071				zend_find_live_range(opline-1, opline->op2_type, opline->op2.var);
2072			}
2073		} else if (opline->opcode == ZEND_FETCH_STATIC_PROP_R ||
2074		           opline->opcode == ZEND_FETCH_STATIC_PROP_W ||
2075		           opline->opcode == ZEND_FETCH_STATIC_PROP_RW ||
2076		           opline->opcode == ZEND_FETCH_STATIC_PROP_IS ||
2077		           opline->opcode == ZEND_FETCH_STATIC_PROP_FUNC_ARG ||
2078		           opline->opcode == ZEND_FETCH_STATIC_PROP_UNSET ||
2079		           opline->opcode == ZEND_UNSET_STATIC_PROP ||
2080		           opline->opcode == ZEND_ISSET_ISEMPTY_STATIC_PROP ||
2081		           opline->opcode == ZEND_INSTANCEOF) {
2082			/* classes don't have to be destroyed */
2083		} else {
2084			zend_find_live_range(opline, opline->op2_type, opline->op2.var);
2085		}
2086	}
2087}
2088/* }}} */
2089
2090static zend_op *zend_emit_op(znode *result, zend_uchar opcode, znode *op1, znode *op2) /* {{{ */
2091{
2092	zend_op *opline = get_next_op(CG(active_op_array));
2093	opline->opcode = opcode;
2094
2095	if (op1 == NULL) {
2096		SET_UNUSED(opline->op1);
2097	} else {
2098		SET_NODE(opline->op1, op1);
2099	}
2100
2101	if (op2 == NULL) {
2102		SET_UNUSED(opline->op2);
2103	} else {
2104		SET_NODE(opline->op2, op2);
2105	}
2106
2107	zend_check_live_ranges(opline);
2108
2109	if (result) {
2110		zend_make_var_result(result, opline);
2111	}
2112	return opline;
2113}
2114/* }}} */
2115
2116static zend_op *zend_emit_op_tmp(znode *result, zend_uchar opcode, znode *op1, znode *op2) /* {{{ */
2117{
2118	zend_op *opline = get_next_op(CG(active_op_array));
2119	opline->opcode = opcode;
2120
2121	if (op1 == NULL) {
2122		SET_UNUSED(opline->op1);
2123	} else {
2124		SET_NODE(opline->op1, op1);
2125	}
2126
2127	if (op2 == NULL) {
2128		SET_UNUSED(opline->op2);
2129	} else {
2130		SET_NODE(opline->op2, op2);
2131	}
2132
2133	zend_check_live_ranges(opline);
2134
2135	if (result) {
2136		zend_make_tmp_result(result, opline);
2137	}
2138
2139	return opline;
2140}
2141/* }}} */
2142
2143static void zend_emit_tick(void) /* {{{ */
2144{
2145	zend_op *opline;
2146
2147	/* This prevents a double TICK generated by the parser statement of "declare()" */
2148	if (CG(active_op_array)->last && CG(active_op_array)->opcodes[CG(active_op_array)->last - 1].opcode == ZEND_TICKS) {
2149		return;
2150	}
2151
2152	opline = get_next_op(CG(active_op_array));
2153
2154	opline->opcode = ZEND_TICKS;
2155	SET_UNUSED(opline->op1);
2156	SET_UNUSED(opline->op2);
2157	opline->extended_value = FC(declarables).ticks;
2158}
2159/* }}} */
2160
2161static inline zend_op *zend_emit_op_data(znode *value) /* {{{ */
2162{
2163	return zend_emit_op(NULL, ZEND_OP_DATA, value, NULL);
2164}
2165/* }}} */
2166
2167static inline uint32_t zend_emit_jump(uint32_t opnum_target) /* {{{ */
2168{
2169	uint32_t opnum = get_next_op_number(CG(active_op_array));
2170	zend_op *opline = zend_emit_op(NULL, ZEND_JMP, NULL, NULL);
2171	opline->op1.opline_num = opnum_target;
2172	return opnum;
2173}
2174/* }}} */
2175
2176static inline uint32_t zend_emit_cond_jump(zend_uchar opcode, znode *cond, uint32_t opnum_target) /* {{{ */
2177{
2178	uint32_t opnum = get_next_op_number(CG(active_op_array));
2179	zend_op *opline = zend_emit_op(NULL, opcode, cond, NULL);
2180	opline->op2.opline_num = opnum_target;
2181	return opnum;
2182}
2183/* }}} */
2184
2185static inline void zend_update_jump_target(uint32_t opnum_jump, uint32_t opnum_target) /* {{{ */
2186{
2187	zend_op *opline = &CG(active_op_array)->opcodes[opnum_jump];
2188	switch (opline->opcode) {
2189		case ZEND_JMP:
2190			opline->op1.opline_num = opnum_target;
2191			break;
2192		case ZEND_JMPZ:
2193		case ZEND_JMPNZ:
2194		case ZEND_JMPZ_EX:
2195		case ZEND_JMPNZ_EX:
2196		case ZEND_JMP_SET:
2197			opline->op2.opline_num = opnum_target;
2198			break;
2199		EMPTY_SWITCH_DEFAULT_CASE()
2200	}
2201}
2202/* }}} */
2203
2204static inline void zend_update_jump_target_to_next(uint32_t opnum_jump) /* {{{ */
2205{
2206	zend_update_jump_target(opnum_jump, get_next_op_number(CG(active_op_array)));
2207}
2208/* }}} */
2209
2210static inline zend_op *zend_delayed_emit_op(znode *result, zend_uchar opcode, znode *op1, znode *op2) /* {{{ */
2211{
2212	zend_op tmp_opline;
2213	init_op(&tmp_opline);
2214	tmp_opline.opcode = opcode;
2215	if (op1 == NULL) {
2216		SET_UNUSED(tmp_opline.op1);
2217	} else {
2218		SET_NODE(tmp_opline.op1, op1);
2219	}
2220	if (op2 == NULL) {
2221		SET_UNUSED(tmp_opline.op2);
2222	} else {
2223		SET_NODE(tmp_opline.op2, op2);
2224	}
2225	if (result) {
2226		zend_make_var_result(result, &tmp_opline);
2227	}
2228
2229	zend_stack_push(&CG(delayed_oplines_stack), &tmp_opline);
2230	return zend_stack_top(&CG(delayed_oplines_stack));
2231}
2232/* }}} */
2233
2234static inline uint32_t zend_delayed_compile_begin(void) /* {{{ */
2235{
2236	return zend_stack_count(&CG(delayed_oplines_stack));
2237}
2238/* }}} */
2239
2240static zend_op *zend_delayed_compile_end(uint32_t offset) /* {{{ */
2241{
2242	zend_op *opline = NULL, *oplines = zend_stack_base(&CG(delayed_oplines_stack));
2243	uint32_t i, count = zend_stack_count(&CG(delayed_oplines_stack));
2244
2245	ZEND_ASSERT(count >= offset);
2246	for (i = offset; i < count; ++i) {
2247		opline = get_next_op(CG(active_op_array));
2248		memcpy(opline, &oplines[i], sizeof(zend_op));
2249		zend_check_live_ranges(opline);
2250	}
2251	CG(delayed_oplines_stack).top = offset;
2252	return opline;
2253}
2254/* }}} */
2255
2256static void zend_emit_return_type_check(znode *expr, zend_arg_info *return_info) /* {{{ */
2257{
2258	/* `return ...;` is illegal in a void function (but `return;` isn't) */
2259	if (expr && return_info->type_hint == IS_VOID) {
2260		zend_error_noreturn(E_COMPILE_ERROR, "A void function must not return a value");
2261	}
2262
2263	if (return_info->type_hint != IS_UNDEF) {
2264		zend_op *opline = zend_emit_op(NULL, ZEND_VERIFY_RETURN_TYPE, expr, NULL);
2265		if (expr && expr->op_type == IS_CONST) {
2266			opline->result_type = expr->op_type = IS_TMP_VAR;
2267			opline->result.var = expr->u.op.var = get_temporary_variable(CG(active_op_array));
2268		}
2269		if (return_info->class_name) {
2270			opline->op2.num = CG(active_op_array)->cache_size;
2271			CG(active_op_array)->cache_size += sizeof(void*);
2272		} else {
2273			opline->op2.num = -1;
2274		}
2275	}
2276}
2277/* }}} */
2278
2279void zend_emit_final_return(int return_one) /* {{{ */
2280{
2281	znode zn;
2282	zend_op *ret;
2283	zend_bool returns_reference = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
2284
2285	if (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
2286		zend_emit_return_type_check(NULL, CG(active_op_array)->arg_info - 1);
2287	}
2288
2289	zn.op_type = IS_CONST;
2290	if (return_one) {
2291		ZVAL_LONG(&zn.u.constant, 1);
2292	} else {
2293		ZVAL_NULL(&zn.u.constant);
2294	}
2295
2296	ret = zend_emit_op(NULL, returns_reference ? ZEND_RETURN_BY_REF : ZEND_RETURN, &zn, NULL);
2297	ret->extended_value = -1;
2298}
2299/* }}} */
2300
2301static inline zend_bool zend_is_variable(zend_ast *ast) /* {{{ */
2302{
2303	return ast->kind == ZEND_AST_VAR || ast->kind == ZEND_AST_DIM
2304		|| ast->kind == ZEND_AST_PROP || ast->kind == ZEND_AST_STATIC_PROP
2305		|| ast->kind == ZEND_AST_CALL || ast->kind == ZEND_AST_METHOD_CALL
2306		|| ast->kind == ZEND_AST_STATIC_CALL;
2307}
2308/* }}} */
2309
2310static inline zend_bool zend_is_call(zend_ast *ast) /* {{{ */
2311{
2312	return ast->kind == ZEND_AST_CALL
2313		|| ast->kind == ZEND_AST_METHOD_CALL
2314		|| ast->kind == ZEND_AST_STATIC_CALL;
2315}
2316/* }}} */
2317
2318static inline zend_bool zend_is_unticked_stmt(zend_ast *ast) /* {{{ */
2319{
2320	return ast->kind == ZEND_AST_STMT_LIST || ast->kind == ZEND_AST_LABEL
2321		|| ast->kind == ZEND_AST_PROP_DECL || ast->kind == ZEND_AST_CLASS_CONST_DECL
2322		|| ast->kind == ZEND_AST_USE_TRAIT || ast->kind == ZEND_AST_METHOD;
2323}
2324/* }}} */
2325
2326static inline zend_bool zend_can_write_to_variable(zend_ast *ast) /* {{{ */
2327{
2328	while (ast->kind == ZEND_AST_DIM || ast->kind == ZEND_AST_PROP) {
2329		ast = ast->child[0];
2330	}
2331
2332	return zend_is_variable(ast);
2333}
2334/* }}} */
2335
2336static inline zend_bool zend_is_const_default_class_ref(zend_ast *name_ast) /* {{{ */
2337{
2338	if (name_ast->kind != ZEND_AST_ZVAL) {
2339		return 0;
2340	}
2341
2342	return ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type_ast(name_ast);
2343}
2344/* }}} */
2345
2346static inline void zend_handle_numeric_op(znode *node) /* {{{ */
2347{
2348	if (node->op_type == IS_CONST && Z_TYPE(node->u.constant) == IS_STRING) {
2349		zend_ulong index;
2350
2351		if (ZEND_HANDLE_NUMERIC(Z_STR(node->u.constant), index)) {
2352			zval_ptr_dtor(&node->u.constant);
2353			ZVAL_LONG(&node->u.constant, index);
2354		}
2355	}
2356}
2357/* }}} */
2358
2359static inline void zend_set_class_name_op1(zend_op *opline, znode *class_node) /* {{{ */
2360{
2361	if (class_node->op_type == IS_CONST) {
2362		opline->op1_type = IS_CONST;
2363		opline->op1.constant = zend_add_class_name_literal(
2364			CG(active_op_array), Z_STR(class_node->u.constant));
2365	} else {
2366		SET_NODE(opline->op1, class_node);
2367	}
2368}
2369/* }}} */
2370
2371static zend_op *zend_compile_class_ref(znode *result, zend_ast *name_ast, int throw_exception) /* {{{ */
2372{
2373	zend_op *opline;
2374	znode name_node;
2375	zend_compile_expr(&name_node, name_ast);
2376
2377	if (name_node.op_type == IS_CONST) {
2378		zend_string *name;
2379		uint32_t fetch_type;
2380
2381		if (Z_TYPE(name_node.u.constant) != IS_STRING) {
2382			zend_error_noreturn(E_COMPILE_ERROR, "Illegal class name");
2383		}
2384
2385		name = Z_STR(name_node.u.constant);
2386		fetch_type = zend_get_class_fetch_type(name);
2387
2388		opline = zend_emit_op(result, ZEND_FETCH_CLASS, NULL, NULL);
2389		opline->extended_value = fetch_type | (throw_exception ? ZEND_FETCH_CLASS_EXCEPTION : 0);
2390
2391		if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
2392			uint32_t type = name_ast->kind == ZEND_AST_ZVAL ? name_ast->attr : ZEND_NAME_FQ;
2393			opline->op2_type = IS_CONST;
2394			opline->op2.constant = zend_add_class_name_literal(CG(active_op_array),
2395				zend_resolve_class_name(name, type));
2396		} else {
2397			zend_ensure_valid_class_fetch_type(fetch_type);
2398		}
2399
2400		zend_string_release(name);
2401	} else {
2402		opline = zend_emit_op(result, ZEND_FETCH_CLASS, NULL, &name_node);
2403		opline->extended_value = ZEND_FETCH_CLASS_DEFAULT | (throw_exception ? ZEND_FETCH_CLASS_EXCEPTION : 0);
2404	}
2405
2406	return opline;
2407}
2408/* }}} */
2409
2410static void zend_compile_class_ref_ex(znode *result, zend_ast *name_ast, uint32_t fetch_flags) /* {{{ */
2411{
2412	uint32_t fetch_type;
2413
2414	if (name_ast->kind != ZEND_AST_ZVAL) {
2415		znode name_node;
2416
2417		zend_compile_expr(&name_node, name_ast);
2418
2419		if (name_node.op_type == IS_CONST) {
2420			zend_string *name;
2421
2422			if (Z_TYPE(name_node.u.constant) != IS_STRING) {
2423				zend_error_noreturn(E_COMPILE_ERROR, "Illegal class name");
2424			}
2425
2426			name = Z_STR(name_node.u.constant);
2427			fetch_type = zend_get_class_fetch_type(name);
2428
2429			if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
2430				result->op_type = IS_CONST;
2431				ZVAL_STR(&result->u.constant, zend_resolve_class_name(name, ZEND_NAME_FQ));
2432			} else {
2433				zend_ensure_valid_class_fetch_type(fetch_type);
2434				result->op_type = IS_UNUSED;
2435				result->u.op.num = fetch_type | fetch_flags;
2436			}
2437
2438			zend_string_release(name);
2439		} else {
2440			zend_op *opline = zend_emit_op(result, ZEND_FETCH_CLASS, NULL, &name_node);
2441			opline->extended_value = ZEND_FETCH_CLASS_DEFAULT | fetch_flags;
2442		}
2443		return;
2444	}
2445
2446	/* Fully qualified names are always default refs */
2447	if (name_ast->attr == ZEND_NAME_FQ) {
2448		result->op_type = IS_CONST;
2449		ZVAL_STR(&result->u.constant, zend_resolve_class_name_ast(name_ast));
2450		return;
2451	}
2452
2453	fetch_type = zend_get_class_fetch_type(zend_ast_get_str(name_ast));
2454	if (ZEND_FETCH_CLASS_DEFAULT == fetch_type) {
2455		result->op_type = IS_CONST;
2456		ZVAL_STR(&result->u.constant, zend_resolve_class_name_ast(name_ast));
2457	} else {
2458		zend_ensure_valid_class_fetch_type(fetch_type);
2459		result->op_type = IS_UNUSED;
2460		result->u.op.num = fetch_type | fetch_flags;
2461	}
2462}
2463/* }}} */
2464
2465static int zend_try_compile_cv(znode *result, zend_ast *ast) /* {{{ */
2466{
2467	zend_ast *name_ast = ast->child[0];
2468	if (name_ast->kind == ZEND_AST_ZVAL) {
2469		zend_string *name = zval_get_string(zend_ast_get_zval(name_ast));
2470
2471		if (zend_is_auto_global(name)) {
2472			zend_string_release(name);
2473			return FAILURE;
2474		}
2475
2476		result->op_type = IS_CV;
2477		result->u.op.var = lookup_cv(CG(active_op_array), name);
2478
2479		/* lookup_cv may be using another zend_string instance  */
2480		name = CG(active_op_array)->vars[EX_VAR_TO_NUM(result->u.op.var)];
2481
2482		if (zend_string_equals_literal(name, "this")) {
2483			CG(active_op_array)->this_var = result->u.op.var;
2484		}
2485		return SUCCESS;
2486	}
2487
2488	return FAILURE;
2489}
2490/* }}} */
2491
2492static zend_op *zend_compile_simple_var_no_cv(znode *result, zend_ast *ast, uint32_t type, int delayed) /* {{{ */
2493{
2494	zend_ast *name_ast = ast->child[0];
2495	znode name_node;
2496	zend_op *opline;
2497
2498	zend_compile_expr(&name_node, name_ast);
2499	if (name_node.op_type == IS_CONST) {
2500		convert_to_string(&name_node.u.constant);
2501	}
2502
2503	if (delayed) {
2504		opline = zend_delayed_emit_op(result, ZEND_FETCH_R, &name_node, NULL);
2505	} else {
2506		opline = zend_emit_op(result, ZEND_FETCH_R, &name_node, NULL);
2507	}
2508
2509	if (name_node.op_type == IS_CONST &&
2510	    zend_is_auto_global(Z_STR(name_node.u.constant))) {
2511
2512		opline->extended_value = ZEND_FETCH_GLOBAL;
2513	} else {
2514		opline->extended_value = ZEND_FETCH_LOCAL;
2515		/* there is a chance someone is accessing $this */
2516		if (ast->kind != ZEND_AST_ZVAL
2517			&& CG(active_op_array)->scope && CG(active_op_array)->this_var == (uint32_t)-1
2518		) {
2519			zend_string *key = zend_string_init("this", sizeof("this") - 1, 0);
2520			CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), key);
2521		}
2522	}
2523
2524	return opline;
2525}
2526/* }}} */
2527
2528static void zend_compile_simple_var(znode *result, zend_ast *ast, uint32_t type, int delayed) /* {{{ */
2529{
2530	if (zend_try_compile_cv(result, ast) == FAILURE) {
2531		zend_op *opline = zend_compile_simple_var_no_cv(result, ast, type, delayed);
2532		zend_adjust_for_fetch_type(opline, type);
2533	}
2534}
2535/* }}} */
2536
2537static void zend_separate_if_call_and_write(znode *node, zend_ast *ast, uint32_t type) /* {{{ */
2538{
2539	if (type != BP_VAR_R && type != BP_VAR_IS && zend_is_call(ast)) {
2540		if (node->op_type == IS_VAR) {
2541			zend_op *opline = zend_emit_op(NULL, ZEND_SEPARATE, node, NULL);
2542			opline->result_type = IS_VAR;
2543			opline->result.var = opline->op1.var;
2544		} else {
2545			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use result of built-in function in write context");
2546		}
2547	}
2548}
2549/* }}} */
2550
2551void zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type);
2552void zend_compile_assign(znode *result, zend_ast *ast);
2553static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_node);
2554
2555static inline void zend_emit_assign_znode(zend_ast *var_ast, znode *value_node) /* {{{ */
2556{
2557	znode dummy_node;
2558	if (var_ast->kind == ZEND_AST_LIST) {
2559		zend_compile_list_assign(&dummy_node, var_ast, value_node);
2560	} else {
2561		zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN, var_ast,
2562			zend_ast_create_znode(value_node));
2563		zend_compile_assign(&dummy_node, assign_ast);
2564	}
2565	zend_do_free(&dummy_node);
2566}
2567/* }}} */
2568
2569static zend_op *zend_delayed_compile_dim(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
2570{
2571	zend_ast *var_ast = ast->child[0];
2572	zend_ast *dim_ast = ast->child[1];
2573
2574	znode var_node, dim_node;
2575
2576	zend_delayed_compile_var(&var_node, var_ast, type);
2577	zend_separate_if_call_and_write(&var_node, var_ast, type);
2578
2579	if (dim_ast == NULL) {
2580		if (type == BP_VAR_R || type == BP_VAR_IS) {
2581			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
2582		}
2583		if (type == BP_VAR_UNSET) {
2584			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for unsetting");
2585		}
2586		dim_node.op_type = IS_UNUSED;
2587	} else {
2588		zend_compile_expr(&dim_node, dim_ast);
2589		zend_handle_numeric_op(&dim_node);
2590	}
2591
2592	return zend_delayed_emit_op(result, ZEND_FETCH_DIM_R, &var_node, &dim_node);
2593}
2594/* }}} */
2595
2596static inline zend_op *zend_compile_dim_common(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
2597{
2598	uint32_t offset = zend_delayed_compile_begin();
2599	zend_delayed_compile_dim(result, ast, type);
2600	return zend_delayed_compile_end(offset);
2601}
2602/* }}} */
2603
2604void zend_compile_dim(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
2605{
2606	zend_op *opline = zend_compile_dim_common(result, ast, type);
2607	zend_adjust_for_fetch_type(opline, type);
2608}
2609/* }}} */
2610
2611static zend_bool is_this_fetch(zend_ast *ast) /* {{{ */
2612{
2613	if (ast->kind == ZEND_AST_VAR && ast->child[0]->kind == ZEND_AST_ZVAL) {
2614		zval *name = zend_ast_get_zval(ast->child[0]);
2615		return Z_TYPE_P(name) == IS_STRING && zend_string_equals_literal(Z_STR_P(name), "this");
2616	}
2617
2618	return 0;
2619}
2620/* }}} */
2621
2622static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
2623{
2624	zend_ast *obj_ast = ast->child[0];
2625	zend_ast *prop_ast = ast->child[1];
2626
2627	znode obj_node, prop_node;
2628	zend_op *opline;
2629
2630	if (is_this_fetch(obj_ast)) {
2631		obj_node.op_type = IS_UNUSED;
2632	} else {
2633		zend_delayed_compile_var(&obj_node, obj_ast, type);
2634		zend_separate_if_call_and_write(&obj_node, obj_ast, type);
2635	}
2636	zend_compile_expr(&prop_node, prop_ast);
2637
2638	opline = zend_delayed_emit_op(result, ZEND_FETCH_OBJ_R, &obj_node, &prop_node);
2639	if (opline->op2_type == IS_CONST) {
2640		convert_to_string(CT_CONSTANT(opline->op2));
2641		zend_alloc_polymorphic_cache_slot(opline->op2.constant);
2642	}
2643
2644	return opline;
2645}
2646/* }}} */
2647
2648static zend_op *zend_compile_prop_common(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
2649{
2650	uint32_t offset = zend_delayed_compile_begin();
2651	zend_delayed_compile_prop(result, ast, type);
2652	return zend_delayed_compile_end(offset);
2653}
2654/* }}} */
2655
2656void zend_compile_prop(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
2657{
2658	zend_op *opline = zend_compile_prop_common(result, ast, type);
2659	zend_adjust_for_fetch_type(opline, type);
2660}
2661/* }}} */
2662
2663zend_op *zend_compile_static_prop_common(znode *result, zend_ast *ast, uint32_t type, int delayed) /* {{{ */
2664{
2665	zend_ast *class_ast = ast->child[0];
2666	zend_ast *prop_ast = ast->child[1];
2667
2668	znode class_node, prop_node;
2669	zend_op *opline;
2670
2671	zend_compile_class_ref_ex(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
2672
2673	zend_compile_expr(&prop_node, prop_ast);
2674
2675	if (delayed) {
2676		opline = zend_delayed_emit_op(result, ZEND_FETCH_STATIC_PROP_R, &prop_node, NULL);
2677	} else {
2678		opline = zend_emit_op(result, ZEND_FETCH_STATIC_PROP_R, &prop_node, NULL);
2679	}
2680	if (opline->op1_type == IS_CONST) {
2681		convert_to_string(CT_CONSTANT(opline->op1));
2682		zend_alloc_polymorphic_cache_slot(opline->op1.constant);
2683	}
2684	if (class_node.op_type == IS_CONST) {
2685		opline->op2_type = IS_CONST;
2686		opline->op2.constant = zend_add_class_name_literal(
2687			CG(active_op_array), Z_STR(class_node.u.constant));
2688	} else {
2689		SET_NODE(opline->op2, &class_node);
2690	}
2691
2692	return opline;
2693}
2694/* }}} */
2695
2696void zend_compile_static_prop(znode *result, zend_ast *ast, uint32_t type, int delayed) /* {{{ */
2697{
2698	zend_op *opline = zend_compile_static_prop_common(result, ast, type, delayed);
2699	zend_adjust_for_fetch_type(opline, type);
2700}
2701/* }}} */
2702
2703static void zend_compile_list_assign(znode *result, zend_ast *ast, znode *expr_node) /* {{{ */
2704{
2705	zend_ast_list *list = zend_ast_get_list(ast);
2706	uint32_t i;
2707	zend_bool has_elems = 0;
2708
2709	for (i = 0; i < list->children; ++i) {
2710		zend_ast *var_ast = list->child[i];
2711		znode fetch_result, dim_node;
2712
2713		if (var_ast == NULL) {
2714			continue;
2715		}
2716		has_elems = 1;
2717
2718		dim_node.op_type = IS_CONST;
2719		ZVAL_LONG(&dim_node.u.constant, i);
2720
2721		if (expr_node->op_type == IS_CONST) {
2722			Z_TRY_ADDREF(expr_node->u.constant);
2723		}
2724
2725		zend_emit_op(&fetch_result, ZEND_FETCH_LIST, expr_node, &dim_node);
2726		zend_emit_assign_znode(var_ast, &fetch_result);
2727	}
2728
2729	if (!has_elems) {
2730		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use empty list");
2731	}
2732
2733	*result = *expr_node;
2734}
2735/* }}} */
2736
2737static void zend_ensure_writable_variable(const zend_ast *ast) /* {{{ */
2738{
2739	if (ast->kind == ZEND_AST_CALL) {
2740		zend_error_noreturn(E_COMPILE_ERROR, "Can't use function return value in write context");
2741	}
2742	if (ast->kind == ZEND_AST_METHOD_CALL || ast->kind == ZEND_AST_STATIC_CALL) {
2743		zend_error_noreturn(E_COMPILE_ERROR, "Can't use method return value in write context");
2744	}
2745}
2746/* }}} */
2747
2748/* Detects $a... = $a pattern */
2749zend_bool zend_is_assign_to_self(zend_ast *var_ast, zend_ast *expr_ast) /* {{{ */
2750{
2751	if (expr_ast->kind != ZEND_AST_VAR || expr_ast->child[0]->kind != ZEND_AST_ZVAL) {
2752		return 0;
2753	}
2754
2755	while (zend_is_variable(var_ast) && var_ast->kind != ZEND_AST_VAR) {
2756		var_ast = var_ast->child[0];
2757	}
2758
2759	if (var_ast->kind != ZEND_AST_VAR || var_ast->child[0]->kind != ZEND_AST_ZVAL) {
2760		return 0;
2761	}
2762
2763	{
2764		zend_string *name1 = zval_get_string(zend_ast_get_zval(var_ast->child[0]));
2765		zend_string *name2 = zval_get_string(zend_ast_get_zval(expr_ast->child[0]));
2766		zend_bool result = zend_string_equals(name1, name2);
2767		zend_string_release(name1);
2768		zend_string_release(name2);
2769		return result;
2770	}
2771}
2772/* }}} */
2773
2774/* Detects if list($a, $b, $c) contains variable with given name */
2775zend_bool zend_list_has_assign_to(zend_ast *list_ast, zend_string *name) /* {{{ */
2776{
2777	zend_ast_list *list = zend_ast_get_list(list_ast);
2778	uint32_t i;
2779	for (i = 0; i < list->children; i++) {
2780		zend_ast *var_ast = list->child[i];
2781		if (!var_ast) {
2782			continue;
2783		}
2784
2785		/* Recursively check nested list()s */
2786		if (var_ast->kind == ZEND_AST_LIST && zend_list_has_assign_to(var_ast, name)) {
2787			return 1;
2788		}
2789
2790		if (var_ast->kind == ZEND_AST_VAR && var_ast->child[0]->kind == ZEND_AST_ZVAL) {
2791			zend_string *var_name = zval_get_string(zend_ast_get_zval(var_ast->child[0]));
2792			zend_bool result = zend_string_equals(var_name, name);
2793			zend_string_release(var_name);
2794			if (result) {
2795				return 1;
2796			}
2797		}
2798	}
2799
2800	return 0;
2801}
2802/* }}} */
2803
2804/* Detects patterns like list($a, $b, $c) = $a */
2805zend_bool zend_list_has_assign_to_self(zend_ast *list_ast, zend_ast *expr_ast) /* {{{ */
2806{
2807	/* Only check simple variables on the RHS, as only CVs cause issues with this. */
2808	if (expr_ast->kind == ZEND_AST_VAR && expr_ast->child[0]->kind == ZEND_AST_ZVAL) {
2809		zend_string *name = zval_get_string(zend_ast_get_zval(expr_ast->child[0]));
2810		zend_bool result = zend_list_has_assign_to(list_ast, name);
2811		zend_string_release(name);
2812		return result;
2813	}
2814	return 0;
2815}
2816/* }}} */
2817
2818void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
2819{
2820	zend_ast *var_ast = ast->child[0];
2821	zend_ast *expr_ast = ast->child[1];
2822
2823	znode var_node, expr_node;
2824	zend_op *opline;
2825	uint32_t offset;
2826
2827	if (is_this_fetch(var_ast)) {
2828		zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
2829	}
2830
2831	zend_ensure_writable_variable(var_ast);
2832
2833	switch (var_ast->kind) {
2834		case ZEND_AST_VAR:
2835		case ZEND_AST_STATIC_PROP:
2836			offset = zend_delayed_compile_begin();
2837			zend_delayed_compile_var(&var_node, var_ast, BP_VAR_W);
2838			zend_compile_expr(&expr_node, expr_ast);
2839			zend_delayed_compile_end(offset);
2840			zend_emit_op(result, ZEND_ASSIGN, &var_node, &expr_node);
2841			return;
2842		case ZEND_AST_DIM:
2843			offset = zend_delayed_compile_begin();
2844			zend_delayed_compile_dim(result, var_ast, BP_VAR_W);
2845
2846			if (zend_is_assign_to_self(var_ast, expr_ast)) {
2847				/* $a[0] = $a should evaluate the right $a first */
2848				zend_compile_simple_var_no_cv(&expr_node, expr_ast, BP_VAR_R, 0);
2849			} else {
2850				zend_compile_expr(&expr_node, expr_ast);
2851			}
2852
2853			opline = zend_delayed_compile_end(offset);
2854			opline->opcode = ZEND_ASSIGN_DIM;
2855
2856			opline = zend_emit_op_data(&expr_node);
2857			return;
2858		case ZEND_AST_PROP:
2859			offset = zend_delayed_compile_begin();
2860			zend_delayed_compile_prop(result, var_ast, BP_VAR_W);
2861			zend_compile_expr(&expr_node, expr_ast);
2862
2863			opline = zend_delayed_compile_end(offset);
2864			opline->opcode = ZEND_ASSIGN_OBJ;
2865
2866			zend_emit_op_data(&expr_node);
2867			return;
2868		case ZEND_AST_LIST:
2869			if (zend_list_has_assign_to_self(var_ast, expr_ast)) {
2870				/* list($a, $b) = $a should evaluate the right $a first */
2871				zend_compile_simple_var_no_cv(&expr_node, expr_ast, BP_VAR_R, 0);
2872			} else {
2873				zend_compile_expr(&expr_node, expr_ast);
2874			}
2875
2876			zend_compile_list_assign(result, var_ast, &expr_node);
2877			return;
2878		EMPTY_SWITCH_DEFAULT_CASE();
2879	}
2880}
2881/* }}} */
2882
2883void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */
2884{
2885	zend_ast *target_ast = ast->child[0];
2886	zend_ast *source_ast = ast->child[1];
2887
2888	znode target_node, source_node;
2889	zend_op *opline;
2890	uint32_t offset;
2891
2892	if (is_this_fetch(target_ast)) {
2893		zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
2894	}
2895	zend_ensure_writable_variable(target_ast);
2896
2897	offset = zend_delayed_compile_begin();
2898	zend_delayed_compile_var(&target_node, target_ast, BP_VAR_W);
2899	zend_delayed_compile_var(&source_node, source_ast, BP_VAR_W);
2900	zend_delayed_compile_end(offset);
2901
2902	if (source_node.op_type != IS_VAR && zend_is_call(source_ast)) {
2903		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use result of built-in function in write context");
2904	}
2905
2906	opline = zend_emit_op(result, ZEND_ASSIGN_REF, &target_node, &source_node);
2907	if (!result) {
2908		opline->result_type |= EXT_TYPE_UNUSED;
2909	}
2910
2911	if (zend_is_call(source_ast)) {
2912		opline->extended_value = ZEND_RETURNS_FUNCTION;
2913	}
2914}
2915/* }}} */
2916
2917static inline void zend_emit_assign_ref_znode(zend_ast *var_ast, znode *value_node) /* {{{ */
2918{
2919	zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN_REF, var_ast,
2920		zend_ast_create_znode(value_node));
2921	zend_compile_assign_ref(NULL, assign_ast);
2922}
2923/* }}} */
2924
2925void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */
2926{
2927	zend_ast *var_ast = ast->child[0];
2928	zend_ast *expr_ast = ast->child[1];
2929	uint32_t opcode = ast->attr;
2930
2931	znode var_node, expr_node;
2932	zend_op *opline;
2933	uint32_t offset;
2934
2935	zend_ensure_writable_variable(var_ast);
2936
2937	switch (var_ast->kind) {
2938		case ZEND_AST_VAR:
2939		case ZEND_AST_STATIC_PROP:
2940			offset = zend_delayed_compile_begin();
2941			zend_delayed_compile_var(&var_node, var_ast, BP_VAR_RW);
2942			zend_compile_expr(&expr_node, expr_ast);
2943			zend_delayed_compile_end(offset);
2944			zend_emit_op(result, opcode, &var_node, &expr_node);
2945			return;
2946		case ZEND_AST_DIM:
2947			offset = zend_delayed_compile_begin();
2948			zend_delayed_compile_dim(result, var_ast, BP_VAR_RW);
2949			zend_compile_expr(&expr_node, expr_ast);
2950
2951			opline = zend_delayed_compile_end(offset);
2952			opline->opcode = opcode;
2953			opline->extended_value = ZEND_ASSIGN_DIM;
2954
2955			opline = zend_emit_op_data(&expr_node);
2956			return;
2957		case ZEND_AST_PROP:
2958			offset = zend_delayed_compile_begin();
2959			zend_delayed_compile_prop(result, var_ast, BP_VAR_RW);
2960			zend_compile_expr(&expr_node, expr_ast);
2961
2962			opline = zend_delayed_compile_end(offset);
2963			opline->opcode = opcode;
2964			opline->extended_value = ZEND_ASSIGN_OBJ;
2965
2966			zend_emit_op_data(&expr_node);
2967			return;
2968		EMPTY_SWITCH_DEFAULT_CASE()
2969	}
2970}
2971/* }}} */
2972
2973uint32_t zend_compile_args(zend_ast *ast, zend_function *fbc) /* {{{ */
2974{
2975	zend_ast_list *args = zend_ast_get_list(ast);
2976	uint32_t i;
2977	zend_bool uses_arg_unpack = 0;
2978	uint32_t arg_count = 0; /* number of arguments not including unpacks */
2979
2980	for (i = 0; i < args->children; ++i) {
2981		zend_ast *arg = args->child[i];
2982		uint32_t arg_num = i + 1;
2983
2984		znode arg_node;
2985		zend_op *opline;
2986		zend_uchar opcode;
2987		zend_ulong flags = 0;
2988
2989		if (arg->kind == ZEND_AST_UNPACK) {
2990			uses_arg_unpack = 1;
2991			fbc = NULL;
2992
2993			zend_compile_expr(&arg_node, arg->child[0]);
2994			opline = zend_emit_op(NULL, ZEND_SEND_UNPACK, &arg_node, NULL);
2995			opline->op2.num = arg_count;
2996			opline->result.var = (uint32_t)(zend_intptr_t)ZEND_CALL_ARG(NULL, arg_count);
2997			continue;
2998		}
2999
3000		if (uses_arg_unpack) {
3001			zend_error_noreturn(E_COMPILE_ERROR,
3002				"Cannot use positional argument after argument unpacking");
3003		}
3004
3005		arg_count++;
3006		if (zend_is_variable(arg)) {
3007			if (zend_is_call(arg)) {
3008				zend_compile_var(&arg_node, arg, BP_VAR_R);
3009				if (arg_node.op_type & (IS_CONST|IS_TMP_VAR)) {
3010					/* Function call was converted into builtin instruction */
3011					opcode = ZEND_SEND_VAL;
3012				} else {
3013					opcode = ZEND_SEND_VAR_NO_REF;
3014					flags |= ZEND_ARG_SEND_FUNCTION;
3015					if (fbc && ARG_SHOULD_BE_SENT_BY_REF(fbc, arg_num)) {
3016						flags |= ZEND_ARG_SEND_BY_REF;
3017						if (ARG_MAY_BE_SENT_BY_REF(fbc, arg_num)) {
3018							flags |= ZEND_ARG_SEND_SILENT;
3019						}
3020					}
3021				}
3022			} else if (fbc) {
3023				if (ARG_SHOULD_BE_SENT_BY_REF(fbc, arg_num)) {
3024					zend_compile_var(&arg_node, arg, BP_VAR_W);
3025					opcode = ZEND_SEND_REF;
3026				} else {
3027					zend_compile_var(&arg_node, arg, BP_VAR_R);
3028					opcode = ZEND_SEND_VAR;
3029				}
3030			} else {
3031				zend_compile_var(&arg_node, arg,
3032					BP_VAR_FUNC_ARG | (arg_num << BP_VAR_SHIFT));
3033				opcode = ZEND_SEND_VAR_EX;
3034			}
3035		} else {
3036			zend_compile_expr(&arg_node, arg);
3037			ZEND_ASSERT(arg_node.op_type != IS_CV);
3038			if (arg_node.op_type == IS_VAR) {
3039				opcode = ZEND_SEND_VAR_NO_REF;
3040				if (fbc && ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
3041					flags |= ZEND_ARG_SEND_BY_REF;
3042				}
3043			} else {
3044				if (fbc) {
3045					opcode = ZEND_SEND_VAL;
3046					if (ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
3047						zend_error_noreturn(E_COMPILE_ERROR, "Only variables can be passed by reference");
3048					}
3049				} else {
3050					opcode = ZEND_SEND_VAL_EX;
3051				}
3052			}
3053		}
3054
3055		opline = zend_emit_op(NULL, opcode, &arg_node, NULL);
3056		opline->op2.opline_num = arg_num;
3057		opline->result.var = (uint32_t)(zend_intptr_t)ZEND_CALL_ARG(NULL, arg_num);
3058
3059		if (opcode == ZEND_SEND_VAR_NO_REF) {
3060			if (fbc) {
3061				flags |= ZEND_ARG_COMPILE_TIME_BOUND;
3062			}
3063			if ((flags & ZEND_ARG_COMPILE_TIME_BOUND) && !(flags & ZEND_ARG_SEND_BY_REF)) {
3064				opline->opcode = ZEND_SEND_VAR;
3065				opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
3066			} else {
3067				opline->extended_value = flags;
3068			}
3069		} else if (fbc) {
3070			opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
3071		}
3072	}
3073
3074	return arg_count;
3075}
3076/* }}} */
3077
3078ZEND_API zend_uchar zend_get_call_op(zend_uchar init_op, zend_function *fbc) /* {{{ */
3079{
3080	if (fbc) {
3081		if (fbc->type == ZEND_INTERNAL_FUNCTION) {
3082			if (!zend_execute_internal &&
3083			    !fbc->common.scope &&
3084			    !(fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED|ZEND_ACC_HAS_TYPE_HINTS|ZEND_ACC_RETURN_REFERENCE))) {
3085				return ZEND_DO_ICALL;
3086			}
3087		} else {
3088			if (zend_execute_ex == execute_ex &&
3089			    !(fbc->common.fn_flags & ZEND_ACC_GENERATOR)) {
3090				return ZEND_DO_UCALL;
3091			}
3092		}
3093	} else if (zend_execute_ex == execute_ex &&
3094	           !zend_execute_internal &&
3095	           (init_op == ZEND_INIT_FCALL_BY_NAME ||
3096	            init_op == ZEND_INIT_NS_FCALL_BY_NAME)) {
3097		return ZEND_DO_FCALL_BY_NAME;
3098	}
3099	return ZEND_DO_FCALL;
3100}
3101/* }}} */
3102
3103void zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *fbc) /* {{{ */
3104{
3105	zend_op *opline;
3106	uint32_t opnum_init = get_next_op_number(CG(active_op_array)) - 1;
3107	uint32_t arg_count;
3108	uint32_t call_flags;
3109
3110	zend_do_extended_fcall_begin();
3111
3112	arg_count = zend_compile_args(args_ast, fbc);
3113
3114	opline = &CG(active_op_array)->opcodes[opnum_init];
3115	opline->extended_value = arg_count;
3116
3117	if (opline->opcode == ZEND_INIT_FCALL) {
3118		opline->op1.num = zend_vm_calc_used_stack(arg_count, fbc);
3119	}
3120
3121	call_flags = (opline->opcode == ZEND_NEW ? ZEND_CALL_CTOR : 0);
3122	opline = zend_emit_op(result, zend_get_call_op(opline->opcode, fbc), NULL, NULL);
3123	opline->op1.num = call_flags;
3124
3125	zend_do_extended_fcall_end();
3126}
3127/* }}} */
3128
3129zend_bool zend_compile_function_name(znode *name_node, zend_ast *name_ast) /* {{{ */
3130{
3131	zend_string *orig_name = zend_ast_get_str(name_ast);
3132	zend_bool is_fully_qualified;
3133
3134	name_node->op_type = IS_CONST;
3135	ZVAL_STR(&name_node->u.constant, zend_resolve_function_name(
3136		orig_name, name_ast->attr, &is_fully_qualified));
3137
3138	return !is_fully_qualified && FC(current_namespace);
3139}
3140/* }}} */
3141
3142void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args_ast) /* {{{ */
3143{
3144	zend_op *opline = get_next_op(CG(active_op_array));
3145	opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
3146	SET_UNUSED(opline->op1);
3147	opline->op2_type = IS_CONST;
3148	opline->op2.constant = zend_add_ns_func_name_literal(
3149		CG(active_op_array), Z_STR(name_node->u.constant));
3150	zend_alloc_cache_slot(opline->op2.constant);
3151
3152	zend_compile_call_common(result, args_ast, NULL);
3153}
3154/* }}} */
3155
3156void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_ast) /* {{{ */
3157{
3158	if (name_node->op_type == IS_CONST && Z_TYPE(name_node->u.constant) == IS_STRING) {
3159		const char *colon;
3160		zend_string *str = Z_STR(name_node->u.constant);
3161		if ((colon = zend_memrchr(ZSTR_VAL(str), ':', ZSTR_LEN(str))) != NULL && colon > ZSTR_VAL(str) && *(colon - 1) == ':') {
3162			zend_string *class = zend_string_init(ZSTR_VAL(str), colon - ZSTR_VAL(str) - 1, 0);
3163			zend_string *method = zend_string_init(colon + 1, ZSTR_LEN(str) - (colon - ZSTR_VAL(str)) - 1, 0);
3164			zend_op *opline = get_next_op(CG(active_op_array));
3165
3166			opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
3167			opline->op1_type = IS_CONST;
3168			opline->op1.constant = zend_add_class_name_literal(CG(active_op_array), class);
3169			opline->op2_type = IS_CONST;
3170			opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), method);
3171			zend_alloc_cache_slot(opline->op2.constant);
3172			zval_ptr_dtor(&name_node->u.constant);
3173		} else {
3174			zend_op *opline = get_next_op(CG(active_op_array));
3175
3176			opline->opcode = ZEND_INIT_FCALL_BY_NAME;
3177			SET_UNUSED(opline->op1);
3178			opline->op2_type = IS_CONST;
3179			opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), str);
3180			zend_alloc_cache_slot(opline->op2.constant);
3181		}
3182	} else {
3183		zend_emit_op(NULL, ZEND_INIT_DYNAMIC_CALL, NULL, name_node);
3184	}
3185
3186	zend_compile_call_common(result, args_ast, NULL);
3187}
3188/* }}} */
3189
3190static zend_bool zend_args_contain_unpack(zend_ast_list *args) /* {{{ */
3191{
3192	uint32_t i;
3193	for (i = 0; i < args->children; ++i) {
3194		if (args->child[i]->kind == ZEND_AST_UNPACK) {
3195			return 1;
3196		}
3197	}
3198	return 0;
3199}
3200/* }}} */
3201
3202int zend_compile_func_strlen(znode *result, zend_ast_list *args) /* {{{ */
3203{
3204	znode arg_node;
3205
3206	if ((CG(compiler_options) & ZEND_COMPILE_NO_BUILTIN_STRLEN)
3207		|| args->children != 1 || args->child[0]->kind == ZEND_AST_UNPACK
3208	) {
3209		return FAILURE;
3210	}
3211
3212	zend_compile_expr(&arg_node, args->child[0]);
3213	if (arg_node.op_type == IS_CONST && Z_TYPE(arg_node.u.constant) == IS_STRING) {
3214		result->op_type = IS_CONST;
3215		ZVAL_LONG(&result->u.constant, Z_STRLEN(arg_node.u.constant));
3216		zval_dtor(&arg_node.u.constant);
3217	} else {
3218		zend_emit_op_tmp(result, ZEND_STRLEN, &arg_node, NULL);
3219	}
3220	return SUCCESS;
3221}
3222/* }}} */
3223
3224int zend_compile_func_typecheck(znode *result, zend_ast_list *args, uint32_t type) /* {{{ */
3225{
3226	znode arg_node;
3227	zend_op *opline;
3228
3229	if (args->children != 1 || args->child[0]->kind == ZEND_AST_UNPACK) {
3230		return FAILURE;
3231	}
3232
3233	zend_compile_expr(&arg_node, args->child[0]);
3234	opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &arg_node, NULL);
3235	opline->extended_value = type;
3236	return SUCCESS;
3237}
3238/* }}} */
3239
3240int zend_compile_func_defined(znode *result, zend_ast_list *args) /* {{{ */
3241{
3242	zend_string *name;
3243	zend_op *opline;
3244
3245	if (args->children != 1 || args->child[0]->kind != ZEND_AST_ZVAL) {
3246		return FAILURE;
3247	}
3248
3249	name = zval_get_string(zend_ast_get_zval(args->child[0]));
3250	if (zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name)) || zend_memrchr(ZSTR_VAL(name), ':', ZSTR_LEN(name))) {
3251		zend_string_release(name);
3252		return FAILURE;
3253	}
3254
3255	opline = zend_emit_op_tmp(result, ZEND_DEFINED, NULL, NULL);
3256	opline->op1_type = IS_CONST;
3257	LITERAL_STR(opline->op1, name);
3258	zend_alloc_cache_slot(opline->op1.constant);
3259
3260	/* Lowercase constant name in a separate literal */
3261	{
3262		zval c;
3263		zend_string *lcname = zend_string_tolower(name);
3264		ZVAL_NEW_STR(&c, lcname);
3265		zend_add_literal(CG(active_op_array), &c);
3266	}
3267	return SUCCESS;
3268}
3269/* }}} */
3270
3271static int zend_try_compile_ct_bound_init_user_func(zend_ast *name_ast, uint32_t num_args) /* {{{ */
3272{
3273	zend_string *name, *lcname;
3274	zend_function *fbc;
3275	zend_op *opline;
3276
3277	if (name_ast->kind != ZEND_AST_ZVAL || Z_TYPE_P(zend_ast_get_zval(name_ast)) != IS_STRING) {
3278		return FAILURE;
3279	}
3280
3281	name = zend_ast_get_str(name_ast);
3282	lcname = zend_string_tolower(name);
3283
3284	fbc = zend_hash_find_ptr(CG(function_table), lcname);
3285	if (!fbc
3286	 || (fbc->type == ZEND_INTERNAL_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS))
3287	 || (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_USER_FUNCTIONS))
3288	) {
3289		zend_string_release(lcname);
3290		return FAILURE;
3291	}
3292
3293	opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, NULL);
3294	opline->extended_value = num_args;
3295	opline->op1.num = zend_vm_calc_used_stack(num_args, fbc);
3296	opline->op2_type = IS_CONST;
3297	LITERAL_STR(opline->op2, lcname);
3298	zend_alloc_cache_slot(opline->op2.constant);
3299
3300	return SUCCESS;
3301}
3302/* }}} */
3303
3304static void zend_compile_init_user_func(zend_ast *name_ast, uint32_t num_args, zend_string *orig_func_name) /* {{{ */
3305{
3306	zend_op *opline;
3307	znode name_node;
3308
3309	if (zend_try_compile_ct_bound_init_user_func(name_ast, num_args) == SUCCESS) {
3310		return;
3311	}
3312
3313	zend_compile_expr(&name_node, name_ast);
3314
3315	opline = zend_emit_op(NULL, ZEND_INIT_USER_CALL, NULL, &name_node);
3316	opline->op1_type = IS_CONST;
3317	LITERAL_STR(opline->op1, zend_string_copy(orig_func_name));
3318	opline->extended_value = num_args;
3319}
3320/* }}} */
3321
3322/* cufa = call_user_func_array */
3323int zend_compile_func_cufa(znode *result, zend_ast_list *args, zend_string *lcname) /* {{{ */
3324{
3325	znode arg_node;
3326
3327	if (args->children != 2 || zend_args_contain_unpack(args)) {
3328		return FAILURE;
3329	}
3330
3331	zend_compile_init_user_func(args->child[0], 0, lcname);
3332	zend_compile_expr(&arg_node, args->child[1]);
3333	zend_emit_op(NULL, ZEND_SEND_ARRAY, &arg_node, NULL);
3334	zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL);
3335
3336	return SUCCESS;
3337}
3338/* }}} */
3339
3340/* cuf = call_user_func */
3341int zend_compile_func_cuf(znode *result, zend_ast_list *args, zend_string *lcname) /* {{{ */
3342{
3343	uint32_t i;
3344
3345	if (args->children < 1 || zend_args_contain_unpack(args)) {
3346		return FAILURE;
3347	}
3348
3349	zend_compile_init_user_func(args->child[0], args->children - 1, lcname);
3350	for (i = 1; i < args->children; ++i) {
3351		zend_ast *arg_ast = args->child[i];
3352		znode arg_node;
3353		zend_op *opline;
3354		zend_bool send_user = 0;
3355
3356		if (zend_is_variable(arg_ast) && !zend_is_call(arg_ast)) {
3357			zend_compile_var(&arg_node, arg_ast, BP_VAR_FUNC_ARG | (i << BP_VAR_SHIFT));
3358			send_user = 1;
3359		} else {
3360			zend_compile_expr(&arg_node, arg_ast);
3361			if (arg_node.op_type & (IS_VAR|IS_CV)) {
3362				send_user = 1;
3363			}
3364		}
3365
3366		if (send_user) {
3367			opline = zend_emit_op(NULL, ZEND_SEND_USER, &arg_node, NULL);
3368		} else {
3369			opline = zend_emit_op(NULL, ZEND_SEND_VAL, &arg_node, NULL);
3370		}
3371
3372		opline->op2.num = i;
3373		opline->result.var = (uint32_t)(zend_intptr_t)ZEND_CALL_ARG(NULL, i);
3374	}
3375	zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL);
3376
3377	return SUCCESS;
3378}
3379/* }}} */
3380
3381static void zend_compile_assert_side_effects(zend_ast *ast) /* {{{ */
3382{
3383	int i;
3384	int children = zend_ast_is_list(ast) ? zend_ast_get_list(ast)->children : zend_ast_get_num_children(ast);
3385
3386	for (i = 0; i < children; i++) {
3387		zend_ast *child = (zend_ast_is_list(ast) ? zend_ast_get_list(ast)->child : ast->child)[i];
3388		if (child) {
3389			if (child->kind == ZEND_AST_YIELD) {
3390				zend_mark_function_as_generator();
3391			} else if (ast->kind >= ZEND_AST_IS_LIST_SHIFT) {
3392				zend_compile_assert_side_effects(child);
3393			}
3394		}
3395	}
3396}
3397/* }}} */
3398
3399static int zend_compile_assert(znode *result, zend_ast_list *args, zend_string *name, zend_function *fbc) /* {{{ */
3400{
3401	if (EG(assertions) >= 0) {
3402		znode name_node;
3403		zend_op *opline;
3404		uint32_t check_op_number = get_next_op_number(CG(active_op_array));
3405
3406		zend_emit_op(NULL, ZEND_ASSERT_CHECK, NULL, NULL);
3407
3408		if (fbc) {
3409			name_node.op_type = IS_CONST;
3410			ZVAL_STR_COPY(&name_node.u.constant, name);
3411
3412			opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, &name_node);
3413		} else {
3414			opline = zend_emit_op(NULL, ZEND_INIT_NS_FCALL_BY_NAME, NULL, NULL);
3415			opline->op2_type = IS_CONST;
3416			opline->op2.constant = zend_add_ns_func_name_literal(
3417				CG(active_op_array), name);
3418		}
3419		zend_alloc_cache_slot(opline->op2.constant);
3420
3421		if (args->children == 1 &&
3422		    (args->child[0]->kind != ZEND_AST_ZVAL ||
3423		     Z_TYPE_P(zend_ast_get_zval(args->child[0])) != IS_STRING)) {
3424			/* add "assert(condition) as assertion message */
3425			zend_ast_list_add((zend_ast*)args,
3426				zend_ast_create_zval_from_str(
3427					zend_ast_export("assert(", args->child[0], ")")));
3428		}
3429
3430		zend_compile_call_common(result, (zend_ast*)args, fbc);
3431
3432		opline = &CG(active_op_array)->opcodes[check_op_number];
3433		opline->op2.opline_num = get_next_op_number(CG(active_op_array));
3434		SET_NODE(opline->result, result);
3435	} else {
3436		if (!fbc) {
3437			zend_string_release(name);
3438		}
3439		result->op_type = IS_CONST;
3440		ZVAL_TRUE(&result->u.constant);
3441
3442		zend_compile_assert_side_effects((zend_ast *) args);
3443	}
3444
3445	return SUCCESS;
3446}
3447/* }}} */
3448
3449int zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_list *args, zend_function *fbc) /* {{{ */
3450{
3451	if (fbc->internal_function.handler == ZEND_FN(display_disabled_function)) {
3452		return FAILURE;
3453	}
3454
3455	if (zend_string_equals_literal(lcname, "strlen")) {
3456		return zend_compile_func_strlen(result, args);
3457	} else if (zend_string_equals_literal(lcname, "is_null")) {
3458		return zend_compile_func_typecheck(result, args, IS_NULL);
3459	} else if (zend_string_equals_literal(lcname, "is_bool")) {
3460		return zend_compile_func_typecheck(result, args, _IS_BOOL);
3461	} else if (zend_string_equals_literal(lcname, "is_long")
3462		|| zend_string_equals_literal(lcname, "is_int")
3463		|| zend_string_equals_literal(lcname, "is_integer")
3464	) {
3465		return zend_compile_func_typecheck(result, args, IS_LONG);
3466	} else if (zend_string_equals_literal(lcname, "is_float")
3467		|| zend_string_equals_literal(lcname, "is_double")
3468		|| zend_string_equals_literal(lcname, "is_real")
3469	) {
3470		return zend_compile_func_typecheck(result, args, IS_DOUBLE);
3471	} else if (zend_string_equals_literal(lcname, "is_string")) {
3472		return zend_compile_func_typecheck(result, args, IS_STRING);
3473	} else if (zend_string_equals_literal(lcname, "is_array")) {
3474		return zend_compile_func_typecheck(result, args, IS_ARRAY);
3475	} else if (zend_string_equals_literal(lcname, "is_object")) {
3476		return zend_compile_func_typecheck(result, args, IS_OBJECT);
3477	} else if (zend_string_equals_literal(lcname, "is_resource")) {
3478		return zend_compile_func_typecheck(result, args, IS_RESOURCE);
3479	} else if (zend_string_equals_literal(lcname, "defined")) {
3480		return zend_compile_func_defined(result, args);
3481	} else if (zend_string_equals_literal(lcname, "call_user_func_array")) {
3482		return zend_compile_func_cufa(result, args, lcname);
3483	} else if (zend_string_equals_literal(lcname, "call_user_func")) {
3484		return zend_compile_func_cuf(result, args, lcname);
3485	} else if (zend_string_equals_literal(lcname, "assert")) {
3486		return zend_compile_assert(result, args, lcname, fbc);
3487	} else {
3488		return FAILURE;
3489	}
3490}
3491/* }}} */
3492
3493void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
3494{
3495	zend_ast *name_ast = ast->child[0];
3496	zend_ast *args_ast = ast->child[1];
3497
3498	znode name_node;
3499
3500	if (name_ast->kind != ZEND_AST_ZVAL || Z_TYPE_P(zend_ast_get_zval(name_ast)) != IS_STRING) {
3501		zend_compile_expr(&name_node, name_ast);
3502		zend_compile_dynamic_call(result, &name_node, args_ast);
3503		return;
3504	}
3505
3506	{
3507		zend_bool runtime_resolution = zend_compile_function_name(&name_node, name_ast);
3508		if (runtime_resolution) {
3509			if (zend_string_equals_literal_ci(zend_ast_get_str(name_ast), "assert")) {
3510				zend_compile_assert(result, zend_ast_get_list(args_ast), Z_STR(name_node.u.constant), NULL);
3511			} else {
3512				zend_compile_ns_call(result, &name_node, args_ast);
3513			}
3514			return;
3515		}
3516	}
3517
3518	{
3519		zval *name = &name_node.u.constant;
3520		zend_string *lcname;
3521		zend_function *fbc;
3522		zend_op *opline;
3523
3524		lcname = zend_string_tolower(Z_STR_P(name));
3525
3526		fbc = zend_hash_find_ptr(CG(function_table), lcname);
3527		if (!fbc
3528		 || (fbc->type == ZEND_INTERNAL_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS))
3529		 || (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_USER_FUNCTIONS))
3530		) {
3531			zend_string_release(lcname);
3532			zend_compile_dynamic_call(result, &name_node, args_ast);
3533			return;
3534		}
3535
3536		if (zend_try_compile_special_func(result, lcname,
3537				zend_ast_get_list(args_ast), fbc) == SUCCESS
3538		) {
3539			zend_string_release(lcname);
3540			zval_ptr_dtor(&name_node.u.constant);
3541			return;
3542		}
3543
3544		zval_ptr_dtor(&name_node.u.constant);
3545		ZVAL_NEW_STR(&name_node.u.constant, lcname);
3546
3547		opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, &name_node);
3548		zend_alloc_cache_slot(opline->op2.constant);
3549
3550		zend_compile_call_common(result, args_ast, fbc);
3551	}
3552}
3553/* }}} */
3554
3555void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
3556{
3557	zend_ast *obj_ast = ast->child[0];
3558	zend_ast *method_ast = ast->child[1];
3559	zend_ast *args_ast = ast->child[2];
3560
3561	znode obj_node, method_node;
3562	zend_op *opline;
3563
3564	if (is_this_fetch(obj_ast)) {
3565		obj_node.op_type = IS_UNUSED;
3566	} else {
3567		zend_compile_expr(&obj_node, obj_ast);
3568	}
3569
3570	zend_compile_expr(&method_node, method_ast);
3571	opline = zend_emit_op(NULL, ZEND_INIT_METHOD_CALL, &obj_node, NULL);
3572
3573	if (method_node.op_type == IS_CONST) {
3574		if (Z_TYPE(method_node.u.constant) != IS_STRING) {
3575			zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string");
3576		}
3577
3578		opline->op2_type = IS_CONST;
3579		opline->op2.constant = zend_add_func_name_literal(CG(active_op_array),
3580			Z_STR(method_node.u.constant));
3581		zend_alloc_polymorphic_cache_slot(opline->op2.constant);
3582	} else {
3583		SET_NODE(opline->op2, &method_node);
3584	}
3585
3586	zend_compile_call_common(result, args_ast, NULL);
3587}
3588/* }}} */
3589
3590static zend_bool zend_is_constructor(zend_string *name) /* {{{ */
3591{
3592	return zend_string_equals_literal_ci(name, ZEND_CONSTRUCTOR_FUNC_NAME);
3593}
3594/* }}} */
3595
3596void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
3597{
3598	zend_ast *class_ast = ast->child[0];
3599	zend_ast *method_ast = ast->child[1];
3600	zend_ast *args_ast = ast->child[2];
3601
3602	znode class_node, method_node;
3603	zend_op *opline;
3604
3605	zend_compile_class_ref_ex(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
3606
3607	zend_compile_expr(&method_node, method_ast);
3608	if (method_node.op_type == IS_CONST) {
3609		zval *name = &method_node.u.constant;
3610		if (Z_TYPE_P(name) != IS_STRING) {
3611			zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string");
3612		}
3613		if (zend_is_constructor(Z_STR_P(name))) {
3614			zval_ptr_dtor(name);
3615			method_node.op_type = IS_UNUSED;
3616		}
3617	}
3618
3619	opline = get_next_op(CG(active_op_array));
3620	opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
3621
3622	zend_set_class_name_op1(opline, &class_node);
3623
3624	if (method_node.op_type == IS_CONST) {
3625		opline->op2_type = IS_CONST;
3626		opline->op2.constant = zend_add_func_name_literal(CG(active_op_array),
3627			Z_STR(method_node.u.constant));
3628		if (opline->op1_type == IS_CONST) {
3629			zend_alloc_cache_slot(opline->op2.constant);
3630		} else {
3631			zend_alloc_polymorphic_cache_slot(opline->op2.constant);
3632		}
3633	} else {
3634		SET_NODE(opline->op2, &method_node);
3635	}
3636	zend_check_live_ranges(opline);
3637
3638	zend_compile_call_common(result, args_ast, NULL);
3639}
3640/* }}} */
3641
3642void zend_compile_class_decl(zend_ast *ast);
3643
3644void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */
3645{
3646	zend_ast *class_ast = ast->child[0];
3647	zend_ast *args_ast = ast->child[1];
3648
3649	znode class_node, ctor_result;
3650	zend_op *opline;
3651	uint32_t opnum;
3652
3653	if (class_ast->kind == ZEND_AST_CLASS) {
3654		uint32_t dcl_opnum = get_next_op_number(CG(active_op_array));
3655		zend_compile_class_decl(class_ast);
3656		/* jump over anon class declaration */
3657		opline = &CG(active_op_array)->opcodes[dcl_opnum];
3658		if (opline->opcode == ZEND_FETCH_CLASS) {
3659			opline++;
3660		}
3661		class_node.op_type = opline->result_type;
3662		class_node.u.op.var = opline->result.var;
3663		opline->extended_value = get_next_op_number(CG(active_op_array));
3664	} else {
3665		zend_compile_class_ref_ex(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
3666	}
3667
3668	opnum = get_next_op_number(CG(active_op_array));
3669	opline = zend_emit_op(result, ZEND_NEW, NULL, NULL);
3670
3671	if (class_node.op_type == IS_CONST) {
3672		opline->op1_type = IS_CONST;
3673		opline->op1.constant = zend_add_class_name_literal(
3674			CG(active_op_array), Z_STR(class_node.u.constant));
3675	} else {
3676		SET_NODE(opline->op1, &class_node);
3677	}
3678
3679	zend_compile_call_common(&ctor_result, args_ast, NULL);
3680	zend_do_free(&ctor_result);
3681
3682	/* New jumps over ctor call if ctor does not exist */
3683	opline = &CG(active_op_array)->opcodes[opnum];
3684	opline->op2.opline_num = get_next_op_number(CG(active_op_array));
3685}
3686/* }}} */
3687
3688void zend_compile_clone(znode *result, zend_ast *ast) /* {{{ */
3689{
3690	zend_ast *obj_ast = ast->child[0];
3691
3692	znode obj_node;
3693	zend_compile_expr(&obj_node, obj_ast);
3694
3695	zend_emit_op_tmp(result, ZEND_CLONE, &obj_node, NULL);
3696}
3697/* }}} */
3698
3699void zend_compile_global_var(zend_ast *ast) /* {{{ */
3700{
3701	zend_ast *var_ast = ast->child[0];
3702	zend_ast *name_ast = var_ast->child[0];
3703
3704	znode name_node, result;
3705
3706	zend_compile_expr(&name_node, name_ast);
3707	if (name_node.op_type == IS_CONST) {
3708		convert_to_string(&name_node.u.constant);
3709	}
3710
3711	if (zend_try_compile_cv(&result, var_ast) == SUCCESS) {
3712		zend_op *opline = zend_emit_op(NULL, ZEND_BIND_GLOBAL, &result, &name_node);
3713		zend_alloc_cache_slot(opline->op2.constant);
3714	} else {
3715		/* name_ast should be evaluated only. FETCH_GLOBAL_LOCK instructs FETCH_W
3716		 * to not free the name_node operand, so it can be reused in the following
3717		 * ASSIGN_REF, which then frees it. */
3718		zend_op *opline = zend_emit_op(&result, ZEND_FETCH_W, &name_node, NULL);
3719		opline->extended_value = ZEND_FETCH_GLOBAL_LOCK;
3720
3721		zend_emit_assign_ref_znode(
3722			zend_ast_create(ZEND_AST_VAR, zend_ast_create_znode(&name_node)),
3723			&result
3724		);
3725	}
3726}
3727/* }}} */
3728
3729static void zend_compile_static_var_common(zend_ast *var_ast, zval *value, zend_bool by_ref) /* {{{ */
3730{
3731	znode var_node;
3732	zend_op *opline;
3733
3734	zend_compile_expr(&var_node, var_ast);
3735
3736	if (!CG(active_op_array)->static_variables) {
3737		if (CG(active_op_array)->scope) {
3738			CG(active_op_array)->scope->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
3739		}
3740		ALLOC_HASHTABLE(CG(active_op_array)->static_variables);
3741		zend_hash_init(CG(active_op_array)->static_variables, 8, NULL, ZVAL_PTR_DTOR, 0);
3742	}
3743
3744	if (GC_REFCOUNT(CG(active_op_array)->static_variables) > 1) {
3745		if (!(GC_FLAGS(CG(active_op_array)->static_variables) & IS_ARRAY_IMMUTABLE)) {
3746			GC_REFCOUNT(CG(active_op_array)->static_variables)--;
3747		}
3748		CG(active_op_array)->static_variables = zend_array_dup(CG(active_op_array)->static_variables);
3749	}
3750	zend_hash_update(CG(active_op_array)->static_variables, Z_STR(var_node.u.constant), value);
3751
3752	opline = zend_emit_op(NULL, ZEND_BIND_STATIC, NULL, &var_node);
3753	opline->op1_type = IS_CV;
3754	opline->op1.var = lookup_cv(CG(active_op_array), zend_string_copy(Z_STR(var_node.u.constant)));
3755	opline->extended_value = by_ref;
3756}
3757/* }}} */
3758
3759void zend_compile_static_var(zend_ast *ast) /* {{{ */
3760{
3761	zend_ast *var_ast = ast->child[0];
3762	zend_ast *value_ast = ast->child[1];
3763	zval value_zv;
3764
3765	if (value_ast) {
3766		zend_const_expr_to_zval(&value_zv, value_ast);
3767	} else {
3768		ZVAL_NULL(&value_zv);
3769	}
3770
3771	zend_compile_static_var_common(var_ast, &value_zv, 1);
3772}
3773/* }}} */
3774
3775void zend_compile_unset(zend_ast *ast) /* {{{ */
3776{
3777	zend_ast *var_ast = ast->child[0];
3778	znode var_node;
3779	zend_op *opline;
3780
3781	zend_ensure_writable_variable(var_ast);
3782
3783	switch (var_ast->kind) {
3784		case ZEND_AST_VAR:
3785			if (zend_try_compile_cv(&var_node, var_ast) == SUCCESS) {
3786				opline = zend_emit_op(NULL, ZEND_UNSET_VAR, &var_node, NULL);
3787				opline->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
3788			} else {
3789				opline = zend_compile_simple_var_no_cv(NULL, var_ast, BP_VAR_UNSET, 0);
3790				opline->opcode = ZEND_UNSET_VAR;
3791			}
3792			return;
3793		case ZEND_AST_DIM:
3794			opline = zend_compile_dim_common(NULL, var_ast, BP_VAR_UNSET);
3795			opline->opcode = ZEND_UNSET_DIM;
3796			return;
3797		case ZEND_AST_PROP:
3798			opline = zend_compile_prop_common(NULL, var_ast, BP_VAR_UNSET);
3799			opline->opcode = ZEND_UNSET_OBJ;
3800			return;
3801		case ZEND_AST_STATIC_PROP:
3802			opline = zend_compile_static_prop_common(NULL, var_ast, BP_VAR_UNSET, 0);
3803			opline->opcode = ZEND_UNSET_STATIC_PROP;
3804			return;
3805		EMPTY_SWITCH_DEFAULT_CASE()
3806	}
3807}
3808/* }}} */
3809
3810static int zend_handle_loops_and_finally_ex(zend_long depth) /* {{{ */
3811{
3812	zend_loop_var *base;
3813	zend_loop_var *loop_var = zend_stack_top(&CG(loop_var_stack));
3814
3815	if (!loop_var) {
3816		return 1;
3817	}
3818	base = zend_stack_base(&CG(loop_var_stack));
3819	for (; loop_var >= base; loop_var--) {
3820		if (loop_var->opcode == ZEND_FAST_CALL) {
3821			zend_op *opline = get_next_op(CG(active_op_array));
3822
3823			opline->opcode = ZEND_FAST_CALL;
3824			opline->result_type = IS_TMP_VAR;
3825			opline->result.var = loop_var->var_num;
3826			SET_UNUSED(opline->op1);
3827			SET_UNUSED(opline->op2);
3828			opline->op1.num = loop_var->u.try_catch_offset;
3829		} else if (loop_var->opcode == ZEND_RETURN) {
3830			/* Stack separator */
3831			break;
3832		} else if (depth <= 1) {
3833			return 1;
3834		} else if (loop_var->opcode == ZEND_NOP) {
3835			/* Loop doesn't have freeable variable */
3836			depth--;
3837		} else {
3838			zend_op *opline;
3839
3840			ZEND_ASSERT(loop_var->var_type == IS_VAR || loop_var->var_type == IS_TMP_VAR);
3841			opline = get_next_op(CG(active_op_array));
3842			opline->opcode = loop_var->opcode;
3843			opline->op1_type = loop_var->var_type;
3844			opline->op1.var = loop_var->var_num;
3845			SET_UNUSED(opline->op2);
3846			opline->op2.num = loop_var->u.live_range_offset;
3847			opline->extended_value = ZEND_FREE_ON_RETURN;
3848			depth--;
3849	    }
3850	}
3851	return (depth == 0);
3852}
3853/* }}} */
3854
3855static int zend_handle_loops_and_finally(void) /* {{{ */
3856{
3857	return zend_handle_loops_and_finally_ex(zend_stack_count(&CG(loop_var_stack)) + 1);
3858}
3859/* }}} */
3860
3861void zend_compile_return(zend_ast *ast) /* {{{ */
3862{
3863	zend_ast *expr_ast = ast->child[0];
3864	zend_bool by_ref = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
3865
3866	znode expr_node;
3867	zend_op *opline;
3868
3869	if (!expr_ast) {
3870		expr_node.op_type = IS_CONST;
3871		ZVAL_NULL(&expr_node.u.constant);
3872	} else if (by_ref && zend_is_variable(expr_ast) && !zend_is_call(expr_ast)) {
3873		zend_compile_var(&expr_node, expr_ast, BP_VAR_W);
3874	} else {
3875		zend_compile_expr(&expr_node, expr_ast);
3876	}
3877
3878	if (CG(context).in_finally) {
3879		opline = zend_emit_op(NULL, ZEND_DISCARD_EXCEPTION, NULL, NULL);
3880		opline->op1_type = IS_TMP_VAR;
3881		opline->op1.var = CG(context).fast_call_var;
3882	}
3883
3884	/* Generator return types are handled separately */
3885	if (!(CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) && CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
3886		zend_emit_return_type_check(expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1);
3887	}
3888
3889	zend_handle_loops_and_finally();
3890
3891	opline = zend_emit_op(NULL, by_ref ? ZEND_RETURN_BY_REF : ZEND_RETURN,
3892		&expr_node, NULL);
3893
3894	if (expr_ast) {
3895		if (zend_is_call(expr_ast)) {
3896			opline->extended_value = ZEND_RETURNS_FUNCTION;
3897		} else if (by_ref && !zend_is_variable(expr_ast)) {
3898			opline->extended_value = ZEND_RETURNS_VALUE;
3899		}
3900	}
3901}
3902/* }}} */
3903
3904void zend_compile_echo(zend_ast *ast) /* {{{ */
3905{
3906	zend_op *opline;
3907	zend_ast *expr_ast = ast->child[0];
3908
3909	znode expr_node;
3910	zend_compile_expr(&expr_node, expr_ast);
3911
3912	opline = zend_emit_op(NULL, ZEND_ECHO, &expr_node, NULL);
3913	opline->extended_value = 0;
3914}
3915/* }}} */
3916
3917void zend_compile_throw(zend_ast *ast) /* {{{ */
3918{
3919	zend_ast *expr_ast = ast->child[0];
3920
3921	znode expr_node;
3922	zend_compile_expr(&expr_node, expr_ast);
3923
3924	zend_emit_op(NULL, ZEND_THROW, &expr_node, NULL);
3925}
3926/* }}} */
3927
3928void zend_compile_break_continue(zend_ast *ast) /* {{{ */
3929{
3930	zend_ast *depth_ast = ast->child[0];
3931
3932	zend_op *opline;
3933	int depth;
3934
3935	ZEND_ASSERT(ast->kind == ZEND_AST_BREAK || ast->kind == ZEND_AST_CONTINUE);
3936
3937	if (depth_ast) {
3938		zval *depth_zv;
3939		if (depth_ast->kind != ZEND_AST_ZVAL) {
3940			zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator with non-constant operand "
3941				"is no longer supported", ast->kind == ZEND_AST_BREAK ? "break" : "continue");
3942		}
3943
3944		depth_zv = zend_ast_get_zval(depth_ast);
3945		if (Z_TYPE_P(depth_zv) != IS_LONG || Z_LVAL_P(depth_zv) < 1) {
3946			zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator accepts only positive numbers",
3947				ast->kind == ZEND_AST_BREAK ? "break" : "continue");
3948		}
3949
3950		depth = Z_LVAL_P(depth_zv);
3951	} else {
3952		depth = 1;
3953	}
3954
3955	if (CG(context).current_brk_cont == -1) {
3956		zend_error_noreturn(E_COMPILE_ERROR, "'%s' not in the 'loop' or 'switch' context",
3957			ast->kind == ZEND_AST_BREAK ? "break" : "continue");
3958	} else {
3959		if (!zend_handle_loops_and_finally_ex(depth)) {
3960			zend_error_noreturn(E_COMPILE_ERROR, "Cannot '%s' %d level%s",
3961				ast->kind == ZEND_AST_BREAK ? "break" : "continue",
3962				depth, depth == 1 ? "" : "s");
3963		}
3964	}
3965	opline = zend_emit_op(NULL, ast->kind == ZEND_AST_BREAK ? ZEND_BRK : ZEND_CONT, NULL, NULL);
3966	opline->op1.num = CG(context).current_brk_cont;
3967	opline->op2.num = depth;
3968}
3969/* }}} */
3970
3971void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline) /* {{{ */
3972{
3973	zend_label *dest;
3974	int current, remove_oplines = opline->op1.num;
3975	zval *label;
3976	uint32_t opnum = opline - op_array->opcodes;
3977
3978	label = CT_CONSTANT_EX(op_array, opline->op2.constant);
3979	if (CG(context).labels == NULL ||
3980	    (dest = zend_hash_find_ptr(CG(context).labels, Z_STR_P(label))) == NULL
3981	) {
3982		CG(in_compilation) = 1;
3983		CG(active_op_array) = op_array;
3984		CG(zend_lineno) = opline->lineno;
3985		zend_error_noreturn(E_COMPILE_ERROR, "'goto' to undefined label '%s'", Z_STRVAL_P(label));
3986	}
3987
3988	zval_dtor(label);
3989	ZVAL_NULL(label);
3990
3991	current = opline->extended_value;
3992	for (; current != dest->brk_cont; current = CG(context).brk_cont_array[current].parent) {
3993		if (current == -1) {
3994			CG(in_compilation) = 1;
3995			CG(active_op_array) = op_array;
3996			CG(zend_lineno) = opline->lineno;
3997			zend_error_noreturn(E_COMPILE_ERROR, "'goto' into loop or switch statement is disallowed");
3998		}
3999		if (CG(context).brk_cont_array[current].start >= 0) {
4000			remove_oplines--;
4001		}
4002	}
4003
4004	for (current = 0; current < op_array->last_try_catch; ++current) {
4005		zend_try_catch_element *elem = &op_array->try_catch_array[current];
4006		if (elem->try_op > opnum) {
4007			break;
4008		}
4009		if (elem->finally_op && opnum < elem->finally_op - 1
4010			&& (dest->opline_num > elem->finally_end || dest->opline_num < elem->try_op)
4011		) {
4012			remove_oplines--;
4013		}
4014	}
4015
4016	opline->opcode = ZEND_JMP;
4017	opline->op1.opline_num = dest->opline_num;
4018	opline->extended_value = 0;
4019	SET_UNUSED(opline->op1);
4020	SET_UNUSED(opline->op2);
4021	SET_UNUSED(opline->result);
4022
4023	ZEND_ASSERT(remove_oplines >= 0);
4024	while (remove_oplines--) {
4025		opline--;
4026		MAKE_NOP(opline);
4027		ZEND_VM_SET_OPCODE_HANDLER(opline);
4028	}
4029}
4030/* }}} */
4031
4032void zend_compile_goto(zend_ast *ast) /* {{{ */
4033{
4034	zend_ast *label_ast = ast->child[0];
4035	znode label_node;
4036	zend_op *opline;
4037	uint32_t opnum_start = get_next_op_number(CG(active_op_array));
4038
4039	zend_compile_expr(&label_node, label_ast);
4040
4041	/* Label resolution and unwinding adjustments happen in pass two. */
4042	zend_handle_loops_and_finally();
4043	opline = zend_emit_op(NULL, ZEND_GOTO, NULL, &label_node);
4044	opline->op1.num = get_next_op_number(CG(active_op_array)) - opnum_start - 1;
4045	opline->extended_value = CG(context).current_brk_cont;
4046}
4047/* }}} */
4048
4049void zend_compile_label(zend_ast *ast) /* {{{ */
4050{
4051	zend_string *label = zend_ast_get_str(ast->child[0]);
4052	zend_label dest;
4053
4054	if (!CG(context).labels) {
4055		ALLOC_HASHTABLE(CG(context).labels);
4056		zend_hash_init(CG(context).labels, 8, NULL, label_ptr_dtor, 0);
4057	}
4058
4059	dest.brk_cont = CG(context).current_brk_cont;
4060	dest.opline_num = get_next_op_number(CG(active_op_array));
4061
4062	if (!zend_hash_add_mem(CG(context).labels, label, &dest, sizeof(zend_label))) {
4063		zend_error_noreturn(E_COMPILE_ERROR, "Label '%s' already defined", ZSTR_VAL(label));
4064	}
4065}
4066/* }}} */
4067
4068void zend_compile_while(zend_ast *ast) /* {{{ */
4069{
4070	zend_ast *cond_ast = ast->child[0];
4071	zend_ast *stmt_ast = ast->child[1];
4072	znode cond_node;
4073	uint32_t opnum_start, opnum_jmp, opnum_cond;
4074
4075	opnum_jmp = zend_emit_jump(0);
4076
4077	zend_begin_loop(ZEND_NOP, NULL);
4078
4079	opnum_start = get_next_op_number(CG(active_op_array));
4080	zend_compile_stmt(stmt_ast);
4081
4082	opnum_cond = get_next_op_number(CG(active_op_array));
4083	zend_update_jump_target(opnum_jmp, opnum_cond);
4084	zend_compile_expr(&cond_node, cond_ast);
4085
4086	zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, opnum_start);
4087
4088	zend_end_loop(opnum_cond, NULL);
4089}
4090/* }}} */
4091
4092void zend_compile_do_while(zend_ast *ast) /* {{{ */
4093{
4094	zend_ast *stmt_ast = ast->child[0];
4095	zend_ast *cond_ast = ast->child[1];
4096
4097	znode cond_node;
4098	uint32_t opnum_start, opnum_cond;
4099
4100	zend_begin_loop(ZEND_NOP, NULL);
4101
4102	opnum_start = get_next_op_number(CG(active_op_array));
4103	zend_compile_stmt(stmt_ast);
4104
4105	opnum_cond = get_next_op_number(CG(active_op_array));
4106	zend_compile_expr(&cond_node, cond_ast);
4107
4108	zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, opnum_start);
4109
4110	zend_end_loop(opnum_cond, NULL);
4111}
4112/* }}} */
4113
4114void zend_compile_expr_list(znode *result, zend_ast *ast) /* {{{ */
4115{
4116	zend_ast_list *list;
4117	uint32_t i;
4118
4119	result->op_type = IS_CONST;
4120	ZVAL_TRUE(&result->u.constant);
4121
4122	if (!ast) {
4123		return;
4124	}
4125
4126	list = zend_ast_get_list(ast);
4127	for (i = 0; i < list->children; ++i) {
4128		zend_ast *expr_ast = list->child[i];
4129
4130		zend_do_free(result);
4131		zend_compile_expr(result, expr_ast);
4132	}
4133}
4134/* }}} */
4135
4136void zend_compile_for(zend_ast *ast) /* {{{ */
4137{
4138	zend_ast *init_ast = ast->child[0];
4139	zend_ast *cond_ast = ast->child[1];
4140	zend_ast *loop_ast = ast->child[2];
4141	zend_ast *stmt_ast = ast->child[3];
4142
4143	znode result;
4144	uint32_t opnum_start, opnum_jmp, opnum_loop;
4145
4146	zend_compile_expr_list(&result, init_ast);
4147	zend_do_free(&result);
4148
4149	opnum_jmp = zend_emit_jump(0);
4150
4151	zend_begin_loop(ZEND_NOP, NULL);
4152
4153	opnum_start = get_next_op_number(CG(active_op_array));
4154	zend_compile_stmt(stmt_ast);
4155
4156	opnum_loop = get_next_op_number(CG(active_op_array));
4157	zend_compile_expr_list(&result, loop_ast);
4158	zend_do_free(&result);
4159
4160	zend_update_jump_target_to_next(opnum_jmp);
4161	zend_compile_expr_list(&result, cond_ast);
4162	zend_do_extended_info();
4163
4164	zend_emit_cond_jump(ZEND_JMPNZ, &result, opnum_start);
4165
4166	zend_end_loop(opnum_loop, NULL);
4167}
4168/* }}} */
4169
4170void zend_compile_foreach(zend_ast *ast) /* {{{ */
4171{
4172	zend_ast *expr_ast = ast->child[0];
4173	zend_ast *value_ast = ast->child[1];
4174	zend_ast *key_ast = ast->child[2];
4175	zend_ast *stmt_ast = ast->child[3];
4176	zend_bool by_ref = value_ast->kind == ZEND_AST_REF;
4177	zend_bool is_variable = zend_is_variable(expr_ast) && !zend_is_call(expr_ast)
4178		&& zend_can_write_to_variable(expr_ast);
4179
4180	znode expr_node, reset_node, value_node, key_node;
4181	zend_op *opline;
4182	uint32_t opnum_reset, opnum_fetch;
4183
4184	if (key_ast) {
4185		if (key_ast->kind == ZEND_AST_REF) {
4186			zend_error_noreturn(E_COMPILE_ERROR, "Key element cannot be a reference");
4187		}
4188		if (key_ast->kind == ZEND_AST_LIST) {
4189			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use list as key element");
4190		}
4191	}
4192
4193	if (by_ref) {
4194		value_ast = value_ast->child[0];
4195	}
4196
4197	if (by_ref && is_variable) {
4198		zend_compile_var(&expr_node, expr_ast, BP_VAR_W);
4199	} else {
4200		zend_compile_expr(&expr_node, expr_ast);
4201	}
4202
4203	if (by_ref) {
4204		zend_separate_if_call_and_write(&expr_node, expr_ast, BP_VAR_W);
4205	}
4206
4207	opnum_reset = get_next_op_number(CG(active_op_array));
4208	opline = zend_emit_op(&reset_node, by_ref ? ZEND_FE_RESET_RW : ZEND_FE_RESET_R, &expr_node, NULL);
4209
4210	zend_begin_loop(ZEND_FE_FREE, &reset_node);
4211
4212	opnum_fetch = get_next_op_number(CG(active_op_array));
4213	opline = zend_emit_op(NULL, by_ref ? ZEND_FE_FETCH_RW : ZEND_FE_FETCH_R, &reset_node, NULL);
4214
4215	if (value_ast->kind == ZEND_AST_VAR &&
4216	    zend_try_compile_cv(&value_node, value_ast) == SUCCESS) {
4217		SET_NODE(opline->op2, &value_node);
4218	} else {
4219		opline->op2_type = IS_VAR;
4220		opline->op2.var = get_temporary_variable(CG(active_op_array));
4221		GET_NODE(&value_node, opline->op2);
4222		if (by_ref) {
4223			zend_emit_assign_ref_znode(value_ast, &value_node);
4224		} else {
4225			zend_emit_assign_znode(value_ast, &value_node);
4226		}
4227	}
4228
4229	if (key_ast) {
4230		opline = &CG(active_op_array)->opcodes[opnum_fetch];
4231		zend_make_tmp_result(&key_node, opline);
4232		zend_emit_assign_znode(key_ast, &key_node);
4233	}
4234
4235	zend_compile_stmt(stmt_ast);
4236
4237	zend_emit_jump(opnum_fetch);
4238
4239	opline = &CG(active_op_array)->opcodes[opnum_reset];
4240	opline->op2.opline_num = get_next_op_number(CG(active_op_array));
4241
4242	opline = &CG(active_op_array)->opcodes[opnum_fetch];
4243	opline->extended_value = get_next_op_number(CG(active_op_array));
4244
4245	zend_end_loop(opnum_fetch, &reset_node);
4246
4247	opline = zend_emit_op(NULL, ZEND_FE_FREE, &reset_node, NULL);
4248}
4249/* }}} */
4250
4251void zend_compile_if(zend_ast *ast) /* {{{ */
4252{
4253	zend_ast_list *list = zend_ast_get_list(ast);
4254	uint32_t i;
4255	uint32_t *jmp_opnums = NULL;
4256
4257	if (list->children > 1) {
4258		jmp_opnums = safe_emalloc(sizeof(uint32_t), list->children - 1, 0);
4259	}
4260
4261	for (i = 0; i < list->children; ++i) {
4262		zend_ast *elem_ast = list->child[i];
4263		zend_ast *cond_ast = elem_ast->child[0];
4264		zend_ast *stmt_ast = elem_ast->child[1];
4265
4266		znode cond_node;
4267		uint32_t opnum_jmpz;
4268		if (cond_ast) {
4269			zend_compile_expr(&cond_node, cond_ast);
4270			opnum_jmpz = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0);
4271		}
4272
4273		zend_compile_stmt(stmt_ast);
4274
4275		if (i != list->children - 1) {
4276			jmp_opnums[i] = zend_emit_jump(0);
4277		}
4278
4279		if (cond_ast) {
4280			zend_update_jump_target_to_next(opnum_jmpz);
4281		}
4282	}
4283
4284	if (list->children > 1) {
4285		for (i = 0; i < list->children - 1; ++i) {
4286			zend_update_jump_target_to_next(jmp_opnums[i]);
4287		}
4288		efree(jmp_opnums);
4289	}
4290}
4291/* }}} */
4292
4293void zend_compile_switch(zend_ast *ast) /* {{{ */
4294{
4295	zend_ast *expr_ast = ast->child[0];
4296	zend_ast_list *cases = zend_ast_get_list(ast->child[1]);
4297
4298	uint32_t i;
4299	zend_bool has_default_case = 0;
4300
4301	znode expr_node, case_node;
4302	zend_op *opline;
4303	uint32_t *jmpnz_opnums = safe_emalloc(sizeof(uint32_t), cases->children, 0);
4304	uint32_t opnum_default_jmp;
4305
4306	zend_compile_expr(&expr_node, expr_ast);
4307
4308	zend_begin_loop(ZEND_FREE, &expr_node);
4309
4310	case_node.op_type = IS_TMP_VAR;
4311	case_node.u.op.var = get_temporary_variable(CG(active_op_array));
4312
4313	for (i = 0; i < cases->children; ++i) {
4314		zend_ast *case_ast = cases->child[i];
4315		zend_ast *cond_ast = case_ast->child[0];
4316		znode cond_node;
4317
4318		if (!cond_ast) {
4319			if (has_default_case) {
4320				CG(zend_lineno) = case_ast->lineno;
4321				zend_error_noreturn(E_COMPILE_ERROR,
4322					"Switch statements may only contain one default clause");
4323			}
4324			has_default_case = 1;
4325			continue;
4326		}
4327
4328		zend_compile_expr(&cond_node, cond_ast);
4329
4330		if (expr_node.op_type == IS_CONST
4331			&& Z_TYPE(expr_node.u.constant) == IS_FALSE) {
4332			jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0);
4333		} else if (expr_node.op_type == IS_CONST
4334			&& Z_TYPE(expr_node.u.constant) == IS_TRUE) {
4335			jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, 0);
4336		} else {
4337			opline = zend_emit_op(NULL, ZEND_CASE, &expr_node, &cond_node);
4338			SET_NODE(opline->result, &case_node);
4339			if (opline->op1_type == IS_CONST) {
4340				zval_copy_ctor(CT_CONSTANT(opline->op1));
4341			}
4342
4343			jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPNZ, &case_node, 0);
4344		}
4345	}
4346
4347	opnum_default_jmp = zend_emit_jump(0);
4348
4349	for (i = 0; i < cases->children; ++i) {
4350		zend_ast *case_ast = cases->child[i];
4351		zend_ast *cond_ast = case_ast->child[0];
4352		zend_ast *stmt_ast = case_ast->child[1];
4353
4354		if (cond_ast) {
4355			zend_update_jump_target_to_next(jmpnz_opnums[i]);
4356		} else {
4357			zend_update_jump_target_to_next(opnum_default_jmp);
4358		}
4359
4360		zend_compile_stmt(stmt_ast);
4361	}
4362
4363	if (!has_default_case) {
4364		zend_update_jump_target_to_next(opnum_default_jmp);
4365	}
4366
4367	zend_end_loop(get_next_op_number(CG(active_op_array)), &expr_node);
4368
4369	if (expr_node.op_type == IS_VAR || expr_node.op_type == IS_TMP_VAR) {
4370		/* don't use emit_op() to prevent automatic live-range construction */
4371		opline = get_next_op(CG(active_op_array));
4372		opline->opcode = ZEND_FREE;
4373		SET_NODE(opline->op1, &expr_node);
4374		SET_UNUSED(opline->op2);
4375	} else if (expr_node.op_type == IS_CONST) {
4376		zval_dtor(&expr_node.u.constant);
4377	}
4378
4379	efree(jmpnz_opnums);
4380}
4381/* }}} */
4382
4383void zend_compile_try(zend_ast *ast) /* {{{ */
4384{
4385	zend_ast *try_ast = ast->child[0];
4386	zend_ast_list *catches = zend_ast_get_list(ast->child[1]);
4387	zend_ast *finally_ast = ast->child[2];
4388
4389	uint32_t i;
4390	zend_op *opline;
4391	uint32_t try_catch_offset;
4392	uint32_t *jmp_opnums = safe_emalloc(sizeof(uint32_t), catches->children, 0);
4393
4394	if (catches->children == 0 && !finally_ast) {
4395		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use try without catch or finally");
4396	}
4397
4398	/* label: try { } must not be equal to try { label: } */
4399	if (CG(context).labels) {
4400		zend_label *label;
4401		ZEND_HASH_REVERSE_FOREACH_PTR(CG(context).labels, label) {
4402			if (label->opline_num == get_next_op_number(CG(active_op_array))) {
4403				zend_emit_op(NULL, ZEND_NOP, NULL, NULL);
4404			}
4405			break;
4406		} ZEND_HASH_FOREACH_END();
4407	}
4408
4409	try_catch_offset = zend_add_try_element(get_next_op_number(CG(active_op_array)));
4410
4411	if (finally_ast) {
4412		zend_loop_var fast_call;
4413		if (!(CG(active_op_array)->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK)) {
4414			CG(active_op_array)->fn_flags |= ZEND_ACC_HAS_FINALLY_BLOCK;
4415			CG(context).fast_call_var = get_temporary_variable(CG(active_op_array));
4416		}
4417
4418		/* Push FAST_CALL on unwind stack */
4419		fast_call.opcode = ZEND_FAST_CALL;
4420		fast_call.var_type = IS_TMP_VAR;
4421		fast_call.var_num = CG(context).fast_call_var;
4422		fast_call.u.try_catch_offset = try_catch_offset;
4423		zend_stack_push(&CG(loop_var_stack), &fast_call);
4424	}
4425
4426	zend_compile_stmt(try_ast);
4427
4428	if (catches->children != 0) {
4429		jmp_opnums[0] = zend_emit_jump(0);
4430	}
4431
4432	for (i = 0; i < catches->children; ++i) {
4433		zend_ast *catch_ast = catches->child[i];
4434		zend_ast *class_ast = catch_ast->child[0];
4435		zend_ast *var_ast = catch_ast->child[1];
4436		zend_ast *stmt_ast = catch_ast->child[2];
4437		zval *var_name = zend_ast_get_zval(var_ast);
4438		zend_bool is_last_catch = (i + 1 == catches->children);
4439
4440		uint32_t opnum_catch;
4441
4442		if (!zend_is_const_default_class_ref(class_ast)) {
4443			zend_error_noreturn(E_COMPILE_ERROR, "Bad class name in the catch statement");
4444		}
4445
4446		opnum_catch = get_next_op_number(CG(active_op_array));
4447		if (i == 0) {
4448			CG(active_op_array)->try_catch_array[try_catch_offset].catch_op = opnum_catch;
4449		}
4450
4451		CG(zend_lineno) = catch_ast->lineno;
4452
4453		opline = get_next_op(CG(active_op_array));
4454		opline->opcode = ZEND_CATCH;
4455		opline->op1_type = IS_CONST;
4456		opline->op1.constant = zend_add_class_name_literal(CG(active_op_array),
4457			zend_resolve_class_name_ast(class_ast));
4458
4459		opline->op2_type = IS_CV;
4460		opline->op2.var = lookup_cv(CG(active_op_array), zend_string_copy(Z_STR_P(var_name)));
4461		opline->result.num = is_last_catch;
4462
4463		zend_compile_stmt(stmt_ast);
4464
4465		if (!is_last_catch) {
4466			jmp_opnums[i + 1] = zend_emit_jump(0);
4467		}
4468
4469		opline = &CG(active_op_array)->opcodes[opnum_catch];
4470		if (!is_last_catch) {
4471			opline->extended_value = get_next_op_number(CG(active_op_array));
4472		}
4473	}
4474
4475	for (i = 0; i < catches->children; ++i) {
4476		zend_update_jump_target_to_next(jmp_opnums[i]);
4477	}
4478
4479	if (finally_ast) {
4480		uint32_t opnum_jmp = get_next_op_number(CG(active_op_array)) + 1;
4481
4482		/* Pop FAST_CALL from unwind stack */
4483		zend_stack_del_top(&CG(loop_var_stack));
4484
4485		CG(zend_lineno) = finally_ast->lineno;
4486
4487		opline = zend_emit_op(NULL, ZEND_FAST_CALL, NULL, NULL);
4488		opline->op1.num = try_catch_offset;
4489		opline->result_type = IS_TMP_VAR;
4490		opline->result.var = CG(context).fast_call_var;
4491
4492		zend_emit_op(NULL, ZEND_JMP, NULL, NULL);
4493
4494		CG(context).in_finally++;
4495		zend_compile_stmt(finally_ast);
4496		CG(context).in_finally--;
4497
4498		CG(active_op_array)->try_catch_array[try_catch_offset].finally_op = opnum_jmp + 1;
4499		CG(active_op_array)->try_catch_array[try_catch_offset].finally_end
4500			= get_next_op_number(CG(active_op_array));
4501
4502		opline = zend_emit_op(NULL, ZEND_FAST_RET, NULL, NULL);
4503		opline->op1_type = IS_TMP_VAR;
4504		opline->op1.var = CG(context).fast_call_var;
4505
4506		zend_update_jump_target_to_next(opnum_jmp);
4507	}
4508
4509	efree(jmp_opnums);
4510}
4511/* }}} */
4512
4513/* Encoding declarations must already be handled during parsing */
4514void zend_handle_encoding_declaration(zend_ast *ast) /* {{{ */
4515{
4516	zend_ast_list *declares = zend_ast_get_list(ast);
4517	uint32_t i;
4518	for (i = 0; i < declares->children; ++i) {
4519		zend_ast *declare_ast = declares->child[i];
4520		zend_ast *name_ast = declare_ast->child[0];
4521		zend_ast *value_ast = declare_ast->child[1];
4522		zend_string *name = zend_ast_get_str(name_ast);
4523
4524		if (zend_string_equals_literal_ci(name, "encoding")) {
4525			if (value_ast->kind != ZEND_AST_ZVAL) {
4526				zend_error_noreturn(E_COMPILE_ERROR, "Encoding must be a literal");
4527			}
4528
4529			if (CG(multibyte)) {
4530				zend_string *encoding_name = zval_get_string(zend_ast_get_zval(value_ast));
4531
4532				const zend_encoding *new_encoding, *old_encoding;
4533				zend_encoding_filter old_input_filter;
4534
4535				CG(encoding_declared) = 1;
4536
4537				new_encoding = zend_multibyte_fetch_encoding(ZSTR_VAL(encoding_name));
4538				if (!new_encoding) {
4539					zend_error(E_COMPILE_WARNING, "Unsupported encoding [%s]", ZSTR_VAL(encoding_name));
4540				} else {
4541					old_input_filter = LANG_SCNG(input_filter);
4542					old_encoding = LANG_SCNG(script_encoding);
4543					zend_multibyte_set_filter(new_encoding);
4544
4545					/* need to re-scan if input filter changed */
4546					if (old_input_filter != LANG_SCNG(input_filter) ||
4547						 (old_input_filter && new_encoding != old_encoding)) {
4548						zend_multibyte_yyinput_again(old_input_filter, old_encoding);
4549					}
4550				}
4551
4552				zend_string_release(encoding_name);
4553			} else {
4554				zend_error(E_COMPILE_WARNING, "declare(encoding=...) ignored because "
4555					"Zend multibyte feature is turned off by settings");
4556			}
4557		}
4558	}
4559}
4560/* }}} */
4561
4562static int zend_declare_is_first_statement(zend_ast *ast) /* {{{ */
4563{
4564	uint32_t i = 0;
4565	zend_ast_list *file_ast = zend_ast_get_list(CG(ast));
4566
4567	/* Check to see if this declare is preceeded only by declare statements */
4568	while (i < file_ast->children) {
4569		if (file_ast->child[i] == ast) {
4570			return SUCCESS;
4571		} else if (file_ast->child[i] == NULL) {
4572			/* Empty statements are not allowed prior to a declare */
4573			return FAILURE;
4574		} else if (file_ast->child[i]->kind != ZEND_AST_DECLARE) {
4575			/* declares can only be preceeded by other declares */
4576			return FAILURE;
4577		}
4578		i++;
4579	}
4580	return FAILURE;
4581}
4582/* }}} */
4583
4584void zend_compile_declare(zend_ast *ast) /* {{{ */
4585{
4586	zend_ast_list *declares = zend_ast_get_list(ast->child[0]);
4587	zend_ast *stmt_ast = ast->child[1];
4588	zend_declarables orig_declarables = FC(declarables);
4589	uint32_t i;
4590
4591	for (i = 0; i < declares->children; ++i) {
4592		zend_ast *declare_ast = declares->child[i];
4593		zend_ast *name_ast = declare_ast->child[0];
4594		zend_ast *value_ast = declare_ast->child[1];
4595
4596		zend_string *name = zend_ast_get_str(name_ast);
4597		if (zend_string_equals_literal_ci(name, "ticks")) {
4598			zval value_zv;
4599			zend_const_expr_to_zval(&value_zv, value_ast);
4600			FC(declarables).ticks = zval_get_long(&value_zv);
4601			zval_dtor(&value_zv);
4602		} else if (zend_string_equals_literal_ci(name, "encoding")) {
4603
4604			if (FAILURE == zend_declare_is_first_statement(ast)) {
4605				zend_error_noreturn(E_COMPILE_ERROR, "Encoding declaration pragma must be "
4606					"the very first statement in the script");
4607			}
4608		} else if (zend_string_equals_literal_ci(name, "strict_types")) {
4609			zval value_zv;
4610
4611			if (FAILURE == zend_declare_is_first_statement(ast)) {
4612				zend_error_noreturn(E_COMPILE_ERROR, "strict_types declaration must be "
4613					"the very first statement in the script");
4614			}
4615
4616			if (ast->child[1] != NULL) {
4617				zend_error_noreturn(E_COMPILE_ERROR, "strict_types declaration must not "
4618					"use block mode");
4619			}
4620
4621			zend_const_expr_to_zval(&value_zv, value_ast);
4622
4623			if (Z_TYPE(value_zv) != IS_LONG || (Z_LVAL(value_zv) != 0 && Z_LVAL(value_zv) != 1)) {
4624				zend_error_noreturn(E_COMPILE_ERROR, "strict_types declaration must have 0 or 1 as its value");
4625			}
4626
4627			if (Z_LVAL(value_zv) == 1) {
4628				CG(active_op_array)->fn_flags |= ZEND_ACC_STRICT_TYPES;
4629			}
4630
4631		} else {
4632			zend_error(E_COMPILE_WARNING, "Unsupported declare '%s'", ZSTR_VAL(name));
4633		}
4634	}
4635
4636	if (stmt_ast) {
4637		zend_compile_stmt(stmt_ast);
4638
4639		FC(declarables) = orig_declarables;
4640	}
4641}
4642/* }}} */
4643
4644void zend_compile_stmt_list(zend_ast *ast) /* {{{ */
4645{
4646	zend_ast_list *list = zend_ast_get_list(ast);
4647	uint32_t i;
4648	for (i = 0; i < list->children; ++i) {
4649		zend_compile_stmt(list->child[i]);
4650	}
4651}
4652/* }}} */
4653
4654ZEND_API void zend_set_function_arg_flags(zend_function *func) /* {{{ */
4655{
4656	uint32_t i, n;
4657
4658	func->common.arg_flags[0] = 0;
4659	func->common.arg_flags[1] = 0;
4660	func->common.arg_flags[2] = 0;
4661	if (func->common.arg_info) {
4662		n = MIN(func->common.num_args, MAX_ARG_FLAG_NUM);
4663		i = 0;
4664		while (i < n) {
4665			ZEND_SET_ARG_FLAG(func, i + 1, func->common.arg_info[i].pass_by_reference);
4666			i++;
4667		}
4668		if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_VARIADIC && func->common.arg_info[i].pass_by_reference)) {
4669			uint32_t pass_by_reference = func->common.arg_info[i].pass_by_reference;
4670			while (i < MAX_ARG_FLAG_NUM) {
4671				ZEND_SET_ARG_FLAG(func, i + 1, pass_by_reference);
4672				i++;
4673			}
4674		}
4675	}
4676}
4677/* }}} */
4678
4679static void zend_compile_typename(zend_ast *ast, zend_arg_info *arg_info) /* {{{ */
4680{
4681	if (ast->kind == ZEND_AST_TYPE) {
4682		arg_info->type_hint = ast->attr;
4683	} else {
4684		zend_string *class_name = zend_ast_get_str(ast);
4685		zend_uchar type = zend_lookup_builtin_type_by_name(class_name);
4686
4687		if (type != 0) {
4688			if (ast->attr != ZEND_NAME_NOT_FQ) {
4689				zend_error_noreturn(E_COMPILE_ERROR,
4690					"Scalar type declaration '%s' must be unqualified",
4691					ZSTR_VAL(zend_string_tolower(class_name)));
4692			}
4693			arg_info->type_hint = type;
4694		} else {
4695			uint32_t fetch_type = zend_get_class_fetch_type_ast(ast);
4696			if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
4697				class_name = zend_resolve_class_name_ast(ast);
4698				zend_assert_valid_class_name(class_name);
4699			} else {
4700				zend_ensure_valid_class_fetch_type(fetch_type);
4701				zend_string_addref(class_name);
4702			}
4703
4704			arg_info->type_hint = IS_OBJECT;
4705			arg_info->class_name = class_name;
4706		}
4707	}
4708}
4709/* }}} */
4710
4711void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
4712{
4713	zend_ast_list *list = zend_ast_get_list(ast);
4714	uint32_t i;
4715	zend_op_array *op_array = CG(active_op_array);
4716	zend_arg_info *arg_infos;
4717
4718	if (return_type_ast) {
4719		/* Use op_array->arg_info[-1] for return type */
4720		arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children + 1, 0);
4721		arg_infos->name = NULL;
4722		arg_infos->pass_by_reference = (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
4723		arg_infos->is_variadic = 0;
4724		arg_infos->type_hint = 0;
4725		arg_infos->allow_null = 0;
4726		arg_infos->class_name = NULL;
4727
4728		zend_compile_typename(return_type_ast, arg_infos);
4729
4730		arg_infos++;
4731		op_array->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
4732	} else {
4733		if (list->children == 0) {
4734			return;
4735		}
4736		arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children, 0);
4737	}
4738
4739	for (i = 0; i < list->children; ++i) {
4740		zend_ast *param_ast = list->child[i];
4741		zend_ast *type_ast = param_ast->child[0];
4742		zend_ast *var_ast = param_ast->child[1];
4743		zend_ast *default_ast = param_ast->child[2];
4744		zend_string *name = zend_ast_get_str(var_ast);
4745		zend_bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0;
4746		zend_bool is_variadic = (param_ast->attr & ZEND_PARAM_VARIADIC) != 0;
4747
4748		znode var_node, default_node;
4749		zend_uchar opcode;
4750		zend_op *opline;
4751		zend_arg_info *arg_info;
4752
4753		if (zend_is_auto_global(name)) {
4754			zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign auto-global variable %s",
4755				ZSTR_VAL(name));
4756		}
4757
4758		var_node.op_type = IS_CV;
4759		var_node.u.op.var = lookup_cv(CG(active_op_array), zend_string_copy(name));
4760
4761		if (EX_VAR_TO_NUM(var_node.u.op.var) != i) {
4762			zend_error_noreturn(E_COMPILE_ERROR, "Redefinition of parameter $%s",
4763				ZSTR_VAL(name));
4764		} else if (zend_string_equals_literal(name, "this")) {
4765			if (op_array->scope && (op_array->fn_flags & ZEND_ACC_STATIC) == 0) {
4766				zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
4767			}
4768			op_array->this_var = var_node.u.op.var;
4769		}
4770
4771		if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
4772			zend_error_noreturn(E_COMPILE_ERROR, "Only the last parameter can be variadic");
4773		}
4774
4775		if (is_variadic) {
4776			opcode = ZEND_RECV_VARIADIC;
4777			default_node.op_type = IS_UNUSED;
4778			op_array->fn_flags |= ZEND_ACC_VARIADIC;
4779
4780			if (default_ast) {
4781				zend_error_noreturn(E_COMPILE_ERROR,
4782					"Variadic parameter cannot have a default value");
4783			}
4784		} else if (default_ast) {
4785			/* we cannot substitute constants here or it will break ReflectionParameter::getDefaultValueConstantName() and ReflectionParameter::isDefaultValueConstant() */
4786			uint32_t cops = CG(compiler_options);
4787			CG(compiler_options) |= ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION | ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION;
4788			opcode = ZEND_RECV_INIT;
4789			default_node.op_type = IS_CONST;
4790			zend_const_expr_to_zval(&default_node.u.constant, default_ast);
4791			CG(compiler_options) = cops;
4792		} else {
4793			opcode = ZEND_RECV;
4794			default_node.op_type = IS_UNUSED;
4795			op_array->required_num_args = i + 1;
4796		}
4797
4798		opline = zend_emit_op(NULL, opcode, NULL, &default_node);
4799		SET_NODE(opline->result, &var_node);
4800		opline->op1.num = i + 1;
4801
4802		arg_info = &arg_infos[i];
4803		arg_info->name = zend_string_copy(name);
4804		arg_info->pass_by_reference = is_ref;
4805		arg_info->is_variadic = is_variadic;
4806		arg_info->type_hint = 0;
4807		arg_info->allow_null = 1;
4808		arg_info->class_name = NULL;
4809
4810		if (type_ast) {
4811			zend_bool has_null_default = default_ast
4812				&& (Z_TYPE(default_node.u.constant) == IS_NULL
4813					|| (Z_TYPE(default_node.u.constant) == IS_CONSTANT
4814						&& strcasecmp(Z_STRVAL(default_node.u.constant), "NULL") == 0));
4815
4816			op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
4817			arg_info->allow_null = has_null_default;
4818
4819			zend_compile_typename(type_ast, arg_info);
4820
4821			if (arg_info->type_hint == IS_VOID) {
4822				zend_error_noreturn(E_COMPILE_ERROR, "void cannot be used as a parameter type");
4823			}
4824
4825			if (type_ast->kind == ZEND_AST_TYPE) {
4826				if (arg_info->type_hint == IS_ARRAY) {
4827					if (default_ast && !has_null_default
4828						&& Z_TYPE(default_node.u.constant) != IS_ARRAY
4829						&& !Z_CONSTANT(default_node.u.constant)
4830					) {
4831						zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
4832							"with array type can only be an array or NULL");
4833					}
4834				} else if (arg_info->type_hint == IS_CALLABLE && default_ast) {
4835					if (!has_null_default && !Z_CONSTANT(default_node.u.constant)) {
4836						zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
4837							"with callable type can only be NULL");
4838					}
4839				}
4840			} else {
4841				if (default_ast && !has_null_default && !Z_CONSTANT(default_node.u.constant)) {
4842					if (arg_info->class_name) {
4843						zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
4844							"with a class type can only be NULL");
4845					} else switch (arg_info->type_hint) {
4846						case IS_DOUBLE:
4847							if (Z_TYPE(default_node.u.constant) != IS_DOUBLE && Z_TYPE(default_node.u.constant) != IS_LONG) {
4848								zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
4849									"with a float type can only be float, integer, or NULL");
4850							}
4851							break;
4852
4853						default:
4854							if (!ZEND_SAME_FAKE_TYPE(arg_info->type_hint, Z_TYPE(default_node.u.constant))) {
4855								zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
4856									"with a %s type can only be %s or NULL",
4857									zend_get_type_by_const(arg_info->type_hint), zend_get_type_by_const(arg_info->type_hint));
4858							}
4859							break;
4860					}
4861				}
4862			}
4863
4864			/* Allocate cache slot to speed-up run-time class resolution */
4865			if (opline->opcode == ZEND_RECV_INIT) {
4866				if (arg_info->class_name) {
4867					zend_alloc_cache_slot(opline->op2.constant);
4868				} else {
4869					Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = -1;
4870				}
4871			} else {
4872				if (arg_info->class_name) {
4873					opline->op2.num = op_array->cache_size;
4874					op_array->cache_size += sizeof(void*);
4875				} else {
4876					opline->op2.num = -1;
4877				}
4878			}
4879		} else {
4880			if (opline->opcode == ZEND_RECV_INIT) {
4881				Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = -1;
4882			} else {
4883				opline->op2.num = -1;
4884			}
4885		}
4886	}
4887
4888	/* These are assigned at the end to avoid unitialized memory in case of an error */
4889	op_array->num_args = list->children;
4890	op_array->arg_info = arg_infos;
4891
4892	/* Don't count the variadic argument */
4893	if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
4894		op_array->num_args--;
4895	}
4896	zend_set_function_arg_flags((zend_function*)op_array);
4897}
4898/* }}} */
4899
4900static void zend_compile_closure_binding(znode *closure, zend_ast *uses_ast) /* {{{ */
4901{
4902	zend_ast_list *list = zend_ast_get_list(uses_ast);
4903	uint32_t i;
4904
4905	for (i = 0; i < list->children; ++i) {
4906		zend_ast *var_name_ast = list->child[i];
4907		zend_string *var_name = zend_ast_get_str(var_name_ast);
4908		zend_bool by_ref = var_name_ast->attr;
4909		zend_op *opline;
4910
4911		if (zend_string_equals_literal(var_name, "this")) {
4912			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as lexical variable");
4913		}
4914
4915		if (zend_is_auto_global(var_name)) {
4916			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use auto-global as lexical variable");
4917		}
4918
4919		opline = zend_emit_op(NULL, ZEND_BIND_LEXICAL, closure, NULL);
4920		opline->op2_type = IS_CV;
4921		opline->op2.var = lookup_cv(CG(active_op_array), zend_string_copy(var_name));
4922		opline->extended_value = by_ref;
4923	}
4924}
4925/* }}} */
4926
4927void zend_compile_closure_uses(zend_ast *ast) /* {{{ */
4928{
4929	zend_op_array *op_array = CG(active_op_array);
4930	zend_ast_list *list = zend_ast_get_list(ast);
4931	uint32_t i;
4932
4933	for (i = 0; i < list->children; ++i) {
4934		zend_ast *var_ast = list->child[i];
4935		zend_string *var_name = zend_ast_get_str(var_ast);
4936		zend_bool by_ref = var_ast->attr;
4937		zval zv;
4938		ZVAL_NULL(&zv);
4939
4940		if (op_array->static_variables
4941				&& zend_hash_exists(op_array->static_variables, var_name)) {
4942			zend_error_noreturn(E_COMPILE_ERROR,
4943				"Cannot use variable $%s twice", ZSTR_VAL(var_name));
4944		}
4945
4946		{
4947			int i;
4948			for (i = 0; i < op_array->last_var; i++) {
4949				if (zend_string_equals(op_array->vars[i], var_name)) {
4950					zend_error_noreturn(E_COMPILE_ERROR,
4951						"Cannot use lexical variable $%s as a parameter name", ZSTR_VAL(var_name));
4952				}
4953			}
4954		}
4955
4956		zend_compile_static_var_common(var_ast, &zv, by_ref);
4957	}
4958}
4959/* }}} */
4960
4961void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_bool has_body) /* {{{ */
4962{
4963	zend_class_entry *ce = CG(active_class_entry);
4964	zend_bool in_interface = (ce->ce_flags & ZEND_ACC_INTERFACE) != 0;
4965	zend_bool in_trait = (ce->ce_flags & ZEND_ACC_TRAIT) != 0;
4966	zend_bool is_public = (op_array->fn_flags & ZEND_ACC_PUBLIC) != 0;
4967	zend_bool is_static = (op_array->fn_flags & ZEND_ACC_STATIC) != 0;
4968
4969	zend_string *lcname;
4970
4971	if (in_interface) {
4972		if ((op_array->fn_flags & ZEND_ACC_PPP_MASK) != ZEND_ACC_PUBLIC) {
4973			zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface method "
4974				"%s::%s() must be omitted", ZSTR_VAL(ce->name), ZSTR_VAL(name));
4975		}
4976		op_array->fn_flags |= ZEND_ACC_ABSTRACT;
4977	}
4978
4979	if (op_array->fn_flags & ZEND_ACC_ABSTRACT) {
4980		if (op_array->fn_flags & ZEND_ACC_PRIVATE) {
4981			zend_error_noreturn(E_COMPILE_ERROR, "%s function %s::%s() cannot be declared private",
4982				in_interface ? "Interface" : "Abstract", ZSTR_VAL(ce->name), ZSTR_VAL(name));
4983		}
4984
4985		if (has_body) {
4986			zend_error_noreturn(E_COMPILE_ERROR, "%s function %s::%s() cannot contain body",
4987				in_interface ? "Interface" : "Abstract", ZSTR_VAL(ce->name), ZSTR_VAL(name));
4988		}
4989
4990		ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
4991	} else if (!has_body) {
4992		zend_error_noreturn(E_COMPILE_ERROR, "Non-abstract method %s::%s() must contain body",
4993			ZSTR_VAL(ce->name), ZSTR_VAL(name));
4994	}
4995
4996	op_array->scope = ce;
4997	op_array->function_name = zend_string_copy(name);
4998
4999	lcname = zend_string_tolower(name);
5000	lcname = zend_new_interned_string(lcname);
5001
5002	if (zend_hash_add_ptr(&ce->function_table, lcname, op_array) == NULL) {
5003		zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::%s()",
5004			ZSTR_VAL(ce->name), ZSTR_VAL(name));
5005	}
5006
5007	if (in_interface) {
5008		if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) {
5009			if (!is_public || is_static) {
5010				zend_error(E_WARNING, "The magic method __call() must have "
5011					"public visibility and cannot be static");
5012			}
5013		} else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) {
5014			if (!is_public || !is_static) {
5015				zend_error(E_WARNING, "The magic method __callStatic() must have "
5016					"public visibility and be static");
5017			}
5018		} else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) {
5019			if (!is_public || is_static) {
5020				zend_error(E_WARNING, "The magic method __get() must have "
5021					"public visibility and cannot be static");
5022			}
5023		} else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) {
5024			if (!is_public || is_static) {
5025				zend_error(E_WARNING, "The magic method __set() must have "
5026					"public visibility and cannot be static");
5027			}
5028		} else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) {
5029			if (!is_public || is_static) {
5030				zend_error(E_WARNING, "The magic method __unset() must have "
5031					"public visibility and cannot be static");
5032			}
5033		} else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) {
5034			if (!is_public || is_static) {
5035				zend_error(E_WARNING, "The magic method __isset() must have "
5036					"public visibility and cannot be static");
5037			}
5038		} else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) {
5039			if (!is_public || is_static) {
5040				zend_error(E_WARNING, "The magic method __toString() must have "
5041					"public visibility and cannot be static");
5042			}
5043		} else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) {
5044			if (!is_public || is_static) {
5045				zend_error(E_WARNING, "The magic method __invoke() must have "
5046					"public visibility and cannot be static");
5047			}
5048		} else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) {
5049			if (!is_public || is_static) {
5050				zend_error(E_WARNING, "The magic method __debugInfo() must have "
5051					"public visibility and cannot be static");
5052			}
5053		}
5054	} else {
5055		if (!in_trait && zend_string_equals_ci(lcname, ce->name)) {
5056			if (!ce->constructor) {
5057				ce->constructor = (zend_function *) op_array;
5058			}
5059		} else if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
5060			ce->constructor = (zend_function *) op_array;
5061		} else if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) {
5062			ce->destructor = (zend_function *) op_array;
5063		} else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) {
5064			ce->clone = (zend_function *) op_array;
5065		} else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) {
5066			if (!is_public || is_static) {
5067				zend_error(E_WARNING, "The magic method __call() must have "
5068					"public visibility and cannot be static");
5069			}
5070			ce->__call = (zend_function *) op_array;
5071		} else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) {
5072			if (!is_public || !is_static) {
5073				zend_error(E_WARNING, "The magic method __callStatic() must have "
5074					"public visibility and be static");
5075			}
5076			ce->__callstatic = (zend_function *) op_array;
5077		} else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) {
5078			if (!is_public || is_static) {
5079				zend_error(E_WARNING, "The magic method __get() must have "
5080					"public visibility and cannot be static");
5081			}
5082			ce->__get = (zend_function *) op_array;
5083			ce->ce_flags |= ZEND_ACC_USE_GUARDS;
5084		} else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) {
5085			if (!is_public || is_static) {
5086				zend_error(E_WARNING, "The magic method __set() must have "
5087					"public visibility and cannot be static");
5088			}
5089			ce->__set = (zend_function *) op_array;
5090			ce->ce_flags |= ZEND_ACC_USE_GUARDS;
5091		} else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) {
5092			if (!is_public || is_static) {
5093				zend_error(E_WARNING, "The magic method __unset() must have "
5094					"public visibility and cannot be static");
5095			}
5096			ce->__unset = (zend_function *) op_array;
5097			ce->ce_flags |= ZEND_ACC_USE_GUARDS;
5098		} else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) {
5099			if (!is_public || is_static) {
5100				zend_error(E_WARNING, "The magic method __isset() must have "
5101					"public visibility and cannot be static");
5102			}
5103			ce->__isset = (zend_function *) op_array;
5104			ce->ce_flags |= ZEND_ACC_USE_GUARDS;
5105		} else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) {
5106			if (!is_public || is_static) {
5107				zend_error(E_WARNING, "The magic method __toString() must have "
5108					"public visibility and cannot be static");
5109			}
5110			ce->__tostring = (zend_function *) op_array;
5111		} else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) {
5112			if (!is_public || is_static) {
5113				zend_error(E_WARNING, "The magic method __invoke() must have "
5114					"public visibility and cannot be static");
5115			}
5116		} else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) {
5117			if (!is_public || is_static) {
5118				zend_error(E_WARNING, "The magic method __debugInfo() must have "
5119					"public visibility and cannot be static");
5120			}
5121			ce->__debugInfo = (zend_function *) op_array;
5122		} else if (!is_static) {
5123			op_array->fn_flags |= ZEND_ACC_ALLOW_STATIC;
5124		}
5125	}
5126
5127	zend_string_release(lcname);
5128}
5129/* }}} */
5130
5131static void zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_ast_decl *decl) /* {{{ */
5132{
5133	zend_ast *params_ast = decl->child[0];
5134	zend_string *name = decl->name, *lcname, *key;
5135	zend_op *opline;
5136
5137	op_array->function_name = name = zend_prefix_with_ns(name);
5138
5139	lcname = zend_string_tolower(name);
5140
5141	if (FC(imports_function)) {
5142		zend_string *import_name = zend_hash_find_ptr(FC(imports_function), lcname);
5143		if (import_name && !zend_string_equals_ci(lcname, import_name)) {
5144			zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare function %s "
5145				"because the name is already in use", ZSTR_VAL(name));
5146		}
5147	}
5148
5149	if (zend_string_equals_literal(lcname, ZEND_AUTOLOAD_FUNC_NAME)
5150		&& zend_ast_get_list(params_ast)->children != 1
5151	) {
5152		zend_error_noreturn(E_COMPILE_ERROR, "%s() must take exactly 1 argument",
5153			ZEND_AUTOLOAD_FUNC_NAME);
5154	}
5155
5156	key = zend_build_runtime_definition_key(lcname, decl->lex_pos);
5157	zend_hash_update_ptr(CG(function_table), key, op_array);
5158
5159	if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
5160		opline = zend_emit_op_tmp(result, ZEND_DECLARE_LAMBDA_FUNCTION, NULL, NULL);
5161		opline->op1_type = IS_CONST;
5162		LITERAL_STR(opline->op1, key);
5163	} else {
5164		opline = get_next_op(CG(active_op_array));
5165		opline->opcode = ZEND_DECLARE_FUNCTION;
5166		opline->op1_type = IS_CONST;
5167		LITERAL_STR(opline->op1, zend_string_copy(lcname));
5168		/* RTD key is placed after lcname literal in op1 */
5169		zend_add_literal_string(CG(active_op_array), &key);
5170	}
5171
5172	zend_string_release(lcname);
5173}
5174/* }}} */
5175
5176void zend_compile_func_decl(znode *result, zend_ast *ast) /* {{{ */
5177{
5178	zend_ast_decl *decl = (zend_ast_decl *) ast;
5179	zend_ast *params_ast = decl->child[0];
5180	zend_ast *uses_ast = decl->child[1];
5181	zend_ast *stmt_ast = decl->child[2];
5182	zend_ast *return_type_ast = decl->child[3];
5183	zend_bool is_method = decl->kind == ZEND_AST_METHOD;
5184
5185	zend_op_array *orig_op_array = CG(active_op_array);
5186	zend_op_array *op_array = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
5187	zend_oparray_context orig_oparray_context;
5188
5189	init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE);
5190
5191	op_array->fn_flags |= (orig_op_array->fn_flags & ZEND_ACC_STRICT_TYPES);
5192	op_array->fn_flags |= decl->flags;
5193	op_array->line_start = decl->start_lineno;
5194	op_array->line_end = decl->end_lineno;
5195	if (decl->doc_comment) {
5196		op_array->doc_comment = zend_string_copy(decl->doc_comment);
5197	}
5198	if (decl->kind == ZEND_AST_CLOSURE) {
5199		op_array->fn_flags |= ZEND_ACC_CLOSURE;
5200	}
5201
5202	if (is_method) {
5203		zend_bool has_body = stmt_ast != NULL;
5204		zend_begin_method_decl(op_array, decl->name, has_body);
5205	} else {
5206		zend_begin_func_decl(result, op_array, decl);
5207		if (uses_ast) {
5208			zend_compile_closure_binding(result, uses_ast);
5209		}
5210	}
5211
5212	CG(active_op_array) = op_array;
5213
5214	zend_oparray_context_begin(&orig_oparray_context);
5215
5216	if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
5217		zend_op *opline_ext = zend_emit_op(NULL, ZEND_EXT_NOP, NULL, NULL);
5218		opline_ext->lineno = decl->start_lineno;
5219	}
5220
5221	{
5222		/* Push a separator to the loop variable stack */
5223		zend_loop_var dummy_var;
5224		dummy_var.opcode = ZEND_RETURN;
5225
5226		zend_stack_push(&CG(loop_var_stack), (void *) &dummy_var);
5227	}
5228
5229	zend_compile_params(params_ast, return_type_ast);
5230	if (uses_ast) {
5231		zend_compile_closure_uses(uses_ast);
5232	}
5233	zend_compile_stmt(stmt_ast);
5234
5235	if (is_method) {
5236		zend_check_magic_method_implementation(
5237			CG(active_class_entry), (zend_function *) op_array, E_COMPILE_ERROR);
5238	}
5239
5240	/* put the implicit return on the really last line */
5241	CG(zend_lineno) = decl->end_lineno;
5242
5243	zend_do_extended_info();
5244	zend_emit_final_return(0);
5245
5246	pass_two(CG(active_op_array));
5247	zend_oparray_context_end(&orig_oparray_context);
5248
5249	/* Pop the loop variable stack separator */
5250	zend_stack_del_top(&CG(loop_var_stack));
5251
5252	CG(active_op_array) = orig_op_array;
5253}
5254/* }}} */
5255
5256void zend_compile_prop_decl(zend_ast *ast) /* {{{ */
5257{
5258	zend_ast_list *list = zend_ast_get_list(ast);
5259	uint32_t flags = list->attr;
5260	zend_class_entry *ce = CG(active_class_entry);
5261	uint32_t i, children = list->children;
5262
5263	if (ce->ce_flags & ZEND_ACC_INTERFACE) {
5264		zend_error_noreturn(E_COMPILE_ERROR, "Interfaces may not include member variables");
5265	}
5266
5267	if (flags & ZEND_ACC_ABSTRACT) {
5268		zend_error_noreturn(E_COMPILE_ERROR, "Properties cannot be declared abstract");
5269	}
5270
5271	for (i = 0; i < children; ++i) {
5272		zend_ast *prop_ast = list->child[i];
5273		zend_ast *name_ast = prop_ast->child[0];
5274		zend_ast *value_ast = prop_ast->child[1];
5275		zend_ast *doc_comment_ast = prop_ast->child[2];
5276		zend_string *name = zend_ast_get_str(name_ast);
5277		zend_string *doc_comment = NULL;
5278		zval value_zv;
5279
5280		/* Doc comment has been appended as last element in ZEND_AST_PROP_ELEM ast */
5281		if (doc_comment_ast) {
5282			doc_comment = zend_string_copy(zend_ast_get_str(doc_comment_ast));
5283		}
5284
5285		if (flags & ZEND_ACC_FINAL) {
5286			zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare property %s::$%s final, "
5287				"the final modifier is allowed only for methods and classes",
5288				ZSTR_VAL(ce->name), ZSTR_VAL(name));
5289		}
5290
5291		if (zend_hash_exists(&ce->properties_info, name)) {
5292			zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::$%s",
5293				ZSTR_VAL(ce->name), ZSTR_VAL(name));
5294		}
5295
5296		if (value_ast) {
5297			zend_const_expr_to_zval(&value_zv, value_ast);
5298		} else {
5299			ZVAL_NULL(&value_zv);
5300		}
5301
5302		name = zend_new_interned_string_safe(name);
5303		zend_declare_property_ex(ce, name, &value_zv, flags, doc_comment);
5304	}
5305}
5306/* }}} */
5307
5308void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */
5309{
5310	zend_ast_list *list = zend_ast_get_list(ast);
5311	zend_class_entry *ce = CG(active_class_entry);
5312	uint32_t i;
5313
5314	if ((ce->ce_flags & ZEND_ACC_TRAIT) != 0) {
5315		zend_error_noreturn(E_COMPILE_ERROR, "Traits cannot have constants");
5316		return;
5317	}
5318
5319	for (i = 0; i < list->children; ++i) {
5320		zend_ast *const_ast = list->child[i];
5321		zend_ast *name_ast = const_ast->child[0];
5322		zend_ast *value_ast = const_ast->child[1];
5323		zend_ast *doc_comment_ast = const_ast->child[2];
5324		zend_string *name = zend_ast_get_str(name_ast);
5325		zend_string *doc_comment = doc_comment_ast ? zend_string_copy(zend_ast_get_str(doc_comment_ast)) : NULL;
5326		zval value_zv;
5327
5328		if (UNEXPECTED(ast->attr & (ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_FINAL))) {
5329			if (ast->attr & ZEND_ACC_STATIC) {
5330				zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as constant modifier");
5331			} else if (ast->attr & ZEND_ACC_ABSTRACT) {
5332				zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as constant modifier");
5333			} else if (ast->attr & ZEND_ACC_FINAL) {
5334				zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as constant modifier");
5335			}
5336		}
5337
5338		zend_const_expr_to_zval(&value_zv, value_ast);
5339
5340		name = zend_new_interned_string_safe(name);
5341		zend_declare_class_constant_ex(ce, name, &value_zv, ast->attr, doc_comment);
5342	}
5343}
5344/* }}} */
5345
5346static zend_trait_method_reference *zend_compile_method_ref(zend_ast *ast) /* {{{ */
5347{
5348	zend_ast *class_ast = ast->child[0];
5349	zend_ast *method_ast = ast->child[1];
5350
5351	zend_trait_method_reference *method_ref = emalloc(sizeof(zend_trait_method_reference));
5352	method_ref->ce = NULL;
5353	method_ref->method_name = zend_string_copy(zend_ast_get_str(method_ast));
5354
5355	if (class_ast) {
5356		method_ref->class_name = zend_resolve_class_name_ast(class_ast);
5357	} else {
5358		method_ref->class_name = NULL;
5359	}
5360
5361	return method_ref;
5362}
5363/* }}} */
5364
5365static zend_string **zend_compile_name_list(zend_ast *ast) /* {{{ */
5366{
5367	zend_ast_list *list = zend_ast_get_list(ast);
5368	zend_string **names = safe_emalloc(sizeof(zend_string *), list->children + 1, 0);
5369	uint32_t i;
5370
5371	for (i = 0; i < list->children; ++i) {
5372		zend_ast *name_ast = list->child[i];
5373		names[i] = zend_resolve_class_name_ast(name_ast);
5374	}
5375
5376	names[list->children] = NULL;
5377
5378	return names;
5379}
5380/* }}} */
5381
5382static void zend_compile_trait_precedence(zend_ast *ast) /* {{{ */
5383{
5384	zend_ast *method_ref_ast = ast->child[0];
5385	zend_ast *insteadof_ast = ast->child[1];
5386
5387	zend_trait_precedence *precedence = emalloc(sizeof(zend_trait_precedence));
5388	precedence->trait_method = zend_compile_method_ref(method_ref_ast);
5389	precedence->exclude_from_classes
5390		= (void *) zend_compile_name_list(insteadof_ast);
5391
5392	zend_add_to_list(&CG(active_class_entry)->trait_precedences, precedence);
5393}
5394/* }}} */
5395
5396static void zend_compile_trait_alias(zend_ast *ast) /* {{{ */
5397{
5398	zend_ast *method_ref_ast = ast->child[0];
5399	zend_ast *alias_ast = ast->child[1];
5400	uint32_t modifiers = ast->attr;
5401
5402	zend_trait_alias *alias;
5403
5404	if (modifiers == ZEND_ACC_STATIC) {
5405		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as method modifier");
5406	} else if (modifiers == ZEND_ACC_ABSTRACT) {
5407		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as method modifier");
5408	} else if (modifiers == ZEND_ACC_FINAL) {
5409		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as method modifier");
5410	}
5411
5412	alias = emalloc(sizeof(zend_trait_alias));
5413	alias->trait_method = zend_compile_method_ref(method_ref_ast);
5414	alias->modifiers = modifiers;
5415
5416	if (alias_ast) {
5417		alias->alias = zend_string_copy(zend_ast_get_str(alias_ast));
5418	} else {
5419		alias->alias = NULL;
5420	}
5421
5422	zend_add_to_list(&CG(active_class_entry)->trait_aliases, alias);
5423}
5424/* }}} */
5425
5426void zend_compile_use_trait(zend_ast *ast) /* {{{ */
5427{
5428	zend_ast_list *traits = zend_ast_get_list(ast->child[0]);
5429	zend_ast_list *adaptations = ast->child[1] ? zend_ast_get_list(ast->child[1]) : NULL;
5430	zend_class_entry *ce = CG(active_class_entry);
5431	zend_op *opline;
5432	uint32_t i;
5433
5434	for (i = 0; i < traits->children; ++i) {
5435		zend_ast *trait_ast = traits->child[i];
5436		zend_string *name = zend_ast_get_str(trait_ast);
5437
5438		if (ce->ce_flags & ZEND_ACC_INTERFACE) {
5439			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use traits inside of interfaces. "
5440				"%s is used in %s", ZSTR_VAL(name), ZSTR_VAL(ce->name));
5441		}
5442
5443		switch (zend_get_class_fetch_type(name)) {
5444			case ZEND_FETCH_CLASS_SELF:
5445			case ZEND_FETCH_CLASS_PARENT:
5446			case ZEND_FETCH_CLASS_STATIC:
5447				zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as trait name "
5448					"as it is reserved", ZSTR_VAL(name));
5449				break;
5450		}
5451
5452		opline = get_next_op(CG(active_op_array));
5453		opline->opcode = ZEND_ADD_TRAIT;
5454		SET_NODE(opline->op1, &FC(implementing_class));
5455		opline->op2_type = IS_CONST;
5456		opline->op2.constant = zend_add_class_name_literal(CG(active_op_array),
5457			zend_resolve_class_name_ast(trait_ast));
5458
5459		ce->num_traits++;
5460	}
5461
5462	if (!adaptations) {
5463		return;
5464	}
5465
5466	for (i = 0; i < adaptations->children; ++i) {
5467		zend_ast *adaptation_ast = adaptations->child[i];
5468		switch (adaptation_ast->kind) {
5469			case ZEND_AST_TRAIT_PRECEDENCE:
5470				zend_compile_trait_precedence(adaptation_ast);
5471				break;
5472			case ZEND_AST_TRAIT_ALIAS:
5473				zend_compile_trait_alias(adaptation_ast);
5474				break;
5475			EMPTY_SWITCH_DEFAULT_CASE()
5476		}
5477	}
5478}
5479/* }}} */
5480
5481void zend_compile_implements(znode *class_node, zend_ast *ast) /* {{{ */
5482{
5483	zend_ast_list *list = zend_ast_get_list(ast);
5484	uint32_t i;
5485	for (i = 0; i < list->children; ++i) {
5486		zend_ast *class_ast = list->child[i];
5487		zend_string *name = zend_ast_get_str(class_ast);
5488
5489		zend_op *opline;
5490
5491		if (!zend_is_const_default_class_ref(class_ast)) {
5492			zend_error_noreturn(E_COMPILE_ERROR,
5493				"Cannot use '%s' as interface name as it is reserved", ZSTR_VAL(name));
5494		}
5495
5496		opline = zend_emit_op(NULL, ZEND_ADD_INTERFACE, class_node, NULL);
5497		opline->op2_type = IS_CONST;
5498		opline->op2.constant = zend_add_class_name_literal(CG(active_op_array),
5499			zend_resolve_class_name_ast(class_ast));
5500
5501		CG(active_class_entry)->num_interfaces++;
5502	}
5503}
5504/* }}} */
5505
5506static zend_string *zend_generate_anon_class_name(unsigned char *lex_pos) /* {{{ */
5507{
5508	zend_string *result;
5509	char char_pos_buf[32];
5510	size_t char_pos_len = zend_sprintf(char_pos_buf, "%p", lex_pos);
5511	zend_string *filename = CG(active_op_array)->filename;
5512
5513	/* NULL, name length, filename length, last accepting char position length */
5514	result = zend_string_alloc(sizeof("class@anonymous") + ZSTR_LEN(filename) + char_pos_len, 0);
5515	sprintf(ZSTR_VAL(result), "class@anonymous%c%s%s", '\0', ZSTR_VAL(filename), char_pos_buf);
5516	return zend_new_interned_string(result);
5517}
5518/* }}} */
5519
5520void zend_compile_class_decl(zend_ast *ast) /* {{{ */
5521{
5522	zend_ast_decl *decl = (zend_ast_decl *) ast;
5523	zend_ast *extends_ast = decl->child[0];
5524	zend_ast *implements_ast = decl->child[1];
5525	zend_ast *stmt_ast = decl->child[2];
5526	zend_string *name, *lcname, *import_name = NULL;
5527	zend_class_entry *ce = zend_arena_alloc(&CG(arena), sizeof(zend_class_entry));
5528	zend_op *opline;
5529	znode declare_node, extends_node;
5530
5531	zend_class_entry *original_ce = CG(active_class_entry);
5532	znode original_implementing_class = FC(implementing_class);
5533
5534	if (EXPECTED((decl->flags & ZEND_ACC_ANON_CLASS) == 0)) {
5535		if (CG(active_class_entry)) {
5536			zend_error_noreturn(E_COMPILE_ERROR, "Class declarations may not be nested");
5537		}
5538		name = decl->name;
5539		zend_assert_valid_class_name(name);
5540		lcname = zend_string_tolower(name);
5541		if (FC(current_namespace)) {
5542			name = zend_prefix_with_ns(name);
5543
5544			zend_string_release(lcname);
5545			lcname = zend_string_tolower(name);
5546		} else {
5547			zend_string_addref(name);
5548		}
5549
5550		if (FC(imports)) {
5551			import_name = zend_hash_find_ptr(FC(imports), lcname);
5552		}
5553
5554		if (import_name && !zend_string_equals_ci(lcname, import_name)) {
5555			zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare class %s "
5556					"because the name is already in use", ZSTR_VAL(name));
5557		}
5558
5559		name = zend_new_interned_string(name);
5560	} else {
5561		name = zend_generate_anon_class_name(decl->lex_pos);
5562		lcname = zend_string_tolower(name);
5563	}
5564	lcname = zend_new_interned_string(lcname);
5565
5566	ce->type = ZEND_USER_CLASS;
5567	ce->name = name;
5568	zend_initialize_class_data(ce, 1);
5569
5570	ce->ce_flags |= decl->flags;
5571	ce->info.user.filename = zend_get_compiled_filename();
5572	ce->info.user.line_start = decl->start_lineno;
5573	ce->info.user.line_end = decl->end_lineno;
5574
5575	if (decl->doc_comment) {
5576		ce->info.user.doc_comment = zend_string_copy(decl->doc_comment);
5577	}
5578
5579	if (UNEXPECTED((decl->flags & ZEND_ACC_ANON_CLASS))) {
5580		/* Serialization is not supported for anonymous classes */
5581		ce->serialize = zend_class_serialize_deny;
5582		ce->unserialize = zend_class_unserialize_deny;
5583	}
5584
5585	if (extends_ast) {
5586		if (!zend_is_const_default_class_ref(extends_ast)) {
5587			zend_string *extends_name = zend_ast_get_str(extends_ast);
5588			zend_error_noreturn(E_COMPILE_ERROR,
5589				"Cannot use '%s' as class name as it is reserved", ZSTR_VAL(extends_name));
5590		}
5591
5592		zend_compile_class_ref(&extends_node, extends_ast, 0);
5593	}
5594
5595	opline = get_next_op(CG(active_op_array));
5596	zend_make_var_result(&declare_node, opline);
5597
5598	GET_NODE(&FC(implementing_class), opline->result);
5599
5600	opline->op1_type = IS_CONST;
5601	LITERAL_STR(opline->op1, lcname);
5602
5603	if (decl->flags & ZEND_ACC_ANON_CLASS) {
5604		if (extends_ast) {
5605			opline->opcode = ZEND_DECLARE_ANON_INHERITED_CLASS;
5606			SET_NODE(opline->op2, &extends_node);
5607		} else {
5608			opline->opcode = ZEND_DECLARE_ANON_CLASS;
5609		}
5610
5611		zend_hash_update_ptr(CG(class_table), lcname, ce);
5612	} else {
5613		zend_string *key;
5614
5615		if (extends_ast) {
5616			opline->opcode = ZEND_DECLARE_INHERITED_CLASS;
5617			SET_NODE(opline->op2, &extends_node);
5618		} else {
5619			opline->opcode = ZEND_DECLARE_CLASS;
5620		}
5621
5622		key = zend_build_runtime_definition_key(lcname, decl->lex_pos);
5623		/* RTD key is placed after lcname literal in op1 */
5624		zend_add_literal_string(CG(active_op_array), &key);
5625
5626		zend_hash_update_ptr(CG(class_table), key, ce);
5627	}
5628
5629	CG(active_class_entry) = ce;
5630
5631	if (implements_ast) {
5632		zend_compile_implements(&declare_node, implements_ast);
5633	}
5634
5635	zend_compile_stmt(stmt_ast);
5636
5637	/* Reset lineno for final opcodes and errors */
5638	CG(zend_lineno) = ast->lineno;
5639
5640	if (ce->num_traits == 0) {
5641		/* For traits this check is delayed until after trait binding */
5642		zend_check_deprecated_constructor(ce);
5643	}
5644
5645	if (ce->constructor) {
5646		ce->constructor->common.fn_flags |= ZEND_ACC_CTOR;
5647		if (ce->constructor->common.fn_flags & ZEND_ACC_STATIC) {
5648			zend_error_noreturn(E_COMPILE_ERROR, "Constructor %s::%s() cannot be static",
5649				ZSTR_VAL(ce->name), ZSTR_VAL(ce->constructor->common.function_name));
5650		}
5651		if (ce->constructor->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
5652			zend_error_noreturn(E_COMPILE_ERROR,
5653				"Constructor %s::%s() cannot declare a return type",
5654				ZSTR_VAL(ce->name), ZSTR_VAL(ce->constructor->common.function_name));
5655		}
5656	}
5657	if (ce->destructor) {
5658		ce->destructor->common.fn_flags |= ZEND_ACC_DTOR;
5659		if (ce->destructor->common.fn_flags & ZEND_ACC_STATIC) {
5660			zend_error_noreturn(E_COMPILE_ERROR, "Destructor %s::%s() cannot be static",
5661				ZSTR_VAL(ce->name), ZSTR_VAL(ce->destructor->common.function_name));
5662		} else if (ce->destructor->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
5663			zend_error_noreturn(E_COMPILE_ERROR,
5664				"Destructor %s::%s() cannot declare a return type",
5665				ZSTR_VAL(ce->name), ZSTR_VAL(ce->destructor->common.function_name));
5666		}
5667	}
5668	if (ce->clone) {
5669		ce->clone->common.fn_flags |= ZEND_ACC_CLONE;
5670		if (ce->clone->common.fn_flags & ZEND_ACC_STATIC) {
5671			zend_error_noreturn(E_COMPILE_ERROR, "Clone method %s::%s() cannot be static",
5672				ZSTR_VAL(ce->name), ZSTR_VAL(ce->clone->common.function_name));
5673		} else if (ce->clone->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
5674			zend_error_noreturn(E_COMPILE_ERROR,
5675				"%s::%s() cannot declare a return type",
5676				ZSTR_VAL(ce->name), ZSTR_VAL(ce->clone->common.function_name));
5677		}
5678	}
5679
5680	/* Check for traits and proceed like with interfaces.
5681	 * The only difference will be a combined handling of them in the end.
5682	 * Thus, we need another opcode here. */
5683	if (ce->num_traits > 0) {
5684		ce->traits = NULL;
5685		ce->num_traits = 0;
5686		ce->ce_flags |= ZEND_ACC_IMPLEMENT_TRAITS;
5687
5688		zend_emit_op(NULL, ZEND_BIND_TRAITS, &declare_node, NULL);
5689	}
5690
5691	if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))
5692		&& (extends_ast || ce->num_interfaces > 0)
5693	) {
5694		zend_verify_abstract_class(ce);
5695		if (ce->num_interfaces && !(ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS)) {
5696			zend_emit_op(NULL, ZEND_VERIFY_ABSTRACT_CLASS, &declare_node, NULL);
5697		}
5698	}
5699
5700	/* Inherit interfaces; reset number to zero, we need it for above check and
5701	 * will restore it during actual implementation.
5702	 * The ZEND_ACC_IMPLEMENT_INTERFACES flag disables double call to
5703	 * zend_verify_abstract_class() */
5704	if (ce->num_interfaces > 0) {
5705		ce->interfaces = NULL;
5706		ce->num_interfaces = 0;
5707		ce->ce_flags |= ZEND_ACC_IMPLEMENT_INTERFACES;
5708	}
5709
5710	FC(implementing_class) = original_implementing_class;
5711	CG(active_class_entry) = original_ce;
5712}
5713/* }}} */
5714
5715static HashTable *zend_get_import_ht(uint32_t type) /* {{{ */
5716{
5717	switch (type) {
5718		case T_CLASS:
5719			if (!FC(imports)) {
5720				FC(imports) = emalloc(sizeof(HashTable));
5721				zend_hash_init(FC(imports), 8, NULL, str_dtor, 0);
5722			}
5723			return FC(imports);
5724		case T_FUNCTION:
5725			if (!FC(imports_function)) {
5726				FC(imports_function) = emalloc(sizeof(HashTable));
5727				zend_hash_init(FC(imports_function), 8, NULL, str_dtor, 0);
5728			}
5729			return FC(imports_function);
5730		case T_CONST:
5731			if (!FC(imports_const)) {
5732				FC(imports_const) = emalloc(sizeof(HashTable));
5733				zend_hash_init(FC(imports_const), 8, NULL, str_dtor, 0);
5734			}
5735			return FC(imports_const);
5736		EMPTY_SWITCH_DEFAULT_CASE()
5737	}
5738
5739	return NULL;
5740}
5741/* }}} */
5742
5743static char *zend_get_use_type_str(uint32_t type) /* {{{ */
5744{
5745	switch (type) {
5746		case T_CLASS:
5747			return "";
5748		case T_FUNCTION:
5749			return " function";
5750		case T_CONST:
5751			return " const";
5752		EMPTY_SWITCH_DEFAULT_CASE()
5753	}
5754
5755	return " unknown";
5756}
5757/* }}} */
5758
5759static void zend_check_already_in_use(uint32_t type, zend_string *old_name, zend_string *new_name, zend_string *check_name) /* {{{ */
5760{
5761	if (zend_string_equals_ci(old_name, check_name)) {
5762		return;
5763	}
5764
5765	zend_error_noreturn(E_COMPILE_ERROR, "Cannot use%s %s as %s because the name "
5766		"is already in use", zend_get_use_type_str(type), ZSTR_VAL(old_name), ZSTR_VAL(new_name));
5767}
5768/* }}} */
5769
5770void zend_compile_use(zend_ast *ast) /* {{{ */
5771{
5772	zend_ast_list *list = zend_ast_get_list(ast);
5773	uint32_t i;
5774	zend_string *current_ns = FC(current_namespace);
5775	uint32_t type = ast->attr;
5776	HashTable *current_import = zend_get_import_ht(type);
5777	zend_bool case_sensitive = type == T_CONST;
5778
5779	for (i = 0; i < list->children; ++i) {
5780		zend_ast *use_ast = list->child[i];
5781		zend_ast *old_name_ast = use_ast->child[0];
5782		zend_ast *new_name_ast = use_ast->child[1];
5783		zend_string *old_name = zend_ast_get_str(old_name_ast);
5784		zend_string *new_name, *lookup_name;
5785
5786		if (new_name_ast) {
5787			new_name = zend_string_copy(zend_ast_get_str(new_name_ast));
5788		} else {
5789			const char *unqualified_name;
5790			size_t unqualified_name_len;
5791			if (zend_get_unqualified_name(old_name, &unqualified_name, &unqualified_name_len)) {
5792				/* The form "use A\B" is equivalent to "use A\B as B" */
5793				new_name = zend_string_init(unqualified_name, unqualified_name_len, 0);
5794			} else {
5795				new_name = zend_string_copy(old_name);
5796
5797				if (!current_ns) {
5798					if (type == T_CLASS && zend_string_equals_literal(new_name, "strict")) {
5799						zend_error_noreturn(E_COMPILE_ERROR,
5800							"You seem to be trying to use a different language...");
5801					}
5802
5803					zend_error(E_WARNING, "The use statement with non-compound name '%s' "
5804						"has no effect", ZSTR_VAL(new_name));
5805				}
5806			}
5807		}
5808
5809		if (case_sensitive) {
5810			lookup_name = zend_string_copy(new_name);
5811		} else {
5812			lookup_name = zend_string_tolower(new_name);
5813		}
5814
5815		if (type == T_CLASS && zend_is_reserved_class_name(new_name)) {
5816			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because '%s' "
5817				"is a special class name", ZSTR_VAL(old_name), ZSTR_VAL(new_name), ZSTR_VAL(new_name));
5818		}
5819
5820		if (current_ns) {
5821			zend_string *ns_name = zend_string_alloc(ZSTR_LEN(current_ns) + 1 + ZSTR_LEN(new_name), 0);
5822			zend_str_tolower_copy(ZSTR_VAL(ns_name), ZSTR_VAL(current_ns), ZSTR_LEN(current_ns));
5823			ZSTR_VAL(ns_name)[ZSTR_LEN(current_ns)] = '\\';
5824			memcpy(ZSTR_VAL(ns_name) + ZSTR_LEN(current_ns) + 1, ZSTR_VAL(lookup_name), ZSTR_LEN(lookup_name));
5825
5826			if (zend_hash_exists(CG(class_table), ns_name)) {
5827				zend_check_already_in_use(type, old_name, new_name, ns_name);
5828			}
5829
5830			zend_string_free(ns_name);
5831		} else {
5832			switch (type) {
5833				case T_CLASS:
5834				{
5835					zend_class_entry *ce = zend_hash_find_ptr(CG(class_table), lookup_name);
5836					if (ce && ce->type == ZEND_USER_CLASS
5837						&& ce->info.user.filename == CG(compiled_filename)
5838					) {
5839						zend_check_already_in_use(type, old_name, new_name, lookup_name);
5840					}
5841					break;
5842				}
5843				case T_FUNCTION:
5844				{
5845					zend_function *fn = zend_hash_find_ptr(CG(function_table), lookup_name);
5846					if (fn && fn->type == ZEND_USER_FUNCTION
5847						&& fn->op_array.filename == CG(compiled_filename)
5848					) {
5849						zend_check_already_in_use(type, old_name, new_name, lookup_name);
5850					}
5851					break;
5852				}
5853				case T_CONST:
5854				{
5855					zend_string *filename = zend_hash_find_ptr(&CG(const_filenames), lookup_name);
5856					if (filename && filename == CG(compiled_filename)) {
5857						zend_check_already_in_use(type, old_name, new_name, lookup_name);
5858					}
5859					break;
5860				}
5861				EMPTY_SWITCH_DEFAULT_CASE()
5862			}
5863		}
5864
5865		zend_string_addref(old_name);
5866		if (!zend_hash_add_ptr(current_import, lookup_name, old_name)) {
5867			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use%s %s as %s because the name "
5868				"is already in use", zend_get_use_type_str(type), ZSTR_VAL(old_name), ZSTR_VAL(new_name));
5869		}
5870
5871		zend_string_release(lookup_name);
5872		zend_string_release(new_name);
5873	}
5874}
5875/* }}} */
5876
5877void zend_compile_group_use(zend_ast *ast) /* {{{ */
5878{
5879	uint32_t i;
5880	zend_string *ns = zend_ast_get_str(ast->child[0]);
5881	zend_ast_list *list = zend_ast_get_list(ast->child[1]);
5882
5883	for (i = 0; i < list->children; i++) {
5884		zend_ast *inline_use, *use = list->child[i];
5885		zval *name_zval = zend_ast_get_zval(use->child[0]);
5886		zend_string *name = Z_STR_P(name_zval);
5887		zend_string *compound_ns = zend_concat_names(ZSTR_VAL(ns), ZSTR_LEN(ns), ZSTR_VAL(name), ZSTR_LEN(name));
5888		zend_string_release(name);
5889		ZVAL_STR(name_zval, compound_ns);
5890		inline_use = zend_ast_create_list(1, ZEND_AST_USE, use);
5891		inline_use->attr = ast->attr ? ast->attr : use->attr;
5892		zend_compile_use(inline_use);
5893	}
5894}
5895/* }}} */
5896
5897
5898void zend_compile_const_decl(zend_ast *ast) /* {{{ */
5899{
5900	zend_ast_list *list = zend_ast_get_list(ast);
5901	uint32_t i;
5902	for (i = 0; i < list->children; ++i) {
5903		zend_ast *const_ast = list->child[i];
5904		zend_ast *name_ast = const_ast->child[0];
5905		zend_ast *value_ast = const_ast->child[1];
5906		zend_string *name = zend_ast_get_str(name_ast);
5907
5908		zend_string *import_name;
5909		znode name_node, value_node;
5910		zval *value_zv = &value_node.u.constant;
5911
5912		value_node.op_type = IS_CONST;
5913		zend_const_expr_to_zval(value_zv, value_ast);
5914
5915		if (zend_lookup_reserved_const(ZSTR_VAL(name), ZSTR_LEN(name))) {
5916			zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare constant '%s'", ZSTR_VAL(name));
5917		}
5918
5919		name = zend_prefix_with_ns(name);
5920		name = zend_new_interned_string(name);
5921
5922		if (FC(imports_const)
5923			&& (import_name = zend_hash_find_ptr(FC(imports_const), name))
5924		) {
5925			if (!zend_string_equals(import_name, name)) {
5926				zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare const %s because "
5927					"the name is already in use", ZSTR_VAL(name));
5928			}
5929		}
5930
5931		name_node.op_type = IS_CONST;
5932		ZVAL_STR(&name_node.u.constant, name);
5933
5934		zend_emit_op(NULL, ZEND_DECLARE_CONST, &name_node, &value_node);
5935
5936		zend_hash_add_ptr(&CG(const_filenames), name, CG(compiled_filename));
5937	}
5938}
5939/* }}}*/
5940
5941void zend_compile_namespace(zend_ast *ast) /* {{{ */
5942{
5943	zend_ast *name_ast = ast->child[0];
5944	zend_ast *stmt_ast = ast->child[1];
5945	zend_string *name;
5946	zend_bool with_bracket = stmt_ast != NULL;
5947
5948	/* handle mixed syntax declaration or nested namespaces */
5949	if (!FC(has_bracketed_namespaces)) {
5950		if (FC(current_namespace)) {
5951			/* previous namespace declarations were unbracketed */
5952			if (with_bracket) {
5953				zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations "
5954					"with unbracketed namespace declarations");
5955			}
5956		}
5957	} else {
5958		/* previous namespace declarations were bracketed */
5959		if (!with_bracket) {
5960			zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations "
5961				"with unbracketed namespace declarations");
5962		} else if (FC(current_namespace) || FC(in_namespace)) {
5963			zend_error_noreturn(E_COMPILE_ERROR, "Namespace declarations cannot be nested");
5964		}
5965	}
5966
5967	if (((!with_bracket && !FC(current_namespace))
5968		 || (with_bracket && !FC(has_bracketed_namespaces))) && CG(active_op_array)->last > 0
5969	) {
5970		/* ignore ZEND_EXT_STMT and ZEND_TICKS */
5971		uint32_t num = CG(active_op_array)->last;
5972		while (num > 0 &&
5973		       (CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
5974		        CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
5975			--num;
5976		}
5977		if (num > 0) {
5978			zend_error_noreturn(E_COMPILE_ERROR, "Namespace declaration statement has to be "
5979				"the very first statement or after any declare call in the script");
5980		}
5981	}
5982
5983	if (FC(current_namespace)) {
5984		zend_string_release(FC(current_namespace));
5985	}
5986
5987	if (name_ast) {
5988		name = zend_ast_get_str(name_ast);
5989
5990		if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
5991			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as namespace name", ZSTR_VAL(name));
5992		}
5993
5994		FC(current_namespace) = zend_string_copy(name);
5995	} else {
5996		FC(current_namespace) = NULL;
5997	}
5998
5999	zend_reset_import_tables();
6000
6001	FC(in_namespace) = 1;
6002	if (with_bracket) {
6003		FC(has_bracketed_namespaces) = 1;
6004	}
6005
6006	if (stmt_ast) {
6007		zend_compile_top_stmt(stmt_ast);
6008		zend_end_namespace();
6009	}
6010}
6011/* }}} */
6012
6013void zend_compile_halt_compiler(zend_ast *ast) /* {{{ */
6014{
6015	zend_ast *offset_ast = ast->child[0];
6016	zend_long offset = Z_LVAL_P(zend_ast_get_zval(offset_ast));
6017
6018	zend_string *filename, *name;
6019	const char const_name[] = "__COMPILER_HALT_OFFSET__";
6020
6021	if (FC(has_bracketed_namespaces) && FC(in_namespace)) {
6022		zend_error_noreturn(E_COMPILE_ERROR,
6023			"__HALT_COMPILER() can only be used from the outermost scope");
6024	}
6025
6026	filename = zend_get_compiled_filename();
6027	name = zend_mangle_property_name(const_name, sizeof(const_name) - 1,
6028		ZSTR_VAL(filename), ZSTR_LEN(filename), 0);
6029
6030	zend_register_long_constant(ZSTR_VAL(name), ZSTR_LEN(name), offset, CONST_CS, 0);
6031	zend_string_release(name);
6032}
6033/* }}} */
6034
6035static zend_bool zend_try_ct_eval_magic_const(zval *zv, zend_ast *ast) /* {{{ */
6036{
6037	zend_op_array *op_array = CG(active_op_array);
6038	zend_class_entry *ce = CG(active_class_entry);
6039
6040	switch (ast->attr) {
6041		case T_LINE:
6042			ZVAL_LONG(zv, ast->lineno);
6043			break;
6044		case T_FILE:
6045			ZVAL_STR_COPY(zv, CG(compiled_filename));
6046			break;
6047		case T_DIR:
6048		{
6049			zend_string *filename = CG(compiled_filename);
6050			zend_string *dirname = zend_string_init(ZSTR_VAL(filename), ZSTR_LEN(filename), 0);
6051			zend_dirname(ZSTR_VAL(dirname), ZSTR_LEN(dirname));
6052
6053			if (strcmp(ZSTR_VAL(dirname), ".") == 0) {
6054				dirname = zend_string_extend(dirname, MAXPATHLEN, 0);
6055#if HAVE_GETCWD
6056				ZEND_IGNORE_VALUE(VCWD_GETCWD(ZSTR_VAL(dirname), MAXPATHLEN));
6057#elif HAVE_GETWD
6058				ZEND_IGNORE_VALUE(VCWD_GETWD(ZSTR_VAL(dirname)));
6059#endif
6060			}
6061
6062			ZSTR_LEN(dirname) = strlen(ZSTR_VAL(dirname));
6063			ZVAL_STR(zv, dirname);
6064			break;
6065		}
6066		case T_FUNC_C:
6067			if (op_array && op_array->function_name) {
6068				ZVAL_STR_COPY(zv, op_array->function_name);
6069			} else {
6070				ZVAL_EMPTY_STRING(zv);
6071			}
6072			break;
6073		case T_METHOD_C:
6074			if ((op_array && !op_array->scope && op_array->function_name) || (op_array->fn_flags & ZEND_ACC_CLOSURE)) {
6075				ZVAL_STR_COPY(zv, op_array->function_name);
6076			} else if (ce) {
6077				if (op_array && op_array->function_name) {
6078					ZVAL_NEW_STR(zv, zend_concat3(ZSTR_VAL(ce->name), ZSTR_LEN(ce->name), "::", 2,
6079						ZSTR_VAL(op_array->function_name), ZSTR_LEN(op_array->function_name)));
6080				} else {
6081					ZVAL_STR_COPY(zv, ce->name);
6082				}
6083			} else if (op_array && op_array->function_name) {
6084				ZVAL_STR_COPY(zv, op_array->function_name);
6085			} else {
6086				ZVAL_EMPTY_STRING(zv);
6087			}
6088			break;
6089		case T_CLASS_C:
6090			if (ce) {
6091				if ((ce->ce_flags & ZEND_ACC_TRAIT) != 0) {
6092					return 0;
6093				} else {
6094					ZVAL_STR_COPY(zv, ce->name);
6095				}
6096			} else {
6097				ZVAL_EMPTY_STRING(zv);
6098			}
6099			break;
6100		case T_TRAIT_C:
6101			if (ce && (ce->ce_flags & ZEND_ACC_TRAIT) != 0) {
6102				ZVAL_STR_COPY(zv, ce->name);
6103			} else {
6104				ZVAL_EMPTY_STRING(zv);
6105			}
6106			break;
6107		case T_NS_C:
6108			if (FC(current_namespace)) {
6109				ZVAL_STR_COPY(zv, FC(current_namespace));
6110			} else {
6111				ZVAL_EMPTY_STRING(zv);
6112			}
6113			break;
6114		EMPTY_SWITCH_DEFAULT_CASE()
6115	}
6116
6117	return 1;
6118}
6119/* }}} */
6120
6121static inline zend_bool zend_try_ct_eval_binary_op(zval *result, uint32_t opcode, zval *op1, zval *op2) /* {{{ */
6122{
6123	binary_op_type fn = get_binary_op(opcode);
6124
6125	/* don't evaluate division by zero at compile-time */
6126	if ((opcode == ZEND_DIV || opcode == ZEND_MOD) &&
6127	    zval_get_long(op2) == 0) {
6128		return 0;
6129	} else if ((opcode == ZEND_SL || opcode == ZEND_SR) &&
6130	    zval_get_long(op2) < 0) {
6131		return 0;
6132	}
6133
6134	fn(result, op1, op2);
6135	return 1;
6136}
6137/* }}} */
6138
6139static inline void zend_ct_eval_unary_op(zval *result, uint32_t opcode, zval *op) /* {{{ */
6140{
6141	unary_op_type fn = get_unary_op(opcode);
6142	fn(result, op);
6143}
6144/* }}} */
6145
6146static inline void zend_ct_eval_unary_pm(zval *result, zend_ast_kind kind, zval *op) /* {{{ */
6147{
6148	zval left;
6149	ZVAL_LONG(&left, (kind == ZEND_AST_UNARY_PLUS) ? 1 : -1);
6150	mul_function(result, &left, op);
6151}
6152/* }}} */
6153
6154static inline void zend_ct_eval_greater(zval *result, zend_ast_kind kind, zval *op1, zval *op2) /* {{{ */
6155{
6156	binary_op_type fn = kind == ZEND_AST_GREATER
6157		? is_smaller_function : is_smaller_or_equal_function;
6158	fn(result, op2, op1);
6159}
6160/* }}} */
6161
6162static zend_bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */
6163{
6164	zend_ast_list *list = zend_ast_get_list(ast);
6165	uint32_t i;
6166	zend_bool is_constant = 1;
6167
6168	/* First ensure that *all* child nodes are constant and by-val */
6169	for (i = 0; i < list->children; ++i) {
6170		zend_ast *elem_ast = list->child[i];
6171		zend_bool by_ref = elem_ast->attr;
6172		zend_eval_const_expr(&elem_ast->child[0]);
6173		zend_eval_const_expr(&elem_ast->child[1]);
6174
6175		if (by_ref || elem_ast->child[0]->kind != ZEND_AST_ZVAL
6176			|| (elem_ast->child[1] && elem_ast->child[1]->kind != ZEND_AST_ZVAL)
6177		) {
6178			is_constant = 0;
6179		}
6180	}
6181
6182	if (!is_constant) {
6183		return 0;
6184	}
6185
6186	array_init_size(result, list->children);
6187	for (i = 0; i < list->children; ++i) {
6188		zend_ast *elem_ast = list->child[i];
6189		zend_ast *value_ast = elem_ast->child[0];
6190		zend_ast *key_ast = elem_ast->child[1];
6191
6192		zval *value = zend_ast_get_zval(value_ast);
6193		if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value);
6194
6195		if (key_ast) {
6196			zval *key = zend_ast_get_zval(key_ast);
6197			switch (Z_TYPE_P(key)) {
6198				case IS_LONG:
6199					zend_hash_index_update(Z_ARRVAL_P(result), Z_LVAL_P(key), value);
6200					break;
6201				case IS_STRING:
6202					zend_symtable_update(Z_ARRVAL_P(result), Z_STR_P(key), value);
6203					break;
6204				case IS_DOUBLE:
6205					zend_hash_index_update(Z_ARRVAL_P(result),
6206						zend_dval_to_lval(Z_DVAL_P(key)), value);
6207					break;
6208				case IS_FALSE:
6209					zend_hash_index_update(Z_ARRVAL_P(result), 0, value);
6210					break;
6211				case IS_TRUE:
6212					zend_hash_index_update(Z_ARRVAL_P(result), 1, value);
6213					break;
6214				case IS_NULL:
6215					zend_hash_update(Z_ARRVAL_P(result), ZSTR_EMPTY_ALLOC(), value);
6216					break;
6217				default:
6218					zend_error_noreturn(E_COMPILE_ERROR, "Illegal offset type");
6219					break;
6220			}
6221		} else {
6222			zend_hash_next_index_insert(Z_ARRVAL_P(result), value);
6223		}
6224	}
6225
6226	return 1;
6227}
6228/* }}} */
6229
6230void zend_compile_binary_op(znode *result, zend_ast *ast) /* {{{ */
6231{
6232	zend_ast *left_ast = ast->child[0];
6233	zend_ast *right_ast = ast->child[1];
6234	uint32_t opcode = ast->attr;
6235
6236	znode left_node, right_node;
6237	zend_compile_expr(&left_node, left_ast);
6238	zend_compile_expr(&right_node, right_ast);
6239
6240	if (left_node.op_type == IS_CONST && right_node.op_type == IS_CONST) {
6241		if (zend_try_ct_eval_binary_op(&result->u.constant, opcode,
6242				&left_node.u.constant, &right_node.u.constant)
6243		) {
6244			result->op_type = IS_CONST;
6245			zval_ptr_dtor(&left_node.u.constant);
6246			zval_ptr_dtor(&right_node.u.constant);
6247			return;
6248		}
6249	}
6250
6251	do {
6252		if (opcode == ZEND_IS_EQUAL || opcode == ZEND_IS_NOT_EQUAL) {
6253			if (left_node.op_type == IS_CONST) {
6254				if (Z_TYPE(left_node.u.constant) == IS_FALSE) {
6255					opcode = (opcode == ZEND_IS_NOT_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
6256					zend_emit_op_tmp(result, opcode, &right_node, NULL);
6257					break;
6258				} else if (Z_TYPE(left_node.u.constant) == IS_TRUE) {
6259					opcode = (opcode == ZEND_IS_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
6260					zend_emit_op_tmp(result, opcode, &right_node, NULL);
6261					break;
6262				}
6263			} else if (right_node.op_type == IS_CONST) {
6264				if (Z_TYPE(right_node.u.constant) == IS_FALSE) {
6265					opcode = (opcode == ZEND_IS_NOT_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
6266					zend_emit_op_tmp(result, opcode, &left_node, NULL);
6267					break;
6268				} else if (Z_TYPE(right_node.u.constant) == IS_TRUE) {
6269					opcode = (opcode == ZEND_IS_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
6270					zend_emit_op_tmp(result, opcode, &left_node, NULL);
6271					break;
6272				}
6273			}
6274		}
6275		if (opcode == ZEND_CONCAT) {
6276			/* convert constant operands to strings at compile-time */
6277			if (left_node.op_type == IS_CONST) {
6278				convert_to_string(&left_node.u.constant);
6279			}
6280			if (right_node.op_type == IS_CONST) {
6281				convert_to_string(&right_node.u.constant);
6282			}
6283		}
6284		zend_emit_op_tmp(result, opcode, &left_node, &right_node);
6285	} while (0);
6286}
6287/* }}} */
6288
6289/* We do not use zend_compile_binary_op for this because we want to retain the left-to-right
6290 * evaluation order. */
6291void zend_compile_greater(znode *result, zend_ast *ast) /* {{{ */
6292{
6293	zend_ast *left_ast = ast->child[0];
6294	zend_ast *right_ast = ast->child[1];
6295	znode left_node, right_node;
6296
6297	ZEND_ASSERT(ast->kind == ZEND_AST_GREATER || ast->kind == ZEND_AST_GREATER_EQUAL);
6298
6299	zend_compile_expr(&left_node, left_ast);
6300	zend_compile_expr(&right_node, right_ast);
6301
6302	if (left_node.op_type == IS_CONST && right_node.op_type == IS_CONST) {
6303		result->op_type = IS_CONST;
6304		zend_ct_eval_greater(&result->u.constant, ast->kind,
6305			&left_node.u.constant, &right_node.u.constant);
6306		zval_ptr_dtor(&left_node.u.constant);
6307		zval_ptr_dtor(&right_node.u.constant);
6308		return;
6309	}
6310
6311	zend_emit_op_tmp(result,
6312		ast->kind == ZEND_AST_GREATER ? ZEND_IS_SMALLER : ZEND_IS_SMALLER_OR_EQUAL,
6313		&right_node, &left_node);
6314}
6315/* }}} */
6316
6317void zend_compile_unary_op(znode *result, zend_ast *ast) /* {{{ */
6318{
6319	zend_ast *expr_ast = ast->child[0];
6320	uint32_t opcode = ast->attr;
6321
6322	znode expr_node;
6323	zend_compile_expr(&expr_node, expr_ast);
6324
6325	if (expr_node.op_type == IS_CONST) {
6326		result->op_type = IS_CONST;
6327		zend_ct_eval_unary_op(&result->u.constant, opcode,
6328			&expr_node.u.constant);
6329		zval_ptr_dtor(&expr_node.u.constant);
6330		return;
6331	}
6332
6333	zend_emit_op_tmp(result, opcode, &expr_node, NULL);
6334}
6335/* }}} */
6336
6337void zend_compile_unary_pm(znode *result, zend_ast *ast) /* {{{ */
6338{
6339	zend_ast *expr_ast = ast->child[0];
6340	znode expr_node;
6341	znode lefthand_node;
6342
6343	ZEND_ASSERT(ast->kind == ZEND_AST_UNARY_PLUS || ast->kind == ZEND_AST_UNARY_MINUS);
6344
6345	zend_compile_expr(&expr_node, expr_ast);
6346
6347	if (expr_node.op_type == IS_CONST) {
6348		result->op_type = IS_CONST;
6349		zend_ct_eval_unary_pm(&result->u.constant, ast->kind, &expr_node.u.constant);
6350		zval_ptr_dtor(&expr_node.u.constant);
6351		return;
6352	}
6353
6354	lefthand_node.op_type = IS_CONST;
6355	ZVAL_LONG(&lefthand_node.u.constant, (ast->kind == ZEND_AST_UNARY_PLUS) ? 1 : -1);
6356	zend_emit_op_tmp(result, ZEND_MUL, &lefthand_node, &expr_node);
6357}
6358/* }}} */
6359
6360void zend_compile_short_circuiting(znode *result, zend_ast *ast) /* {{{ */
6361{
6362	zend_ast *left_ast = ast->child[0];
6363	zend_ast *right_ast = ast->child[1];
6364
6365	znode left_node, right_node;
6366	zend_op *opline_jmpz, *opline_bool;
6367	uint32_t opnum_jmpz;
6368
6369	ZEND_ASSERT(ast->kind == ZEND_AST_AND || ast->kind == ZEND_AST_OR);
6370
6371	zend_compile_expr(&left_node, left_ast);
6372
6373	if (left_node.op_type == IS_CONST) {
6374		if ((ast->kind == ZEND_AST_AND && !zend_is_true(&left_node.u.constant))
6375		 || (ast->kind == ZEND_AST_OR && zend_is_true(&left_node.u.constant))) {
6376			result->op_type = IS_CONST;
6377			ZVAL_BOOL(&result->u.constant, zend_is_true(&left_node.u.constant));
6378		} else {
6379			zend_compile_expr(&right_node, right_ast);
6380
6381			if (right_node.op_type == IS_CONST) {
6382				result->op_type = IS_CONST;
6383				ZVAL_BOOL(&result->u.constant, zend_is_true(&right_node.u.constant));
6384
6385				zval_ptr_dtor(&right_node.u.constant);
6386			} else {
6387				zend_emit_op(result, ZEND_BOOL, &right_node, NULL);
6388			}
6389		}
6390
6391		zval_ptr_dtor(&left_node.u.constant);
6392		return;
6393	}
6394
6395	opnum_jmpz = get_next_op_number(CG(active_op_array));
6396	opline_jmpz = zend_emit_op(NULL, ast->kind == ZEND_AST_AND ? ZEND_JMPZ_EX : ZEND_JMPNZ_EX,
6397		&left_node, NULL);
6398
6399	if (left_node.op_type == IS_TMP_VAR) {
6400		SET_NODE(opline_jmpz->result, &left_node);
6401	} else {
6402		opline_jmpz->result.var = get_temporary_variable(CG(active_op_array));
6403		opline_jmpz->result_type = IS_TMP_VAR;
6404	}
6405
6406	GET_NODE(result, opline_jmpz->result);
6407	zend_compile_expr(&right_node, right_ast);
6408
6409	opline_bool = zend_emit_op(NULL, ZEND_BOOL, &right_node, NULL);
6410	SET_NODE(opline_bool->result, result);
6411
6412	zend_update_jump_target_to_next(opnum_jmpz);
6413}
6414/* }}} */
6415
6416void zend_compile_post_incdec(znode *result, zend_ast *ast) /* {{{ */
6417{
6418	zend_ast *var_ast = ast->child[0];
6419	ZEND_ASSERT(ast->kind == ZEND_AST_POST_INC || ast->kind == ZEND_AST_POST_DEC);
6420
6421	zend_ensure_writable_variable(var_ast);
6422
6423	if (var_ast->kind == ZEND_AST_PROP) {
6424		zend_op *opline = zend_compile_prop_common(NULL, var_ast, BP_VAR_RW);
6425		opline->opcode = ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC_OBJ : ZEND_POST_DEC_OBJ;
6426		zend_make_tmp_result(result, opline);
6427	} else {
6428		znode var_node;
6429		zend_compile_var(&var_node, var_ast, BP_VAR_RW);
6430		zend_emit_op_tmp(result, ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC : ZEND_POST_DEC,
6431			&var_node, NULL);
6432	}
6433}
6434/* }}} */
6435
6436void zend_compile_pre_incdec(znode *result, zend_ast *ast) /* {{{ */
6437{
6438	zend_ast *var_ast = ast->child[0];
6439	ZEND_ASSERT(ast->kind == ZEND_AST_PRE_INC || ast->kind == ZEND_AST_PRE_DEC);
6440
6441	zend_ensure_writable_variable(var_ast);
6442
6443	if (var_ast->kind == ZEND_AST_PROP) {
6444		zend_op *opline = zend_compile_prop_common(result, var_ast, BP_VAR_RW);
6445		opline->opcode = ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC_OBJ : ZEND_PRE_DEC_OBJ;
6446	} else {
6447		znode var_node;
6448		zend_compile_var(&var_node, var_ast, BP_VAR_RW);
6449		zend_emit_op(result, ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC : ZEND_PRE_DEC,
6450			&var_node, NULL);
6451	}
6452}
6453/* }}} */
6454
6455void zend_compile_cast(znode *result, zend_ast *ast) /* {{{ */
6456{
6457	zend_ast *expr_ast = ast->child[0];
6458	znode expr_node;
6459	zend_op *opline;
6460
6461	zend_compile_expr(&expr_node, expr_ast);
6462
6463	opline = zend_emit_op_tmp(result, ZEND_CAST, &expr_node, NULL);
6464	opline->extended_value = ast->attr;
6465}
6466/* }}} */
6467
6468static void zend_compile_shorthand_conditional(znode *result, zend_ast *ast) /* {{{ */
6469{
6470	zend_ast *cond_ast = ast->child[0];
6471	zend_ast *false_ast = ast->child[2];
6472
6473	znode cond_node, false_node;
6474	zend_op *opline_qm_assign;
6475	uint32_t opnum_jmp_set;
6476
6477	ZEND_ASSERT(ast->child[1] == NULL);
6478
6479	zend_compile_expr(&cond_node, cond_ast);
6480
6481	opnum_jmp_set = get_next_op_number(CG(active_op_array));
6482	zend_emit_op_tmp(result, ZEND_JMP_SET, &cond_node, NULL);
6483
6484	zend_compile_expr(&false_node, false_ast);
6485
6486	opline_qm_assign = zend_emit_op_tmp(NULL, ZEND_QM_ASSIGN, &false_node, NULL);
6487	SET_NODE(opline_qm_assign->result, result);
6488
6489	zend_update_jump_target_to_next(opnum_jmp_set);
6490}
6491/* }}} */
6492
6493void zend_compile_conditional(znode *result, zend_ast *ast) /* {{{ */
6494{
6495	zend_ast *cond_ast = ast->child[0];
6496	zend_ast *true_ast = ast->child[1];
6497	zend_ast *false_ast = ast->child[2];
6498
6499	znode cond_node, true_node, false_node;
6500	zend_op *opline_qm_assign2;
6501	uint32_t opnum_jmpz, opnum_jmp;
6502
6503	if (!true_ast) {
6504		zend_compile_shorthand_conditional(result, ast);
6505		return;
6506	}
6507
6508	zend_compile_expr(&cond_node, cond_ast);
6509
6510	opnum_jmpz = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0);
6511
6512	zend_compile_expr(&true_node, true_ast);
6513
6514	zend_emit_op_tmp(result, ZEND_QM_ASSIGN, &true_node, NULL);
6515
6516	opnum_jmp = zend_emit_jump(0);
6517
6518	zend_update_jump_target_to_next(opnum_jmpz);
6519
6520	zend_compile_expr(&false_node, false_ast);
6521
6522	opline_qm_assign2 = zend_emit_op(NULL, ZEND_QM_ASSIGN, &false_node, NULL);
6523	SET_NODE(opline_qm_assign2->result, result);
6524
6525	zend_update_jump_target_to_next(opnum_jmp);
6526}
6527/* }}} */
6528
6529void zend_compile_coalesce(znode *result, zend_ast *ast) /* {{{ */
6530{
6531	zend_ast *expr_ast = ast->child[0];
6532	zend_ast *default_ast = ast->child[1];
6533
6534	znode expr_node, default_node;
6535	zend_op *opline;
6536	uint32_t opnum;
6537
6538	zend_compile_var(&expr_node, expr_ast, BP_VAR_IS);
6539
6540	opnum = get_next_op_number(CG(active_op_array));
6541	zend_emit_op_tmp(result, ZEND_COALESCE, &expr_node, NULL);
6542
6543	zend_compile_expr(&default_node, default_ast);
6544
6545	opline = zend_emit_op_tmp(NULL, ZEND_QM_ASSIGN, &default_node, NULL);
6546	SET_NODE(opline->result, result);
6547
6548	opline = &CG(active_op_array)->opcodes[opnum];
6549	opline->op2.opline_num = get_next_op_number(CG(active_op_array));
6550}
6551/* }}} */
6552
6553void zend_compile_print(znode *result, zend_ast *ast) /* {{{ */
6554{
6555	zend_op *opline;
6556	zend_ast *expr_ast = ast->child[0];
6557
6558	znode expr_node;
6559	zend_compile_expr(&expr_node, expr_ast);
6560
6561	opline = zend_emit_op(NULL, ZEND_ECHO, &expr_node, NULL);
6562	opline->extended_value = 1;
6563
6564	result->op_type = IS_CONST;
6565	ZVAL_LONG(&result->u.constant, 1);
6566}
6567/* }}} */
6568
6569void zend_compile_exit(znode *result, zend_ast *ast) /* {{{ */
6570{
6571	zend_ast *expr_ast = ast->child[0];
6572
6573	if (expr_ast) {
6574		znode expr_node;
6575		zend_compile_expr(&expr_node, expr_ast);
6576		zend_emit_op(NULL, ZEND_EXIT, &expr_node, NULL);
6577	} else {
6578		zend_emit_op(NULL, ZEND_EXIT, NULL, NULL);
6579	}
6580
6581	result->op_type = IS_CONST;
6582	ZVAL_BOOL(&result->u.constant, 1);
6583}
6584/* }}} */
6585
6586void zend_compile_yield(znode *result, zend_ast *ast) /* {{{ */
6587{
6588	zend_ast *value_ast = ast->child[0];
6589	zend_ast *key_ast = ast->child[1];
6590
6591	znode value_node, key_node;
6592	znode *value_node_ptr = NULL, *key_node_ptr = NULL;
6593	zend_op *opline;
6594	zend_bool returns_by_ref = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
6595
6596	zend_mark_function_as_generator();
6597
6598	if (key_ast) {
6599		zend_compile_expr(&key_node, key_ast);
6600		key_node_ptr = &key_node;
6601	}
6602
6603	if (value_ast) {
6604		if (returns_by_ref && zend_is_variable(value_ast) && !zend_is_call(value_ast)) {
6605			zend_compile_var(&value_node, value_ast, BP_VAR_W);
6606		} else {
6607			zend_compile_expr(&value_node, value_ast);
6608		}
6609		value_node_ptr = &value_node;
6610	}
6611
6612	opline = zend_emit_op(result, ZEND_YIELD, value_node_ptr, key_node_ptr);
6613
6614	if (value_ast && returns_by_ref && zend_is_call(value_ast)) {
6615		opline->extended_value = ZEND_RETURNS_FUNCTION;
6616	}
6617}
6618/* }}} */
6619
6620void zend_compile_yield_from(znode *result, zend_ast *ast) /* {{{ */
6621{
6622	zend_ast *expr_ast = ast->child[0];
6623	znode expr_node;
6624
6625	zend_mark_function_as_generator();
6626
6627	zend_compile_expr(&expr_node, expr_ast);
6628	zend_emit_op_tmp(result, ZEND_YIELD_FROM, &expr_node, NULL);
6629}
6630/* }}} */
6631
6632void zend_compile_instanceof(znode *result, zend_ast *ast) /* {{{ */
6633{
6634	zend_ast *obj_ast = ast->child[0];
6635	zend_ast *class_ast = ast->child[1];
6636
6637	znode obj_node, class_node;
6638	zend_op *opline;
6639
6640	zend_compile_expr(&obj_node, obj_ast);
6641	if (obj_node.op_type == IS_CONST) {
6642		zend_error_noreturn(E_COMPILE_ERROR,
6643			"instanceof expects an object instance, constant given");
6644	}
6645
6646	zend_compile_class_ref_ex(&class_node, class_ast,
6647		ZEND_FETCH_CLASS_NO_AUTOLOAD | ZEND_FETCH_CLASS_EXCEPTION);
6648
6649	opline = zend_emit_op_tmp(result, ZEND_INSTANCEOF, &obj_node, NULL);
6650
6651	if (class_node.op_type == IS_CONST) {
6652		opline->op2_type = IS_CONST;
6653		opline->op2.constant = zend_add_class_name_literal(
6654			CG(active_op_array), Z_STR(class_node.u.constant));
6655	} else {
6656		SET_NODE(opline->op2, &class_node);
6657	}
6658}
6659/* }}} */
6660
6661void zend_compile_include_or_eval(znode *result, zend_ast *ast) /* {{{ */
6662{
6663	zend_ast *expr_ast = ast->child[0];
6664	znode expr_node;
6665	zend_op *opline;
6666
6667	zend_do_extended_fcall_begin();
6668	zend_compile_expr(&expr_node, expr_ast);
6669
6670	opline = zend_emit_op(result, ZEND_INCLUDE_OR_EVAL, &expr_node, NULL);
6671	opline->extended_value = ast->attr;
6672
6673	zend_do_extended_fcall_end();
6674}
6675/* }}} */
6676
6677void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */
6678{
6679	zend_ast *var_ast = ast->child[0];
6680
6681	znode var_node;
6682	zend_op *opline = NULL;
6683
6684	ZEND_ASSERT(ast->kind == ZEND_AST_ISSET || ast->kind == ZEND_AST_EMPTY);
6685
6686	if (!zend_is_variable(var_ast) || zend_is_call(var_ast)) {
6687		if (ast->kind == ZEND_AST_EMPTY) {
6688			/* empty(expr) can be transformed to !expr */
6689			zend_ast *not_ast = zend_ast_create_ex(ZEND_AST_UNARY_OP, ZEND_BOOL_NOT, var_ast);
6690			zend_compile_expr(result, not_ast);
6691			return;
6692		} else {
6693			zend_error_noreturn(E_COMPILE_ERROR,
6694				"Cannot use isset() on the result of an expression "
6695				"(you can use \"null !== expression\" instead)");
6696		}
6697	}
6698
6699	switch (var_ast->kind) {
6700		case ZEND_AST_VAR:
6701			if (zend_try_compile_cv(&var_node, var_ast) == SUCCESS) {
6702				opline = zend_emit_op(result, ZEND_ISSET_ISEMPTY_VAR, &var_node, NULL);
6703				opline->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
6704			} else {
6705				opline = zend_compile_simple_var_no_cv(result, var_ast, BP_VAR_IS, 0);
6706				opline->opcode = ZEND_ISSET_ISEMPTY_VAR;
6707			}
6708			break;
6709		case ZEND_AST_DIM:
6710			opline = zend_compile_dim_common(result, var_ast, BP_VAR_IS);
6711			opline->opcode = ZEND_ISSET_ISEMPTY_DIM_OBJ;
6712			break;
6713		case ZEND_AST_PROP:
6714			opline = zend_compile_prop_common(result, var_ast, BP_VAR_IS);
6715			opline->opcode = ZEND_ISSET_ISEMPTY_PROP_OBJ;
6716			break;
6717		case ZEND_AST_STATIC_PROP:
6718			opline = zend_compile_static_prop_common(result, var_ast, BP_VAR_IS, 0);
6719			opline->opcode = ZEND_ISSET_ISEMPTY_STATIC_PROP;
6720			break;
6721		EMPTY_SWITCH_DEFAULT_CASE()
6722	}
6723
6724	result->op_type = opline->result_type = IS_TMP_VAR;
6725	opline->extended_value |= ast->kind == ZEND_AST_ISSET ? ZEND_ISSET : ZEND_ISEMPTY;
6726}
6727/* }}} */
6728
6729void zend_compile_silence(znode *result, zend_ast *ast) /* {{{ */
6730{
6731	zend_ast *expr_ast = ast->child[0];
6732	znode silence_node;
6733	uint32_t range;
6734
6735	range = zend_start_live_range(CG(active_op_array), get_next_op_number(CG(active_op_array)));
6736	zend_emit_op_tmp(&silence_node, ZEND_BEGIN_SILENCE, NULL, NULL);
6737
6738	if (expr_ast->kind == ZEND_AST_VAR) {
6739		/* For @$var we need to force a FETCH instruction, otherwise the CV access will
6740		 * happen outside the silenced section. */
6741		zend_compile_simple_var_no_cv(result, expr_ast, BP_VAR_R, 0 );
6742	} else {
6743		zend_compile_expr(result, expr_ast);
6744	}
6745
6746	/* Store BEGIN_SILENCE/END_SILENCE pair to restore previous
6747	 * EG(error_reporting) value on exception */
6748	zend_end_live_range(CG(active_op_array), range, get_next_op_number(CG(active_op_array)),
6749		ZEND_LIVE_SILENCE, silence_node.u.op.var);
6750
6751	zend_emit_op(NULL, ZEND_END_SILENCE, &silence_node, NULL);
6752}
6753/* }}} */
6754
6755void zend_compile_shell_exec(znode *result, zend_ast *ast) /* {{{ */
6756{
6757	zend_ast *expr_ast = ast->child[0];
6758
6759	zval fn_name;
6760	zend_ast *name_ast, *args_ast, *call_ast;
6761
6762	ZVAL_STRING(&fn_name, "shell_exec");
6763	name_ast = zend_ast_create_zval(&fn_name);
6764	args_ast = zend_ast_create_list(1, ZEND_AST_ARG_LIST, expr_ast);
6765	call_ast = zend_ast_create(ZEND_AST_CALL, name_ast, args_ast);
6766
6767	zend_compile_expr(result, call_ast);
6768
6769	zval_ptr_dtor(&fn_name);
6770}
6771/* }}} */
6772
6773void zend_compile_array(znode *result, zend_ast *ast) /* {{{ */
6774{
6775	zend_ast_list *list = zend_ast_get_list(ast);
6776	zend_op *opline;
6777	uint32_t i, opnum_init = -1;
6778	zend_bool packed = 1;
6779
6780	if (zend_try_ct_eval_array(&result->u.constant, ast)) {
6781		result->op_type = IS_CONST;
6782		return;
6783	}
6784
6785	for (i = 0; i < list->children; ++i) {
6786		zend_ast *elem_ast = list->child[i];
6787		zend_ast *value_ast = elem_ast->child[0];
6788		zend_ast *key_ast = elem_ast->child[1];
6789		zend_bool by_ref = elem_ast->attr;
6790
6791		znode value_node, key_node, *key_node_ptr = NULL;
6792
6793		if (key_ast) {
6794			zend_compile_expr(&key_node, key_ast);
6795			zend_handle_numeric_op(&key_node);
6796			key_node_ptr = &key_node;
6797		}
6798
6799		if (by_ref) {
6800			zend_ensure_writable_variable(value_ast);
6801			zend_compile_var(&value_node, value_ast, BP_VAR_W);
6802		} else {
6803			zend_compile_expr(&value_node, value_ast);
6804		}
6805
6806		if (i == 0) {
6807			opnum_init = get_next_op_number(CG(active_op_array));
6808			opline = zend_emit_op_tmp(result, ZEND_INIT_ARRAY, &value_node, key_node_ptr);
6809			opline->extended_value = list->children << ZEND_ARRAY_SIZE_SHIFT;
6810		} else {
6811			opline = zend_emit_op(NULL, ZEND_ADD_ARRAY_ELEMENT,
6812				&value_node, key_node_ptr);
6813			SET_NODE(opline->result, result);
6814		}
6815		opline->extended_value |= by_ref;
6816
6817		if (key_ast && key_node.op_type == IS_CONST && Z_TYPE(key_node.u.constant) == IS_STRING) {
6818			packed = 0;
6819		}
6820	}
6821
6822	/* Handle empty array */
6823	if (!list->children) {
6824		zend_emit_op_tmp(result, ZEND_INIT_ARRAY, NULL, NULL);
6825	}
6826
6827	/* Add a flag to INIT_ARRAY if we know this array cannot be packed */
6828	if (!packed) {
6829		ZEND_ASSERT(opnum_init != -1);
6830		opline = &CG(active_op_array)->opcodes[opnum_init];
6831		opline->extended_value |= ZEND_ARRAY_NOT_PACKED;
6832	}
6833}
6834/* }}} */
6835
6836void zend_compile_const(znode *result, zend_ast *ast) /* {{{ */
6837{
6838	zend_ast *name_ast = ast->child[0];
6839
6840	zend_op *opline;
6841
6842	zend_bool is_fully_qualified;
6843	zend_string *orig_name = zend_ast_get_str(name_ast);
6844	zend_string *resolved_name = zend_resolve_const_name(orig_name, name_ast->attr, &is_fully_qualified);
6845
6846	if (zend_string_equals_literal(resolved_name, "__COMPILER_HALT_OFFSET__") || (name_ast->attr != ZEND_NAME_RELATIVE && zend_string_equals_literal(orig_name, "__COMPILER_HALT_OFFSET__"))) {
6847		zend_ast *last = CG(ast);
6848
6849		while (last->kind == ZEND_AST_STMT_LIST) {
6850			zend_ast_list *list = zend_ast_get_list(last);
6851			last = list->child[list->children-1];
6852		}
6853		if (last->kind == ZEND_AST_HALT_COMPILER) {
6854			result->op_type = IS_CONST;
6855			ZVAL_LONG(&result->u.constant, Z_LVAL_P(zend_ast_get_zval(last->child[0])));
6856			zend_string_release(resolved_name);
6857			return;
6858		}
6859	}
6860
6861	if (zend_try_ct_eval_const(&result->u.constant, resolved_name, is_fully_qualified)) {
6862		result->op_type = IS_CONST;
6863		zend_string_release(resolved_name);
6864		return;
6865	}
6866
6867	opline = zend_emit_op_tmp(result, ZEND_FETCH_CONSTANT, NULL, NULL);
6868	opline->op2_type = IS_CONST;
6869
6870	if (is_fully_qualified) {
6871		opline->op2.constant = zend_add_const_name_literal(
6872			CG(active_op_array), resolved_name, 0);
6873	} else {
6874		opline->extended_value = IS_CONSTANT_UNQUALIFIED;
6875		if (FC(current_namespace)) {
6876			opline->extended_value |= IS_CONSTANT_IN_NAMESPACE;
6877			opline->op2.constant = zend_add_const_name_literal(
6878				CG(active_op_array), resolved_name, 1);
6879		} else {
6880			opline->op2.constant = zend_add_const_name_literal(
6881				CG(active_op_array), resolved_name, 0);
6882		}
6883	}
6884	zend_alloc_cache_slot(opline->op2.constant);
6885}
6886/* }}} */
6887
6888void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */
6889{
6890	zend_ast *class_ast = ast->child[0];
6891	zend_ast *const_ast = ast->child[1];
6892
6893	znode class_node, const_node;
6894	zend_op *opline;
6895
6896	if (zend_try_compile_const_expr_resolve_class_name(&result->u.constant, class_ast, const_ast, 0)) {
6897		if (Z_TYPE(result->u.constant) == IS_NULL) {
6898			zend_op *opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL);
6899			opline->extended_value = zend_get_class_fetch_type(zend_ast_get_str(class_ast));
6900		} else {
6901			result->op_type = IS_CONST;
6902		}
6903		return;
6904	}
6905
6906	zend_eval_const_expr(&class_ast);
6907	zend_eval_const_expr(&const_ast);
6908
6909	if (class_ast->kind == ZEND_AST_ZVAL) {
6910		zend_string *resolved_name;
6911
6912		resolved_name = zend_resolve_class_name_ast(class_ast);
6913		if (const_ast->kind == ZEND_AST_ZVAL && zend_try_ct_eval_class_const(&result->u.constant, resolved_name, zend_ast_get_str(const_ast))) {
6914			result->op_type = IS_CONST;
6915			zend_string_release(resolved_name);
6916			return;
6917		}
6918		zend_string_release(resolved_name);
6919	}
6920	if (const_ast->kind == ZEND_AST_ZVAL && zend_string_equals_literal_ci(zend_ast_get_str(const_ast), "class")) {
6921		zend_error_noreturn(E_COMPILE_ERROR,
6922			"Dynamic class names are not allowed in compile-time ::class fetch");
6923	}
6924
6925	zend_compile_class_ref_ex(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
6926
6927	zend_compile_expr(&const_node, const_ast);
6928
6929	opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_CONSTANT, NULL, &const_node);
6930
6931	zend_set_class_name_op1(opline, &class_node);
6932
6933	if (opline->op1_type == IS_CONST) {
6934		zend_alloc_cache_slot(opline->op2.constant);
6935	} else {
6936		zend_alloc_polymorphic_cache_slot(opline->op2.constant);
6937	}
6938}
6939/* }}} */
6940
6941void zend_compile_resolve_class_name(znode *result, zend_ast *ast) /* {{{ */
6942{
6943	zend_ast *name_ast = ast->child[0];
6944	uint32_t fetch_type = zend_get_class_fetch_type(zend_ast_get_str(name_ast));
6945	zend_ensure_valid_class_fetch_type(fetch_type);
6946
6947	switch (fetch_type) {
6948		case ZEND_FETCH_CLASS_SELF:
6949			if (CG(active_class_entry) && zend_is_scope_known()) {
6950				result->op_type = IS_CONST;
6951				ZVAL_STR_COPY(&result->u.constant, CG(active_class_entry)->name);
6952			} else {
6953				zend_op *opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL);
6954				opline->extended_value = fetch_type;
6955			}
6956			break;
6957		case ZEND_FETCH_CLASS_STATIC:
6958		case ZEND_FETCH_CLASS_PARENT:
6959			{
6960				zend_op *opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL);
6961				opline->extended_value = fetch_type;
6962			}
6963			break;
6964		case ZEND_FETCH_CLASS_DEFAULT:
6965			result->op_type = IS_CONST;
6966			ZVAL_STR(&result->u.constant, zend_resolve_class_name_ast(name_ast));
6967			break;
6968		EMPTY_SWITCH_DEFAULT_CASE()
6969	}
6970}
6971/* }}} */
6972
6973static zend_op *zend_compile_rope_add(znode *result, uint32_t num, znode *elem_node) /* {{{ */
6974{
6975	zend_op *opline = get_next_op(CG(active_op_array));
6976
6977	if (num == 0) {
6978		result->op_type = IS_TMP_VAR;
6979		result->u.op.var = -1;
6980		opline->opcode = ZEND_ROPE_INIT;
6981		SET_UNUSED(opline->op1);
6982	} else {
6983		opline->opcode = ZEND_ROPE_ADD;
6984		SET_NODE(opline->op1, result);
6985	}
6986	SET_NODE(opline->op2, elem_node);
6987	SET_NODE(opline->result, result);
6988	opline->extended_value = num;
6989	return opline;
6990}
6991/* }}} */
6992
6993static void zend_compile_encaps_list(znode *result, zend_ast *ast) /* {{{ */
6994{
6995	uint32_t i, j;
6996	uint32_t rope_init_lineno = -1;
6997	zend_op *opline = NULL, *init_opline;
6998	znode elem_node, last_const_node;
6999	zend_ast_list *list = zend_ast_get_list(ast);
7000
7001	ZEND_ASSERT(list->children > 0);
7002
7003	j = 0;
7004	last_const_node.op_type = IS_UNUSED;
7005	for (i = 0; i < list->children; i++) {
7006		zend_compile_expr(&elem_node, list->child[i]);
7007
7008		if (elem_node.op_type == IS_CONST) {
7009			convert_to_string(&elem_node.u.constant);
7010
7011			if (Z_STRLEN(elem_node.u.constant) == 0) {
7012				zval_ptr_dtor(&elem_node.u.constant);
7013			} else if (last_const_node.op_type == IS_CONST) {
7014				concat_function(&last_const_node.u.constant, &last_const_node.u.constant, &elem_node.u.constant);
7015				zval_ptr_dtor(&elem_node.u.constant);
7016			} else {
7017				last_const_node.op_type = IS_CONST;
7018				ZVAL_COPY_VALUE(&last_const_node.u.constant, &elem_node.u.constant);
7019			}
7020			continue;
7021		} else {
7022			if (j == 0) {
7023				rope_init_lineno = get_next_op_number(CG(active_op_array));
7024			}
7025			if (last_const_node.op_type == IS_CONST) {
7026				zend_compile_rope_add(result, j++, &last_const_node);
7027				last_const_node.op_type = IS_UNUSED;
7028			}
7029			opline = zend_compile_rope_add(result, j++, &elem_node);
7030		}
7031	}
7032
7033	if (j == 0) {
7034		result->op_type = IS_CONST;
7035		if (last_const_node.op_type == IS_CONST) {
7036			ZVAL_COPY_VALUE(&result->u.constant, &last_const_node.u.constant);
7037		} else {
7038			ZVAL_EMPTY_STRING(&result->u.constant);
7039			/* empty string */
7040		}
7041		return;
7042	} else if (last_const_node.op_type == IS_CONST) {
7043		opline = zend_compile_rope_add(result, j++, &last_const_node);
7044	}
7045	init_opline = CG(active_op_array)->opcodes + rope_init_lineno;
7046	if (j == 1) {
7047		if (opline->op2_type == IS_CONST) {
7048			GET_NODE(result, opline->op2);
7049			MAKE_NOP(opline);
7050		} else {
7051			opline->opcode = ZEND_CAST;
7052			opline->extended_value = IS_STRING;
7053			opline->op1_type = opline->op2_type;
7054			opline->op1 = opline->op2;
7055			opline->result_type = IS_TMP_VAR;
7056			opline->result.var = get_temporary_variable(CG(active_op_array));
7057			SET_UNUSED(opline->op2);
7058			GET_NODE(result, opline->result);
7059		}
7060	} else if (j == 2) {
7061		opline->opcode = ZEND_FAST_CONCAT;
7062		opline->extended_value = 0;
7063		opline->op1_type = init_opline->op2_type;
7064		opline->op1 = init_opline->op2;
7065		opline->result_type = IS_TMP_VAR;
7066		opline->result.var = get_temporary_variable(CG(active_op_array));
7067		MAKE_NOP(init_opline);
7068		GET_NODE(result, opline->result);
7069	} else {
7070		uint32_t var;
7071		uint32_t range = zend_start_live_range(CG(active_op_array), rope_init_lineno);
7072
7073		init_opline->extended_value = j;
7074		opline->opcode = ZEND_ROPE_END;
7075		opline->result.var = get_temporary_variable(CG(active_op_array));
7076		var = opline->op1.var = get_temporary_variable(CG(active_op_array));
7077		GET_NODE(result, opline->result);
7078
7079		/* Allocates the necessary number of zval slots to keep the rope */
7080		i = ((j * sizeof(zend_string*)) + (sizeof(zval) - 1)) / sizeof(zval);
7081		while (i > 1) {
7082			get_temporary_variable(CG(active_op_array));
7083			i--;
7084		}
7085
7086		zend_end_live_range(CG(active_op_array), range, opline - CG(active_op_array)->opcodes,
7087			ZEND_LIVE_ROPE, var);
7088
7089		/* Update all the previous opcodes to use the same variable */
7090		while (opline != init_opline) {
7091			opline--;
7092			if (opline->opcode == ZEND_ROPE_ADD &&
7093			    opline->result.var == -1) {
7094				opline->op1.var = var;
7095				opline->result.var = var;
7096			} else if (opline->opcode == ZEND_ROPE_INIT &&
7097			           opline->result.var == -1) {
7098				opline->result.var = var;
7099			}
7100		}
7101	}
7102}
7103/* }}} */
7104
7105void zend_compile_magic_const(znode *result, zend_ast *ast) /* {{{ */
7106{
7107	zend_op *opline;
7108
7109	if (zend_try_ct_eval_magic_const(&result->u.constant, ast)) {
7110		result->op_type = IS_CONST;
7111		return;
7112	}
7113
7114	ZEND_ASSERT(ast->attr == T_CLASS_C &&
7115	            CG(active_class_entry) &&
7116	            (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) != 0);
7117
7118	opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL);
7119	opline->extended_value = ZEND_FETCH_CLASS_SELF;
7120}
7121/* }}} */
7122
7123zend_bool zend_is_allowed_in_const_expr(zend_ast_kind kind) /* {{{ */
7124{
7125	return kind == ZEND_AST_ZVAL || kind == ZEND_AST_BINARY_OP
7126		|| kind == ZEND_AST_GREATER || kind == ZEND_AST_GREATER_EQUAL
7127		|| kind == ZEND_AST_AND || kind == ZEND_AST_OR
7128		|| kind == ZEND_AST_UNARY_OP
7129		|| kind == ZEND_AST_UNARY_PLUS || kind == ZEND_AST_UNARY_MINUS
7130		|| kind == ZEND_AST_CONDITIONAL || kind == ZEND_AST_DIM
7131		|| kind == ZEND_AST_ARRAY || kind == ZEND_AST_ARRAY_ELEM
7132		|| kind == ZEND_AST_CONST || kind == ZEND_AST_CLASS_CONST
7133		|| kind == ZEND_AST_MAGIC_CONST;
7134}
7135/* }}} */
7136
7137void zend_compile_const_expr_class_const(zend_ast **ast_ptr) /* {{{ */
7138{
7139	zend_ast *ast = *ast_ptr;
7140	zend_ast *class_ast = ast->child[0];
7141	zend_ast *const_ast = ast->child[1];
7142	zend_string *class_name;
7143	zend_string *const_name = zend_ast_get_str(const_ast);
7144	zval result;
7145	int fetch_type;
7146
7147	if (class_ast->kind != ZEND_AST_ZVAL) {
7148		zend_error_noreturn(E_COMPILE_ERROR,
7149			"Dynamic class names are not allowed in compile-time class constant references");
7150	}
7151
7152	if (zend_try_compile_const_expr_resolve_class_name(&result, class_ast, const_ast, 1)) {
7153		*ast_ptr = zend_ast_create_zval(&result);
7154		return;
7155	}
7156
7157	class_name = zend_ast_get_str(class_ast);
7158	fetch_type = zend_get_class_fetch_type(class_name);
7159
7160	if (ZEND_FETCH_CLASS_STATIC == fetch_type) {
7161		zend_error_noreturn(E_COMPILE_ERROR,
7162			"\"static::\" is not allowed in compile-time constants");
7163	}
7164
7165	if (ZEND_FETCH_CLASS_DEFAULT == fetch_type) {
7166		class_name = zend_resolve_class_name_ast(class_ast);
7167	} else {
7168		zend_string_addref(class_name);
7169	}
7170
7171	Z_STR(result) = zend_concat3(
7172		ZSTR_VAL(class_name), ZSTR_LEN(class_name), "::", 2, ZSTR_VAL(const_name), ZSTR_LEN(const_name));
7173
7174	Z_TYPE_INFO(result) = IS_CONSTANT_EX;
7175	Z_CONST_FLAGS(result) = fetch_type;
7176
7177	zend_ast_destroy(ast);
7178	zend_string_release(class_name);
7179
7180	*ast_ptr = zend_ast_create_zval(&result);
7181}
7182/* }}} */
7183
7184void zend_compile_const_expr_const(zend_ast **ast_ptr) /* {{{ */
7185{
7186	zend_ast *ast = *ast_ptr;
7187	zend_ast *name_ast = ast->child[0];
7188	zend_string *orig_name = zend_ast_get_str(name_ast);
7189	zend_bool is_fully_qualified;
7190
7191	zval result, resolved_name;
7192	ZVAL_STR(&resolved_name, zend_resolve_const_name(
7193		orig_name, name_ast->attr, &is_fully_qualified));
7194
7195	if (zend_try_ct_eval_const(&result, Z_STR(resolved_name), is_fully_qualified)) {
7196		zend_string_release(Z_STR(resolved_name));
7197		zend_ast_destroy(ast);
7198		*ast_ptr = zend_ast_create_zval(&result);
7199		return;
7200	}
7201
7202	Z_TYPE_INFO(resolved_name) = IS_CONSTANT_EX;
7203	if (!is_fully_qualified) {
7204		Z_CONST_FLAGS(resolved_name) = IS_CONSTANT_UNQUALIFIED;
7205	}
7206
7207	zend_ast_destroy(ast);
7208	*ast_ptr = zend_ast_create_zval(&resolved_name);
7209}
7210/* }}} */
7211
7212void zend_compile_const_expr_magic_const(zend_ast **ast_ptr) /* {{{ */
7213{
7214	zend_ast *ast = *ast_ptr;
7215
7216	/* Other cases already resolved by constant folding */
7217	ZEND_ASSERT(ast->attr == T_CLASS_C &&
7218	            CG(active_class_entry) &&
7219	            (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) != 0);
7220
7221	{
7222		zval const_zv;
7223		Z_STR(const_zv) = zend_string_init("__CLASS__", sizeof("__CLASS__")-1, 0);
7224		Z_TYPE_INFO(const_zv) = IS_CONSTANT_EX | (IS_CONSTANT_CLASS << Z_CONST_FLAGS_SHIFT);
7225
7226		zend_ast_destroy(ast);
7227		*ast_ptr = zend_ast_create_zval(&const_zv);
7228	}
7229}
7230/* }}} */
7231
7232void zend_compile_const_expr(zend_ast **ast_ptr) /* {{{ */
7233{
7234	zend_ast *ast = *ast_ptr;
7235	if (ast == NULL || ast->kind == ZEND_AST_ZVAL) {
7236		return;
7237	}
7238
7239	if (!zend_is_allowed_in_const_expr(ast->kind)) {
7240		zend_error_noreturn(E_COMPILE_ERROR, "Constant expression contains invalid operations");
7241	}
7242
7243	switch (ast->kind) {
7244		case ZEND_AST_CLASS_CONST:
7245			zend_compile_const_expr_class_const(ast_ptr);
7246			break;
7247		case ZEND_AST_CONST:
7248			zend_compile_const_expr_const(ast_ptr);
7249			break;
7250		case ZEND_AST_MAGIC_CONST:
7251			zend_compile_const_expr_magic_const(ast_ptr);
7252			break;
7253		default:
7254			zend_ast_apply(ast, zend_compile_const_expr);
7255			break;
7256	}
7257}
7258/* }}} */
7259
7260void zend_const_expr_to_zval(zval *result, zend_ast *ast) /* {{{ */
7261{
7262	zend_ast *orig_ast = ast;
7263	zend_eval_const_expr(&ast);
7264	zend_compile_const_expr(&ast);
7265	if (ast->kind == ZEND_AST_ZVAL) {
7266		ZVAL_COPY_VALUE(result, zend_ast_get_zval(ast));
7267
7268		/* Kill this branch of the original AST, as it was already destroyed.
7269		 * It would be nice to find a better solution to this problem in the
7270		 * future. */
7271		orig_ast->kind = 0;
7272	} else {
7273		ZVAL_NEW_AST(result, zend_ast_copy(ast));
7274	}
7275}
7276/* }}} */