[Bug #19862] Skip compiled result of never reachable expression

This commit is contained in:
Nobuyoshi Nakada 2023-09-06 00:44:35 +09:00
parent 19346c2336
commit 6e64d43704
Notes: git 2023-09-12 23:30:56 +00:00
2 changed files with 31 additions and 8 deletions

View File

@ -4154,9 +4154,10 @@ compile_flip_flop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const nod
}
static int
compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *cond,
compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret, const NODE *cond,
LABEL *then_label, LABEL *else_label);
#define COMPILE_SINGLE 2
static int
compile_logical(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *cond,
LABEL *then_label, LABEL *else_label)
@ -4175,28 +4176,39 @@ compile_logical(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *cond,
return COMPILE_OK;
}
if (!label->refcnt) {
ADD_INSN(seq, cond, putnil);
}
else {
ADD_LABEL(seq, label);
return COMPILE_SINGLE;
}
ADD_LABEL(seq, label);
ADD_SEQ(ret, seq);
return COMPILE_OK;
}
static int
compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *cond,
compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret, const NODE *cond,
LABEL *then_label, LABEL *else_label)
{
int ok;
DECL_ANCHOR(ignore);
again:
switch (nd_type(cond)) {
case NODE_AND:
CHECK(compile_logical(iseq, ret, cond->nd_1st, NULL, else_label));
CHECK(ok = compile_logical(iseq, ret, cond->nd_1st, NULL, else_label));
cond = cond->nd_2nd;
if (ok == COMPILE_SINGLE) {
INIT_ANCHOR(ignore);
ret = ignore;
then_label = NEW_LABEL(nd_line(cond));
}
goto again;
case NODE_OR:
CHECK(compile_logical(iseq, ret, cond->nd_1st, then_label, NULL));
CHECK(ok = compile_logical(iseq, ret, cond->nd_1st, then_label, NULL));
cond = cond->nd_2nd;
if (ok == COMPILE_SINGLE) {
INIT_ANCHOR(ignore);
ret = ignore;
else_label = NEW_LABEL(nd_line(cond));
}
goto again;
case NODE_LIT: /* NODE_LIT is always true */
case NODE_TRUE:

View File

@ -770,4 +770,15 @@ class TestISeq < Test::Unit::TestCase
assert_syntax_error("false and break", mesg)
assert_syntax_error("if false and break; end", mesg)
end
def test_unreachable_pattern_matching
assert_in_out_err([], "#{<<~"begin;"}\n#{<<~'end;'}", %w[1])
begin;
if true or {a: 0} in {a:}
p 1
else
p 0
end
end;
end
end