From 8d950f5d43eed56ffeb69b2e74cce3891ca41708 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Wed, 16 Sep 2026 07:09:10 +0800 Subject: [PATCH] =?UTF-8?q?fix(declgen):=20=E8=81=94=E5=90=88=E4=B8=AD=20t?= =?UTF-8?q?.CPtr[T]=20=E4=B8=8B=E6=A0=87=E6=AE=B5=E6=8C=89=20Ptr^N=20?= =?UTF-8?q?=E5=8F=A0=E5=8A=A0=EF=BC=8C=E4=B8=8E=20LLVMTypeMapper=20?= =?UTF-8?q?=E5=8F=A3=E5=BE=84=E5=AF=B9=E9=BD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _get_type_str 的 BinOp 段原先在右段非 i8* 时落到 星号在左值则直接返回左值 的启发式,左值已是指针(BYTEPTR=>i8*)时会吞掉右段层数(BYTEPTR | t.CPtr[t.CPtr] 得 i8*,Mapper 得 i8***,同份 stub 自相矛盾) 新增 t.CPtr[T] 分支(两侧对称,置于该启发式之前),复用文件内既有 _ptr_level_of 取层数并按定义侧 TypeGenResolve 口径改为纯外包 N 层(去掉原 struct 吸收半截语义);LLVM 聚合左值显式排除。A/B 实测 135 个 .pyi 输出逐字节相同,现有语料零影响 --- lib/Projectrans/DeclarationGenerator.py | 29 ++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/Projectrans/DeclarationGenerator.py b/lib/Projectrans/DeclarationGenerator.py index 4c53a07..8d1574d 100644 --- a/lib/Projectrans/DeclarationGenerator.py +++ b/lib/Projectrans/DeclarationGenerator.py @@ -8,7 +8,7 @@ import llvmlite.ir as ir from lib.includes import t from lib.includes.t import CTypeRegistry -from lib.core.SymbolUtils import IsListAnnotation, AnnotationContainsName +from lib.core.SymbolUtils import IsListAnnotation, AnnotationContainsName, IsCPtrSubscriptNode class DeclarationGenerator: @@ -1019,6 +1019,23 @@ class DeclarationGenerator: # 其他未知类型保守估算 return 8 + @staticmethod + def _ptr_level_of(type_str: str) -> int: + """统计类型字符串尾部的指针层数('i8***' → 3,'i32' → 0)""" + return len(type_str) - len(type_str.rstrip('*')) + + def _merge_cptr_subscript(self, base_type: str, cptr_sub_type: str) -> str: + """base | t.CPtr[T] → Ptr^N(base_type),N = t.CPtr[T] 段自身指针层数。 + + 与定义侧 TPV TypeGenResolve.vp:2610-2639 同口径:数 CPtr 侧已解析类型的 + 外层 Ptr 嵌套层 N(TypeGenResolve.vp:2616-2632),再给另一侧**纯外包** + N 层 Ptr(TypeGenResolve.vp:2633-2639,对 struct 基类型亦不吸收)。 + 与 LLVMTypeMapper._resolve_bitor 的 IsCPtrSubscriptNode 分支(_add_pointer_levels + 逐层追加)同口径,对同一批形态两处结果一致。 + 注:裸 | t.CPtr(非下标标记)仍走上方的 %"..."* 吸收分支,与本节无关。 + """ + return base_type + '*' * self._ptr_level_of(cptr_sub_type) + def _get_type_str(self, annotation: ast.AST | None, embedded: bool = False) -> str: if annotation is None: return 'i8*' @@ -1158,6 +1175,16 @@ class DeclarationGenerator: if '*' in left_type: return f'{left_type}*' return f'{left_type}*' + # X | t.CPtr[T](T 为下标段,非裸标记):CPtr 侧贡献自身指针层数 N, + # 另一侧外包 N 层(Ptr^N(X));左右两侧写法对称(定义侧 TPV + # TypeGenResolve.vp:2604-2609 亦两侧皆判)。必须先于下方 + # "'*' in left_type → 直接返回左值":否则左值本身已是指针 + # (BYTEPTR⇒i8*)时会吞掉右段层数(BYTEPTR | t.CPtr[t.CPtr] 改前得 i8*)。 + # LLVM 聚合([N x T] / { ... })不可再外包指针层,保持既有行为(只报不改)。 + if IsCPtrSubscriptNode(annotation.right) and left_type[:1] not in ('[', '{'): + return self._merge_cptr_subscript(left_type, right_type) + if IsCPtrSubscriptNode(annotation.left) and right_type[:1] not in ('[', '{'): + return self._merge_cptr_subscript(right_type, left_type) if '*' in left_type: return left_type if '*' in right_type: