diff --git a/Zend/tests/anon/015.phpt b/Zend/tests/anon/015.phpt new file mode 100644 index 0000000000000..af2aec9cfd1ca --- /dev/null +++ b/Zend/tests/anon/015.phpt @@ -0,0 +1,13 @@ +--TEST-- +anonymous class use global +--FILE-- +glow); + } +}; +?> +--EXPECT-- +int(50) diff --git a/Zend/tests/anon/016.phpt b/Zend/tests/anon/016.phpt new file mode 100644 index 0000000000000..21444639ab01c --- /dev/null +++ b/Zend/tests/anon/016.phpt @@ -0,0 +1,19 @@ +--TEST-- +anonymous class use global again +--FILE-- +glow); + } + }; +} + +thing(400); +thing(500); +?> +--EXPECT-- +int(400) +int(500) diff --git a/Zend/tests/anon/017.phpt b/Zend/tests/anon/017.phpt new file mode 100644 index 0000000000000..1e3287a82636d --- /dev/null +++ b/Zend/tests/anon/017.phpt @@ -0,0 +1,16 @@ +--TEST-- +anonymous class use private +--FILE-- + +--EXPECT-- +object(class@anonymous)#1 (1) { + ["glow":"class@anonymous":private]=> + int(50) +} diff --git a/Zend/tests/anon/018.phpt b/Zend/tests/anon/018.phpt new file mode 100644 index 0000000000000..2ed62cacd1dbd --- /dev/null +++ b/Zend/tests/anon/018.phpt @@ -0,0 +1,19 @@ +--TEST-- +anonymous class use ref +--FILE-- +glow); + $this->glow *= 2; + var_dump($this->glow); + } +}; +var_dump($glow); +?> +--EXPECT-- +int(50) +int(100) +int(100) diff --git a/Zend/tests/anon/019.phpt b/Zend/tests/anon/019.phpt new file mode 100644 index 0000000000000..0e3248f9bc4da --- /dev/null +++ b/Zend/tests/anon/019.phpt @@ -0,0 +1,21 @@ +--TEST-- +anonymous class use counted +--FILE-- +glow); + $this->glow .= " rocks"; + var_dump($this->glow); + } +}; + +var_dump($glow); +?> +--EXPECT-- +string(4) "php7" +string(10) "php7 rocks" +string(10) "php7 rocks" + diff --git a/Zend/tests/anon/020.phpt b/Zend/tests/anon/020.phpt new file mode 100644 index 0000000000000..f9b135bd473cc --- /dev/null +++ b/Zend/tests/anon/020.phpt @@ -0,0 +1,28 @@ +--TEST-- +anonymous class use prop ref +--FILE-- +glow) { + + public function __construct() { + var_dump($this->glow); + $this->glow .= " rocks"; + var_dump($this->glow); + } + }; + } +}; + +var_dump($glow); +?> +--EXPECT-- +string(4) "php7" +string(10) "php7 rocks" +string(10) "php7 rocks" + diff --git a/Zend/tests/anon/021.phpt b/Zend/tests/anon/021.phpt new file mode 100644 index 0000000000000..c2f62293f0315 --- /dev/null +++ b/Zend/tests/anon/021.phpt @@ -0,0 +1,26 @@ +--TEST-- +anonymous class use prop no ref +--FILE-- +glow) { + public function __construct() { + var_dump($this->glow); + $this->glow .= " rocks"; + var_dump($this->glow); + } + }; + } +}; + +var_dump($glow); +?> +--EXPECT-- +string(4) "php7" +string(10) "php7 rocks" +string(4) "php7" + + diff --git a/Zend/tests/anon/022.phpt b/Zend/tests/anon/022.phpt new file mode 100644 index 0000000000000..8bba560037b92 --- /dev/null +++ b/Zend/tests/anon/022.phpt @@ -0,0 +1,41 @@ +--TEST-- +anonymous class use prop object +--FILE-- +php7 = "php7"; + +new class use($glow) { + public function __construct() { + new class use($this->glow) { + public function __construct() { + var_dump($this->glow); + $this->glow->rocks = " rocks"; + var_dump($this->glow); + } + }; + } +}; + +var_dump($glow); +?> +--EXPECT-- +object(stdClass)#1 (1) { + ["php7"]=> + string(4) "php7" +} +object(stdClass)#1 (2) { + ["php7"]=> + string(4) "php7" + ["rocks"]=> + string(6) " rocks" +} +object(stdClass)#1 (2) { + ["php7"]=> + string(4) "php7" + ["rocks"]=> + string(6) " rocks" +} + + + diff --git a/Zend/tests/anon/023.phpt b/Zend/tests/anon/023.phpt new file mode 100644 index 0000000000000..eb59e2577b991 --- /dev/null +++ b/Zend/tests/anon/023.phpt @@ -0,0 +1,43 @@ +--TEST-- +anonymous class use prop object member object +--FILE-- +php7 = new stdClass; + +new class use($glow->php7) { + public function __construct() { + new class use($this->php7) { + public function __construct() { + var_dump($this->php7); + $this->php7->rocks = " rocks"; + var_dump($this->php7); + var_dump($this); + } + }; + } +}; + +var_dump($glow); +?> +--EXPECT-- +object(stdClass)#2 (0) { +} +object(stdClass)#2 (1) { + ["rocks"]=> + string(6) " rocks" +} +object(class@anonymous)#4 (1) { + ["php7":"class@anonymous":private]=> + object(stdClass)#2 (1) { + ["rocks"]=> + string(6) " rocks" + } +} +object(stdClass)#1 (1) { + ["php7"]=> + object(stdClass)#2 (1) { + ["rocks"]=> + string(6) " rocks" + } +} diff --git a/Zend/tests/anon/024.phpt b/Zend/tests/anon/024.phpt new file mode 100644 index 0000000000000..035107ada67d5 --- /dev/null +++ b/Zend/tests/anon/024.phpt @@ -0,0 +1,28 @@ +--TEST-- +anonymous class use prop object member change acc allow +--FILE-- +glow; + } +} + +new class use($glow) { + public function __construct() { + $foo = new class extends Foo use($this->glow) { + protected $glow; + }; + + var_dump($foo->method()); + } +}; + +var_dump($glow); +?> +--EXPECT-- +int(10) +int(10) + diff --git a/Zend/tests/anon/025.phpt b/Zend/tests/anon/025.phpt new file mode 100644 index 0000000000000..a493fd4c7dd0c --- /dev/null +++ b/Zend/tests/anon/025.phpt @@ -0,0 +1,12 @@ +--TEST-- +anonymous class cannot use variable twice +--FILE-- + +--EXPECTF-- +Fatal error: Cannot use property name glow twice in %s on line 4 + + diff --git a/Zend/tests/anon/026.phpt b/Zend/tests/anon/026.phpt new file mode 100644 index 0000000000000..7aa374cfcb16f --- /dev/null +++ b/Zend/tests/anon/026.phpt @@ -0,0 +1,18 @@ +--TEST-- +anonymous class cannot use variable twice +--FILE-- +glow) {}; + } +} + + +?> +--EXPECTF-- +Fatal error: Cannot use property name glow twice in %s on line 6 + + diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index cfcd636269cb8..8f70ccd36366d 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -70,7 +70,7 @@ ZEND_API zend_ast *zend_ast_create_zval_ex(zval *zv, zend_ast_attr attr) { ZEND_API zend_ast *zend_ast_create_decl( zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment, - zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2, zend_ast *child3 + zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2, zend_ast *child3, zend_ast *child4 ) { zend_ast_decl *ast; @@ -87,6 +87,7 @@ ZEND_API zend_ast *zend_ast_create_decl( ast->child[1] = child1; ast->child[2] = child2; ast->child[3] = child3; + ast->child[4] = child4; return (zend_ast *) ast; } @@ -472,6 +473,9 @@ static void zend_ast_destroy_ex(zend_ast *ast, zend_bool free) { zend_ast_destroy_ex(decl->child[1], free); zend_ast_destroy_ex(decl->child[2], free); zend_ast_destroy_ex(decl->child[3], free); + if (decl->child[4]) { + zend_ast_destroy_ex(decl->child[4], free); + } break; } default: diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index ec771003c0c9d..cf8da8d818ea7 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -58,6 +58,7 @@ enum _zend_ast_kind { ZEND_AST_NAME_LIST, ZEND_AST_TRAIT_ADAPTATIONS, ZEND_AST_USE, + ZEND_AST_ANON_USE, /* 0 child nodes */ ZEND_AST_MAGIC_CONST = 0 << ZEND_AST_NUM_CHILDREN_SHIFT, @@ -184,7 +185,7 @@ typedef struct _zend_ast_decl { unsigned char *lex_pos; zend_string *doc_comment; zend_string *name; - zend_ast *child[4]; + zend_ast *child[5]; } zend_ast_decl; typedef void (*zend_ast_process_t)(zend_ast *ast); @@ -197,7 +198,7 @@ ZEND_API zend_ast *zend_ast_create(zend_ast_kind kind, ...); ZEND_API zend_ast *zend_ast_create_decl( zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment, - zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2, zend_ast *child3 + zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2, zend_ast *child3, zend_ast *child4 ); ZEND_API zend_ast *zend_ast_create_list(uint32_t init_children, zend_ast_kind kind, ...); diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index da2c83c55ecd3..31e928409a022 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -3158,10 +3158,9 @@ ZEND_API zend_uchar zend_get_call_op(zend_uchar init_op, zend_function *fbc) /* } /* }}} */ -void zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *fbc) /* {{{ */ +void zend_compile_call_common_ex(znode *result, zend_ast *args_ast, zend_function *fbc, uint32_t opnum_init) /* {{{ */ { zend_op *opline; - uint32_t opnum_init = get_next_op_number(CG(active_op_array)) - 1; uint32_t arg_count; uint32_t call_flags; @@ -3181,6 +3180,11 @@ void zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function * opline->op1.num = call_flags; zend_do_extended_fcall_end(); +} /* }}} */ + +void zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *fbc) /* {{{ */ +{ + zend_compile_call_common_ex(result, args_ast, fbc, get_next_op_number(CG(active_op_array)) - 1); } /* }}} */ @@ -3771,12 +3775,127 @@ void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{ } /* }}} */ -void zend_compile_class_decl(zend_ast *ast); +void zend_compile_anon_declare(zend_class_entry *ce, zend_ast *use_ast) { /* {{{ */ + zend_ast_list *use_list = zend_ast_get_list(use_ast); + uint32_t i = 0; + HashTable used; + zval nil; + zend_class_entry *scope = EG(scope); + + ZVAL_NULL(&nil); + + zend_hash_init(&used, 8, NULL, NULL, 0); + + for (i = 0; i < use_list->children; i++) { + zend_ast *use_var = use_list->child[i]; + zend_op *opline; + zend_bool by_ref = use_var->attr; + zend_property_info *info; + zend_string *var_name; + + switch (use_var->kind) { + case ZEND_AST_ZVAL: { + var_name = zend_ast_get_str(use_var); + + if (zend_hash_exists(&used, var_name)) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use property name %s twice", ZSTR_VAL(var_name)); + } + + if (zend_string_equals_literal(var_name, "this")) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as lexical variable"); + } + + if (zend_is_auto_global(var_name)) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use auto-global as lexical variable"); + } + + if (!zend_hash_exists(&ce->properties_info, var_name)) { + zend_declare_property(ce, ZSTR_VAL(var_name), ZSTR_LEN(var_name), &nil, ZEND_ACC_PRIVATE); + } + } break; + + case ZEND_AST_PROP: { + var_name = zend_ast_get_str(use_var->child[1]); + + if (zend_hash_exists(&used, var_name)) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use property name %s twice", ZSTR_VAL(var_name)); + } + + if (!zend_hash_exists(&ce->properties_info, var_name)) { + zend_declare_property(ce, ZSTR_VAL(var_name), ZSTR_LEN(var_name), &nil, ZEND_ACC_PRIVATE); + } + } break; + } + zend_hash_add_empty_element(&used, var_name); + } + zend_hash_destroy(&used); +} /* }}} */ + +void zend_compile_anon_use(znode *object, zend_ast *use_ast) { /* {{{ */ + zend_ast_list *use_list = zend_ast_get_list(use_ast); + uint32_t i = 0; + HashTable used; + + zend_hash_init(&used, 8, NULL, NULL, 0); + + for (i = 0; i < use_list->children; i++) { + zend_ast *use_var = use_list->child[i]; + zend_op *opline; + zend_bool by_ref = use_var->attr; + + switch (use_var->kind) { + case ZEND_AST_ZVAL: { + zend_string *var_name = + zend_string_copy( + zend_ast_get_str(use_var)); + + if (zend_hash_exists(&used, var_name)) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use variable $%s twice", ZSTR_VAL(var_name)); + } + + if (zend_string_equals_literal(var_name, "this")) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as lexical variable"); + } + + if (zend_is_auto_global(var_name)) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use auto-global as lexical variable"); + } + + opline = zend_emit_op(NULL, ZEND_BIND_ANON_VAR, object, NULL); + opline->op2_type = IS_CV; + opline->op2.var = lookup_cv(CG(active_op_array), var_name); + opline->extended_value = by_ref; + zend_hash_add_empty_element(&used, var_name); + } break; + + case ZEND_AST_PROP: { + znode prop; + zend_string *name = + zend_string_copy( + zend_ast_get_str(use_var->child[1])); + + zend_compile_prop(&prop, use_var, BP_VAR_R); + + opline = zend_emit_op(NULL, ZEND_BIND_ANON_PROP, object, NULL); + opline->op2_type = IS_CONST; + opline->op2.constant = + zend_add_literal_string(CG(active_op_array), &name); + opline->extended_value = by_ref; + zend_emit_op_data(&prop); + } break; + } + } + + zend_hash_destroy(&used); +} /* }}} */ + +zend_ast* zend_compile_class_decl(zend_ast *ast); void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */ { zend_ast *class_ast = ast->child[0]; zend_ast *args_ast = ast->child[1]; + zend_ast *use_ast = NULL; znode class_node, ctor_result; zend_op *opline; @@ -3784,7 +3903,8 @@ void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */ if (class_ast->kind == ZEND_AST_CLASS) { uint32_t dcl_opnum = get_next_op_number(CG(active_op_array)); - zend_compile_class_decl(class_ast); + use_ast = zend_compile_class_decl(class_ast); + /* jump over anon class declaration */ opline = &CG(active_op_array)->opcodes[dcl_opnum]; if (opline->opcode == ZEND_FETCH_CLASS) { @@ -3808,7 +3928,11 @@ void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */ SET_NODE(opline->op1, &class_node); } - zend_compile_call_common(&ctor_result, args_ast, NULL); + if (use_ast) { + zend_compile_anon_use(result, use_ast); + } + + zend_compile_call_common_ex(&ctor_result, args_ast, NULL, opnum); zend_do_free(&ctor_result); /* We save the position of DO_FCALL for convenience in find_live_range(). @@ -5654,12 +5778,14 @@ static zend_string *zend_generate_anon_class_name(unsigned char *lex_pos) /* {{{ } /* }}} */ -void zend_compile_class_decl(zend_ast *ast) /* {{{ */ +zend_ast* zend_compile_class_decl(zend_ast *ast) /* {{{ */ { zend_ast_decl *decl = (zend_ast_decl *) ast; zend_ast *extends_ast = decl->child[0]; zend_ast *implements_ast = decl->child[1]; zend_ast *stmt_ast = decl->child[2]; + zend_ast *use_ast = decl->child[4]; + zend_string *name, *lcname, *import_name = NULL; zend_class_entry *ce = zend_arena_alloc(&CG(arena), sizeof(zend_class_entry)); zend_op *opline; @@ -5767,6 +5893,10 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */ zend_compile_stmt(stmt_ast); + if (use_ast) { + zend_compile_anon_declare(ce, use_ast); + } + /* Reset lineno for final opcodes and errors */ CG(zend_lineno) = ast->lineno; @@ -5846,6 +5976,8 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */ FC(implementing_class) = original_implementing_class; CG(active_class_entry) = original_ce; + + return use_ast; } /* }}} */ diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 5404754cc1dde..4dfff2cd745d5 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2998,6 +2998,47 @@ ZEND_API void ZEND_FASTCALL zend_check_missing_arg(zend_execute_data *execute_da zend_verify_missing_arg(execute_data, arg_num, cache_slot); } +static inline zval* zend_anon_fetch_prop(zval *object, zend_string *prop, int type, zval *val) { + zval name; + zend_class_entry *scope = EG(scope); + zval *val_ptr; + zend_string *key; + ZVAL_STR(&name, prop); + + EG(scope) = Z_OBJCE_P(object); + + val_ptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, &name, type, NULL); + + EG(scope) = scope; + + return val_ptr; +} + +void zend_anon_bind_var(zval *object, zend_string *prop, zval *var) { + zval *var_ptr; + + if (Z_ISREF_P(var)) { + var_ptr = zend_anon_fetch_prop(object, prop, BP_VAR_RW, var); + + if (var_ptr) { + Z_ADDREF_P(var); + ZVAL_REF(var_ptr, Z_REF_P(var)); + return; + } + } + + var_ptr = zend_anon_fetch_prop(object, prop, BP_VAR_R, var); + + if (var_ptr != var) { + zend_class_entry *scope = EG(scope); + zval name; + ZVAL_STR(&name, prop); + + EG(scope) = Z_OBJCE_P(object); + Z_OBJ_HT_P(object)->write_property(object, &name, var, NULL); + EG(scope) = scope; + } +} /* * Local variables: * tab-width: 4 diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 738895e73cad3..4e2b6e7a9ba8a 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -360,6 +360,8 @@ void zend_cleanup_unfinished_execution(zend_execute_data *execute_data, uint32_t } \ } while (0) +void zend_anon_bind_var(zval *object, zend_string *prop, zval *var); + END_EXTERN_C() #endif /* ZEND_EXECUTE_H */ diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 53b2f3f50bea1..cdd2aa48e5b96 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -236,7 +236,8 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %type extends_from parameter optional_type argument expr_without_variable global_var %type static_var class_statement trait_adaptation trait_precedence trait_alias %type absolute_trait_method_reference trait_method_reference property echo_expr -%type new_expr anonymous_class class_name class_name_reference simple_variable +%type new_expr anonymous_class anonymous_class_use anonymous_class_use_list anonymous_class_use_var +%type class_name class_name_reference simple_variable %type internal_functions_in_yacc %type exit_expr scalar backticks_expr lexical_var function_call member_name property_name %type variable_class_name dereferencable_scalar constant dereferencable @@ -478,7 +479,7 @@ function_declaration_statement: function returns_ref T_STRING backup_doc_comment '(' parameter_list ')' return_type '{' inner_statement_list '}' { $$ = zend_ast_create_decl(ZEND_AST_FUNC_DECL, $2, $1, $4, - zend_ast_get_str($3), $6, NULL, $10, $8); } + zend_ast_get_str($3), $6, NULL, $10, $8, NULL); } ; is_reference: @@ -494,10 +495,10 @@ is_variadic: class_declaration_statement: class_modifiers T_CLASS { $$ = CG(zend_lineno); } T_STRING extends_from implements_list backup_doc_comment '{' class_statement_list '}' - { $$ = zend_ast_create_decl(ZEND_AST_CLASS, $1, $3, $7, zend_ast_get_str($4), $5, $6, $9, NULL); } + { $$ = zend_ast_create_decl(ZEND_AST_CLASS, $1, $3, $7, zend_ast_get_str($4), $5, $6, $9, NULL, NULL); } | T_CLASS { $$ = CG(zend_lineno); } T_STRING extends_from implements_list backup_doc_comment '{' class_statement_list '}' - { $$ = zend_ast_create_decl(ZEND_AST_CLASS, 0, $2, $6, zend_ast_get_str($3), $4, $5, $8, NULL); } + { $$ = zend_ast_create_decl(ZEND_AST_CLASS, 0, $2, $6, zend_ast_get_str($3), $4, $5, $8, NULL, NULL); } ; class_modifiers: @@ -513,13 +514,13 @@ class_modifier: trait_declaration_statement: T_TRAIT { $$ = CG(zend_lineno); } T_STRING backup_doc_comment '{' class_statement_list '}' - { $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_TRAIT, $2, $4, zend_ast_get_str($3), NULL, NULL, $6, NULL); } + { $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_TRAIT, $2, $4, zend_ast_get_str($3), NULL, NULL, $6, NULL, NULL); } ; interface_declaration_statement: T_INTERFACE { $$ = CG(zend_lineno); } T_STRING interface_extends_list backup_doc_comment '{' class_statement_list '}' - { $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_INTERFACE, $2, $5, zend_ast_get_str($3), NULL, $4, $7, NULL); } + { $$ = zend_ast_create_decl(ZEND_AST_CLASS, ZEND_ACC_INTERFACE, $2, $5, zend_ast_get_str($3), NULL, $4, $7, NULL, NULL); } ; extends_from: @@ -710,7 +711,7 @@ class_statement: | method_modifiers function returns_ref identifier backup_doc_comment '(' parameter_list ')' return_type method_body { $$ = zend_ast_create_decl(ZEND_AST_METHOD, $3 | $1, $2, $5, - zend_ast_get_str($4), $7, NULL, $10, $9); } + zend_ast_get_str($4), $7, NULL, $10, $9, NULL); } ; name_list: @@ -837,12 +838,30 @@ non_empty_for_exprs: | expr { $$ = zend_ast_create_list(1, ZEND_AST_EXPR_LIST, $1); } ; +anonymous_class_use_var: + lexical_var { $$ = $1; } + | new_variable T_OBJECT_OPERATOR T_STRING + { $$ = zend_ast_create(ZEND_AST_PROP, $1, $3); } + | '&' new_variable T_OBJECT_OPERATOR T_STRING + { $$ = zend_ast_create(ZEND_AST_PROP, $2, $4); $$->attr = 1; } +; + +anonymous_class_use_list: + anonymous_class_use_list ',' anonymous_class_use_var { $$ = zend_ast_list_add($1, $3); } + | anonymous_class_use_var { $$ = zend_ast_create_list(1, ZEND_AST_ANON_USE, $1); } +; + +anonymous_class_use: + /* empty */ { $$ = NULL; } + | T_USE '(' anonymous_class_use_list ')' { $$ = $3; } +; + anonymous_class: T_CLASS { $$ = CG(zend_lineno); } ctor_arguments - extends_from implements_list backup_doc_comment '{' class_statement_list '}' { + extends_from implements_list backup_doc_comment anonymous_class_use '{' class_statement_list '}' { zend_ast *decl = zend_ast_create_decl( ZEND_AST_CLASS, ZEND_ACC_ANON_CLASS, $2, $6, NULL, - $4, $5, $8, NULL); + $4, $5, $9, NULL, $7); $$ = zend_ast_create(ZEND_AST_NEW, decl, $3); } ; @@ -965,12 +984,12 @@ expr_without_variable: '{' inner_statement_list '}' { $$ = zend_ast_create_decl(ZEND_AST_CLOSURE, $2, $1, $3, zend_string_init("{closure}", sizeof("{closure}") - 1, 0), - $5, $7, $10, $8); } + $5, $7, $10, $8, NULL); } | T_STATIC function returns_ref backup_doc_comment '(' parameter_list ')' lexical_vars return_type '{' inner_statement_list '}' { $$ = zend_ast_create_decl(ZEND_AST_CLOSURE, $3 | ZEND_ACC_STATIC, $2, $4, zend_string_init("{closure}", sizeof("{closure}") - 1, 0), - $6, $8, $11, $9); } + $6, $8, $11, $9, NULL); } ; function: diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index b96ce22c0ddec..386a8424f2c1b 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -8217,6 +8217,64 @@ ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, CONST, REF) ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } +ZEND_VM_HANDLER(184, ZEND_BIND_ANON_VAR, VAR, CV, REF) +{ + USE_OPLINE + zend_free_op free_op2; + zval *var; + zval *object = EX_VAR(opline->op1.var); + + if (opline->extended_value) { + /* By-ref binding */ + var = GET_OP2_ZVAL_PTR(BP_VAR_W); + ZVAL_MAKE_REF(var); + Z_ADDREF_P(var); + SAVE_OPLINE(); + } else { + var = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); + if (UNEXPECTED(Z_ISUNDEF_P(var))) { + SAVE_OPLINE(); + var = GET_OP2_UNDEF_CV(var, BP_VAR_R); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + ZVAL_DEREF(var); + Z_TRY_ADDREF_P(var); + SAVE_OPLINE(); + } + + zend_anon_bind_var(object, CV_DEF_OF(EX_VAR_TO_NUM(opline->op2.var)), var); + + FREE_OP2(); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +ZEND_VM_HANDLER(185, ZEND_BIND_ANON_PROP, VAR, CONST, SPEC(OP_DATA=VAR)) +{ + USE_OPLINE + zend_free_op free_op_data; + zval *var; + SAVE_OPLINE(); + + if (opline->extended_value) { + /* By-ref binding */ + var = GET_OP_DATA_ZVAL_PTR(BP_VAR_W); + ZVAL_MAKE_REF(var); + Z_ADDREF_P(var); + } else { + var = GET_OP_DATA_ZVAL_PTR(BP_VAR_R); + ZVAL_DEREF(var); + Z_TRY_ADDREF_P(var); + } + + zend_anon_bind_var(EX_VAR(opline->op1.var), Z_STR_P(EX_CONSTANT(opline->op2)), var); + + FREE_OP_DATA(); + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + ZEND_VM_TYPE_SPEC_HANDLER(ZEND_ADD, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_ADD_LONG_NO_OVERFLOW, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE)) { USE_OPLINE diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index b43ea8f159fd4..12b0971bbc6d5 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -19781,6 +19781,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z ZEND_VM_RETURN(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_ANON_PROP_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op_data; + zval *var; + SAVE_OPLINE(); + + if (opline->extended_value) { + /* By-ref binding */ + var = _get_zval_ptr_var((opline+1)->op1.var, execute_data, &free_op_data); + ZVAL_MAKE_REF(var); + Z_ADDREF_P(var); + } else { + var = _get_zval_ptr_var((opline+1)->op1.var, execute_data, &free_op_data); + ZVAL_DEREF(var); + Z_TRY_ADDREF_P(var); + } + + zend_anon_bind_var(EX_VAR(opline->op1.var), Z_STR_P(EX_CONSTANT(opline->op2)), var); + + zval_ptr_dtor_nogc(free_op_data); + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -24119,6 +24143,38 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND ZEND_VM_RETURN(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_ANON_VAR_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *var; + zval *object = EX_VAR(opline->op1.var); + + if (opline->extended_value) { + /* By-ref binding */ + var = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op2.var); + ZVAL_MAKE_REF(var); + Z_ADDREF_P(var); + SAVE_OPLINE(); + } else { + var = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); + if (UNEXPECTED(Z_ISUNDEF_P(var))) { + SAVE_OPLINE(); + var = GET_OP2_UNDEF_CV(var, BP_VAR_R); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } + } + ZVAL_DEREF(var); + Z_TRY_ADDREF_P(var); + SAVE_OPLINE(); + } + + zend_anon_bind_var(object, CV_DEF_OF(EX_VAR_TO_NUM(opline->op2.var)), var); + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMPVAR(binary_op_type binary_op ZEND_OPCODE_HANDLER_ARGS_DC) { USE_OPLINE @@ -59121,6 +59177,156 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BIND_ANON_VAR_SPEC_VAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BIND_ANON_PROP_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV_HANDLER, ZEND_ADD_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV_HANDLER, ZEND_NULL_HANDLER, @@ -60089,7 +60295,7 @@ void zend_init_opcodes_handlers(void) 776 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_RETVAL, 826 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 851 | SPEC_RULE_OP1, - 3845, + 3995, 856, 857 | SPEC_RULE_OP1, 862 | SPEC_RULE_OP1, @@ -60097,9 +60303,9 @@ void zend_init_opcodes_handlers(void) 872 | SPEC_RULE_OP1, 877 | SPEC_RULE_OP1, 882 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 3845, - 3845, - 3845, + 3995, + 3995, + 3995, 907 | SPEC_RULE_OP1, 912 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 937 | SPEC_RULE_OP1 | SPEC_RULE_OP2, @@ -60148,7 +60354,7 @@ void zend_init_opcodes_handlers(void) 1646 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1671 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 1696 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 3845, + 3995, 1721, 1722, 1723, @@ -60232,7 +60438,9 @@ void zend_init_opcodes_handlers(void) 2845 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 2870 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 2895 | SPEC_RULE_OP1 | SPEC_RULE_OP2, - 3845 + 2920 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2945 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_OP_DATA, + 3995 }; zend_opcode_handlers = labels; zend_handlers_count = sizeof(labels) / sizeof(void*); @@ -60331,7 +60539,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2920 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 3070 | SPEC_RULE_OP1 | SPEC_RULE_OP2; if (op->op1_type > op->op2_type) { zend_swap_operands(op); } @@ -60339,7 +60547,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2945 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 3095 | SPEC_RULE_OP1 | SPEC_RULE_OP2; if (op->op1_type > op->op2_type) { zend_swap_operands(op); } @@ -60347,7 +60555,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2970 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 3120 | SPEC_RULE_OP1 | SPEC_RULE_OP2; if (op->op1_type > op->op2_type) { zend_swap_operands(op); } @@ -60358,17 +60566,17 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 2995 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 3145 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } else if ((op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG)) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3020 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 3170 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } else if ((op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE)) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3045 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 3195 | SPEC_RULE_OP1 | SPEC_RULE_OP2; } break; case ZEND_MUL: @@ -60376,7 +60584,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3070 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 3220 | SPEC_RULE_OP1 | SPEC_RULE_OP2; if (op->op1_type > op->op2_type) { zend_swap_operands(op); } @@ -60384,7 +60592,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3095 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 3245 | SPEC_RULE_OP1 | SPEC_RULE_OP2; if (op->op1_type > op->op2_type) { zend_swap_operands(op); } @@ -60392,7 +60600,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3120 | SPEC_RULE_OP1 | SPEC_RULE_OP2; + spec = 3270 | SPEC_RULE_OP1 | SPEC_RULE_OP2; if (op->op1_type > op->op2_type) { zend_swap_operands(op); } @@ -60403,7 +60611,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3145 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3295 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; if (op->op1_type > op->op2_type) { zend_swap_operands(op); } @@ -60411,7 +60619,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3220 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3370 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; if (op->op1_type > op->op2_type) { zend_swap_operands(op); } @@ -60422,7 +60630,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3295 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3445 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; if (op->op1_type > op->op2_type) { zend_swap_operands(op); } @@ -60430,7 +60638,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3370 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3520 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; if (op->op1_type > op->op2_type) { zend_swap_operands(op); } @@ -60441,12 +60649,12 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3445 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3595 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } else if ((op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE)) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3520 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3670 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } break; case ZEND_IS_SMALLER_OR_EQUAL: @@ -60454,55 +60662,55 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3595 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3745 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } else if ((op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE)) { if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) { break; } - spec = 3670 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; + spec = 3820 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH; } break; case ZEND_QM_ASSIGN: if ((op1_info == MAY_BE_DOUBLE)) { - spec = 3835 | SPEC_RULE_OP1; + spec = 3985 | SPEC_RULE_OP1; } else if ((!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE))))) { - spec = 3840 | SPEC_RULE_OP1; + spec = 3990 | SPEC_RULE_OP1; } break; case ZEND_PRE_INC: if ((res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG)) { - spec = 3745 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL; + spec = 3895 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL; } else if ((op1_info == MAY_BE_LONG)) { - spec = 3755 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL; + spec = 3905 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL; } else if ((op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE))) { - spec = 3765 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL; + spec = 3915 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL; } break; case ZEND_PRE_DEC: if ((res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG)) { - spec = 3775 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL; + spec = 3925 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL; } else if ((op1_info == MAY_BE_LONG)) { - spec = 3785 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL; + spec = 3935 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL; } else if ((op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE))) { - spec = 3795 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL; + spec = 3945 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL; } break; case ZEND_POST_INC: if ((res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG)) { - spec = 3805 | SPEC_RULE_OP1; + spec = 3955 | SPEC_RULE_OP1; } else if ((op1_info == MAY_BE_LONG)) { - spec = 3810 | SPEC_RULE_OP1; + spec = 3960 | SPEC_RULE_OP1; } else if ((op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE))) { - spec = 3815 | SPEC_RULE_OP1; + spec = 3965 | SPEC_RULE_OP1; } break; case ZEND_POST_DEC: if ((res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG)) { - spec = 3820 | SPEC_RULE_OP1; + spec = 3970 | SPEC_RULE_OP1; } else if ((op1_info == MAY_BE_LONG)) { - spec = 3825 | SPEC_RULE_OP1; + spec = 3975 | SPEC_RULE_OP1; } else if ((op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE))) { - spec = 3830 | SPEC_RULE_OP1; + spec = 3980 | SPEC_RULE_OP1; } break; default: diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index d4c76ad2657a1..49c01b4582c73 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -21,7 +21,7 @@ #include #include -static const char *zend_vm_opcodes_names[184] = { +static const char *zend_vm_opcodes_names[186] = { "ZEND_NOP", "ZEND_ADD", "ZEND_SUB", @@ -206,9 +206,11 @@ static const char *zend_vm_opcodes_names[184] = { "ZEND_FETCH_CLASS_CONSTANT", "ZEND_BIND_LEXICAL", "ZEND_BIND_STATIC", + "ZEND_BIND_ANON_VAR", + "ZEND_BIND_ANON_PROP", }; -static uint32_t zend_vm_opcodes_flags[184] = { +static uint32_t zend_vm_opcodes_flags[186] = { 0x00000000, 0x00000707, 0x00000707, @@ -393,6 +395,8 @@ static uint32_t zend_vm_opcodes_flags[184] = { 0x00000373, 0x00100101, 0x00100301, + 0x00100101, + 0x00000301, }; ZEND_API const char* zend_get_opcode_name(zend_uchar opcode) { diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h index 90f2ea4e51a27..f632410b54653 100644 --- a/Zend/zend_vm_opcodes.h +++ b/Zend/zend_vm_opcodes.h @@ -249,7 +249,9 @@ END_EXTERN_C() #define ZEND_FETCH_CLASS_CONSTANT 181 #define ZEND_BIND_LEXICAL 182 #define ZEND_BIND_STATIC 183 +#define ZEND_BIND_ANON_VAR 184 +#define ZEND_BIND_ANON_PROP 185 -#define ZEND_VM_LAST_OPCODE 183 +#define ZEND_VM_LAST_OPCODE 185 #endif