From a7b8118ce85ef127466cafd5988483d02989cb39 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 5 Oct 2026 14:35:50 +0800 Subject: [PATCH] =?UTF-8?q?fix(call):=20c.Set=20=E6=94=AF=E6=8C=81=20Starr?= =?UTF-8?q?ed=20=E8=A7=A3=E5=BC=95=E7=94=A8=E7=9B=AE=E6=A0=87=EF=BC=88*p?= =?UTF-8?q?=20=E5=9C=A8=E5=AE=9E=E5=8F=82=E4=BD=8D=E8=A2=AB=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E4=B8=BA=20Starred=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新规范把 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。 --- App/lib/core/Gen/Call/CallGenCBuiltin.vp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/App/lib/core/Gen/Call/CallGenCBuiltin.vp b/App/lib/core/Gen/Call/CallGenCBuiltin.vp index 7bb3fdc..d5160fa 100644 --- a/App/lib/core/Gen/Call/CallGenCBuiltin.vp +++ b/App/lib/core/Gen/Call/CallGenCBuiltin.vp @@ -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)