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 = IS_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						zend_emit_op(NULL, ZEND_FREE, op1, NULL);
760					}
761					break;
762				}
763				opline--;
764			}
765		}
766	} else if (op1->op_type == IS_CONST) {
767		/* Destroy value without using GC: When opcache moves arrays into SHM it will
768		 * free the zend_array structure, so references to it from outside the op array
769		 * become invalid. GC would cause such a reference in the root buffer. */
770		zval_ptr_dtor_nogc(&op1->u.constant);
771	}
772}
773/* }}} */
774
775uint32_t zend_add_class_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */
776{
777	uint32_t new_flags = flags | new_flag;
778	if ((flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) && (new_flag & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
779		zend_error_noreturn(E_COMPILE_ERROR, "Multiple abstract modifiers are not allowed");
780	}
781	if ((flags & ZEND_ACC_FINAL) && (new_flag & ZEND_ACC_FINAL)) {
782		zend_error_noreturn(E_COMPILE_ERROR, "Multiple final modifiers are not allowed");
783	}
784	if ((new_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) && (new_flags & ZEND_ACC_FINAL)) {
785		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use the final modifier on an abstract class");
786	}
787	return new_flags;
788}
789/* }}} */
790
791uint32_t zend_add_member_modifier(uint32_t flags, uint32_t new_flag) /* {{{ */
792{
793	uint32_t new_flags = flags | new_flag;
794	if ((flags & ZEND_ACC_PPP_MASK) && (new_flag & ZEND_ACC_PPP_MASK)) {
795		zend_error_noreturn(E_COMPILE_ERROR, "Multiple access type modifiers are not allowed");
796	}
797	if ((flags & ZEND_ACC_ABSTRACT) && (new_flag & ZEND_ACC_ABSTRACT)) {
798		zend_error_noreturn(E_COMPILE_ERROR, "Multiple abstract modifiers are not allowed");
799	}
800	if ((flags & ZEND_ACC_STATIC) && (new_flag & ZEND_ACC_STATIC)) {
801		zend_error_noreturn(E_COMPILE_ERROR, "Multiple static modifiers are not allowed");
802	}
803	if ((flags & ZEND_ACC_FINAL) && (new_flag & ZEND_ACC_FINAL)) {
804		zend_error_noreturn(E_COMPILE_ERROR, "Multiple final modifiers are not allowed");
805	}
806	if ((new_flags & ZEND_ACC_ABSTRACT) && (new_flags & ZEND_ACC_FINAL)) {
807		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use the final modifier on an abstract class member");
808	}
809	return new_flags;
810}
811/* }}} */
812
813zend_string *zend_concat3(char *str1, size_t str1_len, char *str2, size_t str2_len, char *str3, size_t str3_len) /* {{{ */
814{
815	size_t len = str1_len + str2_len + str3_len;
816	zend_string *res = zend_string_alloc(len, 0);
817
818	memcpy(ZSTR_VAL(res), str1, str1_len);
819	memcpy(ZSTR_VAL(res) + str1_len, str2, str2_len);
820	memcpy(ZSTR_VAL(res) + str1_len + str2_len, str3, str3_len);
821	ZSTR_VAL(res)[len] = '\0';
822
823	return res;
824}
825
826zend_string *zend_concat_names(char *name1, size_t name1_len, char *name2, size_t name2_len) {
827	return zend_concat3(name1, name1_len, "\\", 1, name2, name2_len);
828}
829
830zend_string *zend_prefix_with_ns(zend_string *name) {
831	if (FC(current_namespace)) {
832		zend_string *ns = FC(current_namespace);
833		return zend_concat_names(ZSTR_VAL(ns), ZSTR_LEN(ns), ZSTR_VAL(name), ZSTR_LEN(name));
834	} else {
835		return zend_string_copy(name);
836	}
837}
838
839void *zend_hash_find_ptr_lc(HashTable *ht, const char *str, size_t len) {
840	void *result;
841	zend_string *lcname;
842	ALLOCA_FLAG(use_heap);
843
844	ZSTR_ALLOCA_ALLOC(lcname, len, use_heap);
845	zend_str_tolower_copy(ZSTR_VAL(lcname), str, len);
846	result = zend_hash_find_ptr(ht, lcname);
847	ZSTR_ALLOCA_FREE(lcname, use_heap);
848
849	return result;
850}
851
852zend_string *zend_resolve_non_class_name(
853	zend_string *name, uint32_t type, zend_bool *is_fully_qualified,
854	zend_bool case_sensitive, HashTable *current_import_sub
855) {
856	char *compound;
857	*is_fully_qualified = 0;
858
859	if (ZSTR_VAL(name)[0] == '\\') {
860		/* Remove \ prefix (only relevant if this is a string rather than a label) */
861		return zend_string_init(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1, 0);
862	}
863
864	if (type == ZEND_NAME_FQ) {
865		*is_fully_qualified = 1;
866		return zend_string_copy(name);
867	}
868
869	if (type == ZEND_NAME_RELATIVE) {
870		*is_fully_qualified = 1;
871		return zend_prefix_with_ns(name);
872	}
873
874	if (current_import_sub) {
875		/* If an unqualified name is a function/const alias, replace it. */
876		zend_string *import_name;
877		if (case_sensitive) {
878			import_name = zend_hash_find_ptr(current_import_sub, name);
879		} else {
880			import_name = zend_hash_find_ptr_lc(current_import_sub, ZSTR_VAL(name), ZSTR_LEN(name));
881		}
882
883		if (import_name) {
884			*is_fully_qualified = 1;
885			return zend_string_copy(import_name);
886		}
887	}
888
889	compound = memchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
890	if (compound) {
891		*is_fully_qualified = 1;
892	}
893
894	if (compound && FC(imports)) {
895		/* If the first part of a qualified name is an alias, substitute it. */
896		size_t len = compound - ZSTR_VAL(name);
897		zend_string *import_name = zend_hash_find_ptr_lc(FC(imports), ZSTR_VAL(name), len);
898
899		if (import_name) {
900			return zend_concat_names(
901				ZSTR_VAL(import_name), ZSTR_LEN(import_name), ZSTR_VAL(name) + len + 1, ZSTR_LEN(name) - len - 1);
902		}
903	}
904
905	return zend_prefix_with_ns(name);
906}
907/* }}} */
908
909zend_string *zend_resolve_function_name(zend_string *name, uint32_t type, zend_bool *is_fully_qualified) /* {{{ */
910{
911	return zend_resolve_non_class_name(
912		name, type, is_fully_qualified, 0, FC(imports_function));
913}
914/* }}} */
915
916zend_string *zend_resolve_const_name(zend_string *name, uint32_t type, zend_bool *is_fully_qualified) /* {{{ */ {
917	return zend_resolve_non_class_name(
918		name, type, is_fully_qualified, 1, FC(imports_const));
919}
920/* }}} */
921
922zend_string *zend_resolve_class_name(zend_string *name, uint32_t type) /* {{{ */
923{
924	char *compound;
925
926	if (type == ZEND_NAME_RELATIVE) {
927		return zend_prefix_with_ns(name);
928	}
929
930	if (type == ZEND_NAME_FQ || ZSTR_VAL(name)[0] == '\\') {
931		/* Remove \ prefix (only relevant if this is a string rather than a label) */
932		if (ZSTR_VAL(name)[0] == '\\') {
933			name = zend_string_init(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 1, 0);
934		} else {
935			zend_string_addref(name);
936		}
937		/* Ensure that \self, \parent and \static are not used */
938		if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
939			zend_error_noreturn(E_COMPILE_ERROR, "'\\%s' is an invalid class name", ZSTR_VAL(name));
940		}
941		return name;
942	}
943
944	if (FC(imports)) {
945		compound = memchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name));
946		if (compound) {
947			/* If the first part of a qualified name is an alias, substitute it. */
948			size_t len = compound - ZSTR_VAL(name);
949			zend_string *import_name =
950				zend_hash_find_ptr_lc(FC(imports), ZSTR_VAL(name), len);
951
952			if (import_name) {
953				return zend_concat_names(
954					ZSTR_VAL(import_name), ZSTR_LEN(import_name), ZSTR_VAL(name) + len + 1, ZSTR_LEN(name) - len - 1);
955			}
956		} else {
957			/* If an unqualified name is an alias, replace it. */
958			zend_string *import_name
959				= zend_hash_find_ptr_lc(FC(imports), ZSTR_VAL(name), ZSTR_LEN(name));
960
961			if (import_name) {
962				return zend_string_copy(import_name);
963			}
964		}
965	}
966
967	/* If not fully qualified and not an alias, prepend the current namespace */
968	return zend_prefix_with_ns(name);
969}
970/* }}} */
971
972zend_string *zend_resolve_class_name_ast(zend_ast *ast) /* {{{ */
973{
974	zval *class_name = zend_ast_get_zval(ast);
975	if (Z_TYPE_P(class_name) != IS_STRING) {
976		zend_error_noreturn(E_COMPILE_ERROR, "Illegal class name");
977	}
978	return zend_resolve_class_name(Z_STR_P(class_name), ast->attr);
979}
980/* }}} */
981
982static void label_ptr_dtor(zval *zv) /* {{{ */
983{
984	efree_size(Z_PTR_P(zv), sizeof(zend_label));
985}
986/* }}} */
987
988static void str_dtor(zval *zv)  /* {{{ */ {
989	zend_string_release(Z_STR_P(zv));
990}
991/* }}} */
992
993static zend_bool zend_is_call(zend_ast *ast);
994
995static uint32_t zend_add_try_element(uint32_t try_op) /* {{{ */
996{
997	zend_op_array *op_array = CG(active_op_array);
998	uint32_t try_catch_offset = op_array->last_try_catch++;
999	zend_try_catch_element *elem;
1000
1001	op_array->try_catch_array = safe_erealloc(
1002		op_array->try_catch_array, sizeof(zend_try_catch_element), op_array->last_try_catch, 0);
1003
1004	elem = &op_array->try_catch_array[try_catch_offset];
1005	elem->try_op = try_op;
1006	elem->catch_op = 0;
1007	elem->finally_op = 0;
1008	elem->finally_end = 0;
1009
1010	return try_catch_offset;
1011}
1012/* }}} */
1013
1014ZEND_API void function_add_ref(zend_function *function) /* {{{ */
1015{
1016	if (function->type == ZEND_USER_FUNCTION) {
1017		zend_op_array *op_array = &function->op_array;
1018
1019		if (op_array->refcount) {
1020			(*op_array->refcount)++;
1021		}
1022		if (op_array->static_variables) {
1023			if (!(GC_FLAGS(op_array->static_variables) & IS_ARRAY_IMMUTABLE)) {
1024				GC_REFCOUNT(op_array->static_variables)++;
1025			}
1026		}
1027		op_array->run_time_cache = NULL;
1028	} else if (function->type == ZEND_INTERNAL_FUNCTION) {
1029		if (function->common.function_name) {
1030			zend_string_addref(function->common.function_name);
1031		}
1032	}
1033}
1034/* }}} */
1035
1036ZEND_API int do_bind_function(const zend_op_array *op_array, const zend_op *opline, HashTable *function_table, zend_bool compile_time) /* {{{ */
1037{
1038	zend_function *function, *new_function;
1039	zval *lcname, *rtd_key;
1040
1041	if (compile_time) {
1042		lcname = CT_CONSTANT_EX(op_array, opline->op1.constant);
1043		rtd_key = lcname + 1;
1044	} else {
1045		lcname = RT_CONSTANT(op_array, opline->op1);
1046		rtd_key = lcname + 1;
1047	}
1048
1049	function = zend_hash_find_ptr(function_table, Z_STR_P(rtd_key));
1050	new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
1051	memcpy(new_function, function, sizeof(zend_op_array));
1052	if (zend_hash_add_ptr(function_table, Z_STR_P(lcname), new_function) == NULL) {
1053		int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR;
1054		zend_function *old_function;
1055
1056		if ((old_function = zend_hash_find_ptr(function_table, Z_STR_P(lcname))) != NULL
1057			&& old_function->type == ZEND_USER_FUNCTION
1058			&& old_function->op_array.last > 0) {
1059			zend_error_noreturn(error_level, "Cannot redeclare %s() (previously declared in %s:%d)",
1060						ZSTR_VAL(function->common.function_name),
1061						ZSTR_VAL(old_function->op_array.filename),
1062						old_function->op_array.opcodes[0].lineno);
1063		} else {
1064			zend_error_noreturn(error_level, "Cannot redeclare %s()", ZSTR_VAL(function->common.function_name));
1065		}
1066		return FAILURE;
1067	} else {
1068		if (function->op_array.refcount) {
1069			(*function->op_array.refcount)++;
1070		}
1071		function->op_array.static_variables = NULL; /* NULL out the unbound function */
1072		return SUCCESS;
1073	}
1074}
1075/* }}} */
1076
1077ZEND_API zend_class_entry *do_bind_class(const zend_op_array* op_array, const zend_op *opline, HashTable *class_table, zend_bool compile_time) /* {{{ */
1078{
1079	zend_class_entry *ce;
1080	zval *lcname, *rtd_key;
1081
1082	if (compile_time) {
1083		lcname = CT_CONSTANT_EX(op_array, opline->op1.constant);
1084		rtd_key = lcname + 1;
1085	} else {
1086		lcname = RT_CONSTANT(op_array, opline->op1);
1087		rtd_key = lcname + 1;
1088	}
1089	if ((ce = zend_hash_find_ptr(class_table, Z_STR_P(rtd_key))) == NULL) {
1090		zend_error_noreturn(E_COMPILE_ERROR, "Internal Zend error - Missing class information for %s", Z_STRVAL_P(rtd_key));
1091		return NULL;
1092	}
1093	ce->refcount++;
1094	if (zend_hash_add_ptr(class_table, Z_STR_P(lcname), ce) == NULL) {
1095		ce->refcount--;
1096		if (!compile_time) {
1097			/* If we're in compile time, in practice, it's quite possible
1098			 * that we'll never reach this class declaration at runtime,
1099			 * so we shut up about it.  This allows the if (!defined('FOO')) { return; }
1100			 * approach to work.
1101			 */
1102			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));
1103		}
1104		return NULL;
1105	} else {
1106		if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLEMENT_INTERFACES|ZEND_ACC_IMPLEMENT_TRAITS))) {
1107			zend_verify_abstract_class(ce);
1108		}
1109		return ce;
1110	}
1111}
1112/* }}} */
1113
1114ZEND_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) /* {{{ */
1115{
1116	zend_class_entry *ce;
1117	zval *lcname, *rtd_key;
1118
1119	if (compile_time) {
1120		lcname = CT_CONSTANT_EX(op_array, opline->op1.constant);
1121		rtd_key = lcname + 1;
1122	} else {
1123		lcname = RT_CONSTANT(op_array, opline->op1);
1124		rtd_key = lcname + 1;
1125	}
1126
1127	ce = zend_hash_find_ptr(class_table, Z_STR_P(rtd_key));
1128
1129	if (!ce) {
1130		if (!compile_time) {
1131			/* If we're in compile time, in practice, it's quite possible
1132			 * that we'll never reach this class declaration at runtime,
1133			 * so we shut up about it.  This allows the if (!defined('FOO')) { return; }
1134			 * approach to work.
1135			 */
1136			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));
1137		}
1138		return NULL;
1139	}
1140
1141	if (zend_hash_exists(class_table, Z_STR_P(lcname))) {
1142		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));
1143	}
1144
1145	zend_do_inheritance(ce, parent_ce);
1146
1147	ce->refcount++;
1148
1149	/* Register the derived class */
1150	if (zend_hash_add_ptr(class_table, Z_STR_P(lcname), ce) == NULL) {
1151		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));
1152	}
1153	return ce;
1154}
1155/* }}} */
1156
1157void zend_do_early_binding(void) /* {{{ */
1158{
1159	zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
1160	HashTable *table;
1161
1162	while (opline->opcode == ZEND_TICKS && opline > CG(active_op_array)->opcodes) {
1163		opline--;
1164	}
1165
1166	switch (opline->opcode) {
1167		case ZEND_DECLARE_FUNCTION:
1168			if (do_bind_function(CG(active_op_array), opline, CG(function_table), 1) == FAILURE) {
1169				return;
1170			}
1171			table = CG(function_table);
1172			break;
1173		case ZEND_DECLARE_CLASS:
1174			if (do_bind_class(CG(active_op_array), opline, CG(class_table), 1) == NULL) {
1175				return;
1176			}
1177			table = CG(class_table);
1178			break;
1179		case ZEND_DECLARE_INHERITED_CLASS:
1180			{
1181				zend_op *fetch_class_opline = opline-1;
1182				zval *parent_name;
1183				zend_class_entry *ce;
1184
1185				parent_name = CT_CONSTANT(fetch_class_opline->op2);
1186				if (((ce = zend_lookup_class_ex(Z_STR_P(parent_name), parent_name + 1, 0)) == NULL) ||
1187				    ((CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_CLASSES) &&
1188				     (ce->type == ZEND_INTERNAL_CLASS))) {
1189					if (CG(compiler_options) & ZEND_COMPILE_DELAYED_BINDING) {
1190						uint32_t *opline_num = &CG(active_op_array)->early_binding;
1191
1192						while (*opline_num != (uint32_t)-1) {
1193							opline_num = &CG(active_op_array)->opcodes[*opline_num].result.opline_num;
1194						}
1195						*opline_num = opline - CG(active_op_array)->opcodes;
1196						opline->opcode = ZEND_DECLARE_INHERITED_CLASS_DELAYED;
1197						opline->result_type = IS_UNUSED;
1198						opline->result.opline_num = -1;
1199					}
1200					return;
1201				}
1202				if (do_bind_inherited_class(CG(active_op_array), opline, CG(class_table), ce, 1) == NULL) {
1203					return;
1204				}
1205				/* clear unnecessary ZEND_FETCH_CLASS opcode */
1206				zend_del_literal(CG(active_op_array), fetch_class_opline->op2.constant);
1207				MAKE_NOP(fetch_class_opline);
1208
1209				table = CG(class_table);
1210				break;
1211			}
1212		case ZEND_VERIFY_ABSTRACT_CLASS:
1213		case ZEND_ADD_INTERFACE:
1214		case ZEND_ADD_TRAIT:
1215		case ZEND_BIND_TRAITS:
1216			/* We currently don't early-bind classes that implement interfaces */
1217			/* Classes with traits are handled exactly the same, no early-bind here */
1218			return;
1219		default:
1220			zend_error_noreturn(E_COMPILE_ERROR, "Invalid binding type");
1221			return;
1222	}
1223
1224	zend_hash_del(table, Z_STR_P(CT_CONSTANT(opline->op1)+1));
1225	zend_del_literal(CG(active_op_array), opline->op1.constant+1);
1226	zend_del_literal(CG(active_op_array), opline->op1.constant);
1227	MAKE_NOP(opline);
1228}
1229/* }}} */
1230
1231static void zend_mark_function_as_generator() /* {{{ */
1232{
1233	if (!CG(active_op_array)->function_name) {
1234		zend_error_noreturn(E_COMPILE_ERROR,
1235			"The \"yield\" expression can only be used inside a function");
1236	}
1237
1238	if (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
1239		const char *msg = "Generators may only declare a return type of Generator, Iterator or Traversable, %s is not permitted";
1240		zend_arg_info return_info = CG(active_op_array)->arg_info[-1];
1241
1242		if (!return_info.class_name) {
1243			zend_error_noreturn(E_COMPILE_ERROR, msg, zend_get_type_by_const(return_info.type_hint));
1244		}
1245
1246		if (!zend_string_equals_literal_ci(return_info.class_name, "Traversable")
1247			&& !zend_string_equals_literal_ci(return_info.class_name, "Iterator")
1248			&& !zend_string_equals_literal_ci(return_info.class_name, "Generator")) {
1249			zend_error_noreturn(E_COMPILE_ERROR, msg, ZSTR_VAL(return_info.class_name));
1250		}
1251	}
1252
1253	CG(active_op_array)->fn_flags |= ZEND_ACC_GENERATOR;
1254}
1255/* }}} */
1256
1257ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array) /* {{{ */
1258{
1259	if (op_array->early_binding != (uint32_t)-1) {
1260		zend_bool orig_in_compilation = CG(in_compilation);
1261		uint32_t opline_num = op_array->early_binding;
1262		zend_class_entry *ce;
1263
1264		CG(in_compilation) = 1;
1265		while (opline_num != (uint32_t)-1) {
1266			zval *parent_name = RT_CONSTANT(op_array, op_array->opcodes[opline_num-1].op2);
1267			if ((ce = zend_lookup_class_ex(Z_STR_P(parent_name), parent_name + 1, 0)) != NULL) {
1268				do_bind_inherited_class(op_array, &op_array->opcodes[opline_num], EG(class_table), ce, 0);
1269			}
1270			opline_num = op_array->opcodes[opline_num].result.opline_num;
1271		}
1272		CG(in_compilation) = orig_in_compilation;
1273	}
1274}
1275/* }}} */
1276
1277ZEND_API zend_string *zend_mangle_property_name(const char *src1, size_t src1_length, const char *src2, size_t src2_length, int internal) /* {{{ */
1278{
1279	size_t prop_name_length = 1 + src1_length + 1 + src2_length;
1280	zend_string *prop_name = zend_string_alloc(prop_name_length, internal);
1281
1282	ZSTR_VAL(prop_name)[0] = '\0';
1283	memcpy(ZSTR_VAL(prop_name) + 1, src1, src1_length+1);
1284	memcpy(ZSTR_VAL(prop_name) + 1 + src1_length + 1, src2, src2_length+1);
1285	return prop_name;
1286}
1287/* }}} */
1288
1289static zend_always_inline size_t zend_strnlen(const char* s, size_t maxlen) /* {{{ */
1290{
1291	size_t len = 0;
1292	while (*s++ && maxlen--) len++;
1293	return len;
1294}
1295/* }}} */
1296
1297ZEND_API int zend_unmangle_property_name_ex(const zend_string *name, const char **class_name, const char **prop_name, size_t *prop_len) /* {{{ */
1298{
1299	size_t class_name_len;
1300	size_t anonclass_src_len;
1301
1302	*class_name = NULL;
1303
1304	if (ZSTR_VAL(name)[0] != '\0') {
1305		*prop_name = ZSTR_VAL(name);
1306		if (prop_len) {
1307			*prop_len = ZSTR_LEN(name);
1308		}
1309		return SUCCESS;
1310	}
1311	if (ZSTR_LEN(name) < 3 || ZSTR_VAL(name)[1] == '\0') {
1312		zend_error(E_NOTICE, "Illegal member variable name");
1313		*prop_name = ZSTR_VAL(name);
1314		if (prop_len) {
1315			*prop_len = ZSTR_LEN(name);
1316		}
1317		return FAILURE;
1318	}
1319
1320	class_name_len = zend_strnlen(ZSTR_VAL(name) + 1, ZSTR_LEN(name) - 2);
1321	if (class_name_len >= ZSTR_LEN(name) - 2 || ZSTR_VAL(name)[class_name_len + 1] != '\0') {
1322		zend_error(E_NOTICE, "Corrupt member variable name");
1323		*prop_name = ZSTR_VAL(name);
1324		if (prop_len) {
1325			*prop_len = ZSTR_LEN(name);
1326		}
1327		return FAILURE;
1328	}
1329
1330	*class_name = ZSTR_VAL(name) + 1;
1331	anonclass_src_len = zend_strnlen(*class_name + class_name_len + 1, ZSTR_LEN(name) - class_name_len - 2);
1332	if (class_name_len + anonclass_src_len + 2 != ZSTR_LEN(name)) {
1333		class_name_len += anonclass_src_len + 1;
1334	}
1335	*prop_name = ZSTR_VAL(name) + class_name_len + 2;
1336	if (prop_len) {
1337		*prop_len = ZSTR_LEN(name) - class_name_len - 2;
1338	}
1339	return SUCCESS;
1340}
1341/* }}} */
1342
1343static zend_constant *zend_lookup_reserved_const(const char *name, size_t len) /* {{{ */
1344{
1345	zend_constant *c = zend_hash_find_ptr_lc(EG(zend_constants), name, len);
1346	if (c && !(c->flags & CONST_CS) && (c->flags & CONST_CT_SUBST)) {
1347		return c;
1348	}
1349	return NULL;
1350}
1351/* }}} */
1352
1353static zend_bool zend_try_ct_eval_const(zval *zv, zend_string *name, zend_bool is_fully_qualified) /* {{{ */
1354{
1355	zend_constant *c;
1356
1357	/* Substitute case-sensitive (or lowercase) constants */
1358	c = zend_hash_find_ptr(EG(zend_constants), name);
1359	if (c && (
1360	      ((c->flags & CONST_PERSISTENT) && !(CG(compiler_options) & ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION))
1361	   || (Z_TYPE(c->value) < IS_OBJECT && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION))
1362	)) {
1363		ZVAL_DUP(zv, &c->value);
1364		return 1;
1365	}
1366
1367	{
1368		/* Substitute true, false and null (including unqualified usage in namespaces) */
1369		const char *lookup_name = ZSTR_VAL(name);
1370		size_t lookup_len = ZSTR_LEN(name);
1371
1372		if (!is_fully_qualified) {
1373			zend_get_unqualified_name(name, &lookup_name, &lookup_len);
1374		}
1375
1376		c = zend_lookup_reserved_const(lookup_name, lookup_len);
1377		if (c) {
1378			ZVAL_DUP(zv, &c->value);
1379			return 1;
1380		}
1381	}
1382
1383	return 0;
1384}
1385/* }}} */
1386
1387static inline zend_bool zend_is_scope_known() /* {{{ */
1388{
1389	if (CG(active_op_array)->fn_flags & ZEND_ACC_CLOSURE) {
1390		/* Closures can be rebound to a different scope */
1391		return 0;
1392	}
1393
1394	if (!CG(active_class_entry)) {
1395		/* The scope is known if we're in a free function (no scope), but not if we're in
1396		 * a file/eval (which inherits including/eval'ing scope). */
1397		return CG(active_op_array)->function_name != NULL;
1398	}
1399
1400	/* For traits self etc refers to the using class, not the trait itself */
1401	return (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) == 0;
1402}
1403/* }}} */
1404
1405static inline zend_bool class_name_refers_to_active_ce(zend_string *class_name, uint32_t fetch_type) /* {{{ */
1406{
1407	if (!CG(active_class_entry)) {
1408		return 0;
1409	}
1410	if (fetch_type == ZEND_FETCH_CLASS_SELF && zend_is_scope_known()) {
1411		return 1;
1412	}
1413	return fetch_type == ZEND_FETCH_CLASS_DEFAULT
1414		&& zend_string_equals_ci(class_name, CG(active_class_entry)->name);
1415}
1416/* }}} */
1417
1418uint32_t zend_get_class_fetch_type(zend_string *name) /* {{{ */
1419{
1420	if (zend_string_equals_literal_ci(name, "self")) {
1421		return ZEND_FETCH_CLASS_SELF;
1422	} else if (zend_string_equals_literal_ci(name, "parent")) {
1423		return ZEND_FETCH_CLASS_PARENT;
1424	} else if (zend_string_equals_literal_ci(name, "static")) {
1425		return ZEND_FETCH_CLASS_STATIC;
1426	} else {
1427		return ZEND_FETCH_CLASS_DEFAULT;
1428	}
1429}
1430/* }}} */
1431
1432static uint32_t zend_get_class_fetch_type_ast(zend_ast *name_ast) /* {{{ */
1433{
1434	/* Fully qualified names are always default refs */
1435	if (name_ast->attr == ZEND_NAME_FQ) {
1436		return ZEND_FETCH_CLASS_DEFAULT;
1437	}
1438
1439	return zend_get_class_fetch_type(zend_ast_get_str(name_ast));
1440}
1441/* }}} */
1442
1443static void zend_ensure_valid_class_fetch_type(uint32_t fetch_type) /* {{{ */
1444{
1445	if (fetch_type != ZEND_FETCH_CLASS_DEFAULT && !CG(active_class_entry) && zend_is_scope_known()) {
1446		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"%s\" when no class scope is active",
1447			fetch_type == ZEND_FETCH_CLASS_SELF ? "self" :
1448			fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static");
1449	}
1450}
1451/* }}} */
1452
1453static zend_bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_ast *class_ast, zend_ast *name_ast, zend_bool constant) /* {{{ */
1454{
1455	uint32_t fetch_type;
1456
1457	if (name_ast->kind != ZEND_AST_ZVAL) {
1458		return 0;
1459	}
1460
1461	if (!zend_string_equals_literal_ci(zend_ast_get_str(name_ast), "class")) {
1462		return 0;
1463	}
1464
1465	if (class_ast->kind != ZEND_AST_ZVAL) {
1466		zend_error_noreturn(E_COMPILE_ERROR,
1467			"Dynamic class names are not allowed in compile-time ::class fetch");
1468	}
1469
1470	fetch_type = zend_get_class_fetch_type(zend_ast_get_str(class_ast));
1471	zend_ensure_valid_class_fetch_type(fetch_type);
1472
1473	switch (fetch_type) {
1474		case ZEND_FETCH_CLASS_SELF:
1475			if (constant || (CG(active_class_entry) && zend_is_scope_known())) {
1476				ZVAL_STR_COPY(zv, CG(active_class_entry)->name);
1477			} else {
1478				ZVAL_NULL(zv);
1479			}
1480			return 1;
1481		case ZEND_FETCH_CLASS_STATIC:
1482		case ZEND_FETCH_CLASS_PARENT:
1483			if (constant) {
1484				zend_error_noreturn(E_COMPILE_ERROR,
1485					"%s::class cannot be used for compile-time class name resolution",
1486					fetch_type == ZEND_FETCH_CLASS_STATIC ? "static" : "parent"
1487				);
1488			} else {
1489				ZVAL_NULL(zv);
1490			}
1491			return 1;
1492		case ZEND_FETCH_CLASS_DEFAULT:
1493			ZVAL_STR(zv, zend_resolve_class_name_ast(class_ast));
1494			return 1;
1495		EMPTY_SWITCH_DEFAULT_CASE()
1496	}
1497}
1498/* }}} */
1499
1500static zend_bool zend_try_ct_eval_class_const(zval *zv, zend_string *class_name, zend_string *name) /* {{{ */
1501{
1502	uint32_t fetch_type = zend_get_class_fetch_type(class_name);
1503	zend_class_constant *cc;
1504	zval *c;
1505
1506	if (class_name_refers_to_active_ce(class_name, fetch_type)) {
1507		cc = zend_hash_find_ptr(&CG(active_class_entry)->constants_table, name);
1508	} else if (fetch_type == ZEND_FETCH_CLASS_DEFAULT && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) {
1509		zend_class_entry *ce = zend_hash_find_ptr_lc(CG(class_table), ZSTR_VAL(class_name), ZSTR_LEN(class_name));
1510		if (ce) {
1511			cc = zend_hash_find_ptr(&ce->constants_table, name);
1512		} else {
1513			return 0;
1514		}
1515	} else {
1516		return 0;
1517	}
1518
1519	if (CG(compiler_options) & ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION) {
1520		return 0;
1521	}
1522
1523	if (!cc || !zend_verify_const_access(cc, CG(active_class_entry))) {
1524		return 0;
1525	}
1526
1527	c = &cc->value;
1528
1529	/* Substitute case-sensitive (or lowercase) persistent class constants */
1530	if (Z_TYPE_P(c) < IS_OBJECT) {
1531		ZVAL_DUP(zv, c);
1532		return 1;
1533	}
1534
1535	return 0;
1536}
1537/* }}} */
1538
1539static void zend_add_to_list(void *result, void *item) /* {{{ */
1540{
1541	void** list = *(void**)result;
1542	size_t n = 0;
1543
1544	if (list) {
1545		while (list[n]) {
1546			n++;
1547		}
1548	}
1549
1550	list = erealloc(list, sizeof(void*) * (n+2));
1551
1552	list[n]   = item;
1553	list[n+1] = NULL;
1554
1555	*(void**)result = list;
1556}
1557/* }}} */
1558
1559void zend_do_extended_info(void) /* {{{ */
1560{
1561	zend_op *opline;
1562
1563	if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
1564		return;
1565	}
1566
1567	opline = get_next_op(CG(active_op_array));
1568
1569	opline->opcode = ZEND_EXT_STMT;
1570	SET_UNUSED(opline->op1);
1571	SET_UNUSED(opline->op2);
1572}
1573/* }}} */
1574
1575void zend_do_extended_fcall_begin(void) /* {{{ */
1576{
1577	zend_op *opline;
1578
1579	if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
1580		return;
1581	}
1582
1583	opline = get_next_op(CG(active_op_array));
1584
1585	opline->opcode = ZEND_EXT_FCALL_BEGIN;
1586	SET_UNUSED(opline->op1);
1587	SET_UNUSED(opline->op2);
1588}
1589/* }}} */
1590
1591void zend_do_extended_fcall_end(void) /* {{{ */
1592{
1593	zend_op *opline;
1594
1595	if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
1596		return;
1597	}
1598
1599	opline = get_next_op(CG(active_op_array));
1600
1601	opline->opcode = ZEND_EXT_FCALL_END;
1602	SET_UNUSED(opline->op1);
1603	SET_UNUSED(opline->op2);
1604}
1605/* }}} */
1606
1607zend_bool zend_is_auto_global_str(char *name, size_t len) /* {{{ */ {
1608	zend_auto_global *auto_global;
1609
1610	if ((auto_global = zend_hash_str_find_ptr(CG(auto_globals), name, len)) != NULL) {
1611		if (auto_global->armed) {
1612			auto_global->armed = auto_global->auto_global_callback(auto_global->name);
1613		}
1614		return 1;
1615	}
1616	return 0;
1617}
1618/* }}} */
1619
1620zend_bool zend_is_auto_global(zend_string *name) /* {{{ */
1621{
1622	zend_auto_global *auto_global;
1623
1624	if ((auto_global = zend_hash_find_ptr(CG(auto_globals), name)) != NULL) {
1625		if (auto_global->armed) {
1626			auto_global->armed = auto_global->auto_global_callback(auto_global->name);
1627		}
1628		return 1;
1629	}
1630	return 0;
1631}
1632/* }}} */
1633
1634int zend_register_auto_global(zend_string *name, zend_bool jit, zend_auto_global_callback auto_global_callback) /* {{{ */
1635{
1636	zend_auto_global auto_global;
1637	int retval;
1638
1639	auto_global.name = zend_new_interned_string(name);
1640	auto_global.auto_global_callback = auto_global_callback;
1641	auto_global.jit = jit;
1642
1643	retval = zend_hash_add_mem(CG(auto_globals), auto_global.name, &auto_global, sizeof(zend_auto_global)) != NULL ? SUCCESS : FAILURE;
1644
1645	zend_string_release(name);
1646	return retval;
1647}
1648/* }}} */
1649
1650ZEND_API void zend_activate_auto_globals(void) /* {{{ */
1651{
1652	zend_auto_global *auto_global;
1653
1654	ZEND_HASH_FOREACH_PTR(CG(auto_globals), auto_global) {
1655		if (auto_global->jit) {
1656			auto_global->armed = 1;
1657		} else if (auto_global->auto_global_callback) {
1658			auto_global->armed = auto_global->auto_global_callback(auto_global->name);
1659		} else {
1660			auto_global->armed = 0;
1661		}
1662	} ZEND_HASH_FOREACH_END();
1663}
1664/* }}} */
1665
1666int zendlex(zend_parser_stack_elem *elem) /* {{{ */
1667{
1668	zval zv;
1669	int retval;
1670
1671	if (CG(increment_lineno)) {
1672		CG(zend_lineno)++;
1673		CG(increment_lineno) = 0;
1674	}
1675
1676again:
1677	ZVAL_UNDEF(&zv);
1678	retval = lex_scan(&zv);
1679	if (EG(exception)) {
1680		return T_ERROR;
1681	}
1682
1683	switch (retval) {
1684		case T_COMMENT:
1685		case T_DOC_COMMENT:
1686		case T_OPEN_TAG:
1687		case T_WHITESPACE:
1688			goto again;
1689
1690		case T_CLOSE_TAG:
1691			if (LANG_SCNG(yy_text)[LANG_SCNG(yy_leng)-1] != '>') {
1692				CG(increment_lineno) = 1;
1693			}
1694			retval = ';'; /* implicit ; */
1695			break;
1696		case T_OPEN_TAG_WITH_ECHO:
1697			retval = T_ECHO;
1698			break;
1699	}
1700	if (Z_TYPE(zv) != IS_UNDEF) {
1701		elem->ast = zend_ast_create_zval(&zv);
1702	}
1703
1704	return retval;
1705}
1706/* }}} */
1707
1708ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers) /* {{{ */
1709{
1710	zend_bool persistent_hashes = (ce->type == ZEND_INTERNAL_CLASS) ? 1 : 0;
1711
1712	ce->refcount = 1;
1713	ce->ce_flags = ZEND_ACC_CONSTANTS_UPDATED;
1714
1715	if (CG(compiler_options) & ZEND_COMPILE_GUARDS) {
1716		ce->ce_flags |= ZEND_ACC_USE_GUARDS;
1717	}
1718
1719	ce->default_properties_table = NULL;
1720	ce->default_static_members_table = NULL;
1721	zend_hash_init_ex(&ce->properties_info, 8, NULL, (persistent_hashes ? zend_destroy_property_info_internal : NULL), persistent_hashes, 0);
1722	zend_hash_init_ex(&ce->constants_table, 8, NULL, (persistent_hashes ? zend_destroy_class_constant_internal : NULL), persistent_hashes, 0);
1723	zend_hash_init_ex(&ce->function_table, 8, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0);
1724
1725	if (ce->type == ZEND_INTERNAL_CLASS) {
1726#ifdef ZTS
1727		int n = zend_hash_num_elements(CG(class_table));
1728
1729		if (CG(static_members_table) && n >= CG(last_static_member)) {
1730			/* Support for run-time declaration: dl() */
1731			CG(last_static_member) = n+1;
1732			CG(static_members_table) = realloc(CG(static_members_table), (n+1)*sizeof(zval*));
1733			CG(static_members_table)[n] = NULL;
1734		}
1735		ce->static_members_table = (zval*)(zend_intptr_t)n;
1736#else
1737		ce->static_members_table = NULL;
1738#endif
1739	} else {
1740		ce->static_members_table = ce->default_static_members_table;
1741		ce->info.user.doc_comment = NULL;
1742	}
1743
1744	ce->default_properties_count = 0;
1745	ce->default_static_members_count = 0;
1746
1747	if (nullify_handlers) {
1748		ce->constructor = NULL;
1749		ce->destructor = NULL;
1750		ce->clone = NULL;
1751		ce->__get = NULL;
1752		ce->__set = NULL;
1753		ce->__unset = NULL;
1754		ce->__isset = NULL;
1755		ce->__call = NULL;
1756		ce->__callstatic = NULL;
1757		ce->__tostring = NULL;
1758		ce->create_object = NULL;
1759		ce->get_iterator = NULL;
1760		ce->iterator_funcs.funcs = NULL;
1761		ce->interface_gets_implemented = NULL;
1762		ce->get_static_method = NULL;
1763		ce->parent = NULL;
1764		ce->num_interfaces = 0;
1765		ce->interfaces = NULL;
1766		ce->num_traits = 0;
1767		ce->traits = NULL;
1768		ce->trait_aliases = NULL;
1769		ce->trait_precedences = NULL;
1770		ce->serialize = NULL;
1771		ce->unserialize = NULL;
1772		ce->serialize_func = NULL;
1773		ce->unserialize_func = NULL;
1774		ce->__debugInfo = NULL;
1775		if (ce->type == ZEND_INTERNAL_CLASS) {
1776			ce->info.internal.module = NULL;
1777			ce->info.internal.builtin_functions = NULL;
1778		}
1779	}
1780}
1781/* }}} */
1782
1783ZEND_API zend_string *zend_get_compiled_variable_name(const zend_op_array *op_array, uint32_t var) /* {{{ */
1784{
1785	return op_array->vars[EX_VAR_TO_NUM(var)];
1786}
1787/* }}} */
1788
1789zend_ast *zend_ast_append_str(zend_ast *left_ast, zend_ast *right_ast) /* {{{ */
1790{
1791	zval *left_zv = zend_ast_get_zval(left_ast);
1792	zend_string *left = Z_STR_P(left_zv);
1793	zend_string *right = zend_ast_get_str(right_ast);
1794
1795	zend_string *result;
1796	size_t left_len = ZSTR_LEN(left);
1797	size_t len = left_len + ZSTR_LEN(right) + 1; /* left\right */
1798
1799	result = zend_string_extend(left, len, 0);
1800	ZSTR_VAL(result)[left_len] = '\\';
1801	memcpy(&ZSTR_VAL(result)[left_len + 1], ZSTR_VAL(right), ZSTR_LEN(right));
1802	ZSTR_VAL(result)[len] = '\0';
1803	zend_string_release(right);
1804
1805	ZVAL_STR(left_zv, result);
1806	return left_ast;
1807}
1808/* }}} */
1809
1810void zend_verify_namespace(void) /* {{{ */
1811{
1812	if (FC(has_bracketed_namespaces) && !FC(in_namespace)) {
1813		zend_error_noreturn(E_COMPILE_ERROR, "No code may exist outside of namespace {}");
1814	}
1815}
1816/* }}} */
1817
1818/* {{{ zend_dirname
1819   Returns directory name component of path */
1820ZEND_API size_t zend_dirname(char *path, size_t len)
1821{
1822	register char *end = path + len - 1;
1823	unsigned int len_adjust = 0;
1824
1825#ifdef ZEND_WIN32
1826	/* Note that on Win32 CWD is per drive (heritage from CP/M).
1827	 * This means dirname("c:foo") maps to "c:." or "c:" - which means CWD on C: drive.
1828	 */
1829	if ((2 <= len) && isalpha((int)((unsigned char *)path)[0]) && (':' == path[1])) {
1830		/* Skip over the drive spec (if any) so as not to change */
1831		path += 2;
1832		len_adjust += 2;
1833		if (2 == len) {
1834			/* Return "c:" on Win32 for dirname("c:").
1835			 * It would be more consistent to return "c:."
1836			 * but that would require making the string *longer*.
1837			 */
1838			return len;
1839		}
1840	}
1841#elif defined(NETWARE)
1842	/*
1843	 * Find the first occurrence of : from the left
1844	 * move the path pointer to the position just after :
1845	 * increment the len_adjust to the length of path till colon character(inclusive)
1846	 * If there is no character beyond : simple return len
1847	 */
1848	char *colonpos = NULL;
1849	colonpos = strchr(path, ':');
1850	if (colonpos != NULL) {
1851		len_adjust = ((colonpos - path) + 1);
1852		path += len_adjust;
1853		if (len_adjust == len) {
1854			return len;
1855		}
1856	}
1857#endif
1858
1859	if (len == 0) {
1860		/* Illegal use of this function */
1861		return 0;
1862	}
1863
1864	/* Strip trailing slashes */
1865	while (end >= path && IS_SLASH_P(end)) {
1866		end--;
1867	}
1868	if (end < path) {
1869		/* The path only contained slashes */
1870		path[0] = DEFAULT_SLASH;
1871		path[1] = '\0';
1872		return 1 + len_adjust;
1873	}
1874
1875	/* Strip filename */
1876	while (end >= path && !IS_SLASH_P(end)) {
1877		end--;
1878	}
1879	if (end < path) {
1880		/* No slash found, therefore return '.' */
1881#ifdef NETWARE
1882		if (len_adjust == 0) {
1883			path[0] = '.';
1884			path[1] = '\0';
1885			return 1; /* only one character */
1886		} else {
1887			path[0] = '\0';
1888			return len_adjust;
1889		}
1890#else
1891		path[0] = '.';
1892		path[1] = '\0';
1893		return 1 + len_adjust;
1894#endif
1895	}
1896
1897	/* Strip slashes which came before the file name */
1898	while (end >= path && IS_SLASH_P(end)) {
1899		end--;
1900	}
1901	if (end < path) {
1902		path[0] = DEFAULT_SLASH;
1903		path[1] = '\0';
1904		return 1 + len_adjust;
1905	}
1906	*(end+1) = '\0';
1907
1908	return (size_t)(end + 1 - path) + len_adjust;
1909}
1910/* }}} */
1911
1912static void zend_adjust_for_fetch_type(zend_op *opline, uint32_t type) /* {{{ */
1913{
1914	zend_uchar factor = (opline->opcode == ZEND_FETCH_STATIC_PROP_R) ? 1 : 3;
1915
1916	switch (type & BP_VAR_MASK) {
1917		case BP_VAR_R:
1918			return;
1919		case BP_VAR_W:
1920			opline->opcode += 1 * factor;
1921			return;
1922		case BP_VAR_RW:
1923			opline->opcode += 2 * factor;
1924			return;
1925		case BP_VAR_IS:
1926			opline->opcode += 3 * factor;
1927			return;
1928		case BP_VAR_FUNC_ARG:
1929			opline->opcode += 4 * factor;
1930			opline->extended_value |= type >> BP_VAR_SHIFT;
1931			return;
1932		case BP_VAR_UNSET:
1933			opline->opcode += 5 * factor;
1934			return;
1935		EMPTY_SWITCH_DEFAULT_CASE()
1936	}
1937}
1938/* }}} */
1939
1940static inline void zend_make_var_result(znode *result, zend_op *opline) /* {{{ */
1941{
1942	opline->result_type = IS_VAR;
1943	opline->result.var = get_temporary_variable(CG(active_op_array));
1944	GET_NODE(result, opline->result);
1945}
1946/* }}} */
1947
1948static inline void zend_make_tmp_result(znode *result, zend_op *opline) /* {{{ */
1949{
1950	opline->result_type = IS_TMP_VAR;
1951	opline->result.var = get_temporary_variable(CG(active_op_array));
1952	GET_NODE(result, opline->result);
1953}
1954/* }}} */
1955
1956static void zend_find_live_range(zend_op *opline, zend_uchar type, uint32_t var) /* {{{ */
1957{
1958	zend_op *def = opline;
1959
1960	while (def != CG(active_op_array)->opcodes) {
1961		def--;
1962		if (def->result_type == type && def->result.var == var) {
1963			uint32_t var;
1964			if (def->opcode == ZEND_ADD_ARRAY_ELEMENT ||
1965			    def->opcode == ZEND_ROPE_ADD) {
1966			    /* not a real definition */
1967				continue;
1968			} else if (def->opcode == ZEND_JMPZ_EX ||
1969			           def->opcode == ZEND_JMPNZ_EX ||
1970			           def->opcode == ZEND_BOOL ||
1971			           def->opcode == ZEND_BOOL_NOT) {
1972				/* result IS_BOOL, it does't have to be destroyed */
1973				break;
1974			} else if (def->opcode == ZEND_DECLARE_CLASS ||
1975			           def->opcode == ZEND_DECLARE_INHERITED_CLASS ||
1976			           def->opcode == ZEND_DECLARE_INHERITED_CLASS_DELAYED ||
1977			           def->opcode == ZEND_DECLARE_ANON_CLASS ||
1978			           def->opcode == ZEND_DECLARE_ANON_INHERITED_CLASS) {
1979				/* classes don't have to be destroyed */
1980				break;
1981			} else if (def->opcode == ZEND_FAST_CALL) {
1982				/* fast_calls don't have to be destroyed */
1983				break;
1984			}
1985
1986			var = def->result.var;
1987			if (def->opcode == ZEND_NEW) {
1988				/* Objects created via ZEND_NEW are only fully initialized
1989				 * after the DO_FCALL (constructor call) */
1990				def = CG(active_op_array)->opcodes + def->op2.opline_num - 1;
1991				if (def + 1 == opline) {
1992					break;
1993				}
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, 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
2908	if (zend_is_call(source_ast)) {
2909		opline->extended_value = ZEND_RETURNS_FUNCTION;
2910	}
2911}
2912/* }}} */
2913
2914static inline void zend_emit_assign_ref_znode(zend_ast *var_ast, znode *value_node) /* {{{ */
2915{
2916	zend_ast *assign_ast = zend_ast_create(ZEND_AST_ASSIGN_REF, var_ast,
2917		zend_ast_create_znode(value_node));
2918	zend_compile_assign_ref(NULL, assign_ast);
2919}
2920/* }}} */
2921
2922void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */
2923{
2924	zend_ast *var_ast = ast->child[0];
2925	zend_ast *expr_ast = ast->child[1];
2926	uint32_t opcode = ast->attr;
2927
2928	znode var_node, expr_node;
2929	zend_op *opline;
2930	uint32_t offset;
2931
2932	zend_ensure_writable_variable(var_ast);
2933
2934	switch (var_ast->kind) {
2935		case ZEND_AST_VAR:
2936		case ZEND_AST_STATIC_PROP:
2937			offset = zend_delayed_compile_begin();
2938			zend_delayed_compile_var(&var_node, var_ast, BP_VAR_RW);
2939			zend_compile_expr(&expr_node, expr_ast);
2940			zend_delayed_compile_end(offset);
2941			zend_emit_op(result, opcode, &var_node, &expr_node);
2942			return;
2943		case ZEND_AST_DIM:
2944			offset = zend_delayed_compile_begin();
2945			zend_delayed_compile_dim(result, var_ast, BP_VAR_RW);
2946			zend_compile_expr(&expr_node, expr_ast);
2947
2948			opline = zend_delayed_compile_end(offset);
2949			opline->opcode = opcode;
2950			opline->extended_value = ZEND_ASSIGN_DIM;
2951
2952			opline = zend_emit_op_data(&expr_node);
2953			return;
2954		case ZEND_AST_PROP:
2955			offset = zend_delayed_compile_begin();
2956			zend_delayed_compile_prop(result, var_ast, BP_VAR_RW);
2957			zend_compile_expr(&expr_node, expr_ast);
2958
2959			opline = zend_delayed_compile_end(offset);
2960			opline->opcode = opcode;
2961			opline->extended_value = ZEND_ASSIGN_OBJ;
2962
2963			zend_emit_op_data(&expr_node);
2964			return;
2965		EMPTY_SWITCH_DEFAULT_CASE()
2966	}
2967}
2968/* }}} */
2969
2970uint32_t zend_compile_args(zend_ast *ast, zend_function *fbc) /* {{{ */
2971{
2972	zend_ast_list *args = zend_ast_get_list(ast);
2973	uint32_t i;
2974	zend_bool uses_arg_unpack = 0;
2975	uint32_t arg_count = 0; /* number of arguments not including unpacks */
2976
2977	for (i = 0; i < args->children; ++i) {
2978		zend_ast *arg = args->child[i];
2979		uint32_t arg_num = i + 1;
2980
2981		znode arg_node;
2982		zend_op *opline;
2983		zend_uchar opcode;
2984		zend_ulong flags = 0;
2985
2986		if (arg->kind == ZEND_AST_UNPACK) {
2987			uses_arg_unpack = 1;
2988			fbc = NULL;
2989
2990			zend_compile_expr(&arg_node, arg->child[0]);
2991			opline = zend_emit_op(NULL, ZEND_SEND_UNPACK, &arg_node, NULL);
2992			opline->op2.num = arg_count;
2993			opline->result.var = (uint32_t)(zend_intptr_t)ZEND_CALL_ARG(NULL, arg_count);
2994			continue;
2995		}
2996
2997		if (uses_arg_unpack) {
2998			zend_error_noreturn(E_COMPILE_ERROR,
2999				"Cannot use positional argument after argument unpacking");
3000		}
3001
3002		arg_count++;
3003		if (zend_is_variable(arg)) {
3004			if (zend_is_call(arg)) {
3005				zend_compile_var(&arg_node, arg, BP_VAR_R);
3006				if (arg_node.op_type & (IS_CONST|IS_TMP_VAR)) {
3007					/* Function call was converted into builtin instruction */
3008					opcode = ZEND_SEND_VAL;
3009				} else {
3010					opcode = ZEND_SEND_VAR_NO_REF;
3011					flags |= ZEND_ARG_SEND_FUNCTION;
3012					if (fbc && ARG_SHOULD_BE_SENT_BY_REF(fbc, arg_num)) {
3013						flags |= ZEND_ARG_SEND_BY_REF;
3014						if (ARG_MAY_BE_SENT_BY_REF(fbc, arg_num)) {
3015							flags |= ZEND_ARG_SEND_SILENT;
3016						}
3017					}
3018				}
3019			} else if (fbc) {
3020				if (ARG_SHOULD_BE_SENT_BY_REF(fbc, arg_num)) {
3021					zend_compile_var(&arg_node, arg, BP_VAR_W);
3022					opcode = ZEND_SEND_REF;
3023				} else {
3024					zend_compile_var(&arg_node, arg, BP_VAR_R);
3025					opcode = ZEND_SEND_VAR;
3026				}
3027			} else {
3028				zend_compile_var(&arg_node, arg,
3029					BP_VAR_FUNC_ARG | (arg_num << BP_VAR_SHIFT));
3030				opcode = ZEND_SEND_VAR_EX;
3031			}
3032		} else {
3033			zend_compile_expr(&arg_node, arg);
3034			ZEND_ASSERT(arg_node.op_type != IS_CV);
3035			if (arg_node.op_type == IS_VAR) {
3036				opcode = ZEND_SEND_VAR_NO_REF;
3037				if (fbc && ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
3038					flags |= ZEND_ARG_SEND_BY_REF;
3039				}
3040			} else {
3041				if (fbc) {
3042					opcode = ZEND_SEND_VAL;
3043					if (ARG_MUST_BE_SENT_BY_REF(fbc, arg_num)) {
3044						zend_error_noreturn(E_COMPILE_ERROR, "Only variables can be passed by reference");
3045					}
3046				} else {
3047					opcode = ZEND_SEND_VAL_EX;
3048				}
3049			}
3050		}
3051
3052		opline = zend_emit_op(NULL, opcode, &arg_node, NULL);
3053		opline->op2.opline_num = arg_num;
3054		opline->result.var = (uint32_t)(zend_intptr_t)ZEND_CALL_ARG(NULL, arg_num);
3055
3056		if (opcode == ZEND_SEND_VAR_NO_REF) {
3057			if (fbc) {
3058				flags |= ZEND_ARG_COMPILE_TIME_BOUND;
3059			}
3060			if ((flags & ZEND_ARG_COMPILE_TIME_BOUND) && !(flags & ZEND_ARG_SEND_BY_REF)) {
3061				opline->opcode = ZEND_SEND_VAR;
3062				opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
3063			} else {
3064				opline->extended_value = flags;
3065			}
3066		} else if (fbc) {
3067			opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND;
3068		}
3069	}
3070
3071	return arg_count;
3072}
3073/* }}} */
3074
3075ZEND_API zend_uchar zend_get_call_op(zend_uchar init_op, zend_function *fbc) /* {{{ */
3076{
3077	if (fbc) {
3078		if (fbc->type == ZEND_INTERNAL_FUNCTION) {
3079			if (!zend_execute_internal &&
3080			    !fbc->common.scope &&
3081			    !(fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED|ZEND_ACC_HAS_TYPE_HINTS|ZEND_ACC_RETURN_REFERENCE))) {
3082				return ZEND_DO_ICALL;
3083			}
3084		} else {
3085			if (zend_execute_ex == execute_ex &&
3086			    !(fbc->common.fn_flags & ZEND_ACC_GENERATOR)) {
3087				return ZEND_DO_UCALL;
3088			}
3089		}
3090	} else if (zend_execute_ex == execute_ex &&
3091	           !zend_execute_internal &&
3092	           (init_op == ZEND_INIT_FCALL_BY_NAME ||
3093	            init_op == ZEND_INIT_NS_FCALL_BY_NAME)) {
3094		return ZEND_DO_FCALL_BY_NAME;
3095	}
3096	return ZEND_DO_FCALL;
3097}
3098/* }}} */
3099
3100void zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *fbc) /* {{{ */
3101{
3102	zend_op *opline;
3103	uint32_t opnum_init = get_next_op_number(CG(active_op_array)) - 1;
3104	uint32_t arg_count;
3105	uint32_t call_flags;
3106
3107	zend_do_extended_fcall_begin();
3108
3109	arg_count = zend_compile_args(args_ast, fbc);
3110
3111	opline = &CG(active_op_array)->opcodes[opnum_init];
3112	opline->extended_value = arg_count;
3113
3114	if (opline->opcode == ZEND_INIT_FCALL) {
3115		opline->op1.num = zend_vm_calc_used_stack(arg_count, fbc);
3116	}
3117
3118	call_flags = (opline->opcode == ZEND_NEW ? ZEND_CALL_CTOR : 0);
3119	opline = zend_emit_op(result, zend_get_call_op(opline->opcode, fbc), NULL, NULL);
3120	opline->op1.num = call_flags;
3121
3122	zend_do_extended_fcall_end();
3123}
3124/* }}} */
3125
3126zend_bool zend_compile_function_name(znode *name_node, zend_ast *name_ast) /* {{{ */
3127{
3128	zend_string *orig_name = zend_ast_get_str(name_ast);
3129	zend_bool is_fully_qualified;
3130
3131	name_node->op_type = IS_CONST;
3132	ZVAL_STR(&name_node->u.constant, zend_resolve_function_name(
3133		orig_name, name_ast->attr, &is_fully_qualified));
3134
3135	return !is_fully_qualified && FC(current_namespace);
3136}
3137/* }}} */
3138
3139void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args_ast) /* {{{ */
3140{
3141	zend_op *opline = get_next_op(CG(active_op_array));
3142	opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
3143	SET_UNUSED(opline->op1);
3144	opline->op2_type = IS_CONST;
3145	opline->op2.constant = zend_add_ns_func_name_literal(
3146		CG(active_op_array), Z_STR(name_node->u.constant));
3147	zend_alloc_cache_slot(opline->op2.constant);
3148
3149	zend_compile_call_common(result, args_ast, NULL);
3150}
3151/* }}} */
3152
3153void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_ast) /* {{{ */
3154{
3155	if (name_node->op_type == IS_CONST && Z_TYPE(name_node->u.constant) == IS_STRING) {
3156		const char *colon;
3157		zend_string *str = Z_STR(name_node->u.constant);
3158		if ((colon = zend_memrchr(ZSTR_VAL(str), ':', ZSTR_LEN(str))) != NULL && colon > ZSTR_VAL(str) && *(colon - 1) == ':') {
3159			zend_string *class = zend_string_init(ZSTR_VAL(str), colon - ZSTR_VAL(str) - 1, 0);
3160			zend_string *method = zend_string_init(colon + 1, ZSTR_LEN(str) - (colon - ZSTR_VAL(str)) - 1, 0);
3161			zend_op *opline = get_next_op(CG(active_op_array));
3162
3163			opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
3164			opline->op1_type = IS_CONST;
3165			opline->op1.constant = zend_add_class_name_literal(CG(active_op_array), class);
3166			opline->op2_type = IS_CONST;
3167			opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), method);
3168			zend_alloc_cache_slot(opline->op2.constant);
3169			zval_ptr_dtor(&name_node->u.constant);
3170		} else {
3171			zend_op *opline = get_next_op(CG(active_op_array));
3172
3173			opline->opcode = ZEND_INIT_FCALL_BY_NAME;
3174			SET_UNUSED(opline->op1);
3175			opline->op2_type = IS_CONST;
3176			opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), str);
3177			zend_alloc_cache_slot(opline->op2.constant);
3178		}
3179	} else {
3180		zend_emit_op(NULL, ZEND_INIT_DYNAMIC_CALL, NULL, name_node);
3181	}
3182
3183	zend_compile_call_common(result, args_ast, NULL);
3184}
3185/* }}} */
3186
3187static zend_bool zend_args_contain_unpack(zend_ast_list *args) /* {{{ */
3188{
3189	uint32_t i;
3190	for (i = 0; i < args->children; ++i) {
3191		if (args->child[i]->kind == ZEND_AST_UNPACK) {
3192			return 1;
3193		}
3194	}
3195	return 0;
3196}
3197/* }}} */
3198
3199int zend_compile_func_strlen(znode *result, zend_ast_list *args) /* {{{ */
3200{
3201	znode arg_node;
3202
3203	if ((CG(compiler_options) & ZEND_COMPILE_NO_BUILTIN_STRLEN)
3204		|| args->children != 1 || args->child[0]->kind == ZEND_AST_UNPACK
3205	) {
3206		return FAILURE;
3207	}
3208
3209	zend_compile_expr(&arg_node, args->child[0]);
3210	if (arg_node.op_type == IS_CONST && Z_TYPE(arg_node.u.constant) == IS_STRING) {
3211		result->op_type = IS_CONST;
3212		ZVAL_LONG(&result->u.constant, Z_STRLEN(arg_node.u.constant));
3213		zval_dtor(&arg_node.u.constant);
3214	} else {
3215		zend_emit_op_tmp(result, ZEND_STRLEN, &arg_node, NULL);
3216	}
3217	return SUCCESS;
3218}
3219/* }}} */
3220
3221int zend_compile_func_typecheck(znode *result, zend_ast_list *args, uint32_t type) /* {{{ */
3222{
3223	znode arg_node;
3224	zend_op *opline;
3225
3226	if (args->children != 1 || args->child[0]->kind == ZEND_AST_UNPACK) {
3227		return FAILURE;
3228	}
3229
3230	zend_compile_expr(&arg_node, args->child[0]);
3231	opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &arg_node, NULL);
3232	opline->extended_value = type;
3233	return SUCCESS;
3234}
3235/* }}} */
3236
3237int zend_compile_func_defined(znode *result, zend_ast_list *args) /* {{{ */
3238{
3239	zend_string *name;
3240	zend_op *opline;
3241
3242	if (args->children != 1 || args->child[0]->kind != ZEND_AST_ZVAL) {
3243		return FAILURE;
3244	}
3245
3246	name = zval_get_string(zend_ast_get_zval(args->child[0]));
3247	if (zend_memrchr(ZSTR_VAL(name), '\\', ZSTR_LEN(name)) || zend_memrchr(ZSTR_VAL(name), ':', ZSTR_LEN(name))) {
3248		zend_string_release(name);
3249		return FAILURE;
3250	}
3251
3252	opline = zend_emit_op_tmp(result, ZEND_DEFINED, NULL, NULL);
3253	opline->op1_type = IS_CONST;
3254	LITERAL_STR(opline->op1, name);
3255	zend_alloc_cache_slot(opline->op1.constant);
3256
3257	/* Lowercase constant name in a separate literal */
3258	{
3259		zval c;
3260		zend_string *lcname = zend_string_tolower(name);
3261		ZVAL_NEW_STR(&c, lcname);
3262		zend_add_literal(CG(active_op_array), &c);
3263	}
3264	return SUCCESS;
3265}
3266/* }}} */
3267
3268static int zend_try_compile_ct_bound_init_user_func(zend_ast *name_ast, uint32_t num_args) /* {{{ */
3269{
3270	zend_string *name, *lcname;
3271	zend_function *fbc;
3272	zend_op *opline;
3273
3274	if (name_ast->kind != ZEND_AST_ZVAL || Z_TYPE_P(zend_ast_get_zval(name_ast)) != IS_STRING) {
3275		return FAILURE;
3276	}
3277
3278	name = zend_ast_get_str(name_ast);
3279	lcname = zend_string_tolower(name);
3280
3281	fbc = zend_hash_find_ptr(CG(function_table), lcname);
3282	if (!fbc
3283	 || (fbc->type == ZEND_INTERNAL_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS))
3284	 || (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_USER_FUNCTIONS))
3285	) {
3286		zend_string_release(lcname);
3287		return FAILURE;
3288	}
3289
3290	opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, NULL);
3291	opline->extended_value = num_args;
3292	opline->op1.num = zend_vm_calc_used_stack(num_args, fbc);
3293	opline->op2_type = IS_CONST;
3294	LITERAL_STR(opline->op2, lcname);
3295	zend_alloc_cache_slot(opline->op2.constant);
3296
3297	return SUCCESS;
3298}
3299/* }}} */
3300
3301static void zend_compile_init_user_func(zend_ast *name_ast, uint32_t num_args, zend_string *orig_func_name) /* {{{ */
3302{
3303	zend_op *opline;
3304	znode name_node;
3305
3306	if (zend_try_compile_ct_bound_init_user_func(name_ast, num_args) == SUCCESS) {
3307		return;
3308	}
3309
3310	zend_compile_expr(&name_node, name_ast);
3311
3312	opline = zend_emit_op(NULL, ZEND_INIT_USER_CALL, NULL, &name_node);
3313	opline->op1_type = IS_CONST;
3314	LITERAL_STR(opline->op1, zend_string_copy(orig_func_name));
3315	opline->extended_value = num_args;
3316}
3317/* }}} */
3318
3319/* cufa = call_user_func_array */
3320int zend_compile_func_cufa(znode *result, zend_ast_list *args, zend_string *lcname) /* {{{ */
3321{
3322	znode arg_node;
3323
3324	if (args->children != 2 || zend_args_contain_unpack(args)) {
3325		return FAILURE;
3326	}
3327
3328	zend_compile_init_user_func(args->child[0], 0, lcname);
3329	zend_compile_expr(&arg_node, args->child[1]);
3330	zend_emit_op(NULL, ZEND_SEND_ARRAY, &arg_node, NULL);
3331	zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL);
3332
3333	return SUCCESS;
3334}
3335/* }}} */
3336
3337/* cuf = call_user_func */
3338int zend_compile_func_cuf(znode *result, zend_ast_list *args, zend_string *lcname) /* {{{ */
3339{
3340	uint32_t i;
3341
3342	if (args->children < 1 || zend_args_contain_unpack(args)) {
3343		return FAILURE;
3344	}
3345
3346	zend_compile_init_user_func(args->child[0], args->children - 1, lcname);
3347	for (i = 1; i < args->children; ++i) {
3348		zend_ast *arg_ast = args->child[i];
3349		znode arg_node;
3350		zend_op *opline;
3351		zend_bool send_user = 0;
3352
3353		if (zend_is_variable(arg_ast) && !zend_is_call(arg_ast)) {
3354			zend_compile_var(&arg_node, arg_ast, BP_VAR_FUNC_ARG | (i << BP_VAR_SHIFT));
3355			send_user = 1;
3356		} else {
3357			zend_compile_expr(&arg_node, arg_ast);
3358			if (arg_node.op_type & (IS_VAR|IS_CV)) {
3359				send_user = 1;
3360			}
3361		}
3362
3363		if (send_user) {
3364			opline = zend_emit_op(NULL, ZEND_SEND_USER, &arg_node, NULL);
3365		} else {
3366			opline = zend_emit_op(NULL, ZEND_SEND_VAL, &arg_node, NULL);
3367		}
3368
3369		opline->op2.num = i;
3370		opline->result.var = (uint32_t)(zend_intptr_t)ZEND_CALL_ARG(NULL, i);
3371	}
3372	zend_emit_op(result, ZEND_DO_FCALL, NULL, NULL);
3373
3374	return SUCCESS;
3375}
3376/* }}} */
3377
3378static void zend_compile_assert_side_effects(zend_ast *ast) /* {{{ */
3379{
3380	int i;
3381	int children = zend_ast_is_list(ast) ? zend_ast_get_list(ast)->children : zend_ast_get_num_children(ast);
3382
3383	for (i = 0; i < children; i++) {
3384		zend_ast *child = (zend_ast_is_list(ast) ? zend_ast_get_list(ast)->child : ast->child)[i];
3385		if (child) {
3386			if (child->kind == ZEND_AST_YIELD) {
3387				zend_mark_function_as_generator();
3388			} else if (ast->kind >= ZEND_AST_IS_LIST_SHIFT) {
3389				zend_compile_assert_side_effects(child);
3390			}
3391		}
3392	}
3393}
3394/* }}} */
3395
3396static int zend_compile_assert(znode *result, zend_ast_list *args, zend_string *name, zend_function *fbc) /* {{{ */
3397{
3398	if (EG(assertions) >= 0) {
3399		znode name_node;
3400		zend_op *opline;
3401		uint32_t check_op_number = get_next_op_number(CG(active_op_array));
3402
3403		zend_emit_op(NULL, ZEND_ASSERT_CHECK, NULL, NULL);
3404
3405		if (fbc) {
3406			name_node.op_type = IS_CONST;
3407			ZVAL_STR_COPY(&name_node.u.constant, name);
3408
3409			opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, &name_node);
3410		} else {
3411			opline = zend_emit_op(NULL, ZEND_INIT_NS_FCALL_BY_NAME, NULL, NULL);
3412			opline->op2_type = IS_CONST;
3413			opline->op2.constant = zend_add_ns_func_name_literal(
3414				CG(active_op_array), name);
3415		}
3416		zend_alloc_cache_slot(opline->op2.constant);
3417
3418		if (args->children == 1 &&
3419		    (args->child[0]->kind != ZEND_AST_ZVAL ||
3420		     Z_TYPE_P(zend_ast_get_zval(args->child[0])) != IS_STRING)) {
3421			/* add "assert(condition) as assertion message */
3422			zend_ast_list_add((zend_ast*)args,
3423				zend_ast_create_zval_from_str(
3424					zend_ast_export("assert(", args->child[0], ")")));
3425		}
3426
3427		zend_compile_call_common(result, (zend_ast*)args, fbc);
3428
3429		opline = &CG(active_op_array)->opcodes[check_op_number];
3430		opline->op2.opline_num = get_next_op_number(CG(active_op_array));
3431		SET_NODE(opline->result, result);
3432	} else {
3433		if (!fbc) {
3434			zend_string_release(name);
3435		}
3436		result->op_type = IS_CONST;
3437		ZVAL_TRUE(&result->u.constant);
3438
3439		zend_compile_assert_side_effects((zend_ast *) args);
3440	}
3441
3442	return SUCCESS;
3443}
3444/* }}} */
3445
3446int zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_list *args, zend_function *fbc) /* {{{ */
3447{
3448	if (fbc->internal_function.handler == ZEND_FN(display_disabled_function)) {
3449		return FAILURE;
3450	}
3451
3452	if (zend_string_equals_literal(lcname, "strlen")) {
3453		return zend_compile_func_strlen(result, args);
3454	} else if (zend_string_equals_literal(lcname, "is_null")) {
3455		return zend_compile_func_typecheck(result, args, IS_NULL);
3456	} else if (zend_string_equals_literal(lcname, "is_bool")) {
3457		return zend_compile_func_typecheck(result, args, _IS_BOOL);
3458	} else if (zend_string_equals_literal(lcname, "is_long")
3459		|| zend_string_equals_literal(lcname, "is_int")
3460		|| zend_string_equals_literal(lcname, "is_integer")
3461	) {
3462		return zend_compile_func_typecheck(result, args, IS_LONG);
3463	} else if (zend_string_equals_literal(lcname, "is_float")
3464		|| zend_string_equals_literal(lcname, "is_double")
3465		|| zend_string_equals_literal(lcname, "is_real")
3466	) {
3467		return zend_compile_func_typecheck(result, args, IS_DOUBLE);
3468	} else if (zend_string_equals_literal(lcname, "is_string")) {
3469		return zend_compile_func_typecheck(result, args, IS_STRING);
3470	} else if (zend_string_equals_literal(lcname, "is_array")) {
3471		return zend_compile_func_typecheck(result, args, IS_ARRAY);
3472	} else if (zend_string_equals_literal(lcname, "is_object")) {
3473		return zend_compile_func_typecheck(result, args, IS_OBJECT);
3474	} else if (zend_string_equals_literal(lcname, "is_resource")) {
3475		return zend_compile_func_typecheck(result, args, IS_RESOURCE);
3476	} else if (zend_string_equals_literal(lcname, "defined")) {
3477		return zend_compile_func_defined(result, args);
3478	} else if (zend_string_equals_literal(lcname, "call_user_func_array")) {
3479		return zend_compile_func_cufa(result, args, lcname);
3480	} else if (zend_string_equals_literal(lcname, "call_user_func")) {
3481		return zend_compile_func_cuf(result, args, lcname);
3482	} else if (zend_string_equals_literal(lcname, "assert")) {
3483		return zend_compile_assert(result, args, lcname, fbc);
3484	} else {
3485		return FAILURE;
3486	}
3487}
3488/* }}} */
3489
3490void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
3491{
3492	zend_ast *name_ast = ast->child[0];
3493	zend_ast *args_ast = ast->child[1];
3494
3495	znode name_node;
3496
3497	if (name_ast->kind != ZEND_AST_ZVAL || Z_TYPE_P(zend_ast_get_zval(name_ast)) != IS_STRING) {
3498		zend_compile_expr(&name_node, name_ast);
3499		zend_compile_dynamic_call(result, &name_node, args_ast);
3500		return;
3501	}
3502
3503	{
3504		zend_bool runtime_resolution = zend_compile_function_name(&name_node, name_ast);
3505		if (runtime_resolution) {
3506			if (zend_string_equals_literal_ci(zend_ast_get_str(name_ast), "assert")) {
3507				zend_compile_assert(result, zend_ast_get_list(args_ast), Z_STR(name_node.u.constant), NULL);
3508			} else {
3509				zend_compile_ns_call(result, &name_node, args_ast);
3510			}
3511			return;
3512		}
3513	}
3514
3515	{
3516		zval *name = &name_node.u.constant;
3517		zend_string *lcname;
3518		zend_function *fbc;
3519		zend_op *opline;
3520
3521		lcname = zend_string_tolower(Z_STR_P(name));
3522
3523		fbc = zend_hash_find_ptr(CG(function_table), lcname);
3524		if (!fbc
3525		 || (fbc->type == ZEND_INTERNAL_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_INTERNAL_FUNCTIONS))
3526		 || (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_USER_FUNCTIONS))
3527		) {
3528			zend_string_release(lcname);
3529			zend_compile_dynamic_call(result, &name_node, args_ast);
3530			return;
3531		}
3532
3533		if (zend_try_compile_special_func(result, lcname,
3534				zend_ast_get_list(args_ast), fbc) == SUCCESS
3535		) {
3536			zend_string_release(lcname);
3537			zval_ptr_dtor(&name_node.u.constant);
3538			return;
3539		}
3540
3541		zval_ptr_dtor(&name_node.u.constant);
3542		ZVAL_NEW_STR(&name_node.u.constant, lcname);
3543
3544		opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, &name_node);
3545		zend_alloc_cache_slot(opline->op2.constant);
3546
3547		zend_compile_call_common(result, args_ast, fbc);
3548	}
3549}
3550/* }}} */
3551
3552void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
3553{
3554	zend_ast *obj_ast = ast->child[0];
3555	zend_ast *method_ast = ast->child[1];
3556	zend_ast *args_ast = ast->child[2];
3557
3558	znode obj_node, method_node;
3559	zend_op *opline;
3560
3561	if (is_this_fetch(obj_ast)) {
3562		obj_node.op_type = IS_UNUSED;
3563	} else {
3564		zend_compile_expr(&obj_node, obj_ast);
3565	}
3566
3567	zend_compile_expr(&method_node, method_ast);
3568	opline = zend_emit_op(NULL, ZEND_INIT_METHOD_CALL, &obj_node, NULL);
3569
3570	if (method_node.op_type == IS_CONST) {
3571		if (Z_TYPE(method_node.u.constant) != IS_STRING) {
3572			zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string");
3573		}
3574
3575		opline->op2_type = IS_CONST;
3576		opline->op2.constant = zend_add_func_name_literal(CG(active_op_array),
3577			Z_STR(method_node.u.constant));
3578		zend_alloc_polymorphic_cache_slot(opline->op2.constant);
3579	} else {
3580		SET_NODE(opline->op2, &method_node);
3581	}
3582
3583	zend_compile_call_common(result, args_ast, NULL);
3584}
3585/* }}} */
3586
3587static zend_bool zend_is_constructor(zend_string *name) /* {{{ */
3588{
3589	return zend_string_equals_literal_ci(name, ZEND_CONSTRUCTOR_FUNC_NAME);
3590}
3591/* }}} */
3592
3593void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
3594{
3595	zend_ast *class_ast = ast->child[0];
3596	zend_ast *method_ast = ast->child[1];
3597	zend_ast *args_ast = ast->child[2];
3598
3599	znode class_node, method_node;
3600	zend_op *opline;
3601
3602	zend_compile_class_ref_ex(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
3603
3604	zend_compile_expr(&method_node, method_ast);
3605	if (method_node.op_type == IS_CONST) {
3606		zval *name = &method_node.u.constant;
3607		if (Z_TYPE_P(name) != IS_STRING) {
3608			zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string");
3609		}
3610		if (zend_is_constructor(Z_STR_P(name))) {
3611			zval_ptr_dtor(name);
3612			method_node.op_type = IS_UNUSED;
3613		}
3614	}
3615
3616	opline = get_next_op(CG(active_op_array));
3617	opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
3618
3619	zend_set_class_name_op1(opline, &class_node);
3620
3621	if (method_node.op_type == IS_CONST) {
3622		opline->op2_type = IS_CONST;
3623		opline->op2.constant = zend_add_func_name_literal(CG(active_op_array),
3624			Z_STR(method_node.u.constant));
3625		if (opline->op1_type == IS_CONST) {
3626			zend_alloc_cache_slot(opline->op2.constant);
3627		} else {
3628			zend_alloc_polymorphic_cache_slot(opline->op2.constant);
3629		}
3630	} else {
3631		SET_NODE(opline->op2, &method_node);
3632	}
3633	zend_check_live_ranges(opline);
3634
3635	zend_compile_call_common(result, args_ast, NULL);
3636}
3637/* }}} */
3638
3639void zend_compile_class_decl(zend_ast *ast);
3640
3641void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */
3642{
3643	zend_ast *class_ast = ast->child[0];
3644	zend_ast *args_ast = ast->child[1];
3645
3646	znode class_node, ctor_result;
3647	zend_op *opline;
3648	uint32_t opnum;
3649
3650	if (class_ast->kind == ZEND_AST_CLASS) {
3651		uint32_t dcl_opnum = get_next_op_number(CG(active_op_array));
3652		zend_compile_class_decl(class_ast);
3653		/* jump over anon class declaration */
3654		opline = &CG(active_op_array)->opcodes[dcl_opnum];
3655		if (opline->opcode == ZEND_FETCH_CLASS) {
3656			opline++;
3657		}
3658		class_node.op_type = opline->result_type;
3659		class_node.u.op.var = opline->result.var;
3660		opline->extended_value = get_next_op_number(CG(active_op_array));
3661	} else {
3662		zend_compile_class_ref_ex(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
3663	}
3664
3665	opnum = get_next_op_number(CG(active_op_array));
3666	opline = zend_emit_op(result, ZEND_NEW, NULL, NULL);
3667
3668	if (class_node.op_type == IS_CONST) {
3669		opline->op1_type = IS_CONST;
3670		opline->op1.constant = zend_add_class_name_literal(
3671			CG(active_op_array), Z_STR(class_node.u.constant));
3672	} else {
3673		SET_NODE(opline->op1, &class_node);
3674	}
3675
3676	zend_compile_call_common(&ctor_result, args_ast, NULL);
3677	zend_do_free(&ctor_result);
3678
3679	/* New jumps over ctor call if ctor does not exist */
3680	opline = &CG(active_op_array)->opcodes[opnum];
3681	opline->op2.opline_num = get_next_op_number(CG(active_op_array));
3682}
3683/* }}} */
3684
3685void zend_compile_clone(znode *result, zend_ast *ast) /* {{{ */
3686{
3687	zend_ast *obj_ast = ast->child[0];
3688
3689	znode obj_node;
3690	zend_compile_expr(&obj_node, obj_ast);
3691
3692	zend_emit_op_tmp(result, ZEND_CLONE, &obj_node, NULL);
3693}
3694/* }}} */
3695
3696void zend_compile_global_var(zend_ast *ast) /* {{{ */
3697{
3698	zend_ast *var_ast = ast->child[0];
3699	zend_ast *name_ast = var_ast->child[0];
3700
3701	znode name_node, result;
3702
3703	zend_compile_expr(&name_node, name_ast);
3704	if (name_node.op_type == IS_CONST) {
3705		convert_to_string(&name_node.u.constant);
3706	}
3707
3708	if (zend_try_compile_cv(&result, var_ast) == SUCCESS) {
3709		zend_op *opline = zend_emit_op(NULL, ZEND_BIND_GLOBAL, &result, &name_node);
3710		zend_alloc_cache_slot(opline->op2.constant);
3711	} else {
3712		/* name_ast should be evaluated only. FETCH_GLOBAL_LOCK instructs FETCH_W
3713		 * to not free the name_node operand, so it can be reused in the following
3714		 * ASSIGN_REF, which then frees it. */
3715		zend_op *opline = zend_emit_op(&result, ZEND_FETCH_W, &name_node, NULL);
3716		opline->extended_value = ZEND_FETCH_GLOBAL_LOCK;
3717
3718		zend_emit_assign_ref_znode(
3719			zend_ast_create(ZEND_AST_VAR, zend_ast_create_znode(&name_node)),
3720			&result
3721		);
3722	}
3723}
3724/* }}} */
3725
3726static void zend_compile_static_var_common(zend_ast *var_ast, zval *value, zend_bool by_ref) /* {{{ */
3727{
3728	znode var_node;
3729	zend_op *opline;
3730
3731	zend_compile_expr(&var_node, var_ast);
3732
3733	if (!CG(active_op_array)->static_variables) {
3734		if (CG(active_op_array)->scope) {
3735			CG(active_op_array)->scope->ce_flags |= ZEND_HAS_STATIC_IN_METHODS;
3736		}
3737		ALLOC_HASHTABLE(CG(active_op_array)->static_variables);
3738		zend_hash_init(CG(active_op_array)->static_variables, 8, NULL, ZVAL_PTR_DTOR, 0);
3739	}
3740
3741	if (GC_REFCOUNT(CG(active_op_array)->static_variables) > 1) {
3742		if (!(GC_FLAGS(CG(active_op_array)->static_variables) & IS_ARRAY_IMMUTABLE)) {
3743			GC_REFCOUNT(CG(active_op_array)->static_variables)--;
3744		}
3745		CG(active_op_array)->static_variables = zend_array_dup(CG(active_op_array)->static_variables);
3746	}
3747	zend_hash_update(CG(active_op_array)->static_variables, Z_STR(var_node.u.constant), value);
3748
3749	opline = zend_emit_op(NULL, ZEND_BIND_STATIC, NULL, &var_node);
3750	opline->op1_type = IS_CV;
3751	opline->op1.var = lookup_cv(CG(active_op_array), zend_string_copy(Z_STR(var_node.u.constant)));
3752	opline->extended_value = by_ref;
3753}
3754/* }}} */
3755
3756void zend_compile_static_var(zend_ast *ast) /* {{{ */
3757{
3758	zend_ast *var_ast = ast->child[0];
3759	zend_ast *value_ast = ast->child[1];
3760	zval value_zv;
3761
3762	if (value_ast) {
3763		zend_const_expr_to_zval(&value_zv, value_ast);
3764	} else {
3765		ZVAL_NULL(&value_zv);
3766	}
3767
3768	zend_compile_static_var_common(var_ast, &value_zv, 1);
3769}
3770/* }}} */
3771
3772void zend_compile_unset(zend_ast *ast) /* {{{ */
3773{
3774	zend_ast *var_ast = ast->child[0];
3775	znode var_node;
3776	zend_op *opline;
3777
3778	zend_ensure_writable_variable(var_ast);
3779
3780	switch (var_ast->kind) {
3781		case ZEND_AST_VAR:
3782			if (zend_try_compile_cv(&var_node, var_ast) == SUCCESS) {
3783				opline = zend_emit_op(NULL, ZEND_UNSET_VAR, &var_node, NULL);
3784				opline->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
3785			} else {
3786				opline = zend_compile_simple_var_no_cv(NULL, var_ast, BP_VAR_UNSET, 0);
3787				opline->opcode = ZEND_UNSET_VAR;
3788			}
3789			return;
3790		case ZEND_AST_DIM:
3791			opline = zend_compile_dim_common(NULL, var_ast, BP_VAR_UNSET);
3792			opline->opcode = ZEND_UNSET_DIM;
3793			return;
3794		case ZEND_AST_PROP:
3795			opline = zend_compile_prop_common(NULL, var_ast, BP_VAR_UNSET);
3796			opline->opcode = ZEND_UNSET_OBJ;
3797			return;
3798		case ZEND_AST_STATIC_PROP:
3799			opline = zend_compile_static_prop_common(NULL, var_ast, BP_VAR_UNSET, 0);
3800			opline->opcode = ZEND_UNSET_STATIC_PROP;
3801			return;
3802		EMPTY_SWITCH_DEFAULT_CASE()
3803	}
3804}
3805/* }}} */
3806
3807static int zend_handle_loops_and_finally_ex(zend_long depth) /* {{{ */
3808{
3809	zend_loop_var *base;
3810	zend_loop_var *loop_var = zend_stack_top(&CG(loop_var_stack));
3811
3812	if (!loop_var) {
3813		return 1;
3814	}
3815	base = zend_stack_base(&CG(loop_var_stack));
3816	for (; loop_var >= base; loop_var--) {
3817		if (loop_var->opcode == ZEND_FAST_CALL) {
3818			zend_op *opline = get_next_op(CG(active_op_array));
3819
3820			opline->opcode = ZEND_FAST_CALL;
3821			opline->result_type = IS_TMP_VAR;
3822			opline->result.var = loop_var->var_num;
3823			SET_UNUSED(opline->op1);
3824			SET_UNUSED(opline->op2);
3825			opline->op1.num = loop_var->u.try_catch_offset;
3826		} else if (loop_var->opcode == ZEND_RETURN) {
3827			/* Stack separator */
3828			break;
3829		} else if (depth <= 1) {
3830			return 1;
3831		} else if (loop_var->opcode == ZEND_NOP) {
3832			/* Loop doesn't have freeable variable */
3833			depth--;
3834		} else {
3835			zend_op *opline;
3836
3837			ZEND_ASSERT(loop_var->var_type & (IS_VAR|IS_TMP_VAR));
3838			opline = get_next_op(CG(active_op_array));
3839			opline->opcode = loop_var->opcode;
3840			opline->op1_type = loop_var->var_type;
3841			opline->op1.var = loop_var->var_num;
3842			SET_UNUSED(opline->op2);
3843			opline->op2.num = loop_var->u.live_range_offset;
3844			opline->extended_value = ZEND_FREE_ON_RETURN;
3845			depth--;
3846	    }
3847	}
3848	return (depth == 0);
3849}
3850/* }}} */
3851
3852static int zend_handle_loops_and_finally(void) /* {{{ */
3853{
3854	return zend_handle_loops_and_finally_ex(zend_stack_count(&CG(loop_var_stack)) + 1);
3855}
3856/* }}} */
3857
3858void zend_compile_return(zend_ast *ast) /* {{{ */
3859{
3860	zend_ast *expr_ast = ast->child[0];
3861	zend_bool by_ref = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
3862
3863	znode expr_node;
3864	zend_op *opline;
3865
3866	if (!expr_ast) {
3867		expr_node.op_type = IS_CONST;
3868		ZVAL_NULL(&expr_node.u.constant);
3869	} else if (by_ref && zend_is_variable(expr_ast) && !zend_is_call(expr_ast)) {
3870		zend_compile_var(&expr_node, expr_ast, BP_VAR_W);
3871	} else {
3872		zend_compile_expr(&expr_node, expr_ast);
3873	}
3874
3875	if (CG(context).in_finally) {
3876		opline = zend_emit_op(NULL, ZEND_DISCARD_EXCEPTION, NULL, NULL);
3877		opline->op1_type = IS_TMP_VAR;
3878		opline->op1.var = CG(context).fast_call_var;
3879	}
3880
3881	/* Generator return types are handled separately */
3882	if (!(CG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) && CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
3883		zend_emit_return_type_check(expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1);
3884	}
3885
3886	zend_handle_loops_and_finally();
3887
3888	opline = zend_emit_op(NULL, by_ref ? ZEND_RETURN_BY_REF : ZEND_RETURN,
3889		&expr_node, NULL);
3890
3891	if (expr_ast) {
3892		if (zend_is_call(expr_ast)) {
3893			opline->extended_value = ZEND_RETURNS_FUNCTION;
3894		} else if (by_ref && !zend_is_variable(expr_ast)) {
3895			opline->extended_value = ZEND_RETURNS_VALUE;
3896		}
3897	}
3898}
3899/* }}} */
3900
3901void zend_compile_echo(zend_ast *ast) /* {{{ */
3902{
3903	zend_op *opline;
3904	zend_ast *expr_ast = ast->child[0];
3905
3906	znode expr_node;
3907	zend_compile_expr(&expr_node, expr_ast);
3908
3909	opline = zend_emit_op(NULL, ZEND_ECHO, &expr_node, NULL);
3910	opline->extended_value = 0;
3911}
3912/* }}} */
3913
3914void zend_compile_throw(zend_ast *ast) /* {{{ */
3915{
3916	zend_ast *expr_ast = ast->child[0];
3917
3918	znode expr_node;
3919	zend_compile_expr(&expr_node, expr_ast);
3920
3921	zend_emit_op(NULL, ZEND_THROW, &expr_node, NULL);
3922}
3923/* }}} */
3924
3925void zend_compile_break_continue(zend_ast *ast) /* {{{ */
3926{
3927	zend_ast *depth_ast = ast->child[0];
3928
3929	zend_op *opline;
3930	int depth;
3931
3932	ZEND_ASSERT(ast->kind == ZEND_AST_BREAK || ast->kind == ZEND_AST_CONTINUE);
3933
3934	if (depth_ast) {
3935		zval *depth_zv;
3936		if (depth_ast->kind != ZEND_AST_ZVAL) {
3937			zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator with non-constant operand "
3938				"is no longer supported", ast->kind == ZEND_AST_BREAK ? "break" : "continue");
3939		}
3940
3941		depth_zv = zend_ast_get_zval(depth_ast);
3942		if (Z_TYPE_P(depth_zv) != IS_LONG || Z_LVAL_P(depth_zv) < 1) {
3943			zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator accepts only positive numbers",
3944				ast->kind == ZEND_AST_BREAK ? "break" : "continue");
3945		}
3946
3947		depth = Z_LVAL_P(depth_zv);
3948	} else {
3949		depth = 1;
3950	}
3951
3952	if (CG(context).current_brk_cont == -1) {
3953		zend_error_noreturn(E_COMPILE_ERROR, "'%s' not in the 'loop' or 'switch' context",
3954			ast->kind == ZEND_AST_BREAK ? "break" : "continue");
3955	} else {
3956		if (!zend_handle_loops_and_finally_ex(depth)) {
3957			zend_error_noreturn(E_COMPILE_ERROR, "Cannot '%s' %d level%s",
3958				ast->kind == ZEND_AST_BREAK ? "break" : "continue",
3959				depth, depth == 1 ? "" : "s");
3960		}
3961	}
3962	opline = zend_emit_op(NULL, ast->kind == ZEND_AST_BREAK ? ZEND_BRK : ZEND_CONT, NULL, NULL);
3963	opline->op1.num = CG(context).current_brk_cont;
3964	opline->op2.num = depth;
3965}
3966/* }}} */
3967
3968void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline) /* {{{ */
3969{
3970	zend_label *dest;
3971	int current, remove_oplines = opline->op1.num;
3972	zval *label;
3973	uint32_t opnum = opline - op_array->opcodes;
3974
3975	label = CT_CONSTANT_EX(op_array, opline->op2.constant);
3976	if (CG(context).labels == NULL ||
3977	    (dest = zend_hash_find_ptr(CG(context).labels, Z_STR_P(label))) == NULL
3978	) {
3979		CG(in_compilation) = 1;
3980		CG(active_op_array) = op_array;
3981		CG(zend_lineno) = opline->lineno;
3982		zend_error_noreturn(E_COMPILE_ERROR, "'goto' to undefined label '%s'", Z_STRVAL_P(label));
3983	}
3984
3985	zval_dtor(label);
3986	ZVAL_NULL(label);
3987
3988	current = opline->extended_value;
3989	for (; current != dest->brk_cont; current = CG(context).brk_cont_array[current].parent) {
3990		if (current == -1) {
3991			CG(in_compilation) = 1;
3992			CG(active_op_array) = op_array;
3993			CG(zend_lineno) = opline->lineno;
3994			zend_error_noreturn(E_COMPILE_ERROR, "'goto' into loop or switch statement is disallowed");
3995		}
3996		if (CG(context).brk_cont_array[current].start >= 0) {
3997			remove_oplines--;
3998		}
3999	}
4000
4001	for (current = 0; current < op_array->last_try_catch; ++current) {
4002		zend_try_catch_element *elem = &op_array->try_catch_array[current];
4003		if (elem->try_op > opnum) {
4004			break;
4005		}
4006		if (elem->finally_op && opnum < elem->finally_op - 1
4007			&& (dest->opline_num > elem->finally_end || dest->opline_num < elem->try_op)
4008		) {
4009			remove_oplines--;
4010		}
4011	}
4012
4013	opline->opcode = ZEND_JMP;
4014	opline->op1.opline_num = dest->opline_num;
4015	opline->extended_value = 0;
4016	SET_UNUSED(opline->op1);
4017	SET_UNUSED(opline->op2);
4018	SET_UNUSED(opline->result);
4019
4020	ZEND_ASSERT(remove_oplines >= 0);
4021	while (remove_oplines--) {
4022		opline--;
4023		MAKE_NOP(opline);
4024		ZEND_VM_SET_OPCODE_HANDLER(opline);
4025	}
4026}
4027/* }}} */
4028
4029void zend_compile_goto(zend_ast *ast) /* {{{ */
4030{
4031	zend_ast *label_ast = ast->child[0];
4032	znode label_node;
4033	zend_op *opline;
4034	uint32_t opnum_start = get_next_op_number(CG(active_op_array));
4035
4036	zend_compile_expr(&label_node, label_ast);
4037
4038	/* Label resolution and unwinding adjustments happen in pass two. */
4039	zend_handle_loops_and_finally();
4040	opline = zend_emit_op(NULL, ZEND_GOTO, NULL, &label_node);
4041	opline->op1.num = get_next_op_number(CG(active_op_array)) - opnum_start - 1;
4042	opline->extended_value = CG(context).current_brk_cont;
4043}
4044/* }}} */
4045
4046void zend_compile_label(zend_ast *ast) /* {{{ */
4047{
4048	zend_string *label = zend_ast_get_str(ast->child[0]);
4049	zend_label dest;
4050
4051	if (!CG(context).labels) {
4052		ALLOC_HASHTABLE(CG(context).labels);
4053		zend_hash_init(CG(context).labels, 8, NULL, label_ptr_dtor, 0);
4054	}
4055
4056	dest.brk_cont = CG(context).current_brk_cont;
4057	dest.opline_num = get_next_op_number(CG(active_op_array));
4058
4059	if (!zend_hash_add_mem(CG(context).labels, label, &dest, sizeof(zend_label))) {
4060		zend_error_noreturn(E_COMPILE_ERROR, "Label '%s' already defined", ZSTR_VAL(label));
4061	}
4062}
4063/* }}} */
4064
4065void zend_compile_while(zend_ast *ast) /* {{{ */
4066{
4067	zend_ast *cond_ast = ast->child[0];
4068	zend_ast *stmt_ast = ast->child[1];
4069	znode cond_node;
4070	uint32_t opnum_start, opnum_jmp, opnum_cond;
4071
4072	opnum_jmp = zend_emit_jump(0);
4073
4074	zend_begin_loop(ZEND_NOP, NULL);
4075
4076	opnum_start = get_next_op_number(CG(active_op_array));
4077	zend_compile_stmt(stmt_ast);
4078
4079	opnum_cond = get_next_op_number(CG(active_op_array));
4080	zend_update_jump_target(opnum_jmp, opnum_cond);
4081	zend_compile_expr(&cond_node, cond_ast);
4082
4083	zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, opnum_start);
4084
4085	zend_end_loop(opnum_cond, NULL);
4086}
4087/* }}} */
4088
4089void zend_compile_do_while(zend_ast *ast) /* {{{ */
4090{
4091	zend_ast *stmt_ast = ast->child[0];
4092	zend_ast *cond_ast = ast->child[1];
4093
4094	znode cond_node;
4095	uint32_t opnum_start, opnum_cond;
4096
4097	zend_begin_loop(ZEND_NOP, NULL);
4098
4099	opnum_start = get_next_op_number(CG(active_op_array));
4100	zend_compile_stmt(stmt_ast);
4101
4102	opnum_cond = get_next_op_number(CG(active_op_array));
4103	zend_compile_expr(&cond_node, cond_ast);
4104
4105	zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, opnum_start);
4106
4107	zend_end_loop(opnum_cond, NULL);
4108}
4109/* }}} */
4110
4111void zend_compile_expr_list(znode *result, zend_ast *ast) /* {{{ */
4112{
4113	zend_ast_list *list;
4114	uint32_t i;
4115
4116	result->op_type = IS_CONST;
4117	ZVAL_TRUE(&result->u.constant);
4118
4119	if (!ast) {
4120		return;
4121	}
4122
4123	list = zend_ast_get_list(ast);
4124	for (i = 0; i < list->children; ++i) {
4125		zend_ast *expr_ast = list->child[i];
4126
4127		zend_do_free(result);
4128		zend_compile_expr(result, expr_ast);
4129	}
4130}
4131/* }}} */
4132
4133void zend_compile_for(zend_ast *ast) /* {{{ */
4134{
4135	zend_ast *init_ast = ast->child[0];
4136	zend_ast *cond_ast = ast->child[1];
4137	zend_ast *loop_ast = ast->child[2];
4138	zend_ast *stmt_ast = ast->child[3];
4139
4140	znode result;
4141	uint32_t opnum_start, opnum_jmp, opnum_loop;
4142
4143	zend_compile_expr_list(&result, init_ast);
4144	zend_do_free(&result);
4145
4146	opnum_jmp = zend_emit_jump(0);
4147
4148	zend_begin_loop(ZEND_NOP, NULL);
4149
4150	opnum_start = get_next_op_number(CG(active_op_array));
4151	zend_compile_stmt(stmt_ast);
4152
4153	opnum_loop = get_next_op_number(CG(active_op_array));
4154	zend_compile_expr_list(&result, loop_ast);
4155	zend_do_free(&result);
4156
4157	zend_update_jump_target_to_next(opnum_jmp);
4158	zend_compile_expr_list(&result, cond_ast);
4159	zend_do_extended_info();
4160
4161	zend_emit_cond_jump(ZEND_JMPNZ, &result, opnum_start);
4162
4163	zend_end_loop(opnum_loop, NULL);
4164}
4165/* }}} */
4166
4167void zend_compile_foreach(zend_ast *ast) /* {{{ */
4168{
4169	zend_ast *expr_ast = ast->child[0];
4170	zend_ast *value_ast = ast->child[1];
4171	zend_ast *key_ast = ast->child[2];
4172	zend_ast *stmt_ast = ast->child[3];
4173	zend_bool by_ref = value_ast->kind == ZEND_AST_REF;
4174	zend_bool is_variable = zend_is_variable(expr_ast) && !zend_is_call(expr_ast)
4175		&& zend_can_write_to_variable(expr_ast);
4176
4177	znode expr_node, reset_node, value_node, key_node;
4178	zend_op *opline;
4179	uint32_t opnum_reset, opnum_fetch;
4180
4181	if (key_ast) {
4182		if (key_ast->kind == ZEND_AST_REF) {
4183			zend_error_noreturn(E_COMPILE_ERROR, "Key element cannot be a reference");
4184		}
4185		if (key_ast->kind == ZEND_AST_LIST) {
4186			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use list as key element");
4187		}
4188	}
4189
4190	if (by_ref) {
4191		value_ast = value_ast->child[0];
4192	}
4193
4194	if (by_ref && is_variable) {
4195		zend_compile_var(&expr_node, expr_ast, BP_VAR_W);
4196	} else {
4197		zend_compile_expr(&expr_node, expr_ast);
4198	}
4199
4200	if (by_ref) {
4201		zend_separate_if_call_and_write(&expr_node, expr_ast, BP_VAR_W);
4202	}
4203
4204	opnum_reset = get_next_op_number(CG(active_op_array));
4205	opline = zend_emit_op(&reset_node, by_ref ? ZEND_FE_RESET_RW : ZEND_FE_RESET_R, &expr_node, NULL);
4206
4207	zend_begin_loop(ZEND_FE_FREE, &reset_node);
4208
4209	opnum_fetch = get_next_op_number(CG(active_op_array));
4210	opline = zend_emit_op(NULL, by_ref ? ZEND_FE_FETCH_RW : ZEND_FE_FETCH_R, &reset_node, NULL);
4211
4212	if (value_ast->kind == ZEND_AST_VAR &&
4213	    zend_try_compile_cv(&value_node, value_ast) == SUCCESS) {
4214		SET_NODE(opline->op2, &value_node);
4215	} else {
4216		opline->op2_type = IS_VAR;
4217		opline->op2.var = get_temporary_variable(CG(active_op_array));
4218		GET_NODE(&value_node, opline->op2);
4219		if (by_ref) {
4220			zend_emit_assign_ref_znode(value_ast, &value_node);
4221		} else {
4222			zend_emit_assign_znode(value_ast, &value_node);
4223		}
4224	}
4225
4226	if (key_ast) {
4227		opline = &CG(active_op_array)->opcodes[opnum_fetch];
4228		zend_make_tmp_result(&key_node, opline);
4229		zend_emit_assign_znode(key_ast, &key_node);
4230	}
4231
4232	zend_compile_stmt(stmt_ast);
4233
4234	zend_emit_jump(opnum_fetch);
4235
4236	opline = &CG(active_op_array)->opcodes[opnum_reset];
4237	opline->op2.opline_num = get_next_op_number(CG(active_op_array));
4238
4239	opline = &CG(active_op_array)->opcodes[opnum_fetch];
4240	opline->extended_value = get_next_op_number(CG(active_op_array));
4241
4242	zend_end_loop(opnum_fetch, &reset_node);
4243
4244	opline = zend_emit_op(NULL, ZEND_FE_FREE, &reset_node, NULL);
4245}
4246/* }}} */
4247
4248void zend_compile_if(zend_ast *ast) /* {{{ */
4249{
4250	zend_ast_list *list = zend_ast_get_list(ast);
4251	uint32_t i;
4252	uint32_t *jmp_opnums = NULL;
4253
4254	if (list->children > 1) {
4255		jmp_opnums = safe_emalloc(sizeof(uint32_t), list->children - 1, 0);
4256	}
4257
4258	for (i = 0; i < list->children; ++i) {
4259		zend_ast *elem_ast = list->child[i];
4260		zend_ast *cond_ast = elem_ast->child[0];
4261		zend_ast *stmt_ast = elem_ast->child[1];
4262
4263		znode cond_node;
4264		uint32_t opnum_jmpz;
4265		if (cond_ast) {
4266			zend_compile_expr(&cond_node, cond_ast);
4267			opnum_jmpz = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0);
4268		}
4269
4270		zend_compile_stmt(stmt_ast);
4271
4272		if (i != list->children - 1) {
4273			jmp_opnums[i] = zend_emit_jump(0);
4274		}
4275
4276		if (cond_ast) {
4277			zend_update_jump_target_to_next(opnum_jmpz);
4278		}
4279	}
4280
4281	if (list->children > 1) {
4282		for (i = 0; i < list->children - 1; ++i) {
4283			zend_update_jump_target_to_next(jmp_opnums[i]);
4284		}
4285		efree(jmp_opnums);
4286	}
4287}
4288/* }}} */
4289
4290void zend_compile_switch(zend_ast *ast) /* {{{ */
4291{
4292	zend_ast *expr_ast = ast->child[0];
4293	zend_ast_list *cases = zend_ast_get_list(ast->child[1]);
4294
4295	uint32_t i;
4296	zend_bool has_default_case = 0;
4297
4298	znode expr_node, case_node;
4299	zend_op *opline;
4300	uint32_t *jmpnz_opnums = safe_emalloc(sizeof(uint32_t), cases->children, 0);
4301	uint32_t opnum_default_jmp;
4302
4303	zend_compile_expr(&expr_node, expr_ast);
4304
4305	zend_begin_loop(ZEND_FREE, &expr_node);
4306
4307	case_node.op_type = IS_TMP_VAR;
4308	case_node.u.op.var = get_temporary_variable(CG(active_op_array));
4309
4310	for (i = 0; i < cases->children; ++i) {
4311		zend_ast *case_ast = cases->child[i];
4312		zend_ast *cond_ast = case_ast->child[0];
4313		znode cond_node;
4314
4315		if (!cond_ast) {
4316			if (has_default_case) {
4317				CG(zend_lineno) = case_ast->lineno;
4318				zend_error_noreturn(E_COMPILE_ERROR,
4319					"Switch statements may only contain one default clause");
4320			}
4321			has_default_case = 1;
4322			continue;
4323		}
4324
4325		zend_compile_expr(&cond_node, cond_ast);
4326
4327		if (expr_node.op_type == IS_CONST
4328			&& Z_TYPE(expr_node.u.constant) == IS_FALSE) {
4329			jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0);
4330		} else if (expr_node.op_type == IS_CONST
4331			&& Z_TYPE(expr_node.u.constant) == IS_TRUE) {
4332			jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, 0);
4333		} else {
4334			opline = zend_emit_op(NULL, ZEND_CASE, &expr_node, &cond_node);
4335			SET_NODE(opline->result, &case_node);
4336			if (opline->op1_type == IS_CONST) {
4337				zval_copy_ctor(CT_CONSTANT(opline->op1));
4338			}
4339
4340			jmpnz_opnums[i] = zend_emit_cond_jump(ZEND_JMPNZ, &case_node, 0);
4341		}
4342	}
4343
4344	opnum_default_jmp = zend_emit_jump(0);
4345
4346	for (i = 0; i < cases->children; ++i) {
4347		zend_ast *case_ast = cases->child[i];
4348		zend_ast *cond_ast = case_ast->child[0];
4349		zend_ast *stmt_ast = case_ast->child[1];
4350
4351		if (cond_ast) {
4352			zend_update_jump_target_to_next(jmpnz_opnums[i]);
4353		} else {
4354			zend_update_jump_target_to_next(opnum_default_jmp);
4355		}
4356
4357		zend_compile_stmt(stmt_ast);
4358	}
4359
4360	if (!has_default_case) {
4361		zend_update_jump_target_to_next(opnum_default_jmp);
4362	}
4363
4364	zend_end_loop(get_next_op_number(CG(active_op_array)), &expr_node);
4365
4366	if (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) {
4367		/* don't use emit_op() to prevent automatic live-range construction */
4368		opline = get_next_op(CG(active_op_array));
4369		opline->opcode = ZEND_FREE;
4370		SET_NODE(opline->op1, &expr_node);
4371		SET_UNUSED(opline->op2);
4372	} else if (expr_node.op_type == IS_CONST) {
4373		zval_dtor(&expr_node.u.constant);
4374	}
4375
4376	efree(jmpnz_opnums);
4377}
4378/* }}} */
4379
4380void zend_compile_try(zend_ast *ast) /* {{{ */
4381{
4382	zend_ast *try_ast = ast->child[0];
4383	zend_ast_list *catches = zend_ast_get_list(ast->child[1]);
4384	zend_ast *finally_ast = ast->child[2];
4385
4386	uint32_t i;
4387	zend_op *opline;
4388	uint32_t try_catch_offset;
4389	uint32_t *jmp_opnums = safe_emalloc(sizeof(uint32_t), catches->children, 0);
4390
4391	if (catches->children == 0 && !finally_ast) {
4392		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use try without catch or finally");
4393	}
4394
4395	/* label: try { } must not be equal to try { label: } */
4396	if (CG(context).labels) {
4397		zend_label *label;
4398		ZEND_HASH_REVERSE_FOREACH_PTR(CG(context).labels, label) {
4399			if (label->opline_num == get_next_op_number(CG(active_op_array))) {
4400				zend_emit_op(NULL, ZEND_NOP, NULL, NULL);
4401			}
4402			break;
4403		} ZEND_HASH_FOREACH_END();
4404	}
4405
4406	try_catch_offset = zend_add_try_element(get_next_op_number(CG(active_op_array)));
4407
4408	if (finally_ast) {
4409		zend_loop_var fast_call;
4410		if (!(CG(active_op_array)->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK)) {
4411			CG(active_op_array)->fn_flags |= ZEND_ACC_HAS_FINALLY_BLOCK;
4412			CG(context).fast_call_var = get_temporary_variable(CG(active_op_array));
4413		}
4414
4415		/* Push FAST_CALL on unwind stack */
4416		fast_call.opcode = ZEND_FAST_CALL;
4417		fast_call.var_type = IS_TMP_VAR;
4418		fast_call.var_num = CG(context).fast_call_var;
4419		fast_call.u.try_catch_offset = try_catch_offset;
4420		zend_stack_push(&CG(loop_var_stack), &fast_call);
4421	}
4422
4423	zend_compile_stmt(try_ast);
4424
4425	if (catches->children != 0) {
4426		jmp_opnums[0] = zend_emit_jump(0);
4427	}
4428
4429	for (i = 0; i < catches->children; ++i) {
4430		zend_ast *catch_ast = catches->child[i];
4431		zend_ast *class_ast = catch_ast->child[0];
4432		zend_ast *var_ast = catch_ast->child[1];
4433		zend_ast *stmt_ast = catch_ast->child[2];
4434		zval *var_name = zend_ast_get_zval(var_ast);
4435		zend_bool is_last_catch = (i + 1 == catches->children);
4436
4437		uint32_t opnum_catch;
4438
4439		if (!zend_is_const_default_class_ref(class_ast)) {
4440			zend_error_noreturn(E_COMPILE_ERROR, "Bad class name in the catch statement");
4441		}
4442
4443		opnum_catch = get_next_op_number(CG(active_op_array));
4444		if (i == 0) {
4445			CG(active_op_array)->try_catch_array[try_catch_offset].catch_op = opnum_catch;
4446		}
4447
4448		CG(zend_lineno) = catch_ast->lineno;
4449
4450		opline = get_next_op(CG(active_op_array));
4451		opline->opcode = ZEND_CATCH;
4452		opline->op1_type = IS_CONST;
4453		opline->op1.constant = zend_add_class_name_literal(CG(active_op_array),
4454			zend_resolve_class_name_ast(class_ast));
4455
4456		opline->op2_type = IS_CV;
4457		opline->op2.var = lookup_cv(CG(active_op_array), zend_string_copy(Z_STR_P(var_name)));
4458		opline->result.num = is_last_catch;
4459
4460		zend_compile_stmt(stmt_ast);
4461
4462		if (!is_last_catch) {
4463			jmp_opnums[i + 1] = zend_emit_jump(0);
4464		}
4465
4466		opline = &CG(active_op_array)->opcodes[opnum_catch];
4467		if (!is_last_catch) {
4468			opline->extended_value = get_next_op_number(CG(active_op_array));
4469		}
4470	}
4471
4472	for (i = 0; i < catches->children; ++i) {
4473		zend_update_jump_target_to_next(jmp_opnums[i]);
4474	}
4475
4476	if (finally_ast) {
4477		uint32_t opnum_jmp = get_next_op_number(CG(active_op_array)) + 1;
4478
4479		/* Pop FAST_CALL from unwind stack */
4480		zend_stack_del_top(&CG(loop_var_stack));
4481
4482		CG(zend_lineno) = finally_ast->lineno;
4483
4484		opline = zend_emit_op(NULL, ZEND_FAST_CALL, NULL, NULL);
4485		opline->op1.num = try_catch_offset;
4486		opline->result_type = IS_TMP_VAR;
4487		opline->result.var = CG(context).fast_call_var;
4488
4489		zend_emit_op(NULL, ZEND_JMP, NULL, NULL);
4490
4491		CG(context).in_finally++;
4492		zend_compile_stmt(finally_ast);
4493		CG(context).in_finally--;
4494
4495		CG(active_op_array)->try_catch_array[try_catch_offset].finally_op = opnum_jmp + 1;
4496		CG(active_op_array)->try_catch_array[try_catch_offset].finally_end
4497			= get_next_op_number(CG(active_op_array));
4498
4499		opline = zend_emit_op(NULL, ZEND_FAST_RET, NULL, NULL);
4500		opline->op1_type = IS_TMP_VAR;
4501		opline->op1.var = CG(context).fast_call_var;
4502
4503		zend_update_jump_target_to_next(opnum_jmp);
4504	}
4505
4506	efree(jmp_opnums);
4507}
4508/* }}} */
4509
4510/* Encoding declarations must already be handled during parsing */
4511void zend_handle_encoding_declaration(zend_ast *ast) /* {{{ */
4512{
4513	zend_ast_list *declares = zend_ast_get_list(ast);
4514	uint32_t i;
4515	for (i = 0; i < declares->children; ++i) {
4516		zend_ast *declare_ast = declares->child[i];
4517		zend_ast *name_ast = declare_ast->child[0];
4518		zend_ast *value_ast = declare_ast->child[1];
4519		zend_string *name = zend_ast_get_str(name_ast);
4520
4521		if (zend_string_equals_literal_ci(name, "encoding")) {
4522			if (value_ast->kind != ZEND_AST_ZVAL) {
4523				zend_error_noreturn(E_COMPILE_ERROR, "Encoding must be a literal");
4524			}
4525
4526			if (CG(multibyte)) {
4527				zend_string *encoding_name = zval_get_string(zend_ast_get_zval(value_ast));
4528
4529				const zend_encoding *new_encoding, *old_encoding;
4530				zend_encoding_filter old_input_filter;
4531
4532				CG(encoding_declared) = 1;
4533
4534				new_encoding = zend_multibyte_fetch_encoding(ZSTR_VAL(encoding_name));
4535				if (!new_encoding) {
4536					zend_error(E_COMPILE_WARNING, "Unsupported encoding [%s]", ZSTR_VAL(encoding_name));
4537				} else {
4538					old_input_filter = LANG_SCNG(input_filter);
4539					old_encoding = LANG_SCNG(script_encoding);
4540					zend_multibyte_set_filter(new_encoding);
4541
4542					/* need to re-scan if input filter changed */
4543					if (old_input_filter != LANG_SCNG(input_filter) ||
4544						 (old_input_filter && new_encoding != old_encoding)) {
4545						zend_multibyte_yyinput_again(old_input_filter, old_encoding);
4546					}
4547				}
4548
4549				zend_string_release(encoding_name);
4550			} else {
4551				zend_error(E_COMPILE_WARNING, "declare(encoding=...) ignored because "
4552					"Zend multibyte feature is turned off by settings");
4553			}
4554		}
4555	}
4556}
4557/* }}} */
4558
4559static int zend_declare_is_first_statement(zend_ast *ast) /* {{{ */
4560{
4561	uint32_t i = 0;
4562	zend_ast_list *file_ast = zend_ast_get_list(CG(ast));
4563
4564	/* Check to see if this declare is preceeded only by declare statements */
4565	while (i < file_ast->children) {
4566		if (file_ast->child[i] == ast) {
4567			return SUCCESS;
4568		} else if (file_ast->child[i] == NULL) {
4569			/* Empty statements are not allowed prior to a declare */
4570			return FAILURE;
4571		} else if (file_ast->child[i]->kind != ZEND_AST_DECLARE) {
4572			/* declares can only be preceeded by other declares */
4573			return FAILURE;
4574		}
4575		i++;
4576	}
4577	return FAILURE;
4578}
4579/* }}} */
4580
4581void zend_compile_declare(zend_ast *ast) /* {{{ */
4582{
4583	zend_ast_list *declares = zend_ast_get_list(ast->child[0]);
4584	zend_ast *stmt_ast = ast->child[1];
4585	zend_declarables orig_declarables = FC(declarables);
4586	uint32_t i;
4587
4588	for (i = 0; i < declares->children; ++i) {
4589		zend_ast *declare_ast = declares->child[i];
4590		zend_ast *name_ast = declare_ast->child[0];
4591		zend_ast *value_ast = declare_ast->child[1];
4592
4593		zend_string *name = zend_ast_get_str(name_ast);
4594		if (zend_string_equals_literal_ci(name, "ticks")) {
4595			zval value_zv;
4596			zend_const_expr_to_zval(&value_zv, value_ast);
4597			FC(declarables).ticks = zval_get_long(&value_zv);
4598			zval_dtor(&value_zv);
4599		} else if (zend_string_equals_literal_ci(name, "encoding")) {
4600
4601			if (FAILURE == zend_declare_is_first_statement(ast)) {
4602				zend_error_noreturn(E_COMPILE_ERROR, "Encoding declaration pragma must be "
4603					"the very first statement in the script");
4604			}
4605		} else if (zend_string_equals_literal_ci(name, "strict_types")) {
4606			zval value_zv;
4607
4608			if (FAILURE == zend_declare_is_first_statement(ast)) {
4609				zend_error_noreturn(E_COMPILE_ERROR, "strict_types declaration must be "
4610					"the very first statement in the script");
4611			}
4612
4613			if (ast->child[1] != NULL) {
4614				zend_error_noreturn(E_COMPILE_ERROR, "strict_types declaration must not "
4615					"use block mode");
4616			}
4617
4618			zend_const_expr_to_zval(&value_zv, value_ast);
4619
4620			if (Z_TYPE(value_zv) != IS_LONG || (Z_LVAL(value_zv) != 0 && Z_LVAL(value_zv) != 1)) {
4621				zend_error_noreturn(E_COMPILE_ERROR, "strict_types declaration must have 0 or 1 as its value");
4622			}
4623
4624			if (Z_LVAL(value_zv) == 1) {
4625				CG(active_op_array)->fn_flags |= ZEND_ACC_STRICT_TYPES;
4626			}
4627
4628		} else {
4629			zend_error(E_COMPILE_WARNING, "Unsupported declare '%s'", ZSTR_VAL(name));
4630		}
4631	}
4632
4633	if (stmt_ast) {
4634		zend_compile_stmt(stmt_ast);
4635
4636		FC(declarables) = orig_declarables;
4637	}
4638}
4639/* }}} */
4640
4641void zend_compile_stmt_list(zend_ast *ast) /* {{{ */
4642{
4643	zend_ast_list *list = zend_ast_get_list(ast);
4644	uint32_t i;
4645	for (i = 0; i < list->children; ++i) {
4646		zend_compile_stmt(list->child[i]);
4647	}
4648}
4649/* }}} */
4650
4651ZEND_API void zend_set_function_arg_flags(zend_function *func) /* {{{ */
4652{
4653	uint32_t i, n;
4654
4655	func->common.arg_flags[0] = 0;
4656	func->common.arg_flags[1] = 0;
4657	func->common.arg_flags[2] = 0;
4658	if (func->common.arg_info) {
4659		n = MIN(func->common.num_args, MAX_ARG_FLAG_NUM);
4660		i = 0;
4661		while (i < n) {
4662			ZEND_SET_ARG_FLAG(func, i + 1, func->common.arg_info[i].pass_by_reference);
4663			i++;
4664		}
4665		if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_VARIADIC && func->common.arg_info[i].pass_by_reference)) {
4666			uint32_t pass_by_reference = func->common.arg_info[i].pass_by_reference;
4667			while (i < MAX_ARG_FLAG_NUM) {
4668				ZEND_SET_ARG_FLAG(func, i + 1, pass_by_reference);
4669				i++;
4670			}
4671		}
4672	}
4673}
4674/* }}} */
4675
4676static void zend_compile_typename(zend_ast *ast, zend_arg_info *arg_info) /* {{{ */
4677{
4678	if (ast->kind == ZEND_AST_TYPE) {
4679		arg_info->type_hint = ast->attr;
4680	} else {
4681		zend_string *class_name = zend_ast_get_str(ast);
4682		zend_uchar type = zend_lookup_builtin_type_by_name(class_name);
4683
4684		if (type != 0) {
4685			if (ast->attr != ZEND_NAME_NOT_FQ) {
4686				zend_error_noreturn(E_COMPILE_ERROR,
4687					"Scalar type declaration '%s' must be unqualified",
4688					ZSTR_VAL(zend_string_tolower(class_name)));
4689			}
4690			arg_info->type_hint = type;
4691		} else {
4692			uint32_t fetch_type = zend_get_class_fetch_type_ast(ast);
4693			if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
4694				class_name = zend_resolve_class_name_ast(ast);
4695				zend_assert_valid_class_name(class_name);
4696			} else {
4697				zend_ensure_valid_class_fetch_type(fetch_type);
4698				zend_string_addref(class_name);
4699			}
4700
4701			arg_info->type_hint = IS_OBJECT;
4702			arg_info->class_name = class_name;
4703		}
4704	}
4705}
4706/* }}} */
4707
4708void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
4709{
4710	zend_ast_list *list = zend_ast_get_list(ast);
4711	uint32_t i;
4712	zend_op_array *op_array = CG(active_op_array);
4713	zend_arg_info *arg_infos;
4714
4715	if (return_type_ast) {
4716		/* Use op_array->arg_info[-1] for return type */
4717		arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children + 1, 0);
4718		arg_infos->name = NULL;
4719		arg_infos->pass_by_reference = (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
4720		arg_infos->is_variadic = 0;
4721		arg_infos->type_hint = 0;
4722		arg_infos->allow_null = 0;
4723		arg_infos->class_name = NULL;
4724
4725		zend_compile_typename(return_type_ast, arg_infos);
4726
4727		arg_infos++;
4728		op_array->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
4729	} else {
4730		if (list->children == 0) {
4731			return;
4732		}
4733		arg_infos = safe_emalloc(sizeof(zend_arg_info), list->children, 0);
4734	}
4735
4736	for (i = 0; i < list->children; ++i) {
4737		zend_ast *param_ast = list->child[i];
4738		zend_ast *type_ast = param_ast->child[0];
4739		zend_ast *var_ast = param_ast->child[1];
4740		zend_ast *default_ast = param_ast->child[2];
4741		zend_string *name = zend_ast_get_str(var_ast);
4742		zend_bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0;
4743		zend_bool is_variadic = (param_ast->attr & ZEND_PARAM_VARIADIC) != 0;
4744
4745		znode var_node, default_node;
4746		zend_uchar opcode;
4747		zend_op *opline;
4748		zend_arg_info *arg_info;
4749
4750		if (zend_is_auto_global(name)) {
4751			zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign auto-global variable %s",
4752				ZSTR_VAL(name));
4753		}
4754
4755		var_node.op_type = IS_CV;
4756		var_node.u.op.var = lookup_cv(CG(active_op_array), zend_string_copy(name));
4757
4758		if (EX_VAR_TO_NUM(var_node.u.op.var) != i) {
4759			zend_error_noreturn(E_COMPILE_ERROR, "Redefinition of parameter $%s",
4760				ZSTR_VAL(name));
4761		} else if (zend_string_equals_literal(name, "this")) {
4762			if (op_array->scope && (op_array->fn_flags & ZEND_ACC_STATIC) == 0) {
4763				zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
4764			}
4765			op_array->this_var = var_node.u.op.var;
4766		}
4767
4768		if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
4769			zend_error_noreturn(E_COMPILE_ERROR, "Only the last parameter can be variadic");
4770		}
4771
4772		if (is_variadic) {
4773			opcode = ZEND_RECV_VARIADIC;
4774			default_node.op_type = IS_UNUSED;
4775			op_array->fn_flags |= ZEND_ACC_VARIADIC;
4776
4777			if (default_ast) {
4778				zend_error_noreturn(E_COMPILE_ERROR,
4779					"Variadic parameter cannot have a default value");
4780			}
4781		} else if (default_ast) {
4782			/* we cannot substitute constants here or it will break ReflectionParameter::getDefaultValueConstantName() and ReflectionParameter::isDefaultValueConstant() */
4783			uint32_t cops = CG(compiler_options);
4784			CG(compiler_options) |= ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION | ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION;
4785			opcode = ZEND_RECV_INIT;
4786			default_node.op_type = IS_CONST;
4787			zend_const_expr_to_zval(&default_node.u.constant, default_ast);
4788			CG(compiler_options) = cops;
4789		} else {
4790			opcode = ZEND_RECV;
4791			default_node.op_type = IS_UNUSED;
4792			op_array->required_num_args = i + 1;
4793		}
4794
4795		opline = zend_emit_op(NULL, opcode, NULL, &default_node);
4796		SET_NODE(opline->result, &var_node);
4797		opline->op1.num = i + 1;
4798
4799		arg_info = &arg_infos[i];
4800		arg_info->name = zend_string_copy(name);
4801		arg_info->pass_by_reference = is_ref;
4802		arg_info->is_variadic = is_variadic;
4803		arg_info->type_hint = 0;
4804		arg_info->allow_null = 1;
4805		arg_info->class_name = NULL;
4806
4807		if (type_ast) {
4808			zend_bool has_null_default = default_ast
4809				&& (Z_TYPE(default_node.u.constant) == IS_NULL
4810					|| (Z_TYPE(default_node.u.constant) == IS_CONSTANT
4811						&& strcasecmp(Z_STRVAL(default_node.u.constant), "NULL") == 0));
4812
4813			op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
4814			arg_info->allow_null = has_null_default;
4815
4816			zend_compile_typename(type_ast, arg_info);
4817
4818			if (arg_info->type_hint == IS_VOID) {
4819				zend_error_noreturn(E_COMPILE_ERROR, "void cannot be used as a parameter type");
4820			}
4821
4822			if (type_ast->kind == ZEND_AST_TYPE) {
4823				if (arg_info->type_hint == IS_ARRAY) {
4824					if (default_ast && !has_null_default
4825						&& Z_TYPE(default_node.u.constant) != IS_ARRAY
4826						&& !Z_CONSTANT(default_node.u.constant)
4827					) {
4828						zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
4829							"with array type can only be an array or NULL");
4830					}
4831				} else if (arg_info->type_hint == IS_CALLABLE && default_ast) {
4832					if (!has_null_default && !Z_CONSTANT(default_node.u.constant)) {
4833						zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
4834							"with callable type can only be NULL");
4835					}
4836				}
4837			} else {
4838				if (default_ast && !has_null_default && !Z_CONSTANT(default_node.u.constant)) {
4839					if (arg_info->class_name) {
4840						zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
4841							"with a class type can only be NULL");
4842					} else switch (arg_info->type_hint) {
4843						case IS_DOUBLE:
4844							if (Z_TYPE(default_node.u.constant) != IS_DOUBLE && Z_TYPE(default_node.u.constant) != IS_LONG) {
4845								zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
4846									"with a float type can only be float, integer, or NULL");
4847							}
4848							break;
4849
4850						default:
4851							if (!ZEND_SAME_FAKE_TYPE(arg_info->type_hint, Z_TYPE(default_node.u.constant))) {
4852								zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
4853									"with a %s type can only be %s or NULL",
4854									zend_get_type_by_const(arg_info->type_hint), zend_get_type_by_const(arg_info->type_hint));
4855							}
4856							break;
4857					}
4858				}
4859			}
4860
4861			/* Allocate cache slot to speed-up run-time class resolution */
4862			if (opline->opcode == ZEND_RECV_INIT) {
4863				if (arg_info->class_name) {
4864					zend_alloc_cache_slot(opline->op2.constant);
4865				} else {
4866					Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = -1;
4867				}
4868			} else {
4869				if (arg_info->class_name) {
4870					opline->op2.num = op_array->cache_size;
4871					op_array->cache_size += sizeof(void*);
4872				} else {
4873					opline->op2.num = -1;
4874				}
4875			}
4876		} else {
4877			if (opline->opcode == ZEND_RECV_INIT) {
4878				Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = -1;
4879			} else {
4880				opline->op2.num = -1;
4881			}
4882		}
4883	}
4884
4885	/* These are assigned at the end to avoid unitialized memory in case of an error */
4886	op_array->num_args = list->children;
4887	op_array->arg_info = arg_infos;
4888
4889	/* Don't count the variadic argument */
4890	if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
4891		op_array->num_args--;
4892	}
4893	zend_set_function_arg_flags((zend_function*)op_array);
4894}
4895/* }}} */
4896
4897static void zend_compile_closure_binding(znode *closure, zend_ast *uses_ast) /* {{{ */
4898{
4899	zend_ast_list *list = zend_ast_get_list(uses_ast);
4900	uint32_t i;
4901
4902	for (i = 0; i < list->children; ++i) {
4903		zend_ast *var_name_ast = list->child[i];
4904		zend_string *var_name = zend_ast_get_str(var_name_ast);
4905		zend_bool by_ref = var_name_ast->attr;
4906		zend_op *opline;
4907
4908		if (zend_string_equals_literal(var_name, "this")) {
4909			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as lexical variable");
4910		}
4911
4912		if (zend_is_auto_global(var_name)) {
4913			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use auto-global as lexical variable");
4914		}
4915
4916		opline = zend_emit_op(NULL, ZEND_BIND_LEXICAL, closure, NULL);
4917		opline->op2_type = IS_CV;
4918		opline->op2.var = lookup_cv(CG(active_op_array), zend_string_copy(var_name));
4919		opline->extended_value = by_ref;
4920	}
4921}
4922/* }}} */
4923
4924void zend_compile_closure_uses(zend_ast *ast) /* {{{ */
4925{
4926	zend_op_array *op_array = CG(active_op_array);
4927	zend_ast_list *list = zend_ast_get_list(ast);
4928	uint32_t i;
4929
4930	for (i = 0; i < list->children; ++i) {
4931		zend_ast *var_ast = list->child[i];
4932		zend_string *var_name = zend_ast_get_str(var_ast);
4933		zend_bool by_ref = var_ast->attr;
4934		zval zv;
4935		ZVAL_NULL(&zv);
4936
4937		if (op_array->static_variables
4938				&& zend_hash_exists(op_array->static_variables, var_name)) {
4939			zend_error_noreturn(E_COMPILE_ERROR,
4940				"Cannot use variable $%s twice", ZSTR_VAL(var_name));
4941		}
4942
4943		{
4944			int i;
4945			for (i = 0; i < op_array->last_var; i++) {
4946				if (zend_string_equals(op_array->vars[i], var_name)) {
4947					zend_error_noreturn(E_COMPILE_ERROR,
4948						"Cannot use lexical variable $%s as a parameter name", ZSTR_VAL(var_name));
4949				}
4950			}
4951		}
4952
4953		zend_compile_static_var_common(var_ast, &zv, by_ref);
4954	}
4955}
4956/* }}} */
4957
4958void zend_begin_method_decl(zend_op_array *op_array, zend_string *name, zend_bool has_body) /* {{{ */
4959{
4960	zend_class_entry *ce = CG(active_class_entry);
4961	zend_bool in_interface = (ce->ce_flags & ZEND_ACC_INTERFACE) != 0;
4962	zend_bool in_trait = (ce->ce_flags & ZEND_ACC_TRAIT) != 0;
4963	zend_bool is_public = (op_array->fn_flags & ZEND_ACC_PUBLIC) != 0;
4964	zend_bool is_static = (op_array->fn_flags & ZEND_ACC_STATIC) != 0;
4965
4966	zend_string *lcname;
4967
4968	if (in_interface) {
4969		if ((op_array->fn_flags & ZEND_ACC_PPP_MASK) != ZEND_ACC_PUBLIC) {
4970			zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface method "
4971				"%s::%s() must be omitted", ZSTR_VAL(ce->name), ZSTR_VAL(name));
4972		}
4973		op_array->fn_flags |= ZEND_ACC_ABSTRACT;
4974	}
4975
4976	if (op_array->fn_flags & ZEND_ACC_ABSTRACT) {
4977		if (op_array->fn_flags & ZEND_ACC_PRIVATE) {
4978			zend_error_noreturn(E_COMPILE_ERROR, "%s function %s::%s() cannot be declared private",
4979				in_interface ? "Interface" : "Abstract", ZSTR_VAL(ce->name), ZSTR_VAL(name));
4980		}
4981
4982		if (has_body) {
4983			zend_error_noreturn(E_COMPILE_ERROR, "%s function %s::%s() cannot contain body",
4984				in_interface ? "Interface" : "Abstract", ZSTR_VAL(ce->name), ZSTR_VAL(name));
4985		}
4986
4987		ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
4988	} else if (!has_body) {
4989		zend_error_noreturn(E_COMPILE_ERROR, "Non-abstract method %s::%s() must contain body",
4990			ZSTR_VAL(ce->name), ZSTR_VAL(name));
4991	}
4992
4993	op_array->scope = ce;
4994	op_array->function_name = zend_string_copy(name);
4995
4996	lcname = zend_string_tolower(name);
4997	lcname = zend_new_interned_string(lcname);
4998
4999	if (zend_hash_add_ptr(&ce->function_table, lcname, op_array) == NULL) {
5000		zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::%s()",
5001			ZSTR_VAL(ce->name), ZSTR_VAL(name));
5002	}
5003
5004	if (in_interface) {
5005		if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) {
5006			if (!is_public || is_static) {
5007				zend_error(E_WARNING, "The magic method __call() must have "
5008					"public visibility and cannot be static");
5009			}
5010		} else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) {
5011			if (!is_public || !is_static) {
5012				zend_error(E_WARNING, "The magic method __callStatic() must have "
5013					"public visibility and be static");
5014			}
5015		} else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) {
5016			if (!is_public || is_static) {
5017				zend_error(E_WARNING, "The magic method __get() must have "
5018					"public visibility and cannot be static");
5019			}
5020		} else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) {
5021			if (!is_public || is_static) {
5022				zend_error(E_WARNING, "The magic method __set() must have "
5023					"public visibility and cannot be static");
5024			}
5025		} else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) {
5026			if (!is_public || is_static) {
5027				zend_error(E_WARNING, "The magic method __unset() must have "
5028					"public visibility and cannot be static");
5029			}
5030		} else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) {
5031			if (!is_public || is_static) {
5032				zend_error(E_WARNING, "The magic method __isset() must have "
5033					"public visibility and cannot be static");
5034			}
5035		} else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) {
5036			if (!is_public || is_static) {
5037				zend_error(E_WARNING, "The magic method __toString() must have "
5038					"public visibility and cannot be static");
5039			}
5040		} else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) {
5041			if (!is_public || is_static) {
5042				zend_error(E_WARNING, "The magic method __invoke() must have "
5043					"public visibility and cannot be static");
5044			}
5045		} else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) {
5046			if (!is_public || is_static) {
5047				zend_error(E_WARNING, "The magic method __debugInfo() must have "
5048					"public visibility and cannot be static");
5049			}
5050		}
5051	} else {
5052		if (!in_trait && zend_string_equals_ci(lcname, ce->name)) {
5053			if (!ce->constructor) {
5054				ce->constructor = (zend_function *) op_array;
5055			}
5056		} else if (zend_string_equals_literal(lcname, ZEND_CONSTRUCTOR_FUNC_NAME)) {
5057			ce->constructor = (zend_function *) op_array;
5058		} else if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) {
5059			ce->destructor = (zend_function *) op_array;
5060		} else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) {
5061			ce->clone = (zend_function *) op_array;
5062		} else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) {
5063			if (!is_public || is_static) {
5064				zend_error(E_WARNING, "The magic method __call() must have "
5065					"public visibility and cannot be static");
5066			}
5067			ce->__call = (zend_function *) op_array;
5068		} else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) {
5069			if (!is_public || !is_static) {
5070				zend_error(E_WARNING, "The magic method __callStatic() must have "
5071					"public visibility and be static");
5072			}
5073			ce->__callstatic = (zend_function *) op_array;
5074		} else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) {
5075			if (!is_public || is_static) {
5076				zend_error(E_WARNING, "The magic method __get() must have "
5077					"public visibility and cannot be static");
5078			}
5079			ce->__get = (zend_function *) op_array;
5080			ce->ce_flags |= ZEND_ACC_USE_GUARDS;
5081		} else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) {
5082			if (!is_public || is_static) {
5083				zend_error(E_WARNING, "The magic method __set() must have "
5084					"public visibility and cannot be static");
5085			}
5086			ce->__set = (zend_function *) op_array;
5087			ce->ce_flags |= ZEND_ACC_USE_GUARDS;
5088		} else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) {
5089			if (!is_public || is_static) {
5090				zend_error(E_WARNING, "The magic method __unset() must have "
5091					"public visibility and cannot be static");
5092			}
5093			ce->__unset = (zend_function *) op_array;
5094			ce->ce_flags |= ZEND_ACC_USE_GUARDS;
5095		} else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) {
5096			if (!is_public || is_static) {
5097				zend_error(E_WARNING, "The magic method __isset() must have "
5098					"public visibility and cannot be static");
5099			}
5100			ce->__isset = (zend_function *) op_array;
5101			ce->ce_flags |= ZEND_ACC_USE_GUARDS;
5102		} else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) {
5103			if (!is_public || is_static) {
5104				zend_error(E_WARNING, "The magic method __toString() must have "
5105					"public visibility and cannot be static");
5106			}
5107			ce->__tostring = (zend_function *) op_array;
5108		} else if (zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME)) {
5109			if (!is_public || is_static) {
5110				zend_error(E_WARNING, "The magic method __invoke() must have "
5111					"public visibility and cannot be static");
5112			}
5113		} else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) {
5114			if (!is_public || is_static) {
5115				zend_error(E_WARNING, "The magic method __debugInfo() must have "
5116					"public visibility and cannot be static");
5117			}
5118			ce->__debugInfo = (zend_function *) op_array;
5119		} else if (!is_static) {
5120			op_array->fn_flags |= ZEND_ACC_ALLOW_STATIC;
5121		}
5122	}
5123
5124	zend_string_release(lcname);
5125}
5126/* }}} */
5127
5128static void zend_begin_func_decl(znode *result, zend_op_array *op_array, zend_ast_decl *decl) /* {{{ */
5129{
5130	zend_ast *params_ast = decl->child[0];
5131	zend_string *name = decl->name, *lcname, *key;
5132	zend_op *opline;
5133
5134	op_array->function_name = name = zend_prefix_with_ns(name);
5135
5136	lcname = zend_string_tolower(name);
5137
5138	if (FC(imports_function)) {
5139		zend_string *import_name = zend_hash_find_ptr(FC(imports_function), lcname);
5140		if (import_name && !zend_string_equals_ci(lcname, import_name)) {
5141			zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare function %s "
5142				"because the name is already in use", ZSTR_VAL(name));
5143		}
5144	}
5145
5146	if (zend_string_equals_literal(lcname, ZEND_AUTOLOAD_FUNC_NAME)
5147		&& zend_ast_get_list(params_ast)->children != 1
5148	) {
5149		zend_error_noreturn(E_COMPILE_ERROR, "%s() must take exactly 1 argument",
5150			ZEND_AUTOLOAD_FUNC_NAME);
5151	}
5152
5153	key = zend_build_runtime_definition_key(lcname, decl->lex_pos);
5154	zend_hash_update_ptr(CG(function_table), key, op_array);
5155
5156	if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
5157		opline = zend_emit_op_tmp(result, ZEND_DECLARE_LAMBDA_FUNCTION, NULL, NULL);
5158		opline->op1_type = IS_CONST;
5159		LITERAL_STR(opline->op1, key);
5160	} else {
5161		opline = get_next_op(CG(active_op_array));
5162		opline->opcode = ZEND_DECLARE_FUNCTION;
5163		opline->op1_type = IS_CONST;
5164		LITERAL_STR(opline->op1, zend_string_copy(lcname));
5165		/* RTD key is placed after lcname literal in op1 */
5166		zend_add_literal_string(CG(active_op_array), &key);
5167	}
5168
5169	zend_string_release(lcname);
5170}
5171/* }}} */
5172
5173void zend_compile_func_decl(znode *result, zend_ast *ast) /* {{{ */
5174{
5175	zend_ast_decl *decl = (zend_ast_decl *) ast;
5176	zend_ast *params_ast = decl->child[0];
5177	zend_ast *uses_ast = decl->child[1];
5178	zend_ast *stmt_ast = decl->child[2];
5179	zend_ast *return_type_ast = decl->child[3];
5180	zend_bool is_method = decl->kind == ZEND_AST_METHOD;
5181
5182	zend_op_array *orig_op_array = CG(active_op_array);
5183	zend_op_array *op_array = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
5184	zend_oparray_context orig_oparray_context;
5185
5186	init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE);
5187
5188	op_array->fn_flags |= (orig_op_array->fn_flags & ZEND_ACC_STRICT_TYPES);
5189	op_array->fn_flags |= decl->flags;
5190	op_array->line_start = decl->start_lineno;
5191	op_array->line_end = decl->end_lineno;
5192	if (decl->doc_comment) {
5193		op_array->doc_comment = zend_string_copy(decl->doc_comment);
5194	}
5195	if (decl->kind == ZEND_AST_CLOSURE) {
5196		op_array->fn_flags |= ZEND_ACC_CLOSURE;
5197	}
5198
5199	if (is_method) {
5200		zend_bool has_body = stmt_ast != NULL;
5201		zend_begin_method_decl(op_array, decl->name, has_body);
5202	} else {
5203		zend_begin_func_decl(result, op_array, decl);
5204		if (uses_ast) {
5205			zend_compile_closure_binding(result, uses_ast);
5206		}
5207	}
5208
5209	CG(active_op_array) = op_array;
5210
5211	zend_oparray_context_begin(&orig_oparray_context);
5212
5213	if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
5214		zend_op *opline_ext = zend_emit_op(NULL, ZEND_EXT_NOP, NULL, NULL);
5215		opline_ext->lineno = decl->start_lineno;
5216	}
5217
5218	{
5219		/* Push a separator to the loop variable stack */
5220		zend_loop_var dummy_var;
5221		dummy_var.opcode = ZEND_RETURN;
5222
5223		zend_stack_push(&CG(loop_var_stack), (void *) &dummy_var);
5224	}
5225
5226	zend_compile_params(params_ast, return_type_ast);
5227	if (uses_ast) {
5228		zend_compile_closure_uses(uses_ast);
5229	}
5230	zend_compile_stmt(stmt_ast);
5231
5232	if (is_method) {
5233		zend_check_magic_method_implementation(
5234			CG(active_class_entry), (zend_function *) op_array, E_COMPILE_ERROR);
5235	}
5236
5237	/* put the implicit return on the really last line */
5238	CG(zend_lineno) = decl->end_lineno;
5239
5240	zend_do_extended_info();
5241	zend_emit_final_return(0);
5242
5243	pass_two(CG(active_op_array));
5244	zend_oparray_context_end(&orig_oparray_context);
5245
5246	/* Pop the loop variable stack separator */
5247	zend_stack_del_top(&CG(loop_var_stack));
5248
5249	CG(active_op_array) = orig_op_array;
5250}
5251/* }}} */
5252
5253void zend_compile_prop_decl(zend_ast *ast) /* {{{ */
5254{
5255	zend_ast_list *list = zend_ast_get_list(ast);
5256	uint32_t flags = list->attr;
5257	zend_class_entry *ce = CG(active_class_entry);
5258	uint32_t i, children = list->children;
5259
5260	if (ce->ce_flags & ZEND_ACC_INTERFACE) {
5261		zend_error_noreturn(E_COMPILE_ERROR, "Interfaces may not include member variables");
5262	}
5263
5264	if (flags & ZEND_ACC_ABSTRACT) {
5265		zend_error_noreturn(E_COMPILE_ERROR, "Properties cannot be declared abstract");
5266	}
5267
5268	for (i = 0; i < children; ++i) {
5269		zend_ast *prop_ast = list->child[i];
5270		zend_ast *name_ast = prop_ast->child[0];
5271		zend_ast *value_ast = prop_ast->child[1];
5272		zend_ast *doc_comment_ast = prop_ast->child[2];
5273		zend_string *name = zend_ast_get_str(name_ast);
5274		zend_string *doc_comment = NULL;
5275		zval value_zv;
5276
5277		/* Doc comment has been appended as last element in ZEND_AST_PROP_ELEM ast */
5278		if (doc_comment_ast) {
5279			doc_comment = zend_string_copy(zend_ast_get_str(doc_comment_ast));
5280		}
5281
5282		if (flags & ZEND_ACC_FINAL) {
5283			zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare property %s::$%s final, "
5284				"the final modifier is allowed only for methods and classes",
5285				ZSTR_VAL(ce->name), ZSTR_VAL(name));
5286		}
5287
5288		if (zend_hash_exists(&ce->properties_info, name)) {
5289			zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::$%s",
5290				ZSTR_VAL(ce->name), ZSTR_VAL(name));
5291		}
5292
5293		if (value_ast) {
5294			zend_const_expr_to_zval(&value_zv, value_ast);
5295		} else {
5296			ZVAL_NULL(&value_zv);
5297		}
5298
5299		name = zend_new_interned_string_safe(name);
5300		zend_declare_property_ex(ce, name, &value_zv, flags, doc_comment);
5301	}
5302}
5303/* }}} */
5304
5305void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */
5306{
5307	zend_ast_list *list = zend_ast_get_list(ast);
5308	zend_class_entry *ce = CG(active_class_entry);
5309	uint32_t i;
5310
5311	if ((ce->ce_flags & ZEND_ACC_TRAIT) != 0) {
5312		zend_error_noreturn(E_COMPILE_ERROR, "Traits cannot have constants");
5313		return;
5314	}
5315
5316	for (i = 0; i < list->children; ++i) {
5317		zend_ast *const_ast = list->child[i];
5318		zend_ast *name_ast = const_ast->child[0];
5319		zend_ast *value_ast = const_ast->child[1];
5320		zend_ast *doc_comment_ast = const_ast->child[2];
5321		zend_string *name = zend_ast_get_str(name_ast);
5322		zend_string *doc_comment = doc_comment_ast ? zend_string_copy(zend_ast_get_str(doc_comment_ast)) : NULL;
5323		zval value_zv;
5324
5325		if (UNEXPECTED(ast->attr & (ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_FINAL))) {
5326			if (ast->attr & ZEND_ACC_STATIC) {
5327				zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as constant modifier");
5328			} else if (ast->attr & ZEND_ACC_ABSTRACT) {
5329				zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as constant modifier");
5330			} else if (ast->attr & ZEND_ACC_FINAL) {
5331				zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as constant modifier");
5332			}
5333		}
5334
5335		zend_const_expr_to_zval(&value_zv, value_ast);
5336
5337		name = zend_new_interned_string_safe(name);
5338		zend_declare_class_constant_ex(ce, name, &value_zv, ast->attr, doc_comment);
5339	}
5340}
5341/* }}} */
5342
5343static zend_trait_method_reference *zend_compile_method_ref(zend_ast *ast) /* {{{ */
5344{
5345	zend_ast *class_ast = ast->child[0];
5346	zend_ast *method_ast = ast->child[1];
5347
5348	zend_trait_method_reference *method_ref = emalloc(sizeof(zend_trait_method_reference));
5349	method_ref->ce = NULL;
5350	method_ref->method_name = zend_string_copy(zend_ast_get_str(method_ast));
5351
5352	if (class_ast) {
5353		method_ref->class_name = zend_resolve_class_name_ast(class_ast);
5354	} else {
5355		method_ref->class_name = NULL;
5356	}
5357
5358	return method_ref;
5359}
5360/* }}} */
5361
5362static zend_string **zend_compile_name_list(zend_ast *ast) /* {{{ */
5363{
5364	zend_ast_list *list = zend_ast_get_list(ast);
5365	zend_string **names = safe_emalloc(sizeof(zend_string *), list->children + 1, 0);
5366	uint32_t i;
5367
5368	for (i = 0; i < list->children; ++i) {
5369		zend_ast *name_ast = list->child[i];
5370		names[i] = zend_resolve_class_name_ast(name_ast);
5371	}
5372
5373	names[list->children] = NULL;
5374
5375	return names;
5376}
5377/* }}} */
5378
5379static void zend_compile_trait_precedence(zend_ast *ast) /* {{{ */
5380{
5381	zend_ast *method_ref_ast = ast->child[0];
5382	zend_ast *insteadof_ast = ast->child[1];
5383
5384	zend_trait_precedence *precedence = emalloc(sizeof(zend_trait_precedence));
5385	precedence->trait_method = zend_compile_method_ref(method_ref_ast);
5386	precedence->exclude_from_classes
5387		= (void *) zend_compile_name_list(insteadof_ast);
5388
5389	zend_add_to_list(&CG(active_class_entry)->trait_precedences, precedence);
5390}
5391/* }}} */
5392
5393static void zend_compile_trait_alias(zend_ast *ast) /* {{{ */
5394{
5395	zend_ast *method_ref_ast = ast->child[0];
5396	zend_ast *alias_ast = ast->child[1];
5397	uint32_t modifiers = ast->attr;
5398
5399	zend_trait_alias *alias;
5400
5401	if (modifiers == ZEND_ACC_STATIC) {
5402		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as method modifier");
5403	} else if (modifiers == ZEND_ACC_ABSTRACT) {
5404		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as method modifier");
5405	} else if (modifiers == ZEND_ACC_FINAL) {
5406		zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as method modifier");
5407	}
5408
5409	alias = emalloc(sizeof(zend_trait_alias));
5410	alias->trait_method = zend_compile_method_ref(method_ref_ast);
5411	alias->modifiers = modifiers;
5412
5413	if (alias_ast) {
5414		alias->alias = zend_string_copy(zend_ast_get_str(alias_ast));
5415	} else {
5416		alias->alias = NULL;
5417	}
5418
5419	zend_add_to_list(&CG(active_class_entry)->trait_aliases, alias);
5420}
5421/* }}} */
5422
5423void zend_compile_use_trait(zend_ast *ast) /* {{{ */
5424{
5425	zend_ast_list *traits = zend_ast_get_list(ast->child[0]);
5426	zend_ast_list *adaptations = ast->child[1] ? zend_ast_get_list(ast->child[1]) : NULL;
5427	zend_class_entry *ce = CG(active_class_entry);
5428	zend_op *opline;
5429	uint32_t i;
5430
5431	for (i = 0; i < traits->children; ++i) {
5432		zend_ast *trait_ast = traits->child[i];
5433		zend_string *name = zend_ast_get_str(trait_ast);
5434
5435		if (ce->ce_flags & ZEND_ACC_INTERFACE) {
5436			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use traits inside of interfaces. "
5437				"%s is used in %s", ZSTR_VAL(name), ZSTR_VAL(ce->name));
5438		}
5439
5440		switch (zend_get_class_fetch_type(name)) {
5441			case ZEND_FETCH_CLASS_SELF:
5442			case ZEND_FETCH_CLASS_PARENT:
5443			case ZEND_FETCH_CLASS_STATIC:
5444				zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as trait name "
5445					"as it is reserved", ZSTR_VAL(name));
5446				break;
5447		}
5448
5449		opline = get_next_op(CG(active_op_array));
5450		opline->opcode = ZEND_ADD_TRAIT;
5451		SET_NODE(opline->op1, &FC(implementing_class));
5452		opline->op2_type = IS_CONST;
5453		opline->op2.constant = zend_add_class_name_literal(CG(active_op_array),
5454			zend_resolve_class_name_ast(trait_ast));
5455
5456		ce->num_traits++;
5457	}
5458
5459	if (!adaptations) {
5460		return;
5461	}
5462
5463	for (i = 0; i < adaptations->children; ++i) {
5464		zend_ast *adaptation_ast = adaptations->child[i];
5465		switch (adaptation_ast->kind) {
5466			case ZEND_AST_TRAIT_PRECEDENCE:
5467				zend_compile_trait_precedence(adaptation_ast);
5468				break;
5469			case ZEND_AST_TRAIT_ALIAS:
5470				zend_compile_trait_alias(adaptation_ast);
5471				break;
5472			EMPTY_SWITCH_DEFAULT_CASE()
5473		}
5474	}
5475}
5476/* }}} */
5477
5478void zend_compile_implements(znode *class_node, zend_ast *ast) /* {{{ */
5479{
5480	zend_ast_list *list = zend_ast_get_list(ast);
5481	uint32_t i;
5482	for (i = 0; i < list->children; ++i) {
5483		zend_ast *class_ast = list->child[i];
5484		zend_string *name = zend_ast_get_str(class_ast);
5485
5486		zend_op *opline;
5487
5488		if (!zend_is_const_default_class_ref(class_ast)) {
5489			zend_error_noreturn(E_COMPILE_ERROR,
5490				"Cannot use '%s' as interface name as it is reserved", ZSTR_VAL(name));
5491		}
5492
5493		opline = zend_emit_op(NULL, ZEND_ADD_INTERFACE, class_node, NULL);
5494		opline->op2_type = IS_CONST;
5495		opline->op2.constant = zend_add_class_name_literal(CG(active_op_array),
5496			zend_resolve_class_name_ast(class_ast));
5497
5498		CG(active_class_entry)->num_interfaces++;
5499	}
5500}
5501/* }}} */
5502
5503static zend_string *zend_generate_anon_class_name(unsigned char *lex_pos) /* {{{ */
5504{
5505	zend_string *result;
5506	char char_pos_buf[32];
5507	size_t char_pos_len = zend_sprintf(char_pos_buf, "%p", lex_pos);
5508	zend_string *filename = CG(active_op_array)->filename;
5509
5510	/* NULL, name length, filename length, last accepting char position length */
5511	result = zend_string_alloc(sizeof("class@anonymous") + ZSTR_LEN(filename) + char_pos_len, 0);
5512	sprintf(ZSTR_VAL(result), "class@anonymous%c%s%s", '\0', ZSTR_VAL(filename), char_pos_buf);
5513	return zend_new_interned_string(result);
5514}
5515/* }}} */
5516
5517void zend_compile_class_decl(zend_ast *ast) /* {{{ */
5518{
5519	zend_ast_decl *decl = (zend_ast_decl *) ast;
5520	zend_ast *extends_ast = decl->child[0];
5521	zend_ast *implements_ast = decl->child[1];
5522	zend_ast *stmt_ast = decl->child[2];
5523	zend_string *name, *lcname, *import_name = NULL;
5524	zend_class_entry *ce = zend_arena_alloc(&CG(arena), sizeof(zend_class_entry));
5525	zend_op *opline;
5526	znode declare_node, extends_node;
5527
5528	zend_class_entry *original_ce = CG(active_class_entry);
5529	znode original_implementing_class = FC(implementing_class);
5530
5531	if (EXPECTED((decl->flags & ZEND_ACC_ANON_CLASS) == 0)) {
5532		if (CG(active_class_entry)) {
5533			zend_error_noreturn(E_COMPILE_ERROR, "Class declarations may not be nested");
5534		}
5535		name = decl->name;
5536		zend_assert_valid_class_name(name);
5537		lcname = zend_string_tolower(name);
5538		if (FC(current_namespace)) {
5539			name = zend_prefix_with_ns(name);
5540
5541			zend_string_release(lcname);
5542			lcname = zend_string_tolower(name);
5543		} else {
5544			zend_string_addref(name);
5545		}
5546
5547		if (FC(imports)) {
5548			import_name = zend_hash_find_ptr(FC(imports), lcname);
5549		}
5550
5551		if (import_name && !zend_string_equals_ci(lcname, import_name)) {
5552			zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare class %s "
5553					"because the name is already in use", ZSTR_VAL(name));
5554		}
5555
5556		name = zend_new_interned_string(name);
5557	} else {
5558		name = zend_generate_anon_class_name(decl->lex_pos);
5559		lcname = zend_string_tolower(name);
5560	}
5561	lcname = zend_new_interned_string(lcname);
5562
5563	ce->type = ZEND_USER_CLASS;
5564	ce->name = name;
5565	zend_initialize_class_data(ce, 1);
5566
5567	ce->ce_flags |= decl->flags;
5568	ce->info.user.filename = zend_get_compiled_filename();
5569	ce->info.user.line_start = decl->start_lineno;
5570	ce->info.user.line_end = decl->end_lineno;
5571
5572	if (decl->doc_comment) {
5573		ce->info.user.doc_comment = zend_string_copy(decl->doc_comment);
5574	}
5575
5576	if (UNEXPECTED((decl->flags & ZEND_ACC_ANON_CLASS))) {
5577		/* Serialization is not supported for anonymous classes */
5578		ce->serialize = zend_class_serialize_deny;
5579		ce->unserialize = zend_class_unserialize_deny;
5580	}
5581
5582	if (extends_ast) {
5583		if (!zend_is_const_default_class_ref(extends_ast)) {
5584			zend_string *extends_name = zend_ast_get_str(extends_ast);
5585			zend_error_noreturn(E_COMPILE_ERROR,
5586				"Cannot use '%s' as class name as it is reserved", ZSTR_VAL(extends_name));
5587		}
5588
5589		zend_compile_class_ref(&extends_node, extends_ast, 0);
5590	}
5591
5592	opline = get_next_op(CG(active_op_array));
5593	zend_make_var_result(&declare_node, opline);
5594
5595	GET_NODE(&FC(implementing_class), opline->result);
5596
5597	opline->op1_type = IS_CONST;
5598	LITERAL_STR(opline->op1, lcname);
5599
5600	if (decl->flags & ZEND_ACC_ANON_CLASS) {
5601		if (extends_ast) {
5602			opline->opcode = ZEND_DECLARE_ANON_INHERITED_CLASS;
5603			SET_NODE(opline->op2, &extends_node);
5604		} else {
5605			opline->opcode = ZEND_DECLARE_ANON_CLASS;
5606		}
5607
5608		zend_hash_update_ptr(CG(class_table), lcname, ce);
5609	} else {
5610		zend_string *key;
5611
5612		if (extends_ast) {
5613			opline->opcode = ZEND_DECLARE_INHERITED_CLASS;
5614			SET_NODE(opline->op2, &extends_node);
5615		} else {
5616			opline->opcode = ZEND_DECLARE_CLASS;
5617		}
5618
5619		key = zend_build_runtime_definition_key(lcname, decl->lex_pos);
5620		/* RTD key is placed after lcname literal in op1 */
5621		zend_add_literal_string(CG(active_op_array), &key);
5622
5623		zend_hash_update_ptr(CG(class_table), key, ce);
5624	}
5625
5626	CG(active_class_entry) = ce;
5627
5628	if (implements_ast) {
5629		zend_compile_implements(&declare_node, implements_ast);
5630	}
5631
5632	zend_compile_stmt(stmt_ast);
5633
5634	/* Reset lineno for final opcodes and errors */
5635	CG(zend_lineno) = ast->lineno;
5636
5637	if (ce->num_traits == 0) {
5638		/* For traits this check is delayed until after trait binding */
5639		zend_check_deprecated_constructor(ce);
5640	}
5641
5642	if (ce->constructor) {
5643		ce->constructor->common.fn_flags |= ZEND_ACC_CTOR;
5644		if (ce->constructor->common.fn_flags & ZEND_ACC_STATIC) {
5645			zend_error_noreturn(E_COMPILE_ERROR, "Constructor %s::%s() cannot be static",
5646				ZSTR_VAL(ce->name), ZSTR_VAL(ce->constructor->common.function_name));
5647		}
5648		if (ce->constructor->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
5649			zend_error_noreturn(E_COMPILE_ERROR,
5650				"Constructor %s::%s() cannot declare a return type",
5651				ZSTR_VAL(ce->name), ZSTR_VAL(ce->constructor->common.function_name));
5652		}
5653	}
5654	if (ce->destructor) {
5655		ce->destructor->common.fn_flags |= ZEND_ACC_DTOR;
5656		if (ce->destructor->common.fn_flags & ZEND_ACC_STATIC) {
5657			zend_error_noreturn(E_COMPILE_ERROR, "Destructor %s::%s() cannot be static",
5658				ZSTR_VAL(ce->name), ZSTR_VAL(ce->destructor->common.function_name));
5659		} else if (ce->destructor->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
5660			zend_error_noreturn(E_COMPILE_ERROR,
5661				"Destructor %s::%s() cannot declare a return type",
5662				ZSTR_VAL(ce->name), ZSTR_VAL(ce->destructor->common.function_name));
5663		}
5664	}
5665	if (ce->clone) {
5666		ce->clone->common.fn_flags |= ZEND_ACC_CLONE;
5667		if (ce->clone->common.fn_flags & ZEND_ACC_STATIC) {
5668			zend_error_noreturn(E_COMPILE_ERROR, "Clone method %s::%s() cannot be static",
5669				ZSTR_VAL(ce->name), ZSTR_VAL(ce->clone->common.function_name));
5670		} else if (ce->clone->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
5671			zend_error_noreturn(E_COMPILE_ERROR,
5672				"%s::%s() cannot declare a return type",
5673				ZSTR_VAL(ce->name), ZSTR_VAL(ce->clone->common.function_name));
5674		}
5675	}
5676
5677	/* Check for traits and proceed like with interfaces.
5678	 * The only difference will be a combined handling of them in the end.
5679	 * Thus, we need another opcode here. */
5680	if (ce->num_traits > 0) {
5681		ce->traits = NULL;
5682		ce->num_traits = 0;
5683		ce->ce_flags |= ZEND_ACC_IMPLEMENT_TRAITS;
5684
5685		zend_emit_op(NULL, ZEND_BIND_TRAITS, &declare_node, NULL);
5686	}
5687
5688	if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))
5689		&& (extends_ast || ce->num_interfaces > 0)
5690	) {
5691		zend_verify_abstract_class(ce);
5692		if (ce->num_interfaces && !(ce->ce_flags & ZEND_ACC_IMPLEMENT_TRAITS)) {
5693			zend_emit_op(NULL, ZEND_VERIFY_ABSTRACT_CLASS, &declare_node, NULL);
5694		}
5695	}
5696
5697	/* Inherit interfaces; reset number to zero, we need it for above check and
5698	 * will restore it during actual implementation.
5699	 * The ZEND_ACC_IMPLEMENT_INTERFACES flag disables double call to
5700	 * zend_verify_abstract_class() */
5701	if (ce->num_interfaces > 0) {
5702		ce->interfaces = NULL;
5703		ce->num_interfaces = 0;
5704		ce->ce_flags |= ZEND_ACC_IMPLEMENT_INTERFACES;
5705	}
5706
5707	FC(implementing_class) = original_implementing_class;
5708	CG(active_class_entry) = original_ce;
5709}
5710/* }}} */
5711
5712static HashTable *zend_get_import_ht(uint32_t type) /* {{{ */
5713{
5714	switch (type) {
5715		case T_CLASS:
5716			if (!FC(imports)) {
5717				FC(imports) = emalloc(sizeof(HashTable));
5718				zend_hash_init(FC(imports), 8, NULL, str_dtor, 0);
5719			}
5720			return FC(imports);
5721		case T_FUNCTION:
5722			if (!FC(imports_function)) {
5723				FC(imports_function) = emalloc(sizeof(HashTable));
5724				zend_hash_init(FC(imports_function), 8, NULL, str_dtor, 0);
5725			}
5726			return FC(imports_function);
5727		case T_CONST:
5728			if (!FC(imports_const)) {
5729				FC(imports_const) = emalloc(sizeof(HashTable));
5730				zend_hash_init(FC(imports_const), 8, NULL, str_dtor, 0);
5731			}
5732			return FC(imports_const);
5733		EMPTY_SWITCH_DEFAULT_CASE()
5734	}
5735
5736	return NULL;
5737}
5738/* }}} */
5739
5740static char *zend_get_use_type_str(uint32_t type) /* {{{ */
5741{
5742	switch (type) {
5743		case T_CLASS:
5744			return "";
5745		case T_FUNCTION:
5746			return " function";
5747		case T_CONST:
5748			return " const";
5749		EMPTY_SWITCH_DEFAULT_CASE()
5750	}
5751
5752	return " unknown";
5753}
5754/* }}} */
5755
5756static void zend_check_already_in_use(uint32_t type, zend_string *old_name, zend_string *new_name, zend_string *check_name) /* {{{ */
5757{
5758	if (zend_string_equals_ci(old_name, check_name)) {
5759		return;
5760	}
5761
5762	zend_error_noreturn(E_COMPILE_ERROR, "Cannot use%s %s as %s because the name "
5763		"is already in use", zend_get_use_type_str(type), ZSTR_VAL(old_name), ZSTR_VAL(new_name));
5764}
5765/* }}} */
5766
5767void zend_compile_use(zend_ast *ast) /* {{{ */
5768{
5769	zend_ast_list *list = zend_ast_get_list(ast);
5770	uint32_t i;
5771	zend_string *current_ns = FC(current_namespace);
5772	uint32_t type = ast->attr;
5773	HashTable *current_import = zend_get_import_ht(type);
5774	zend_bool case_sensitive = type == T_CONST;
5775
5776	for (i = 0; i < list->children; ++i) {
5777		zend_ast *use_ast = list->child[i];
5778		zend_ast *old_name_ast = use_ast->child[0];
5779		zend_ast *new_name_ast = use_ast->child[1];
5780		zend_string *old_name = zend_ast_get_str(old_name_ast);
5781		zend_string *new_name, *lookup_name;
5782
5783		if (new_name_ast) {
5784			new_name = zend_string_copy(zend_ast_get_str(new_name_ast));
5785		} else {
5786			const char *unqualified_name;
5787			size_t unqualified_name_len;
5788			if (zend_get_unqualified_name(old_name, &unqualified_name, &unqualified_name_len)) {
5789				/* The form "use A\B" is equivalent to "use A\B as B" */
5790				new_name = zend_string_init(unqualified_name, unqualified_name_len, 0);
5791			} else {
5792				new_name = zend_string_copy(old_name);
5793
5794				if (!current_ns) {
5795					if (type == T_CLASS && zend_string_equals_literal(new_name, "strict")) {
5796						zend_error_noreturn(E_COMPILE_ERROR,
5797							"You seem to be trying to use a different language...");
5798					}
5799
5800					zend_error(E_WARNING, "The use statement with non-compound name '%s' "
5801						"has no effect", ZSTR_VAL(new_name));
5802				}
5803			}
5804		}
5805
5806		if (case_sensitive) {
5807			lookup_name = zend_string_copy(new_name);
5808		} else {
5809			lookup_name = zend_string_tolower(new_name);
5810		}
5811
5812		if (type == T_CLASS && zend_is_reserved_class_name(new_name)) {
5813			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use %s as %s because '%s' "
5814				"is a special class name", ZSTR_VAL(old_name), ZSTR_VAL(new_name), ZSTR_VAL(new_name));
5815		}
5816
5817		if (current_ns) {
5818			zend_string *ns_name = zend_string_alloc(ZSTR_LEN(current_ns) + 1 + ZSTR_LEN(new_name), 0);
5819			zend_str_tolower_copy(ZSTR_VAL(ns_name), ZSTR_VAL(current_ns), ZSTR_LEN(current_ns));
5820			ZSTR_VAL(ns_name)[ZSTR_LEN(current_ns)] = '\\';
5821			memcpy(ZSTR_VAL(ns_name) + ZSTR_LEN(current_ns) + 1, ZSTR_VAL(lookup_name), ZSTR_LEN(lookup_name));
5822
5823			if (zend_hash_exists(CG(class_table), ns_name)) {
5824				zend_check_already_in_use(type, old_name, new_name, ns_name);
5825			}
5826
5827			zend_string_free(ns_name);
5828		} else {
5829			switch (type) {
5830				case T_CLASS:
5831				{
5832					zend_class_entry *ce = zend_hash_find_ptr(CG(class_table), lookup_name);
5833					if (ce && ce->type == ZEND_USER_CLASS
5834						&& ce->info.user.filename == CG(compiled_filename)
5835					) {
5836						zend_check_already_in_use(type, old_name, new_name, lookup_name);
5837					}
5838					break;
5839				}
5840				case T_FUNCTION:
5841				{
5842					zend_function *fn = zend_hash_find_ptr(CG(function_table), lookup_name);
5843					if (fn && fn->type == ZEND_USER_FUNCTION
5844						&& fn->op_array.filename == CG(compiled_filename)
5845					) {
5846						zend_check_already_in_use(type, old_name, new_name, lookup_name);
5847					}
5848					break;
5849				}
5850				case T_CONST:
5851				{
5852					zend_string *filename = zend_hash_find_ptr(&CG(const_filenames), lookup_name);
5853					if (filename && filename == CG(compiled_filename)) {
5854						zend_check_already_in_use(type, old_name, new_name, lookup_name);
5855					}
5856					break;
5857				}
5858				EMPTY_SWITCH_DEFAULT_CASE()
5859			}
5860		}
5861
5862		zend_string_addref(old_name);
5863		if (!zend_hash_add_ptr(current_import, lookup_name, old_name)) {
5864			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use%s %s as %s because the name "
5865				"is already in use", zend_get_use_type_str(type), ZSTR_VAL(old_name), ZSTR_VAL(new_name));
5866		}
5867
5868		zend_string_release(lookup_name);
5869		zend_string_release(new_name);
5870	}
5871}
5872/* }}} */
5873
5874void zend_compile_group_use(zend_ast *ast) /* {{{ */
5875{
5876	uint32_t i;
5877	zend_string *ns = zend_ast_get_str(ast->child[0]);
5878	zend_ast_list *list = zend_ast_get_list(ast->child[1]);
5879
5880	for (i = 0; i < list->children; i++) {
5881		zend_ast *inline_use, *use = list->child[i];
5882		zval *name_zval = zend_ast_get_zval(use->child[0]);
5883		zend_string *name = Z_STR_P(name_zval);
5884		zend_string *compound_ns = zend_concat_names(ZSTR_VAL(ns), ZSTR_LEN(ns), ZSTR_VAL(name), ZSTR_LEN(name));
5885		zend_string_release(name);
5886		ZVAL_STR(name_zval, compound_ns);
5887		inline_use = zend_ast_create_list(1, ZEND_AST_USE, use);
5888		inline_use->attr = ast->attr ? ast->attr : use->attr;
5889		zend_compile_use(inline_use);
5890	}
5891}
5892/* }}} */
5893
5894
5895void zend_compile_const_decl(zend_ast *ast) /* {{{ */
5896{
5897	zend_ast_list *list = zend_ast_get_list(ast);
5898	uint32_t i;
5899	for (i = 0; i < list->children; ++i) {
5900		zend_ast *const_ast = list->child[i];
5901		zend_ast *name_ast = const_ast->child[0];
5902		zend_ast *value_ast = const_ast->child[1];
5903		zend_string *name = zend_ast_get_str(name_ast);
5904
5905		zend_string *import_name;
5906		znode name_node, value_node;
5907		zval *value_zv = &value_node.u.constant;
5908
5909		value_node.op_type = IS_CONST;
5910		zend_const_expr_to_zval(value_zv, value_ast);
5911
5912		if (zend_lookup_reserved_const(ZSTR_VAL(name), ZSTR_LEN(name))) {
5913			zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare constant '%s'", ZSTR_VAL(name));
5914		}
5915
5916		name = zend_prefix_with_ns(name);
5917		name = zend_new_interned_string(name);
5918
5919		if (FC(imports_const)
5920			&& (import_name = zend_hash_find_ptr(FC(imports_const), name))
5921		) {
5922			if (!zend_string_equals(import_name, name)) {
5923				zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare const %s because "
5924					"the name is already in use", ZSTR_VAL(name));
5925			}
5926		}
5927
5928		name_node.op_type = IS_CONST;
5929		ZVAL_STR(&name_node.u.constant, name);
5930
5931		zend_emit_op(NULL, ZEND_DECLARE_CONST, &name_node, &value_node);
5932
5933		zend_hash_add_ptr(&CG(const_filenames), name, CG(compiled_filename));
5934	}
5935}
5936/* }}}*/
5937
5938void zend_compile_namespace(zend_ast *ast) /* {{{ */
5939{
5940	zend_ast *name_ast = ast->child[0];
5941	zend_ast *stmt_ast = ast->child[1];
5942	zend_string *name;
5943	zend_bool with_bracket = stmt_ast != NULL;
5944
5945	/* handle mixed syntax declaration or nested namespaces */
5946	if (!FC(has_bracketed_namespaces)) {
5947		if (FC(current_namespace)) {
5948			/* previous namespace declarations were unbracketed */
5949			if (with_bracket) {
5950				zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations "
5951					"with unbracketed namespace declarations");
5952			}
5953		}
5954	} else {
5955		/* previous namespace declarations were bracketed */
5956		if (!with_bracket) {
5957			zend_error_noreturn(E_COMPILE_ERROR, "Cannot mix bracketed namespace declarations "
5958				"with unbracketed namespace declarations");
5959		} else if (FC(current_namespace) || FC(in_namespace)) {
5960			zend_error_noreturn(E_COMPILE_ERROR, "Namespace declarations cannot be nested");
5961		}
5962	}
5963
5964	if (((!with_bracket && !FC(current_namespace))
5965		 || (with_bracket && !FC(has_bracketed_namespaces))) && CG(active_op_array)->last > 0
5966	) {
5967		/* ignore ZEND_EXT_STMT and ZEND_TICKS */
5968		uint32_t num = CG(active_op_array)->last;
5969		while (num > 0 &&
5970		       (CG(active_op_array)->opcodes[num-1].opcode == ZEND_EXT_STMT ||
5971		        CG(active_op_array)->opcodes[num-1].opcode == ZEND_TICKS)) {
5972			--num;
5973		}
5974		if (num > 0) {
5975			zend_error_noreturn(E_COMPILE_ERROR, "Namespace declaration statement has to be "
5976				"the very first statement or after any declare call in the script");
5977		}
5978	}
5979
5980	if (FC(current_namespace)) {
5981		zend_string_release(FC(current_namespace));
5982	}
5983
5984	if (name_ast) {
5985		name = zend_ast_get_str(name_ast);
5986
5987		if (ZEND_FETCH_CLASS_DEFAULT != zend_get_class_fetch_type(name)) {
5988			zend_error_noreturn(E_COMPILE_ERROR, "Cannot use '%s' as namespace name", ZSTR_VAL(name));
5989		}
5990
5991		FC(current_namespace) = zend_string_copy(name);
5992	} else {
5993		FC(current_namespace) = NULL;
5994	}
5995
5996	zend_reset_import_tables();
5997
5998	FC(in_namespace) = 1;
5999	if (with_bracket) {
6000		FC(has_bracketed_namespaces) = 1;
6001	}
6002
6003	if (stmt_ast) {
6004		zend_compile_top_stmt(stmt_ast);
6005		zend_end_namespace();
6006	}
6007}
6008/* }}} */
6009
6010void zend_compile_halt_compiler(zend_ast *ast) /* {{{ */
6011{
6012	zend_ast *offset_ast = ast->child[0];
6013	zend_long offset = Z_LVAL_P(zend_ast_get_zval(offset_ast));
6014
6015	zend_string *filename, *name;
6016	const char const_name[] = "__COMPILER_HALT_OFFSET__";
6017
6018	if (FC(has_bracketed_namespaces) && FC(in_namespace)) {
6019		zend_error_noreturn(E_COMPILE_ERROR,
6020			"__HALT_COMPILER() can only be used from the outermost scope");
6021	}
6022
6023	filename = zend_get_compiled_filename();
6024	name = zend_mangle_property_name(const_name, sizeof(const_name) - 1,
6025		ZSTR_VAL(filename), ZSTR_LEN(filename), 0);
6026
6027	zend_register_long_constant(ZSTR_VAL(name), ZSTR_LEN(name), offset, CONST_CS, 0);
6028	zend_string_release(name);
6029}
6030/* }}} */
6031
6032static zend_bool zend_try_ct_eval_magic_const(zval *zv, zend_ast *ast) /* {{{ */
6033{
6034	zend_op_array *op_array = CG(active_op_array);
6035	zend_class_entry *ce = CG(active_class_entry);
6036
6037	switch (ast->attr) {
6038		case T_LINE:
6039			ZVAL_LONG(zv, ast->lineno);
6040			break;
6041		case T_FILE:
6042			ZVAL_STR_COPY(zv, CG(compiled_filename));
6043			break;
6044		case T_DIR:
6045		{
6046			zend_string *filename = CG(compiled_filename);
6047			zend_string *dirname = zend_string_init(ZSTR_VAL(filename), ZSTR_LEN(filename), 0);
6048			zend_dirname(ZSTR_VAL(dirname), ZSTR_LEN(dirname));
6049
6050			if (strcmp(ZSTR_VAL(dirname), ".") == 0) {
6051				dirname = zend_string_extend(dirname, MAXPATHLEN, 0);
6052#if HAVE_GETCWD
6053				ZEND_IGNORE_VALUE(VCWD_GETCWD(ZSTR_VAL(dirname), MAXPATHLEN));
6054#elif HAVE_GETWD
6055				ZEND_IGNORE_VALUE(VCWD_GETWD(ZSTR_VAL(dirname)));
6056#endif
6057			}
6058
6059			ZSTR_LEN(dirname) = strlen(ZSTR_VAL(dirname));
6060			ZVAL_STR(zv, dirname);
6061			break;
6062		}
6063		case T_FUNC_C:
6064			if (op_array && op_array->function_name) {
6065				ZVAL_STR_COPY(zv, op_array->function_name);
6066			} else {
6067				ZVAL_EMPTY_STRING(zv);
6068			}
6069			break;
6070		case T_METHOD_C:
6071			if ((op_array && !op_array->scope && op_array->function_name) || (op_array->fn_flags & ZEND_ACC_CLOSURE)) {
6072				ZVAL_STR_COPY(zv, op_array->function_name);
6073			} else if (ce) {
6074				if (op_array && op_array->function_name) {
6075					ZVAL_NEW_STR(zv, zend_concat3(ZSTR_VAL(ce->name), ZSTR_LEN(ce->name), "::", 2,
6076						ZSTR_VAL(op_array->function_name), ZSTR_LEN(op_array->function_name)));
6077				} else {
6078					ZVAL_STR_COPY(zv, ce->name);
6079				}
6080			} else if (op_array && op_array->function_name) {
6081				ZVAL_STR_COPY(zv, op_array->function_name);
6082			} else {
6083				ZVAL_EMPTY_STRING(zv);
6084			}
6085			break;
6086		case T_CLASS_C:
6087			if (ce) {
6088				if ((ce->ce_flags & ZEND_ACC_TRAIT) != 0) {
6089					return 0;
6090				} else {
6091					ZVAL_STR_COPY(zv, ce->name);
6092				}
6093			} else {
6094				ZVAL_EMPTY_STRING(zv);
6095			}
6096			break;
6097		case T_TRAIT_C:
6098			if (ce && (ce->ce_flags & ZEND_ACC_TRAIT) != 0) {
6099				ZVAL_STR_COPY(zv, ce->name);
6100			} else {
6101				ZVAL_EMPTY_STRING(zv);
6102			}
6103			break;
6104		case T_NS_C:
6105			if (FC(current_namespace)) {
6106				ZVAL_STR_COPY(zv, FC(current_namespace));
6107			} else {
6108				ZVAL_EMPTY_STRING(zv);
6109			}
6110			break;
6111		EMPTY_SWITCH_DEFAULT_CASE()
6112	}
6113
6114	return 1;
6115}
6116/* }}} */
6117
6118static inline zend_bool zend_try_ct_eval_binary_op(zval *result, uint32_t opcode, zval *op1, zval *op2) /* {{{ */
6119{
6120	binary_op_type fn = get_binary_op(opcode);
6121
6122	/* don't evaluate division by zero at compile-time */
6123	if ((opcode == ZEND_DIV || opcode == ZEND_MOD) &&
6124	    zval_get_long(op2) == 0) {
6125		return 0;
6126	} else if ((opcode == ZEND_SL || opcode == ZEND_SR) &&
6127	    zval_get_long(op2) < 0) {
6128		return 0;
6129	}
6130
6131	fn(result, op1, op2);
6132	return 1;
6133}
6134/* }}} */
6135
6136static inline void zend_ct_eval_unary_op(zval *result, uint32_t opcode, zval *op) /* {{{ */
6137{
6138	unary_op_type fn = get_unary_op(opcode);
6139	fn(result, op);
6140}
6141/* }}} */
6142
6143static inline void zend_ct_eval_unary_pm(zval *result, zend_ast_kind kind, zval *op) /* {{{ */
6144{
6145	zval left;
6146	ZVAL_LONG(&left, (kind == ZEND_AST_UNARY_PLUS) ? 1 : -1);
6147	mul_function(result, &left, op);
6148}
6149/* }}} */
6150
6151static inline void zend_ct_eval_greater(zval *result, zend_ast_kind kind, zval *op1, zval *op2) /* {{{ */
6152{
6153	binary_op_type fn = kind == ZEND_AST_GREATER
6154		? is_smaller_function : is_smaller_or_equal_function;
6155	fn(result, op2, op1);
6156}
6157/* }}} */
6158
6159static zend_bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */
6160{
6161	zend_ast_list *list = zend_ast_get_list(ast);
6162	uint32_t i;
6163	zend_bool is_constant = 1;
6164
6165	/* First ensure that *all* child nodes are constant and by-val */
6166	for (i = 0; i < list->children; ++i) {
6167		zend_ast *elem_ast = list->child[i];
6168		zend_bool by_ref = elem_ast->attr;
6169		zend_eval_const_expr(&elem_ast->child[0]);
6170		zend_eval_const_expr(&elem_ast->child[1]);
6171
6172		if (by_ref || elem_ast->child[0]->kind != ZEND_AST_ZVAL
6173			|| (elem_ast->child[1] && elem_ast->child[1]->kind != ZEND_AST_ZVAL)
6174		) {
6175			is_constant = 0;
6176		}
6177	}
6178
6179	if (!is_constant) {
6180		return 0;
6181	}
6182
6183	array_init_size(result, list->children);
6184	for (i = 0; i < list->children; ++i) {
6185		zend_ast *elem_ast = list->child[i];
6186		zend_ast *value_ast = elem_ast->child[0];
6187		zend_ast *key_ast = elem_ast->child[1];
6188
6189		zval *value = zend_ast_get_zval(value_ast);
6190		if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value);
6191
6192		if (key_ast) {
6193			zval *key = zend_ast_get_zval(key_ast);
6194			switch (Z_TYPE_P(key)) {
6195				case IS_LONG:
6196					zend_hash_index_update(Z_ARRVAL_P(result), Z_LVAL_P(key), value);
6197					break;
6198				case IS_STRING:
6199					zend_symtable_update(Z_ARRVAL_P(result), Z_STR_P(key), value);
6200					break;
6201				case IS_DOUBLE:
6202					zend_hash_index_update(Z_ARRVAL_P(result),
6203						zend_dval_to_lval(Z_DVAL_P(key)), value);
6204					break;
6205				case IS_FALSE:
6206					zend_hash_index_update(Z_ARRVAL_P(result), 0, value);
6207					break;
6208				case IS_TRUE:
6209					zend_hash_index_update(Z_ARRVAL_P(result), 1, value);
6210					break;
6211				case IS_NULL:
6212					zend_hash_update(Z_ARRVAL_P(result), ZSTR_EMPTY_ALLOC(), value);
6213					break;
6214				default:
6215					zend_error_noreturn(E_COMPILE_ERROR, "Illegal offset type");
6216					break;
6217			}
6218		} else {
6219			zend_hash_next_index_insert(Z_ARRVAL_P(result), value);
6220		}
6221	}
6222
6223	return 1;
6224}
6225/* }}} */
6226
6227void zend_compile_binary_op(znode *result, zend_ast *ast) /* {{{ */
6228{
6229	zend_ast *left_ast = ast->child[0];
6230	zend_ast *right_ast = ast->child[1];
6231	uint32_t opcode = ast->attr;
6232
6233	znode left_node, right_node;
6234	zend_compile_expr(&left_node, left_ast);
6235	zend_compile_expr(&right_node, right_ast);
6236
6237	if (left_node.op_type == IS_CONST && right_node.op_type == IS_CONST) {
6238		if (zend_try_ct_eval_binary_op(&result->u.constant, opcode,
6239				&left_node.u.constant, &right_node.u.constant)
6240		) {
6241			result->op_type = IS_CONST;
6242			zval_ptr_dtor(&left_node.u.constant);
6243			zval_ptr_dtor(&right_node.u.constant);
6244			return;
6245		}
6246	}
6247
6248	do {
6249		if (opcode == ZEND_IS_EQUAL || opcode == ZEND_IS_NOT_EQUAL) {
6250			if (left_node.op_type == IS_CONST) {
6251				if (Z_TYPE(left_node.u.constant) == IS_FALSE) {
6252					opcode = (opcode == ZEND_IS_NOT_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
6253					zend_emit_op_tmp(result, opcode, &right_node, NULL);
6254					break;
6255				} else if (Z_TYPE(left_node.u.constant) == IS_TRUE) {
6256					opcode = (opcode == ZEND_IS_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
6257					zend_emit_op_tmp(result, opcode, &right_node, NULL);
6258					break;
6259				}
6260			} else if (right_node.op_type == IS_CONST) {
6261				if (Z_TYPE(right_node.u.constant) == IS_FALSE) {
6262					opcode = (opcode == ZEND_IS_NOT_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
6263					zend_emit_op_tmp(result, opcode, &left_node, NULL);
6264					break;
6265				} else if (Z_TYPE(right_node.u.constant) == IS_TRUE) {
6266					opcode = (opcode == ZEND_IS_EQUAL) ? ZEND_BOOL : ZEND_BOOL_NOT;
6267					zend_emit_op_tmp(result, opcode, &left_node, NULL);
6268					break;
6269				}
6270			}
6271		}
6272		if (opcode == ZEND_CONCAT) {
6273			/* convert constant operands to strings at compile-time */
6274			if (left_node.op_type == IS_CONST) {
6275				convert_to_string(&left_node.u.constant);
6276			}
6277			if (right_node.op_type == IS_CONST) {
6278				convert_to_string(&right_node.u.constant);
6279			}
6280		}
6281		zend_emit_op_tmp(result, opcode, &left_node, &right_node);
6282	} while (0);
6283}
6284/* }}} */
6285
6286/* We do not use zend_compile_binary_op for this because we want to retain the left-to-right
6287 * evaluation order. */
6288void zend_compile_greater(znode *result, zend_ast *ast) /* {{{ */
6289{
6290	zend_ast *left_ast = ast->child[0];
6291	zend_ast *right_ast = ast->child[1];
6292	znode left_node, right_node;
6293
6294	ZEND_ASSERT(ast->kind == ZEND_AST_GREATER || ast->kind == ZEND_AST_GREATER_EQUAL);
6295
6296	zend_compile_expr(&left_node, left_ast);
6297	zend_compile_expr(&right_node, right_ast);
6298
6299	if (left_node.op_type == IS_CONST && right_node.op_type == IS_CONST) {
6300		result->op_type = IS_CONST;
6301		zend_ct_eval_greater(&result->u.constant, ast->kind,
6302			&left_node.u.constant, &right_node.u.constant);
6303		zval_ptr_dtor(&left_node.u.constant);
6304		zval_ptr_dtor(&right_node.u.constant);
6305		return;
6306	}
6307
6308	zend_emit_op_tmp(result,
6309		ast->kind == ZEND_AST_GREATER ? ZEND_IS_SMALLER : ZEND_IS_SMALLER_OR_EQUAL,
6310		&right_node, &left_node);
6311}
6312/* }}} */
6313
6314void zend_compile_unary_op(znode *result, zend_ast *ast) /* {{{ */
6315{
6316	zend_ast *expr_ast = ast->child[0];
6317	uint32_t opcode = ast->attr;
6318
6319	znode expr_node;
6320	zend_compile_expr(&expr_node, expr_ast);
6321
6322	if (expr_node.op_type == IS_CONST) {
6323		result->op_type = IS_CONST;
6324		zend_ct_eval_unary_op(&result->u.constant, opcode,
6325			&expr_node.u.constant);
6326		zval_ptr_dtor(&expr_node.u.constant);
6327		return;
6328	}
6329
6330	zend_emit_op_tmp(result, opcode, &expr_node, NULL);
6331}
6332/* }}} */
6333
6334void zend_compile_unary_pm(znode *result, zend_ast *ast) /* {{{ */
6335{
6336	zend_ast *expr_ast = ast->child[0];
6337	znode expr_node;
6338	znode lefthand_node;
6339
6340	ZEND_ASSERT(ast->kind == ZEND_AST_UNARY_PLUS || ast->kind == ZEND_AST_UNARY_MINUS);
6341
6342	zend_compile_expr(&expr_node, expr_ast);
6343
6344	if (expr_node.op_type == IS_CONST) {
6345		result->op_type = IS_CONST;
6346		zend_ct_eval_unary_pm(&result->u.constant, ast->kind, &expr_node.u.constant);
6347		zval_ptr_dtor(&expr_node.u.constant);
6348		return;
6349	}
6350
6351	lefthand_node.op_type = IS_CONST;
6352	ZVAL_LONG(&lefthand_node.u.constant, (ast->kind == ZEND_AST_UNARY_PLUS) ? 1 : -1);
6353	zend_emit_op_tmp(result, ZEND_MUL, &lefthand_node, &expr_node);
6354}
6355/* }}} */
6356
6357void zend_compile_short_circuiting(znode *result, zend_ast *ast) /* {{{ */
6358{
6359	zend_ast *left_ast = ast->child[0];
6360	zend_ast *right_ast = ast->child[1];
6361
6362	znode left_node, right_node;
6363	zend_op *opline_jmpz, *opline_bool;
6364	uint32_t opnum_jmpz;
6365
6366	ZEND_ASSERT(ast->kind == ZEND_AST_AND || ast->kind == ZEND_AST_OR);
6367
6368	zend_compile_expr(&left_node, left_ast);
6369
6370	if (left_node.op_type == IS_CONST) {
6371		if ((ast->kind == ZEND_AST_AND && !zend_is_true(&left_node.u.constant))
6372		 || (ast->kind == ZEND_AST_OR && zend_is_true(&left_node.u.constant))) {
6373			result->op_type = IS_CONST;
6374			ZVAL_BOOL(&result->u.constant, zend_is_true(&left_node.u.constant));
6375		} else {
6376			zend_compile_expr(&right_node, right_ast);
6377
6378			if (right_node.op_type == IS_CONST) {
6379				result->op_type = IS_CONST;
6380				ZVAL_BOOL(&result->u.constant, zend_is_true(&right_node.u.constant));
6381
6382				zval_ptr_dtor(&right_node.u.constant);
6383			} else {
6384				zend_emit_op(result, ZEND_BOOL, &right_node, NULL);
6385			}
6386		}
6387
6388		zval_ptr_dtor(&left_node.u.constant);
6389		return;
6390	}
6391
6392	opnum_jmpz = get_next_op_number(CG(active_op_array));
6393	opline_jmpz = zend_emit_op(NULL, ast->kind == ZEND_AST_AND ? ZEND_JMPZ_EX : ZEND_JMPNZ_EX,
6394		&left_node, NULL);
6395
6396	if (left_node.op_type == IS_TMP_VAR) {
6397		SET_NODE(opline_jmpz->result, &left_node);
6398	} else {
6399		opline_jmpz->result.var = get_temporary_variable(CG(active_op_array));
6400		opline_jmpz->result_type = IS_TMP_VAR;
6401	}
6402
6403	GET_NODE(result, opline_jmpz->result);
6404	zend_compile_expr(&right_node, right_ast);
6405
6406	opline_bool = zend_emit_op(NULL, ZEND_BOOL, &right_node, NULL);
6407	SET_NODE(opline_bool->result, result);
6408
6409	zend_update_jump_target_to_next(opnum_jmpz);
6410}
6411/* }}} */
6412
6413void zend_compile_post_incdec(znode *result, zend_ast *ast) /* {{{ */
6414{
6415	zend_ast *var_ast = ast->child[0];
6416	ZEND_ASSERT(ast->kind == ZEND_AST_POST_INC || ast->kind == ZEND_AST_POST_DEC);
6417
6418	zend_ensure_writable_variable(var_ast);
6419
6420	if (var_ast->kind == ZEND_AST_PROP) {
6421		zend_op *opline = zend_compile_prop_common(NULL, var_ast, BP_VAR_RW);
6422		opline->opcode = ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC_OBJ : ZEND_POST_DEC_OBJ;
6423		zend_make_tmp_result(result, opline);
6424	} else {
6425		znode var_node;
6426		zend_compile_var(&var_node, var_ast, BP_VAR_RW);
6427		zend_emit_op_tmp(result, ast->kind == ZEND_AST_POST_INC ? ZEND_POST_INC : ZEND_POST_DEC,
6428			&var_node, NULL);
6429	}
6430}
6431/* }}} */
6432
6433void zend_compile_pre_incdec(znode *result, zend_ast *ast) /* {{{ */
6434{
6435	zend_ast *var_ast = ast->child[0];
6436	ZEND_ASSERT(ast->kind == ZEND_AST_PRE_INC || ast->kind == ZEND_AST_PRE_DEC);
6437
6438	zend_ensure_writable_variable(var_ast);
6439
6440	if (var_ast->kind == ZEND_AST_PROP) {
6441		zend_op *opline = zend_compile_prop_common(result, var_ast, BP_VAR_RW);
6442		opline->opcode = ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC_OBJ : ZEND_PRE_DEC_OBJ;
6443	} else {
6444		znode var_node;
6445		zend_compile_var(&var_node, var_ast, BP_VAR_RW);
6446		zend_emit_op(result, ast->kind == ZEND_AST_PRE_INC ? ZEND_PRE_INC : ZEND_PRE_DEC,
6447			&var_node, NULL);
6448	}
6449}
6450/* }}} */
6451
6452void zend_compile_cast(znode *result, zend_ast *ast) /* {{{ */
6453{
6454	zend_ast *expr_ast = ast->child[0];
6455	znode expr_node;
6456	zend_op *opline;
6457
6458	zend_compile_expr(&expr_node, expr_ast);
6459
6460	opline = zend_emit_op_tmp(result, ZEND_CAST, &expr_node, NULL);
6461	opline->extended_value = ast->attr;
6462}
6463/* }}} */
6464
6465static void zend_compile_shorthand_conditional(znode *result, zend_ast *ast) /* {{{ */
6466{
6467	zend_ast *cond_ast = ast->child[0];
6468	zend_ast *false_ast = ast->child[2];
6469
6470	znode cond_node, false_node;
6471	zend_op *opline_qm_assign;
6472	uint32_t opnum_jmp_set;
6473
6474	ZEND_ASSERT(ast->child[1] == NULL);
6475
6476	zend_compile_expr(&cond_node, cond_ast);
6477
6478	opnum_jmp_set = get_next_op_number(CG(active_op_array));
6479	zend_emit_op_tmp(result, ZEND_JMP_SET, &cond_node, NULL);
6480
6481	zend_compile_expr(&false_node, false_ast);
6482
6483	opline_qm_assign = zend_emit_op_tmp(NULL, ZEND_QM_ASSIGN, &false_node, NULL);
6484	SET_NODE(opline_qm_assign->result, result);
6485
6486	zend_update_jump_target_to_next(opnum_jmp_set);
6487}
6488/* }}} */
6489
6490void zend_compile_conditional(znode *result, zend_ast *ast) /* {{{ */
6491{
6492	zend_ast *cond_ast = ast->child[0];
6493	zend_ast *true_ast = ast->child[1];
6494	zend_ast *false_ast = ast->child[2];
6495
6496	znode cond_node, true_node, false_node;
6497	zend_op *opline_qm_assign2;
6498	uint32_t opnum_jmpz, opnum_jmp;
6499
6500	if (!true_ast) {
6501		zend_compile_shorthand_conditional(result, ast);
6502		return;
6503	}
6504
6505	zend_compile_expr(&cond_node, cond_ast);
6506
6507	opnum_jmpz = zend_emit_cond_jump(ZEND_JMPZ, &cond_node, 0);
6508
6509	zend_compile_expr(&true_node, true_ast);
6510
6511	zend_emit_op_tmp(result, ZEND_QM_ASSIGN, &true_node, NULL);
6512
6513	opnum_jmp = zend_emit_jump(0);
6514
6515	zend_update_jump_target_to_next(opnum_jmpz);
6516
6517	zend_compile_expr(&false_node, false_ast);
6518
6519	opline_qm_assign2 = zend_emit_op(NULL, ZEND_QM_ASSIGN, &false_node, NULL);
6520	SET_NODE(opline_qm_assign2->result, result);
6521
6522	zend_update_jump_target_to_next(opnum_jmp);
6523}
6524/* }}} */
6525
6526void zend_compile_coalesce(znode *result, zend_ast *ast) /* {{{ */
6527{
6528	zend_ast *expr_ast = ast->child[0];
6529	zend_ast *default_ast = ast->child[1];
6530
6531	znode expr_node, default_node;
6532	zend_op *opline;
6533	uint32_t opnum;
6534
6535	zend_compile_var(&expr_node, expr_ast, BP_VAR_IS);
6536
6537	opnum = get_next_op_number(CG(active_op_array));
6538	zend_emit_op_tmp(result, ZEND_COALESCE, &expr_node, NULL);
6539
6540	zend_compile_expr(&default_node, default_ast);
6541
6542	opline = zend_emit_op_tmp(NULL, ZEND_QM_ASSIGN, &default_node, NULL);
6543	SET_NODE(opline->result, result);
6544
6545	opline = &CG(active_op_array)->opcodes[opnum];
6546	opline->op2.opline_num = get_next_op_number(CG(active_op_array));
6547}
6548/* }}} */
6549
6550void zend_compile_print(znode *result, zend_ast *ast) /* {{{ */
6551{
6552	zend_op *opline;
6553	zend_ast *expr_ast = ast->child[0];
6554
6555	znode expr_node;
6556	zend_compile_expr(&expr_node, expr_ast);
6557
6558	opline = zend_emit_op(NULL, ZEND_ECHO, &expr_node, NULL);
6559	opline->extended_value = 1;
6560
6561	result->op_type = IS_CONST;
6562	ZVAL_LONG(&result->u.constant, 1);
6563}
6564/* }}} */
6565
6566void zend_compile_exit(znode *result, zend_ast *ast) /* {{{ */
6567{
6568	zend_ast *expr_ast = ast->child[0];
6569
6570	if (expr_ast) {
6571		znode expr_node;
6572		zend_compile_expr(&expr_node, expr_ast);
6573		zend_emit_op(NULL, ZEND_EXIT, &expr_node, NULL);
6574	} else {
6575		zend_emit_op(NULL, ZEND_EXIT, NULL, NULL);
6576	}
6577
6578	result->op_type = IS_CONST;
6579	ZVAL_BOOL(&result->u.constant, 1);
6580}
6581/* }}} */
6582
6583void zend_compile_yield(znode *result, zend_ast *ast) /* {{{ */
6584{
6585	zend_ast *value_ast = ast->child[0];
6586	zend_ast *key_ast = ast->child[1];
6587
6588	znode value_node, key_node;
6589	znode *value_node_ptr = NULL, *key_node_ptr = NULL;
6590	zend_op *opline;
6591	zend_bool returns_by_ref = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0;
6592
6593	zend_mark_function_as_generator();
6594
6595	if (key_ast) {
6596		zend_compile_expr(&key_node, key_ast);
6597		key_node_ptr = &key_node;
6598	}
6599
6600	if (value_ast) {
6601		if (returns_by_ref && zend_is_variable(value_ast) && !zend_is_call(value_ast)) {
6602			zend_compile_var(&value_node, value_ast, BP_VAR_W);
6603		} else {
6604			zend_compile_expr(&value_node, value_ast);
6605		}
6606		value_node_ptr = &value_node;
6607	}
6608
6609	opline = zend_emit_op(result, ZEND_YIELD, value_node_ptr, key_node_ptr);
6610
6611	if (value_ast && returns_by_ref && zend_is_call(value_ast)) {
6612		opline->extended_value = ZEND_RETURNS_FUNCTION;
6613	}
6614}
6615/* }}} */
6616
6617void zend_compile_yield_from(znode *result, zend_ast *ast) /* {{{ */
6618{
6619	zend_ast *expr_ast = ast->child[0];
6620	znode expr_node;
6621
6622	zend_mark_function_as_generator();
6623
6624	if (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
6625		zend_error_noreturn(E_COMPILE_ERROR,
6626			"Cannot use \"yield from\" inside a by-reference generator");
6627	}
6628
6629	zend_compile_expr(&expr_node, expr_ast);
6630	zend_emit_op_tmp(result, ZEND_YIELD_FROM, &expr_node, NULL);
6631}
6632/* }}} */
6633
6634void zend_compile_instanceof(znode *result, zend_ast *ast) /* {{{ */
6635{
6636	zend_ast *obj_ast = ast->child[0];
6637	zend_ast *class_ast = ast->child[1];
6638
6639	znode obj_node, class_node;
6640	zend_op *opline;
6641
6642	zend_compile_expr(&obj_node, obj_ast);
6643	if (obj_node.op_type == IS_CONST) {
6644		zend_error_noreturn(E_COMPILE_ERROR,
6645			"instanceof expects an object instance, constant given");
6646	}
6647
6648	zend_compile_class_ref_ex(&class_node, class_ast,
6649		ZEND_FETCH_CLASS_NO_AUTOLOAD | ZEND_FETCH_CLASS_EXCEPTION);
6650
6651	opline = zend_emit_op_tmp(result, ZEND_INSTANCEOF, &obj_node, NULL);
6652
6653	if (class_node.op_type == IS_CONST) {
6654		opline->op2_type = IS_CONST;
6655		opline->op2.constant = zend_add_class_name_literal(
6656			CG(active_op_array), Z_STR(class_node.u.constant));
6657	} else {
6658		SET_NODE(opline->op2, &class_node);
6659	}
6660}
6661/* }}} */
6662
6663void zend_compile_include_or_eval(znode *result, zend_ast *ast) /* {{{ */
6664{
6665	zend_ast *expr_ast = ast->child[0];
6666	znode expr_node;
6667	zend_op *opline;
6668
6669	zend_do_extended_fcall_begin();
6670	zend_compile_expr(&expr_node, expr_ast);
6671
6672	opline = zend_emit_op(result, ZEND_INCLUDE_OR_EVAL, &expr_node, NULL);
6673	opline->extended_value = ast->attr;
6674
6675	zend_do_extended_fcall_end();
6676}
6677/* }}} */
6678
6679void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */
6680{
6681	zend_ast *var_ast = ast->child[0];
6682
6683	znode var_node;
6684	zend_op *opline = NULL;
6685
6686	ZEND_ASSERT(ast->kind == ZEND_AST_ISSET || ast->kind == ZEND_AST_EMPTY);
6687
6688	if (!zend_is_variable(var_ast) || zend_is_call(var_ast)) {
6689		if (ast->kind == ZEND_AST_EMPTY) {
6690			/* empty(expr) can be transformed to !expr */
6691			zend_ast *not_ast = zend_ast_create_ex(ZEND_AST_UNARY_OP, ZEND_BOOL_NOT, var_ast);
6692			zend_compile_expr(result, not_ast);
6693			return;
6694		} else {
6695			zend_error_noreturn(E_COMPILE_ERROR,
6696				"Cannot use isset() on the result of an expression "
6697				"(you can use \"null !== expression\" instead)");
6698		}
6699	}
6700
6701	switch (var_ast->kind) {
6702		case ZEND_AST_VAR:
6703			if (zend_try_compile_cv(&var_node, var_ast) == SUCCESS) {
6704				opline = zend_emit_op(result, ZEND_ISSET_ISEMPTY_VAR, &var_node, NULL);
6705				opline->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
6706			} else {
6707				opline = zend_compile_simple_var_no_cv(result, var_ast, BP_VAR_IS, 0);
6708				opline->opcode = ZEND_ISSET_ISEMPTY_VAR;
6709			}
6710			break;
6711		case ZEND_AST_DIM:
6712			opline = zend_compile_dim_common(result, var_ast, BP_VAR_IS);
6713			opline->opcode = ZEND_ISSET_ISEMPTY_DIM_OBJ;
6714			break;
6715		case ZEND_AST_PROP:
6716			opline = zend_compile_prop_common(result, var_ast, BP_VAR_IS);
6717			opline->opcode = ZEND_ISSET_ISEMPTY_PROP_OBJ;
6718			break;
6719		case ZEND_AST_STATIC_PROP:
6720			opline = zend_compile_static_prop_common(result, var_ast, BP_VAR_IS, 0);
6721			opline->opcode = ZEND_ISSET_ISEMPTY_STATIC_PROP;
6722			break;
6723		EMPTY_SWITCH_DEFAULT_CASE()
6724	}
6725
6726	result->op_type = opline->result_type = IS_TMP_VAR;
6727	opline->extended_value |= ast->kind == ZEND_AST_ISSET ? ZEND_ISSET : ZEND_ISEMPTY;
6728}
6729/* }}} */
6730
6731void zend_compile_silence(znode *result, zend_ast *ast) /* {{{ */
6732{
6733	zend_ast *expr_ast = ast->child[0];
6734	znode silence_node;
6735	uint32_t range;
6736
6737	range = zend_start_live_range(CG(active_op_array), get_next_op_number(CG(active_op_array)));
6738	zend_emit_op_tmp(&silence_node, ZEND_BEGIN_SILENCE, NULL, NULL);
6739
6740	if (expr_ast->kind == ZEND_AST_VAR) {
6741		/* For @$var we need to force a FETCH instruction, otherwise the CV access will
6742		 * happen outside the silenced section. */
6743		zend_compile_simple_var_no_cv(result, expr_ast, BP_VAR_R, 0 );
6744	} else {
6745		zend_compile_expr(result, expr_ast);
6746	}
6747
6748	/* Store BEGIN_SILENCE/END_SILENCE pair to restore previous
6749	 * EG(error_reporting) value on exception */
6750	zend_end_live_range(CG(active_op_array), range, get_next_op_number(CG(active_op_array)),
6751		ZEND_LIVE_SILENCE, silence_node.u.op.var);
6752
6753	zend_emit_op(NULL, ZEND_END_SILENCE, &silence_node, NULL);
6754}
6755/* }}} */
6756
6757void zend_compile_shell_exec(znode *result, zend_ast *ast) /* {{{ */
6758{
6759	zend_ast *expr_ast = ast->child[0];
6760
6761	zval fn_name;
6762	zend_ast *name_ast, *args_ast, *call_ast;
6763
6764	ZVAL_STRING(&fn_name, "shell_exec");
6765	name_ast = zend_ast_create_zval(&fn_name);
6766	args_ast = zend_ast_create_list(1, ZEND_AST_ARG_LIST, expr_ast);
6767	call_ast = zend_ast_create(ZEND_AST_CALL, name_ast, args_ast);
6768
6769	zend_compile_expr(result, call_ast);
6770
6771	zval_ptr_dtor(&fn_name);
6772}
6773/* }}} */
6774
6775void zend_compile_array(znode *result, zend_ast *ast) /* {{{ */
6776{
6777	zend_ast_list *list = zend_ast_get_list(ast);
6778	zend_op *opline;
6779	uint32_t i, opnum_init = -1;
6780	zend_bool packed = 1;
6781
6782	if (zend_try_ct_eval_array(&result->u.constant, ast)) {
6783		result->op_type = IS_CONST;
6784		return;
6785	}
6786
6787	for (i = 0; i < list->children; ++i) {
6788		zend_ast *elem_ast = list->child[i];
6789		zend_ast *value_ast = elem_ast->child[0];
6790		zend_ast *key_ast = elem_ast->child[1];
6791		zend_bool by_ref = elem_ast->attr;
6792
6793		znode value_node, key_node, *key_node_ptr = NULL;
6794
6795		if (key_ast) {
6796			zend_compile_expr(&key_node, key_ast);
6797			zend_handle_numeric_op(&key_node);
6798			key_node_ptr = &key_node;
6799		}
6800
6801		if (by_ref) {
6802			zend_ensure_writable_variable(value_ast);
6803			zend_compile_var(&value_node, value_ast, BP_VAR_W);
6804		} else {
6805			zend_compile_expr(&value_node, value_ast);
6806		}
6807
6808		if (i == 0) {
6809			opnum_init = get_next_op_number(CG(active_op_array));
6810			opline = zend_emit_op_tmp(result, ZEND_INIT_ARRAY, &value_node, key_node_ptr);
6811			opline->extended_value = list->children << ZEND_ARRAY_SIZE_SHIFT;
6812		} else {
6813			opline = zend_emit_op(NULL, ZEND_ADD_ARRAY_ELEMENT,
6814				&value_node, key_node_ptr);
6815			SET_NODE(opline->result, result);
6816		}
6817		opline->extended_value |= by_ref;
6818
6819		if (key_ast && key_node.op_type == IS_CONST && Z_TYPE(key_node.u.constant) == IS_STRING) {
6820			packed = 0;
6821		}
6822	}
6823
6824	/* Handle empty array */
6825	if (!list->children) {
6826		zend_emit_op_tmp(result, ZEND_INIT_ARRAY, NULL, NULL);
6827	}
6828
6829	/* Add a flag to INIT_ARRAY if we know this array cannot be packed */
6830	if (!packed) {
6831		ZEND_ASSERT(opnum_init != -1);
6832		opline = &CG(active_op_array)->opcodes[opnum_init];
6833		opline->extended_value |= ZEND_ARRAY_NOT_PACKED;
6834	}
6835}
6836/* }}} */
6837
6838void zend_compile_const(znode *result, zend_ast *ast) /* {{{ */
6839{
6840	zend_ast *name_ast = ast->child[0];
6841
6842	zend_op *opline;
6843
6844	zend_bool is_fully_qualified;
6845	zend_string *orig_name = zend_ast_get_str(name_ast);
6846	zend_string *resolved_name = zend_resolve_const_name(orig_name, name_ast->attr, &is_fully_qualified);
6847
6848	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__"))) {
6849		zend_ast *last = CG(ast);
6850
6851		while (last->kind == ZEND_AST_STMT_LIST) {
6852			zend_ast_list *list = zend_ast_get_list(last);
6853			last = list->child[list->children-1];
6854		}
6855		if (last->kind == ZEND_AST_HALT_COMPILER) {
6856			result->op_type = IS_CONST;
6857			ZVAL_LONG(&result->u.constant, Z_LVAL_P(zend_ast_get_zval(last->child[0])));
6858			zend_string_release(resolved_name);
6859			return;
6860		}
6861	}
6862
6863	if (zend_try_ct_eval_const(&result->u.constant, resolved_name, is_fully_qualified)) {
6864		result->op_type = IS_CONST;
6865		zend_string_release(resolved_name);
6866		return;
6867	}
6868
6869	opline = zend_emit_op_tmp(result, ZEND_FETCH_CONSTANT, NULL, NULL);
6870	opline->op2_type = IS_CONST;
6871
6872	if (is_fully_qualified) {
6873		opline->op2.constant = zend_add_const_name_literal(
6874			CG(active_op_array), resolved_name, 0);
6875	} else {
6876		opline->extended_value = IS_CONSTANT_UNQUALIFIED;
6877		if (FC(current_namespace)) {
6878			opline->extended_value |= IS_CONSTANT_IN_NAMESPACE;
6879			opline->op2.constant = zend_add_const_name_literal(
6880				CG(active_op_array), resolved_name, 1);
6881		} else {
6882			opline->op2.constant = zend_add_const_name_literal(
6883				CG(active_op_array), resolved_name, 0);
6884		}
6885	}
6886	zend_alloc_cache_slot(opline->op2.constant);
6887}
6888/* }}} */
6889
6890void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */
6891{
6892	zend_ast *class_ast = ast->child[0];
6893	zend_ast *const_ast = ast->child[1];
6894
6895	znode class_node, const_node;
6896	zend_op *opline;
6897
6898	if (zend_try_compile_const_expr_resolve_class_name(&result->u.constant, class_ast, const_ast, 0)) {
6899		if (Z_TYPE(result->u.constant) == IS_NULL) {
6900			zend_op *opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL);
6901			opline->extended_value = zend_get_class_fetch_type(zend_ast_get_str(class_ast));
6902		} else {
6903			result->op_type = IS_CONST;
6904		}
6905		return;
6906	}
6907
6908	zend_eval_const_expr(&class_ast);
6909	zend_eval_const_expr(&const_ast);
6910
6911	if (class_ast->kind == ZEND_AST_ZVAL) {
6912		zend_string *resolved_name;
6913
6914		resolved_name = zend_resolve_class_name_ast(class_ast);
6915		if (const_ast->kind == ZEND_AST_ZVAL && zend_try_ct_eval_class_const(&result->u.constant, resolved_name, zend_ast_get_str(const_ast))) {
6916			result->op_type = IS_CONST;
6917			zend_string_release(resolved_name);
6918			return;
6919		}
6920		zend_string_release(resolved_name);
6921	}
6922	if (const_ast->kind == ZEND_AST_ZVAL && zend_string_equals_literal_ci(zend_ast_get_str(const_ast), "class")) {
6923		zend_error_noreturn(E_COMPILE_ERROR,
6924			"Dynamic class names are not allowed in compile-time ::class fetch");
6925	}
6926
6927	zend_compile_class_ref_ex(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
6928
6929	zend_compile_expr(&const_node, const_ast);
6930
6931	opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_CONSTANT, NULL, &const_node);
6932
6933	zend_set_class_name_op1(opline, &class_node);
6934
6935	if (opline->op1_type == IS_CONST) {
6936		zend_alloc_cache_slot(opline->op2.constant);
6937	} else {
6938		zend_alloc_polymorphic_cache_slot(opline->op2.constant);
6939	}
6940}
6941/* }}} */
6942
6943void zend_compile_resolve_class_name(znode *result, zend_ast *ast) /* {{{ */
6944{
6945	zend_ast *name_ast = ast->child[0];
6946	uint32_t fetch_type = zend_get_class_fetch_type(zend_ast_get_str(name_ast));
6947	zend_ensure_valid_class_fetch_type(fetch_type);
6948
6949	switch (fetch_type) {
6950		case ZEND_FETCH_CLASS_SELF:
6951			if (CG(active_class_entry) && zend_is_scope_known()) {
6952				result->op_type = IS_CONST;
6953				ZVAL_STR_COPY(&result->u.constant, CG(active_class_entry)->name);
6954			} else {
6955				zend_op *opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL);
6956				opline->extended_value = fetch_type;
6957			}
6958			break;
6959		case ZEND_FETCH_CLASS_STATIC:
6960		case ZEND_FETCH_CLASS_PARENT:
6961			{
6962				zend_op *opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL);
6963				opline->extended_value = fetch_type;
6964			}
6965			break;
6966		case ZEND_FETCH_CLASS_DEFAULT:
6967			result->op_type = IS_CONST;
6968			ZVAL_STR(&result->u.constant, zend_resolve_class_name_ast(name_ast));
6969			break;
6970		EMPTY_SWITCH_DEFAULT_CASE()
6971	}
6972}
6973/* }}} */
6974
6975static zend_op *zend_compile_rope_add(znode *result, uint32_t num, znode *elem_node) /* {{{ */
6976{
6977	zend_op *opline = get_next_op(CG(active_op_array));
6978
6979	if (num == 0) {
6980		result->op_type = IS_TMP_VAR;
6981		result->u.op.var = -1;
6982		opline->opcode = ZEND_ROPE_INIT;
6983		SET_UNUSED(opline->op1);
6984	} else {
6985		opline->opcode = ZEND_ROPE_ADD;
6986		SET_NODE(opline->op1, result);
6987	}
6988	SET_NODE(opline->op2, elem_node);
6989	SET_NODE(opline->result, result);
6990	opline->extended_value = num;
6991	return opline;
6992}
6993/* }}} */
6994
6995static void zend_compile_encaps_list(znode *result, zend_ast *ast) /* {{{ */
6996{
6997	uint32_t i, j;
6998	uint32_t rope_init_lineno = -1;
6999	zend_op *opline = NULL, *init_opline;
7000	znode elem_node, last_const_node;
7001	zend_ast_list *list = zend_ast_get_list(ast);
7002
7003	ZEND_ASSERT(list->children > 0);
7004
7005	j = 0;
7006	last_const_node.op_type = IS_UNUSED;
7007	for (i = 0; i < list->children; i++) {
7008		zend_compile_expr(&elem_node, list->child[i]);
7009
7010		if (elem_node.op_type == IS_CONST) {
7011			convert_to_string(&elem_node.u.constant);
7012
7013			if (Z_STRLEN(elem_node.u.constant) == 0) {
7014				zval_ptr_dtor(&elem_node.u.constant);
7015			} else if (last_const_node.op_type == IS_CONST) {
7016				concat_function(&last_const_node.u.constant, &last_const_node.u.constant, &elem_node.u.constant);
7017				zval_ptr_dtor(&elem_node.u.constant);
7018			} else {
7019				last_const_node.op_type = IS_CONST;
7020				ZVAL_COPY_VALUE(&last_const_node.u.constant, &elem_node.u.constant);
7021			}
7022			continue;
7023		} else {
7024			if (j == 0) {
7025				rope_init_lineno = get_next_op_number(CG(active_op_array));
7026			}
7027			if (last_const_node.op_type == IS_CONST) {
7028				zend_compile_rope_add(result, j++, &last_const_node);
7029				last_const_node.op_type = IS_UNUSED;
7030			}
7031			opline = zend_compile_rope_add(result, j++, &elem_node);
7032		}
7033	}
7034
7035	if (j == 0) {
7036		result->op_type = IS_CONST;
7037		if (last_const_node.op_type == IS_CONST) {
7038			ZVAL_COPY_VALUE(&result->u.constant, &last_const_node.u.constant);
7039		} else {
7040			ZVAL_EMPTY_STRING(&result->u.constant);
7041			/* empty string */
7042		}
7043		return;
7044	} else if (last_const_node.op_type == IS_CONST) {
7045		opline = zend_compile_rope_add(result, j++, &last_const_node);
7046	}
7047	init_opline = CG(active_op_array)->opcodes + rope_init_lineno;
7048	if (j == 1) {
7049		if (opline->op2_type == IS_CONST) {
7050			GET_NODE(result, opline->op2);
7051			MAKE_NOP(opline);
7052		} else {
7053			opline->opcode = ZEND_CAST;
7054			opline->extended_value = IS_STRING;
7055			opline->op1_type = opline->op2_type;
7056			opline->op1 = opline->op2;
7057			opline->result_type = IS_TMP_VAR;
7058			opline->result.var = get_temporary_variable(CG(active_op_array));
7059			SET_UNUSED(opline->op2);
7060			GET_NODE(result, opline->result);
7061		}
7062	} else if (j == 2) {
7063		opline->opcode = ZEND_FAST_CONCAT;
7064		opline->extended_value = 0;
7065		opline->op1_type = init_opline->op2_type;
7066		opline->op1 = init_opline->op2;
7067		opline->result_type = IS_TMP_VAR;
7068		opline->result.var = get_temporary_variable(CG(active_op_array));
7069		MAKE_NOP(init_opline);
7070		GET_NODE(result, opline->result);
7071	} else {
7072		uint32_t var;
7073		uint32_t range = zend_start_live_range(CG(active_op_array), rope_init_lineno);
7074
7075		init_opline->extended_value = j;
7076		opline->opcode = ZEND_ROPE_END;
7077		opline->result.var = get_temporary_variable(CG(active_op_array));
7078		var = opline->op1.var = get_temporary_variable(CG(active_op_array));
7079		GET_NODE(result, opline->result);
7080
7081		/* Allocates the necessary number of zval slots to keep the rope */
7082		i = ((j * sizeof(zend_string*)) + (sizeof(zval) - 1)) / sizeof(zval);
7083		while (i > 1) {
7084			get_temporary_variable(CG(active_op_array));
7085			i--;
7086		}
7087
7088		zend_end_live_range(CG(active_op_array), range, opline - CG(active_op_array)->opcodes,
7089			ZEND_LIVE_ROPE, var);
7090
7091		/* Update all the previous opcodes to use the same variable */
7092		while (opline != init_opline) {
7093			opline--;
7094			if (opline->opcode == ZEND_ROPE_ADD &&
7095			    opline->result.var == -1) {
7096				opline->op1.var = var;
7097				opline->result.var = var;
7098			} else if (opline->opcode == ZEND_ROPE_INIT &&
7099			           opline->result.var == -1) {
7100				opline->result.var = var;
7101			}
7102		}
7103	}
7104}
7105/* }}} */
7106
7107void zend_compile_magic_const(znode *result, zend_ast *ast) /* {{{ */
7108{
7109	zend_op *opline;
7110
7111	if (zend_try_ct_eval_magic_const(&result->u.constant, ast)) {
7112		result->op_type = IS_CONST;
7113		return;
7114	}
7115
7116	ZEND_ASSERT(ast->attr == T_CLASS_C &&
7117	            CG(active_class_entry) &&
7118	            (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) != 0);
7119
7120	opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL);
7121	opline->extended_value = ZEND_FETCH_CLASS_SELF;
7122}
7123/* }}} */
7124
7125zend_bool zend_is_allowed_in_const_expr(zend_ast_kind kind) /* {{{ */
7126{
7127	return kind == ZEND_AST_ZVAL || kind == ZEND_AST_BINARY_OP
7128		|| kind == ZEND_AST_GREATER || kind == ZEND_AST_GREATER_EQUAL
7129		|| kind == ZEND_AST_AND || kind == ZEND_AST_OR
7130		|| kind == ZEND_AST_UNARY_OP
7131		|| kind == ZEND_AST_UNARY_PLUS || kind == ZEND_AST_UNARY_MINUS
7132		|| kind == ZEND_AST_CONDITIONAL || kind == ZEND_AST_DIM
7133		|| kind == ZEND_AST_ARRAY || kind == ZEND_AST_ARRAY_ELEM
7134		|| kind == ZEND_AST_CONST || kind == ZEND_AST_CLASS_CONST
7135		|| kind == ZEND_AST_MAGIC_CONST;
7136}
7137/* }}} */
7138
7139void zend_compile_const_expr_class_const(zend_ast **ast_ptr) /* {{{ */
7140{
7141	zend_ast *ast = *ast_ptr;
7142	zend_ast *class_ast = ast->child[0];
7143	zend_ast *const_ast = ast->child[1];
7144	zend_string *class_name;
7145	zend_string *const_name = zend_ast_get_str(const_ast);
7146	zval result;
7147	int fetch_type;
7148
7149	if (class_ast->kind != ZEND_AST_ZVAL) {
7150		zend_error_noreturn(E_COMPILE_ERROR,
7151			"Dynamic class names are not allowed in compile-time class constant references");
7152	}
7153
7154	if (zend_try_compile_const_expr_resolve_class_name(&result, class_ast, const_ast, 1)) {
7155		*ast_ptr = zend_ast_create_zval(&result);
7156		return;
7157	}
7158
7159	class_name = zend_ast_get_str(class_ast);
7160	fetch_type = zend_get_class_fetch_type(class_name);
7161
7162	if (ZEND_FETCH_CLASS_STATIC == fetch_type) {
7163		zend_error_noreturn(E_COMPILE_ERROR,
7164			"\"static::\" is not allowed in compile-time constants");
7165	}
7166
7167	if (ZEND_FETCH_CLASS_DEFAULT == fetch_type) {
7168		class_name = zend_resolve_class_name_ast(class_ast);
7169	} else {
7170		zend_string_addref(class_name);
7171	}
7172
7173	Z_STR(result) = zend_concat3(
7174		ZSTR_VAL(class_name), ZSTR_LEN(class_name), "::", 2, ZSTR_VAL(const_name), ZSTR_LEN(const_name));
7175
7176	Z_TYPE_INFO(result) = IS_CONSTANT_EX;
7177	Z_CONST_FLAGS(result) = fetch_type;
7178
7179	zend_ast_destroy(ast);
7180	zend_string_release(class_name);
7181
7182	*ast_ptr = zend_ast_create_zval(&result);
7183}
7184/* }}} */
7185
7186void zend_compile_const_expr_const(zend_ast **ast_ptr) /* {{{ */
7187{
7188	zend_ast *ast = *ast_ptr;
7189	zend_ast *name_ast = ast->child[0];
7190	zend_string *orig_name = zend_ast_get_str(name_ast);
7191	zend_bool is_fully_qualified;
7192
7193	zval result, resolved_name;
7194	ZVAL_STR(&resolved_name, zend_resolve_const_name(
7195		orig_name, name_ast->attr, &is_fully_qualified));
7196
7197	if (zend_try_ct_eval_const(&result, Z_STR(resolved_name), is_fully_qualified)) {
7198		zend_string_release(Z_STR(resolved_name));
7199		zend_ast_destroy(ast);
7200		*ast_ptr = zend_ast_create_zval(&result);
7201		return;
7202	}
7203
7204	Z_TYPE_INFO(resolved_name) = IS_CONSTANT_EX;
7205	if (!is_fully_qualified) {
7206		Z_CONST_FLAGS(resolved_name) = IS_CONSTANT_UNQUALIFIED;
7207	}
7208
7209	zend_ast_destroy(ast);
7210	*ast_ptr = zend_ast_create_zval(&resolved_name);
7211}
7212/* }}} */
7213
7214void zend_compile_const_expr_magic_const(zend_ast **ast_ptr) /* {{{ */
7215{
7216	zend_ast *ast = *ast_ptr;
7217
7218	/* Other cases already resolved by constant folding */
7219	ZEND_ASSERT(ast->attr == T_CLASS_C &&
7220	            CG(active_class_entry) &&
7221	            (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) != 0);
7222
7223	{
7224		zval const_zv;
7225		Z_STR(const_zv) = zend_string_init("__CLASS__", sizeof("__CLASS__")-1, 0);
7226		Z_TYPE_INFO(const_zv) = IS_CONSTANT_EX | (IS_CONSTANT_CLASS << Z_CONST_FLAGS_SHIFT);
7227
7228		zend_ast_destroy(ast);
7229		*ast_ptr = zend_ast_create_zval(&const_zv);
7230	}
7231}
7232/* }}} */
7233
7234void zend_compile_const_expr(zend_ast **ast_ptr) /* {{{ */
7235{
7236	zend_ast *ast = *ast_ptr;
7237	if (ast == NULL || ast->kind == ZEND_AST_ZVAL) {
7238		return;
7239	}
7240
7241	if (!zend_is_allowed_in_const_expr(ast->kind)) {
7242		zend_error_noreturn(E_COMPILE_ERROR, "Constant expression contains invalid operations");
7243	}
7244
7245	switch (ast->kind) {
7246		case ZEND_AST_CLASS_CONST:
7247			zend_compile_const_expr_class_const(ast_ptr);
7248			break;
7249		case ZEND_AST_CONST:
7250			zend_compile_const_expr_const(ast_ptr);
7251			break;
7252		case ZEND_AST_MAGIC_CONST:
7253			zend_compile_const_expr_magic_const(ast_ptr);
7254			break;
7255		default:
7256			zend_ast_apply(ast, zend_compile_const_expr);
7257			break;
7258	}
7259}
7260/* }}} */
7261
7262void zend_const_expr_to_zval(zval *result, zend_ast *ast) /* {{{ */
7263{
7264	zend_ast *orig_ast = ast;
7265	zend_eval_const_expr(&ast);
7266	zend_compile_const_expr(&ast);
7267	if (ast->kind == ZEND_AST_ZVAL) {
7268		ZVAL_COPY_VALUE(result, zend_ast_get_zval(ast));
7269
7270		/* Kill this branch of the original AST, as it was already destroyed.
7271		 * It would be nice to find a better solution to this problem in the
7272		 * future. */
7273		orig_ast->kind = 0;
7274	} else {
7275		ZVAL_NEW_AST(result, zend_ast_copy(ast));
7276	}
7277}
7278/* }}} */
7279
7280/* Same as compile_stmt, but with early binding */
7281void zend_compile_top_stmt(zend_ast *ast) /* {{{ */
7282{
7283	if (!ast) {
72