mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
[Bug #19021] Fix safe call w/ conditional assign
As of fbaac837cf, when we were performing
a safe call (`o&.x=`) with a conditional assign (`||= 1`) and discarding
the result the stack would end up in a bad state due to a missing pop.
This commit fixes that by adjusting the target label of the branchnil to
be before a pop in that case (as was previously done in the
non-conditional assignment case).
This commit is contained in:
parent
e3cc1a6cae
commit
b361bdc200
Notes:
git
2022-09-26 12:45:16 +09:00
2 changed files with 14 additions and 11 deletions
|
|
@ -8728,10 +8728,6 @@ compile_op_asgn2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
|
||||||
}
|
}
|
||||||
|
|
||||||
ADD_LABEL(ret, lfin);
|
ADD_LABEL(ret, lfin);
|
||||||
ADD_INSN(ret, node, pop);
|
|
||||||
if (lskip) {
|
|
||||||
ADD_LABEL(ret, lskip);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CHECK(COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value));
|
CHECK(COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value));
|
||||||
|
|
@ -8741,6 +8737,7 @@ compile_op_asgn2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
|
||||||
ADD_INSN1(ret, node, topn, INT2FIX(1));
|
ADD_INSN1(ret, node, topn, INT2FIX(1));
|
||||||
}
|
}
|
||||||
ADD_SEND_WITH_FLAG(ret, node, aid, INT2FIX(1), INT2FIX(asgnflag));
|
ADD_SEND_WITH_FLAG(ret, node, aid, INT2FIX(1), INT2FIX(asgnflag));
|
||||||
|
}
|
||||||
if (lskip && popped) {
|
if (lskip && popped) {
|
||||||
ADD_LABEL(ret, lskip);
|
ADD_LABEL(ret, lskip);
|
||||||
}
|
}
|
||||||
|
|
@ -8748,7 +8745,6 @@ compile_op_asgn2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
|
||||||
if (lskip && !popped) {
|
if (lskip && !popped) {
|
||||||
ADD_LABEL(ret, lskip);
|
ADD_LABEL(ret, lskip);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return COMPILE_OK;
|
return COMPILE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,12 +47,19 @@ class TestCall < Test::Unit::TestCase
|
||||||
assert_equal(5, o.y)
|
assert_equal(5, o.y)
|
||||||
o&.z ||= 6
|
o&.z ||= 6
|
||||||
assert_equal(6, o.z)
|
assert_equal(6, o.z)
|
||||||
|
o&.z &&= 7
|
||||||
|
assert_equal(7, o.z)
|
||||||
|
|
||||||
o = nil
|
o = nil
|
||||||
assert_nil(o&.x)
|
assert_nil(o&.x)
|
||||||
assert_nothing_raised(NoMethodError) {o&.x = raise}
|
assert_nothing_raised(NoMethodError) {o&.x = raise}
|
||||||
|
assert_nothing_raised(NoMethodError) {o&.x = raise; nil}
|
||||||
assert_nothing_raised(NoMethodError) {o&.x *= raise}
|
assert_nothing_raised(NoMethodError) {o&.x *= raise}
|
||||||
assert_nothing_raised(NoMethodError) {o&.x *= raise; nil}
|
assert_nothing_raised(NoMethodError) {o&.x *= raise; nil}
|
||||||
|
assert_nothing_raised(NoMethodError) {o&.x ||= raise}
|
||||||
|
assert_nothing_raised(NoMethodError) {o&.x ||= raise; nil}
|
||||||
|
assert_nothing_raised(NoMethodError) {o&.x &&= raise}
|
||||||
|
assert_nothing_raised(NoMethodError) {o&.x &&= raise; nil}
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_safe_call_evaluate_arguments_only_method_call_is_made
|
def test_safe_call_evaluate_arguments_only_method_call_is_made
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue