fix(call): c.Set 支持 Starred 解引用目标(*p 在实参位被解析为 Starred)

新规范把 c.Set(c.Deref(p), v) 改写成 c.Set(*p, v),而实参位的 '*' 由 ast/parser.vp 解析为 Starred(value=p, ctx=Load),translate_c_set 只认 c.Deref/Call 与 Name 形态 ⇒ 整条 store 被静默丢弃。

后果:zlib 侧 includes 全部 47 处 c.Set(*out_len/*out/*length/*cap/*buf/*best_dist/*p_done, ...) 失效 —— 压缩结果长度恒为 0(decompress 报 Z_DATA_ERROR -3),ZlibTest 运行期 0xC0000005。现按 UnaryOp/Deref 与 Starred 两种形态统一走解引用写入,并对非指针目标 fail-fast。
This commit is contained in:
TermiNexus committed 2026-10-05 14:35:50 +08:00
1 parent 87b24c2445
commit a7b8118ce8
1 file changed
+22
+22
View File
@@ -100,6 +100,28 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
b_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, cargs.get(1), None, 0, trans)
if b_val is None: return None
# Form 0: c.Set(*ptr, b) -> *ptr = b. In an argument list a leading '*' is
# parsed as Starred (unpacking), so the new-syntax deref lvalue arrives as
# Starred(value=ptr) (UnaryOp/Deref also accepted). The old c.Deref(ptr)
# spelling is Form 1; without either the store is silently dropped.
ptr_expr: ast.AST* = None
if a_node is not None and a_node.kind() == ast.ASTKind.Starred:
st_a: ast.Starred* = ast.Starred*(a_node)
if st_a.value is not None: ptr_expr = st_a.value
elif a_node is not None and a_node.kind() == ast.ASTKind.UnaryOp:
uo_a: ast.UnaryOp* = ast.UnaryOp*(a_node)
if uo_a.op == ast.OpKind.Deref and uo_a.operand is not None: ptr_expr = uo_a.operand
if ptr_expr is not None:
ptr_a: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, ptr_expr, None, 0, trans)
if ptr_a is None or ptr_a.Ty is None or self.Gen.ExprGenBase.is_ptr_type(ptr_a.Ty) == 0:
self.Gen.TypeGenErr.fatal_error(a_node, "c.Set 的解引用目标必须是指针类型(类型推断退化)", "TypeError")
pointee_a: mlirlite.LLVMType* = ptr_a.Ty.Pointee
if pointee_a is None:
self.Gen.TypeGenErr.fatal_error(a_node, "c.Set 解引用目标的 pointee 类型缺失", "TypeError")
sv_a: mlirlite.Value* = self.Gen.ExprGenBase.coerce_to_type(builder, b_val, pointee_a, a_node, trans)
if sv_a is not None: mlirlite.build_store(builder, sv_a, ptr_a)
return b_val
# Form 1: c.Set(c.Deref(ptr), b) -> *ptr = b
if a_node is not None and a_node.kind() == ast.ASTKind.Call:
d_call: ast.Call* = ast.Call*(a_node)