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