[Bug #20468] Fix safe navigation in for
variable
This commit is contained in:
parent
9d69619623
commit
2dd46bb82f
21
compile.c
21
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));
|
CHECK(COMPILE_POPPED(pre, "masgn lhs (NODE_ATTRASGN)", node));
|
||||||
|
|
||||||
|
bool safenav_call = false;
|
||||||
LINK_ELEMENT *insn_element = LAST_ELEMENT(pre);
|
LINK_ELEMENT *insn_element = LAST_ELEMENT(pre);
|
||||||
iobj = (INSN *)get_prev_insn((INSN *)insn_element); /* send insn */
|
iobj = (INSN *)get_prev_insn((INSN *)insn_element); /* send insn */
|
||||||
ASSUME(iobj);
|
ASSUME(iobj);
|
||||||
ELEM_REMOVE(LAST_ELEMENT(pre));
|
ELEM_REMOVE(insn_element);
|
||||||
ELEM_REMOVE((LINK_ELEMENT *)iobj);
|
if (!IS_INSN_ID(iobj, send)) {
|
||||||
pre->last = iobj->link.prev;
|
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);
|
const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(iobj, 0);
|
||||||
int argc = vm_ci_argc(ci) + 1;
|
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;
|
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) {
|
if (vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT) {
|
||||||
int argc = vm_ci_argc(ci);
|
int argc = vm_ci_argc(ci);
|
||||||
bool dupsplat = false;
|
bool dupsplat = false;
|
||||||
@ -5437,9 +5444,11 @@ 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));
|
INSERT_BEFORE_INSN1(iobj, line_no, node_id, pushtoarray, INT2FIX(1));
|
||||||
}
|
}
|
||||||
ADD_INSN(lhs, line_node, pop);
|
if (!safenav_call) {
|
||||||
if (argc != 1) {
|
|
||||||
ADD_INSN(lhs, line_node, pop);
|
ADD_INSN(lhs, line_node, pop);
|
||||||
|
if (argc != 1) {
|
||||||
|
ADD_INSN(lhs, line_node, pop);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (int i=0; i < argc; i++) {
|
for (int i=0; i < argc; i++) {
|
||||||
ADD_INSN(post, line_node, pop);
|
ADD_INSN(post, line_node, pop);
|
||||||
|
@ -1248,6 +1248,20 @@ eom
|
|||||||
assert_syntax_error("a&.x,=0", /multiple assignment destination/)
|
assert_syntax_error("a&.x,=0", /multiple assignment destination/)
|
||||||
end
|
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
|
def test_no_warning_logop_literal
|
||||||
assert_warning("") do
|
assert_warning("") do
|
||||||
eval("true||raise;nil")
|
eval("true||raise;nil")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user