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: