diff options
author | Nobuyoshi Nakada <[email protected]> | 2024-07-16 19:58:50 +0900 |
---|---|---|
committer | Nobuyoshi Nakada <[email protected]> | 2024-07-16 22:11:28 +0900 |
commit | 60d3ed504393a876a372ceaec67ed29f06a7bcd0 (patch) | |
tree | 2dcc96c503b1181b9430b21fdbc489fc9a7293b7 /compile.c | |
parent | 93489d536bdb17da54613f7ef7a8115577963ceb (diff) |
[Bug #20457] Drop unreachable `return` at end of method
Diffstat (limited to 'compile.c')
-rw-r--r-- | compile.c | 25 |
1 files changed, 24 insertions, 1 deletions
@@ -861,6 +861,8 @@ rb_iseq_compile_callback(rb_iseq_t *iseq, const struct rb_iseq_new_with_callback return iseq_setup(iseq, ret); } +static bool drop_unreachable_return(LINK_ANCHOR *ret); + VALUE rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node) { @@ -960,7 +962,7 @@ rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node) ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0); ADD_INSN1(ret, &dummy_line_node, throw, INT2FIX(0) /* continue throw */ ); } - else { + else if (!drop_unreachable_return(ret)) { ADD_SYNTHETIC_INSN(ret, ISEQ_COMPILE_DATA(iseq)->last_line, -1, leave); } @@ -8582,6 +8584,27 @@ compile_return(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, return COMPILE_OK; } +static bool +drop_unreachable_return(LINK_ANCHOR *ret) +{ + LINK_ELEMENT *i = ret->last, *last; + if (!i) return false; + if (IS_TRACE(i)) i = i->prev; + if (!IS_INSN(i) || !IS_INSN_ID(i, putnil)) return false; + last = i = i->prev; + if (IS_ADJUST(i)) i = i->prev; + if (!IS_INSN(i)) return false; + switch (INSN_OF(i)) { + case BIN(leave): + case BIN(jump): + break; + default: + return false; + } + (ret->last = last->prev)->next = NULL; + return true; +} + static int compile_evstr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) { |