-
Notifications
You must be signed in to change notification settings - Fork 8k
Fix GH-10497: Allow const obj->prop = value #20903
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| --TEST-- | ||
| GH-10497: Allow direct modification of object stored in a constant | ||
| --FILE-- | ||
| <?php | ||
| const a = new stdClass; | ||
| a->b = 42; | ||
| var_dump(a->b); | ||
|
|
||
| const obj = new stdClass; | ||
| obj->foo = 'bar'; | ||
| obj->baz = 123; | ||
| var_dump(obj->foo, obj->baz); | ||
|
|
||
| const nested = new stdClass; | ||
| nested->inner = new stdClass; | ||
| nested->inner->value = 999; | ||
| var_dump(nested->inner->value); | ||
|
|
||
| const readTest = new stdClass; | ||
| readTest->prop = 'test'; | ||
| echo readTest->prop . "\n"; | ||
|
|
||
| var_dump(isset(readTest->prop)); | ||
| var_dump(empty(readTest->missing)); | ||
|
|
||
| const modTest = new stdClass; | ||
| modTest->val = 1; | ||
| modTest->val = 2; | ||
| var_dump(modTest->val); | ||
| ?> | ||
| --EXPECT-- | ||
| int(42) | ||
| string(3) "bar" | ||
| int(123) | ||
| int(999) | ||
| test | ||
| bool(true) | ||
| bool(true) | ||
| int(2) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11101,7 +11101,7 @@ static void zend_compile_array(znode *result, zend_ast *ast) /* {{{ */ | |
| } | ||
| /* }}} */ | ||
|
|
||
| static void zend_compile_const(znode *result, const zend_ast *ast) /* {{{ */ | ||
| static zend_op *zend_compile_const_inner(znode *result, const zend_ast *ast, bool use_tmp) /* {{{ */ | ||
| { | ||
| zend_ast *name_ast = ast->child[0]; | ||
|
|
||
|
|
@@ -11125,17 +11125,21 @@ static void zend_compile_const(znode *result, const zend_ast *ast) /* {{{ */ | |
| result->op_type = IS_CONST; | ||
| ZVAL_LONG(&result->u.constant, Z_LVAL_P(zend_ast_get_zval(last->child[0]))); | ||
| zend_string_release_ex(resolved_name, 0); | ||
| return; | ||
| return NULL; | ||
| } | ||
| } | ||
|
|
||
| if (zend_try_ct_eval_const(&result->u.constant, resolved_name, is_fully_qualified)) { | ||
| result->op_type = IS_CONST; | ||
| zend_string_release_ex(resolved_name, 0); | ||
| return; | ||
| return NULL; | ||
| } | ||
|
|
||
| opline = zend_emit_op_tmp(result, ZEND_FETCH_CONSTANT, NULL, NULL); | ||
| if (use_tmp) { | ||
| opline = zend_emit_op_tmp(result, ZEND_FETCH_CONSTANT, NULL, NULL); | ||
| } else { | ||
| opline = zend_emit_op(result, ZEND_FETCH_CONSTANT, NULL, NULL); | ||
| } | ||
| opline->op2_type = IS_CONST; | ||
|
|
||
| if (is_fully_qualified || !FC(current_namespace)) { | ||
|
|
@@ -11148,6 +11152,13 @@ static void zend_compile_const(znode *result, const zend_ast *ast) /* {{{ */ | |
| resolved_name, true); | ||
| } | ||
| opline->extended_value = zend_alloc_cache_slot(); | ||
| return opline; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This return value should be unneded. It's only needed for specific opcodes, e.g. to add some extended_value flag. Just return |
||
| } | ||
| /* }}} */ | ||
|
|
||
| static void zend_compile_const(znode *result, const zend_ast *ast) /* {{{ */ | ||
| { | ||
| zend_compile_const_inner(result, ast, true); | ||
| } | ||
| /* }}} */ | ||
|
|
||
|
|
@@ -12085,6 +12096,8 @@ static zend_op *zend_compile_var_inner(znode *result, zend_ast *ast, uint32_t ty | |
| case ZEND_AST_ZNODE: | ||
| *result = *zend_ast_get_znode(ast); | ||
| return NULL; | ||
| case ZEND_AST_CONST: | ||
| return zend_compile_const_inner(result, ast, false); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should pass |
||
| default: | ||
| if (type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) { | ||
| zend_error_noreturn(E_COMPILE_ERROR, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
zend_compile_const()is only used from one other place, no need for this BC layer. You can just passBP_VAR_Rfromzend_compile_expr_inner().