[Bug #20468] Fix safe navigation in for
variable
This commit is contained in:
parent
9d69619623
commit
2dd46bb82f
17
compile.c
17
compile.c
@ -5380,12 +5380,17 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const
|
||||
|
||||
CHECK(COMPILE_POPPED(pre, "masgn lhs (NODE_ATTRASGN)", node));
|
||||
|
||||
bool safenav_call = false;
|
||||
LINK_ELEMENT *insn_element = LAST_ELEMENT(pre);
|
||||
iobj = (INSN *)get_prev_insn((INSN *)insn_element); /* send insn */
|
||||
ASSUME(iobj);
|
||||
ELEM_REMOVE(LAST_ELEMENT(pre));
|
||||
ELEM_REMOVE((LINK_ELEMENT *)iobj);
|
||||
pre->last = iobj->link.prev;
|
||||
ELEM_REMOVE(insn_element);
|
||||
if (!IS_INSN_ID(iobj, send)) {
|
||||
safenav_call = true;
|
||||
iobj = (INSN *)get_prev_insn(iobj);
|
||||
ELEM_INSERT_NEXT(&iobj->link, insn_element);
|
||||
}
|
||||
(pre->last = iobj->link.prev)->next = 0;
|
||||
|
||||
const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(iobj, 0);
|
||||
int argc = vm_ci_argc(ci) + 1;
|
||||
@ -5404,7 +5409,9 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const
|
||||
return COMPILE_NG;
|
||||
}
|
||||
|
||||
ADD_ELEM(lhs, (LINK_ELEMENT *)iobj);
|
||||
iobj->link.prev = lhs->last;
|
||||
lhs->last->next = &iobj->link;
|
||||
for (lhs->last = &iobj->link; lhs->last->next; lhs->last = lhs->last->next);
|
||||
if (vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT) {
|
||||
int argc = vm_ci_argc(ci);
|
||||
bool dupsplat = false;
|
||||
@ -5437,10 +5444,12 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const
|
||||
}
|
||||
INSERT_BEFORE_INSN1(iobj, line_no, node_id, pushtoarray, INT2FIX(1));
|
||||
}
|
||||
if (!safenav_call) {
|
||||
ADD_INSN(lhs, line_node, pop);
|
||||
if (argc != 1) {
|
||||
ADD_INSN(lhs, line_node, pop);
|
||||
}
|
||||
}
|
||||
for (int i=0; i < argc; i++) {
|
||||
ADD_INSN(post, line_node, pop);
|
||||
}
|
||||
|
@ -1248,6 +1248,20 @@ eom
|
||||
assert_syntax_error("a&.x,=0", /multiple assignment destination/)
|
||||
end
|
||||
|
||||
def test_safe_call_in_for_variable
|
||||
assert_valid_syntax("for x&.bar in []; end")
|
||||
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
|
||||
begin;
|
||||
foo = nil
|
||||
for foo&.bar in [1]; end
|
||||
assert_nil(foo)
|
||||
|
||||
foo = Struct.new(:bar).new
|
||||
for foo&.bar in [1]; end
|
||||
assert_equal(1, foo.bar)
|
||||
end;
|
||||
end
|
||||
|
||||
def test_no_warning_logop_literal
|
||||
assert_warning("") do
|
||||
eval("true||raise;nil")
|
||||
|
Loading…
x
Reference in New Issue
Block a user