From 1c1f78e7b36d56edaa4f8910b294da51da612cc7 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 28 Sep 2026 22:44:20 +0800 Subject: [PATCH] =?UTF-8?q?fix(tpc):=20=E4=BF=AE=E6=AD=A3=E6=9E=9A?= =?UTF-8?q?=E4=B8=BE=E5=88=A4=E6=8D=AE=E2=80=94=E2=80=94=E6=8C=89=20IsEnum?= =?UTF-8?q?Member=20=E5=8C=BA=E5=88=86=E6=88=90=E5=91=98/=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=EF=BC=88bb05a157=20=E5=88=A4=E5=8F=8D=E4=BA=86?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit a 编译器缺陷:bb05a157 用 `not Entry.IsEnum` 排除"枚举类型",但现场实测枚举 **成员**条目的标志组合是 IsEnum=True + IsEnumMember=True + BaseType=CEnum (成员的 IsEnum 也被置真)⇒ 成员被误判成枚举类型,`rawptr[Constant]` 落 i32*, `constant_get_str_val` 形参再次退化成 i32*。 正确判据(两处同源): 枚举**类型** = IsEnum and not IsEnumMember ⇒ 走枚举分支(宽度 i32 等) 枚举**成员**(IsEnumMember)⇒ 不是类型 ⇒ 让位给类定义("有类定义 ⇒ 是类") 现场证据(51de3b6d 的 [DIAG-decl] 报文,随 Traceback 输出): 实参类=5df907d3a02a0bac.Constant | structs=有 | _struct_sha1_map=5df907d3a02a0bac | class_sha1_map=5df907d3a02a0bac | symtab[IsStruct=False, IsEnum=True, IsEnumMember=True, Base=CEnum] | 声明函数类型=i8* (i32*) | 声明来源=..._EmitExternalFuncDeclLlvm <- _get_or_declare_function 修后 `ResolveAnnotationType(rawptr[Constant])` 得 CStruct/1 ⇒ _ctype_to_llvm 取 structs['Constant'] ⇒ 声明变为 i8* (%"5df907d3a02a0bac.Constant"*),与实参同型。 --- lib/core/Handles/HandlesTypeMerge.py | 17 +++++++++++------ lib/core/LLVMCG/BaseGen.py | 17 ++++++++++------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/lib/core/Handles/HandlesTypeMerge.py b/lib/core/Handles/HandlesTypeMerge.py index 42c8bb5..8a94d4f 100644 --- a/lib/core/Handles/HandlesTypeMerge.py +++ b/lib/core/Handles/HandlesTypeMerge.py @@ -114,14 +114,19 @@ class HandlesTypeMerge(BaseHandle): # 查②后 BaseType=CStruct('Constant'),_get_or_create_struct 会按 # `_struct_sha1_map` 拼出 `".Constant"`(BaseGen.py:527-528), # 与声明端/实参同一结构体对象。 - # 但必须排除**枚举类型本身**(`Entry.IsEnum`,如 `class ASTKind(t.CEnum)`): + # 但必须排除**枚举类型本身**(如 `class ASTKind(t.CEnum)` 的注解 `x: ASTKind`): # _struct_sha1_map 是按 .vpi 里全部 ClassDef 建的,枚举类也在其中;若一并 - # 当结构体,`x: ASTKind` 这类枚举注解会被建成 opaque struct,与 i32 错位 + # 当结构体,枚举注解会被建成 opaque struct,与 i32 错位 # (现场:'IntType' object has no attribute 'is_opaque')。 - # 判据分工:Entry.IsEnum ⇒ 枚举类型(走下方 IsEnum 分支,宽度=i32 等); - # 裸名被枚举**成员**占住(Entry.IsEnumMember / 空标记)⇒ 成员不是类型 - # ⇒ 让位给类定义。 - _is_enum_type: bool = isinstance(Entry, CTypeInfo) and Entry.IsEnum + # 判据必须按 **IsEnumMember** 区分(现场实测):枚举**成员**条目的标志组合是 + # IsEnum=True + IsEnumMember=True + BaseType=CEnum + # (即成员的 IsEnum 也被置真),只判 IsEnum 会把成员误当枚举类型 ⇒ 落 i32*; + # 而枚举**类型**条目是 IsEnum=True + IsEnumMember=False。 + # 故:枚举类型 = IsEnum and not IsEnumMember ⇒ 走下方 IsEnum 分支; + # 成员(IsEnumMember)⇒ 不是类型 ⇒ 让位给类定义。 + _is_enum_type: bool = ( + isinstance(Entry, CTypeInfo) and Entry.IsEnum + and not getattr(Entry, 'IsEnumMember', False)) _Gen = getattr(self.Trans, 'LlvmGen', None) if _Gen and not _is_enum_type and ( TypeName in _Gen.structs diff --git a/lib/core/LLVMCG/BaseGen.py b/lib/core/LLVMCG/BaseGen.py index 5304eae..26d2c15 100644 --- a/lib/core/LLVMCG/BaseGen.py +++ b/lib/core/LLVMCG/BaseGen.py @@ -493,16 +493,19 @@ class BaseGenMixin: # 结构体。否则此处返回 i32 ⇒ 上游 PtrCount=1 叠加后变成 i32*, # 与调用点实参 %".Constant"* 分裂(现场:constant_get_str_val 的 # 形参 i32*)。类型注解语境下枚举**成员**从不是类型,判据只能是"是否有类定义"。 - # 必须排除**枚举类型本身**(`Entry.IsEnum`,如 `class ASTKind(t.CEnum)`): - # _struct_sha1_map 是按 .vpi 里全部 ClassDef 建的,枚举类也在其中 —— - # 若一并当结构体,枚举注解(kind() 返回值等)会被建为 opaque struct, - # 引发 i32 ↔ 结构体错位('IntType' object has no attribute 'is_opaque' 现场)。 - # 判据分工:Entry.IsEnum ⇒ 枚举类型(走下方枚举分支,宽度=i32 等); - # Entry.IsEnumMember(或裸名被成员占住)⇒ 成员,不是类型 ⇒ 让位给类定义。 + # 必须排除**枚举类型本身**(如 `class ASTKind(t.CEnum)`):_struct_sha1_map + # 是按 .vpi 里全部 ClassDef 建的,枚举类也在其中 —— 若一并当结构体,枚举 + # 注解(kind() 返回值等)会被建为 opaque struct,引发 i32 ↔ 结构体错位 + # ('IntType' object has no attribute 'is_opaque' 现场)。 + # 判据必须按 **IsEnumMember** 区分(现场实测标志组合): + # 枚举**成员** = IsEnum=True + IsEnumMember=True + BaseType=CEnum + # 枚举**类型** = IsEnum=True + IsEnumMember=False + # 只判 IsEnum 会把成员误当枚举类型 ⇒ 返回 i32 ⇒ 上游 PtrCount=1 ⇒ i32*。 _known_class_name: bool = ( (clean_name in getattr(self, '_struct_sha1_map', {}) or clean_name in getattr(self, 'class_sha1_map', {})) - and not (Entry and Entry.IsEnum)) + and not (Entry and Entry.IsEnum + and not getattr(Entry, 'IsEnumMember', False))) if Entry and Entry.IsTypedef: resolved_str: str = self._resolve_typedef(clean_name) if resolved_str != clean_name: