fix(flow): 循环/match 外的 break/continue 改为 fail-fast

- StmtGenDeclMixin:translate_break / translate_continue 增加 node 形参,目标块
  缺失(_break_bb / _continue_bb 为 None)时 fatal_error,不再静默不发跳转
- StmtGenMixin:Break / Continue 分派传入 node(供错误定位)
This commit is contained in:
TermiNexus committed 2026-10-02 22:35:26 +08:00
1 parent 43d25e58b9
commit fb4175736f
2 files changed
+18 -12

No files matched your search

+16 -10
View File
@@ -257,8 +257,8 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
return self.translate_nonlocal(trans, node)
return 0
def translate_break(self, trans: HT.Translator*) -> int:
"""翻译 break 语句:跳转到循环 end 块"""
def translate_break(self, trans: HT.Translator*, node: ast.AST*) -> int:
"""翻译 break 语句:跳转到 break 目标(循环 end / match end)"""
builder: llvmlite.IRBuilder* = trans._cur_builder
func: llvmlite.Function* = trans._cur_func
pool: memhub.MemBuddy* = trans.Pool
@@ -266,10 +266,13 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
if builder is None or func is None:
return 0
# 发射 br 到 break 目标
if trans._break_bb is not None:
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
llvmlite.build_br(builder, trans._break_bb)
# 发射 br 到 break 目标(_break_bb 由循环或 match-case 生成侧设置)
if trans._break_bb is None:
# fail-fast:没有循环 / match-case 时 break 无处可跳,禁止静默无效果
self.Gen.TypeGenErr.fatal_error(node,
"break 只能用在循环或 match-case 体内(当前没有可跳出的目标)", "SyntaxError")
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
llvmlite.build_br(builder, trans._break_bb)
# 创建死代码 BB,用于后续语句(break 后面的代码不可达)
cnt: int = trans._label_counter
@@ -294,7 +297,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
"fallthrough 只能用在 match-case 语句体内(语义是落到下一个 case)", "SyntaxError")
return 0
def translate_continue(self, trans: HT.Translator*) -> int:
def translate_continue(self, trans: HT.Translator*, node: ast.AST*) -> int:
"""翻译 continue 语句:跳转到循环 cond/incr 块"""
builder: llvmlite.IRBuilder* = trans._cur_builder
func: llvmlite.Function* = trans._cur_func
@@ -304,9 +307,12 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
return 0
# 发射 br 到 continue 目标
if trans._continue_bb is not None:
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
llvmlite.build_br(builder, trans._continue_bb)
if trans._continue_bb is None:
# fail-fast:循环之外的 continue 无处可跳,禁止静默无效果
self.Gen.TypeGenErr.fatal_error(node,
"continue 只能用在循环体内(当前没有可继续的循环)", "SyntaxError")
if llvmlite.builder_cur_block_is_terminated(builder) == 0:
llvmlite.build_br(builder, trans._continue_bb)
# 创建死代码 BB,用于后续语句
cnt: int = trans._label_counter
+2 -2
View File
@@ -87,9 +87,9 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
elif k == ast.ASTKind.Pass:
return 0
elif k == ast.ASTKind.Break:
return self.translate_break(trans)
return self.translate_break(trans, node)
elif k == ast.ASTKind.Continue:
return self.translate_continue(trans)
return self.translate_continue(trans, node)
elif k == ast.ASTKind.FallThrough:
return self.translate_fallthrough(trans, node)
elif k == ast.ASTKind.Match: