From 5d1620505e4155b52c6646132e27351d3a1e22e1 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 28 Sep 2026 16:35:53 +0800 Subject: [PATCH] =?UTF-8?q?fix(decl):=20=E5=A3=B0=E6=98=8E=E7=AB=AF?= =?UTF-8?q?=E7=9C=8B=E7=A9=BF=E3=80=8C=E8=A3=85=E9=A5=B0=E5=99=A8=E6=A0=87?= =?UTF-8?q?=E8=AE=B0=20+=20=E8=A3=B8=E7=B1=BB=E5=BC=95=E7=94=A8=E3=80=8D?= =?UTF-8?q?=E8=81=94=E5=90=88=EF=BC=8C=E4=BF=AE=20t.CExtern|X|t.CPtr=20?= =?UTF-8?q?=E5=A4=9A=E5=A4=96=E5=8C=85=E4=B8=80=E5=B1=82=E6=8C=87=E9=92=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因:vpi 记录的模块级全局是 `_mbuddy: t.CExtern | memhub.MemBuddy | t.CPtr` 形态,_get_type_str 把该联合展开为 %"sha1.MemBuddy"*(标记 t.CExtern 展开为空串,已被 BinOp 分支丢弃),但外层 | t.CPtr 走 _is_bare_class_ref_annotation 时对 ast.BinOp 一律 return False ⇒ 未吸收"裸类引用自身即指针"那一层 ⇒ 声明端 %X** 与定义端 %X* 差一层。 后果:Phase1 生成的 .stub.ll 声明 @_mbuddy = external global %X**,消费模块按下声明取值得到 %X**,赋给 %X* 字段(VLogger.vp:105 self.__mbuddy__ = _mbuddy)即报"指针隐式转换已禁止(层数不同)"。 修法:BinOp 分支内若恰一侧展开为空/void(纯装饰器标记 CExtern/CExport/State/CStatic...)则按另一侧递归判定,对齐 TPV TypeGenResolve.vp:2596 第 3 条语义「ActualType | DecoratorMarker → ActualType」(TPV 无此问题,故只改 TPC)。 探针验证:t.CExtern|X|t.CPtr / X|None|t.CPtr / t.State|X|t.CPtr → %X*(修正);X|t.CPtr、rawptr[X]|t.CPtr → %X**、bytes|t.CPtr → i8**、int|t.CPtr → i32*(均不变)。注意 .stub.ll 有全局缓存,需 --clear-cache 重编生效。 --- lib/Projectrans/DeclarationGenerator.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/lib/Projectrans/DeclarationGenerator.py b/lib/Projectrans/DeclarationGenerator.py index 44ee0f2..39b4f88 100644 --- a/lib/Projectrans/DeclarationGenerator.py +++ b/lib/Projectrans/DeclarationGenerator.py @@ -1121,10 +1121,29 @@ class DeclarationGenerator: 下标(rawptr[...] / t.CPtr[...])不是裸类引用——它们已自带指针层数, 须逐层外包(rawptr[Node] | t.CPtr → Node**、ast.AST | t.CPtr | t.CPtr → AST**,与定义端整体拉平后只吸收一次 CPtr 一致)。 + + **例外:纯装饰器标记联合**。`t.CExtern | X` / `t.CExport | X` / `t.State | X` + (vpi 记录的模块级全局就是这种写法,见 lib.Phase.Phase1.__init__.vpi 的 + `_mbuddy: t.CExtern | memhub.MemBuddy | t.CPtr`)里标记侧展开为**空串** + (CTypeRegistry.NameToLLVM('CExtern') == ''),该联合语义上仍是 X 这一个 + 裸类引用,故 `t.CExtern | X | t.CPtr` 必须与 `X | t.CPtr` 同判(吸收)—— + 对齐 TPV TypeGenResolve 的第 3 条语义「ActualType | DecoratorMarker → + ActualType」。漏此判据时联合被当成"已自带指针层数的左值"而多外包一层: + 声明端 `%"sha1.X"**` 与定义端 `%"sha1.X"*` 差一层,消费模块里 + `self.__mbuddy__ = _mbuddy` 之类的赋值即报"层数不同"fail-fast。 """ if not inner_type: return False if isinstance(inner, ast.BinOp): + if not isinstance(inner.op, ast.BitOr): + return False + LeftType: str = self._get_type_str(inner.left) + RightType: str = self._get_type_str(inner.right) + # 恰一侧是纯装饰器标记(展开为空/void)⇒ 类型全部来自另一侧,按另一侧判 + if LeftType in ('', 'void') and RightType not in ('', 'void'): + return self._is_bare_class_ref_annotation(inner.right, RightType) + if RightType in ('', 'void') and LeftType not in ('', 'void'): + return self._is_bare_class_ref_annotation(inner.left, LeftType) return False if isinstance(inner, ast.Subscript): return not (IsRawPtrSubscriptNode(inner) or IsCPtrSubscriptNode(inner))