root/Zend/zend_compile.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. zend_alloc_cache_slot
  2. zend_alloc_polymorphic_cache_slot
  3. zend_destroy_property_info_internal
  4. zend_new_interned_string_safe
  5. zend_build_runtime_definition_key
  6. zend_get_unqualified_name
  7. zend_is_reserved_class_name
  8. zend_assert_valid_class_name
  9. zend_lookup_builtin_type_by_name
  10. zend_oparray_context_begin
  11. zend_oparray_context_end
  12. zend_reset_import_tables
  13. zend_end_namespace
  14. zend_file_context_begin
  15. zend_file_context_end
  16. zend_init_compiler_data_structures
  17. file_handle_dtor
  18. init_compiler
  19. shutdown_compiler
  20. zend_set_compiled_filename
  21. zend_restore_compiled_filename
  22. zend_get_compiled_filename
  23. zend_get_compiled_lineno
  24. zend_is_compiling
  25. get_temporary_variable
  26. lookup_cv
  27. zend_del_literal
  28. zend_insert_literal
  29. zend_add_literal
  30. zend_add_literal_string
  31. zend_add_func_name_literal
  32. zend_add_ns_func_name_literal
  33. zend_add_class_name_literal
  34. zend_add_const_name_literal
  35. zend_stop_lexing
  36. zend_begin_loop
  37. zend_end_loop
  38. zend_do_free
  39. zend_add_class_modifier
  40. zend_add_member_modifier
  41. zend_concat3
  42. zend_concat_names
  43. zend_prefix_with_ns
  44. zend_hash_find_ptr_lc
  45. zend_resolve_non_class_name
  46. zend_resolve_function_name
  47. zend_resolve_const_name
  48. zend_resolve_class_name
  49. zend_resolve_class_name_ast
  50. label_ptr_dtor
  51. str_dtor
  52. zend_add_try_element
  53. function_add_ref
  54. do_bind_function
  55. do_bind_class
  56. do_bind_inherited_class
  57. zend_do_early_binding
  58. zend_mark_function_as_generator
  59. zend_do_delayed_early_binding
  60. zend_mangle_property_name
  61. zend_strnlen
  62. zend_unmangle_property_name_ex
  63. zend_lookup_reserved_const
  64. zend_try_ct_eval_const
  65. zend_is_scope_known
  66. class_name_refers_to_active_ce
  67. zend_get_class_fetch_type
  68. zend_get_class_fetch_type_ast
  69. zend_ensure_valid_class_fetch_type
  70. zend_try_compile_const_expr_resolve_class_name
  71. zend_try_ct_eval_class_const
  72. zend_add_to_list
  73. zend_do_extended_info
  74. zend_do_extended_fcall_begin
  75. zend_do_extended_fcall_end
  76. zend_is_auto_global_str
  77. zend_is_auto_global
  78. zend_register_auto_global
  79. zend_activate_auto_globals
  80. zendlex
  81. zend_initialize_class_data
  82. zend_get_compiled_variable_name
  83. zend_ast_append_str
  84. zend_verify_namespace
  85. zend_dirname
  86. zend_adjust_for_fetch_type
  87. zend_make_var_result
  88. zend_make_tmp_result
  89. zend_emit_op
  90. zend_emit_op_tmp
  91. zend_emit_tick
  92. zend_emit_op_data
  93. zend_emit_jump
  94. zend_emit_cond_jump
  95. zend_update_jump_target
  96. zend_update_jump_target_to_next
  97. zend_delayed_emit_op
  98. zend_delayed_compile_begin
  99. zend_delayed_compile_end
  100. zend_emit_return_type_check
  101. zend_emit_final_return
  102. zend_is_variable
  103. zend_is_call
  104. zend_is_unticked_stmt
  105. zend_can_write_to_variable
  106. zend_is_const_default_class_ref
  107. zend_handle_numeric_op
  108. zend_set_class_name_op1
  109. zend_compile_class_ref
  110. zend_try_compile_cv
  111. zend_compile_simple_var_no_cv
  112. zend_compile_simple_var
  113. zend_separate_if_call_and_write
  114. zend_emit_assign_znode
  115. zend_delayed_compile_dim
  116. zend_compile_dim_common
  117. zend_compile_dim
  118. is_this_fetch
  119. zend_delayed_compile_prop
  120. zend_compile_prop_common
  121. zend_compile_prop
  122. zend_compile_static_prop_common
  123. zend_compile_static_prop
  124. zend_compile_list_assign
  125. zend_ensure_writable_variable
  126. zend_is_assign_to_self
  127. zend_list_has_assign_to
  128. zend_list_has_assign_to_self
  129. zend_compile_assign
  130. zend_compile_assign_ref
  131. zend_emit_assign_ref_znode
  132. zend_compile_compound_assign
  133. zend_compile_args
  134. zend_get_call_op
  135. zend_compile_call_common
  136. zend_compile_function_name
  137. zend_compile_ns_call
  138. zend_compile_dynamic_call
  139. zend_args_contain_unpack
  140. zend_compile_func_strlen
  141. zend_compile_func_typecheck
  142. zend_compile_func_defined
  143. zend_try_compile_ct_bound_init_user_func
  144. zend_compile_init_user_func
  145. zend_compile_func_cufa
  146. zend_compile_func_cuf
  147. zend_compile_assert_side_effects
  148. zend_compile_assert
  149. zend_try_compile_special_func
  150. zend_compile_call
  151. zend_compile_method_call
  152. zend_is_constructor
  153. zend_compile_static_call
  154. zend_compile_new
  155. zend_compile_clone
  156. zend_compile_global_var
  157. zend_compile_static_var_common
  158. zend_compile_static_var
  159. zend_compile_unset
  160. zend_handle_loops_and_finally_ex
  161. zend_handle_loops_and_finally
  162. zend_compile_return
  163. zend_compile_echo
  164. zend_compile_throw
  165. zend_compile_break_continue
  166. zend_resolve_goto_label
  167. zend_compile_goto
  168. zend_compile_label
  169. zend_compile_while
  170. zend_compile_do_while
  171. zend_compile_expr_list
  172. zend_compile_for
  173. zend_compile_foreach
  174. zend_compile_if
  175. zend_compile_switch
  176. zend_compile_try
  177. zend_handle_encoding_declaration
  178. zend_declare_is_first_statement
  179. zend_compile_declare
  180. zend_compile_stmt_list
  181. zend_set_function_arg_flags
  182. zend_compile_typename
  183. zend_compile_params
  184. zend_compile_closure_uses
  185. zend_begin_method_decl
  186. zend_begin_func_decl
  187. zend_compile_func_decl
  188. zend_compile_prop_decl
  189. zend_compile_class_const_decl
  190. zend_compile_method_ref
  191. zend_compile_name_list
  192. zend_compile_trait_precedence
  193. zend_compile_trait_alias
  194. zend_compile_use_trait
  195. zend_compile_implements
  196. zend_generate_anon_class_name
  197. zend_compile_class_decl
  198. zend_get_import_ht
  199. zend_get_use_type_str
  200. zend_check_already_in_use
  201. zend_compile_use
  202. zend_compile_group_use
  203. zend_compile_const_decl
  204. zend_compile_namespace
  205. zend_compile_halt_compiler
  206. zend_try_ct_eval_magic_const
  207. zend_try_ct_eval_binary_op
  208. zend_ct_eval_unary_op
  209. zend_ct_eval_unary_pm
  210. zend_ct_eval_greater
  211. zend_try_ct_eval_array
  212. zend_compile_binary_op
  213. zend_compile_greater
  214. zend_compile_unary_op
  215. zend_compile_unary_pm
  216. zend_compile_short_circuiting
  217. zend_compile_post_incdec
  218. zend_compile_pre_incdec
  219. zend_compile_cast
  220. zend_compile_shorthand_conditional
  221. zend_compile_conditional
  222. zend_compile_coalesce
  223. zend_compile_print
  224. zend_compile_exit
  225. zend_compile_yield
  226. zend_compile_yield_from
  227. zend_compile_instanceof
  228. zend_compile_include_or_eval
  229. zend_compile_isset_or_empty
  230. zend_compile_silence
  231. zend_compile_shell_exec
  232. zend_compile_array
  233. zend_compile_const
  234. zend_compile_class_const
  235. zend_compile_resolve_class_name
  236. zend_compile_rope_add
  237. zend_compile_encaps_list
  238. zend_compile_magic_const
  239. zend_is_allowed_in_const_expr
  240. zend_compile_const_expr_class_const
  241. zend_compile_const_expr_const
  242. zend_compile_const_expr_magic_const
  243. zend_compile_const_expr
  244. zend_const_expr_to_zval
  245. zend_compile_top_stmt
  246. zend_compile_stmt
  247. zend_compile_expr
  248. zend_compile_var
  249. zend_delayed_compile_var
  250. zend_eval_const_expr

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

/* [<][>][^][v][top][bottom][index][help] */