From 6e64d4370456190541705ec4c6cf3af6bf4ac647 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 6 Sep 2023 00:44:35 +0900 Subject: [PATCH] [Bug #19862] Skip compiled result of never reachable expression --- compile.c | 28 ++++++++++++++++++++-------- test/ruby/test_iseq.rb | 11 +++++++++++ 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/compile.c b/compile.c index 86797cb793..6144ab4472 100644 --- a/compile.c +++ b/compile.c @@ -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: diff --git a/test/ruby/test_iseq.rb b/test/ruby/test_iseq.rb index 4ff808418f..0af29d9f32 100644 --- a/test/ruby/test_iseq.rb +++ b/test/ruby/test_iseq.rb @@ -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