From 4d7a6db31aed8473093b5fb54d96760474d27109 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Wed, 19 Aug 2026 03:16:16 +0800 Subject: [PATCH] =?UTF-8?q?fix(match):=20case=20=E4=BD=93=E6=9C=AB?= =?UTF-8?q?=E5=8F=A5=E6=8E=A7=E5=88=B6=E6=B5=81=E5=85=A8=20return=20?= =?UTF-8?q?=E8=A1=A5=20unreachable=20=E4=B8=8D=20br=20end=5Fbb?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因(ClassGenEnum._get_type_align 掉出末尾):case 体末句是 If/控制流且 全分支 return 时,处理器把 builder 停在无 terminator 的 merge 块,case 循环的 is_terminated 误判未终止 → 补 br end_bb → rm/sq/sm_merge_reach=1 → 全 case return 的 match 被误判 merge 可达 → 函数收尾 fail-fast '流程掉出末尾'。新增模块级 _case_tail_unreachable:末句控制流 (If/While/For/Match)且 _ctrl_merge_reachable==0 时补 unreachable, 与 HandlesIf L309-315 / ClassGenVTable L1084 同语义;应用于 renum/ sequence/simple 三路的 case 体与 default 收尾(不含 Try/With,其处理器 不维护该标志)。 --- App/lib/core/Handles/HandlesMatch.vp | 71 ++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 9 deletions(-) diff --git a/App/lib/core/Handles/HandlesMatch.vp b/App/lib/core/Handles/HandlesMatch.vp index 8a48ab0..b7dc220 100644 --- a/App/lib/core/Handles/HandlesMatch.vp +++ b/App/lib/core/Handles/HandlesMatch.vp @@ -44,6 +44,44 @@ MAX_MATCH_CASES: t.CDefine = 32 SCOPE_MATCH: t.CDefine = 6 +# ============================================================ +# _case_tail_unreachable - case 体末尾结构性不可达判定 +# +# case 体翻译后当前块若未终止,且末句是控制流语句(If/While/For/Match) +# 且其 merge 结构性不可达(全分支 return,如 case Int(bits): if ... return) +# 时,当前块是控制流的 merge(无 terminator),与 HandlesIf L309-315/ +# ClassGenVTable L1084 同语义补 unreachable。返回 1= 已补 unreachable +# (调用方不应 br end_bb);0= 正常收尾(应 br end_bb)。 +# +# 根因(ClassGenEnum._get_type_align):case 体末句 If 全 return 时,If +# 处理器把 builder 停在无 terminator 的 merge 块,case 循环的 +# is_terminated 检查误判"未终止" → 补 br end_bb → rm_merge_reach=1 → +# 全 case return 的 match 被误判 merge 可达 → 函数收尾 fail-fast +# "流程掉出末尾"。不含 Try/With:其处理器不维护 _ctrl_merge_reachable, +# 避免残留值误判。 +# ============================================================ +def _case_tail_unreachable(trans: HT.Translator | t.CPtr, + builder: llvmlite.IRBuilder | t.CPtr, + body_list: list[ast.AST | t.CPtr] | t.CPtr) -> int: + if trans is None or builder is None: + return 0 + if llvmlite.builder_cur_block_is_terminated(builder) != 0: + return 0 + if body_list is None or len(body_list) == 0: + return 0 + lst: ast.AST | t.CPtr = body_list.get(len(body_list) - 1) + if lst is None: + return 0 + lk: int = lst.kind() + if lk != ast.ASTKind.If and lk != ast.ASTKind.While \ + and lk != ast.ASTKind.For and lk != ast.ASTKind.Match: + return 0 + if trans._ctrl_merge_reachable != 0: + return 0 + llvmlite.build_unreachable(builder) + return 1 + + # ============================================================ # 全局 gen 单例(模块级镜像,同 HandlesStruct 模式) # @@ -519,8 +557,10 @@ class MatchHandle(HandlesBase.Mixin): HandlesVar.exit_scope(trans.SymTab) # 若未终止且无 NoBreak,跳到 end + # 末句控制流全 return(结构性不可达)时补 unreachable,不 br end_bb if llvmlite.builder_cur_block_is_terminated(builder) == 0 \ - and nb == 0: + and nb == 0 \ + and _case_tail_unreachable(trans, builder, body_list) == 0: llvmlite.build_br(builder, end_bb) trans._ctrl_merge_reachable = 1 rm_merge_reach = 1 @@ -537,6 +577,7 @@ class MatchHandle(HandlesBase.Mixin): rm_merge_reach = 1 else: # 有显式 default:翻译 default case body(找到 is_def==1 的 case) + dbody: list[ast.AST | t.CPtr] | t.CPtr = None di: int = 0 while di < collected: if def_arr[di] == 1: @@ -545,7 +586,7 @@ class MatchHandle(HandlesBase.Mixin): dmc: ast.MatchCase | t.CPtr = ( ast.MatchCase | t.CPtr)(dcase) HandlesVar.enter_scope(trans.SymTab, SCOPE_MATCH) - dbody: list[ast.AST | t.CPtr] | t.CPtr = dmc.children + dbody = dmc.children if dbody is not None: dn: t.CSizeT = len(dbody) dj: int = 0 @@ -557,7 +598,9 @@ class MatchHandle(HandlesBase.Mixin): HandlesVar.exit_scope(trans.SymTab) break di = di + 1 - if llvmlite.builder_cur_block_is_terminated(builder) == 0: + # 末句控制流全 return → 补 unreachable(不 br end_bb) + if llvmlite.builder_cur_block_is_terminated(builder) == 0 \ + and _case_tail_unreachable(trans, builder, dbody) == 0: llvmlite.build_br(builder, end_bb) trans._ctrl_merge_reachable = 1 rm_merge_reach = 1 @@ -988,7 +1031,9 @@ class MatchHandle(HandlesBase.Mixin): HandlesBody.translate_stmt(trans, stmt) bi = bi + 1 HandlesVar.exit_scope(trans.SymTab) - if llvmlite.builder_cur_block_is_terminated(builder) == 0: + # 末句控制流全 return → 补 unreachable(不 br end,无 fallthrough) + if llvmlite.builder_cur_block_is_terminated(builder) == 0 \ + and _case_tail_unreachable(trans, builder, body_list2) == 0: if nb_arr[ci] == 0: llvmlite.build_br(builder, end_bb) else: @@ -1011,6 +1056,7 @@ class MatchHandle(HandlesBase.Mixin): # 7. default 块 llvmlite.position_at_end(builder, default_bb) + dbody: list[ast.AST | t.CPtr] | t.CPtr = None if has_default == 1: di: int = 0 while di < collected: @@ -1020,7 +1066,7 @@ class MatchHandle(HandlesBase.Mixin): dmc: ast.MatchCase | t.CPtr = ( ast.MatchCase | t.CPtr)(dnode) HandlesVar.enter_scope(trans.SymTab, SCOPE_MATCH) - dbody: list[ast.AST | t.CPtr] | t.CPtr = dmc.children + dbody = dmc.children if dbody is not None: dn: t.CSizeT = len(dbody) dj: int = 0 @@ -1032,7 +1078,9 @@ class MatchHandle(HandlesBase.Mixin): HandlesVar.exit_scope(trans.SymTab) break di = di + 1 - if llvmlite.builder_cur_block_is_terminated(builder) == 0: + # 末句控制流全 return → 补 unreachable(不 br end_bb) + if llvmlite.builder_cur_block_is_terminated(builder) == 0 \ + and _case_tail_unreachable(trans, builder, dbody) == 0: llvmlite.build_br(builder, end_bb) sq_merge_reach = 1 @@ -1227,8 +1275,10 @@ class MatchHandle(HandlesBase.Mixin): HandlesVar.exit_scope(trans.SymTab) + # 末句控制流全 return → 补 unreachable(不 br end_bb) if llvmlite.builder_cur_block_is_terminated(builder) == 0 \ - and nb == 0: + and nb == 0 \ + and _case_tail_unreachable(trans, builder, body_list) == 0: llvmlite.build_br(builder, end_bb) trans._ctrl_merge_reachable = 1 sm_merge_reach = 1 @@ -1243,6 +1293,7 @@ class MatchHandle(HandlesBase.Mixin): trans._ctrl_merge_reachable = 1 sm_merge_reach = 1 else: + dbody: list[ast.AST | t.CPtr] | t.CPtr = None di: int = 0 while di < collected: if def_arr[di] == 1: @@ -1251,7 +1302,7 @@ class MatchHandle(HandlesBase.Mixin): dmc: ast.MatchCase | t.CPtr = ( ast.MatchCase | t.CPtr)(dcase) HandlesVar.enter_scope(trans.SymTab, SCOPE_MATCH) - dbody: list[ast.AST | t.CPtr] | t.CPtr = dmc.children + dbody = dmc.children if dbody is not None: dn: t.CSizeT = len(dbody) dj: int = 0 @@ -1263,7 +1314,9 @@ class MatchHandle(HandlesBase.Mixin): HandlesVar.exit_scope(trans.SymTab) break di = di + 1 - if llvmlite.builder_cur_block_is_terminated(builder) == 0: + # 末句控制流全 return → 补 unreachable(不 br end_bb) + if llvmlite.builder_cur_block_is_terminated(builder) == 0 \ + and _case_tail_unreachable(trans, builder, dbody) == 0: llvmlite.build_br(builder, end_bb) trans._ctrl_merge_reachable = 1 sm_merge_reach = 1