From 4f9c234ea813ec13dd20d9202b156b0053efb3ee Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sat, 10 Oct 2026 21:25:33 +0800 Subject: [PATCH] =?UTF-8?q?fix(cdef):=20external=20=E5=A3=B0=E6=98=8E?= =?UTF-8?q?=E4=B8=8D=E5=86=8D=E9=81=AE=E8=94=BD=E5=90=8C=E5=90=8D=20CDefin?= =?UTF-8?q?e=20=E5=B8=B8=E9=87=8F=EF=BC=9B=E8=A1=A5=20t=20=E7=B1=BB?= =?UTF-8?q?=E5=90=8D=E5=88=AB=E5=90=8D=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 两处:① 现场证据(_shared_sym_includes.pickle)显示 all_dc 已含 STD_*-10/-11/-12,但模块 IR 仍 load @STD_ERROR_HANDLE —— 因为 stub 注入的 @X = external global(无初值)让 _lookup_cdefine 的遮蔽判据 AttrName in Gen.module.globals 成立,直接跳过了 CDefine 回退。新增 SymbolUtils.GlobalDeclShadowsDefine:只有**带初值**(本模块真正定义)的全局才遮蔽;仅 external 声明不算。裸名路径同判据改用同一 helper。② all_decl_types 为空的根因:DWORD 的 BaseType 为 None,底层类型存在 OriginalType 字符串 'CUInt32T'(t 类名),原解析只认内层 CTypeInfo。补:按 getattr(t, 类名) 解析该串。离线校验 DWORD|t.CDefine → (32, False)。 --- lib/core/Handles/HandlesExpr.py | 5 ++-- lib/core/Handles/HandlesExprAttr.py | 9 ++++--- lib/core/SymbolUtils.py | 42 +++++++++++++++++++++++------ 3 files changed, 42 insertions(+), 14 deletions(-) diff --git a/lib/core/Handles/HandlesExpr.py b/lib/core/Handles/HandlesExpr.py index da8640a..46f1d6a 100644 --- a/lib/core/Handles/HandlesExpr.py +++ b/lib/core/Handles/HandlesExpr.py @@ -9,7 +9,8 @@ import llvmlite.ir as ir from lib.core.Handles.HandlesBase import BaseHandle from lib.constants.config import mode as _config_mode from lib.includes.t import CTypeRegistry as _CR -from lib.core.SymbolUtils import RequireDefineUseWidthAt, RequireIntLiteralStorable, RequireNameDefined, DefineDeclTypeValue +from lib.core.SymbolUtils import (RequireDefineUseWidthAt, RequireIntLiteralStorable, RequireNameDefined, + DefineDeclTypeValue, GlobalDeclShadowsDefine) # --------------------------------------------------------------- @@ -480,7 +481,7 @@ class ExprHandle(BaseHandle): # 治本修复:如果符号表也没有,回退查询 _all_define_constants # _all_define_constants 由 Phase2Translator 从所有 .pyi 文件预提取, # 包含跨模块导入的 CDefine 常量(如 FOREGROUND_GREEN、STD_OUTPUT_HANDLE) - if VarName not in define_constants and VarName not in Gen.variables and not (hasattr(Gen, 'module') and VarName in Gen.module.globals): + if VarName not in define_constants and VarName not in Gen.variables and not GlobalDeclShadowsDefine(Gen, VarName): all_dc: dict[str, Any] = getattr(Gen, '_all_define_constants', None) or getattr(self.Trans, '_all_define_constants', None) or {} if VarName in all_dc: val: Any = all_dc[VarName] diff --git a/lib/core/Handles/HandlesExprAttr.py b/lib/core/Handles/HandlesExprAttr.py index c663fdc..5635847 100644 --- a/lib/core/Handles/HandlesExprAttr.py +++ b/lib/core/Handles/HandlesExprAttr.py @@ -5,7 +5,7 @@ if TYPE_CHECKING: from lib.core.LlvmCodeGenerator import LlvmCodeGenerator from lib.core.Handles.HandlesBase import BaseHandle, FuncMeta from lib.core.VLogger import get_logger as _vlog -from lib.core.SymbolUtils import DefineDeclTypeValue +from lib.core.SymbolUtils import DefineDeclTypeValue, GlobalDeclShadowsDefine import vast as ast import llvmlite.ir as ir @@ -440,9 +440,10 @@ class ExprAttrHandle(BaseHandle): # 与 _HandleNameLlvm 的裸名回退同源)。**模块属性访问**(`win32file.STD_OUTPUT_HANDLE`) # 此前只查 SymbolTable/_define_constants → 未命中就落到 _lookup_module_global 生成 # `@STD_OUTPUT_HANDLE` 全局引用(无定义 → 链接期 undefined symbol)。 - # 与裸名路径同口径:仅当本模块没有同名变量/全局时才用常量(避免遮蔽真正的模块全局)。 - _has_shadow: bool = AttrName in Gen.variables \ - or (hasattr(Gen, 'module') and AttrName in getattr(Gen.module, 'globals', {})) + # 与裸名路径同口径:仅当本模块没有同名变量/(**已定义的**)全局时才用常量。 + # 注意:跨模块 stub 注入的 `@X = external global`(无初值)**不算**遮蔽 —— 否则 + # 一条错误的 stub declare 会把 .vpi 的 CDefine 常量顶掉,退化成未定义全局符号。 + _has_shadow: bool = AttrName in Gen.variables or GlobalDeclShadowsDefine(Gen, AttrName) if not _has_shadow: all_dc: dict[str, Any] = getattr(Gen, '_all_define_constants', None) or getattr(self.Trans, '_all_define_constants', None) or {} for key2 in (f"{VarName}.{AttrName}", AttrName): diff --git a/lib/core/SymbolUtils.py b/lib/core/SymbolUtils.py index d8058d6..5be8ca0 100644 --- a/lib/core/SymbolUtils.py +++ b/lib/core/SymbolUtils.py @@ -1934,16 +1934,25 @@ def DefineDeclIntTypeFromAnnotation(symtab: object, annotation: object) -> tuple if entry is None or not getattr(entry, 'IsTypedef', False): return None base: object | None = getattr(entry, 'BaseType', None) - # 别名链:OriginalType 可能是内层 CTypeInfo(同一 typedef 的底层解析结果) + # 别名链:`DWORD` 这类 typedef 的 BaseType 常为 None,底层类型记在 OriginalType 里: + # ① 字符串 t 类名(实测 `DWORD` → `'CUInt32T'`、`ULONG` → `'CUInt32T'`); + # ② 内层 CTypeInfo(再取它的 BaseType)。 + # 带空格/指针的串(如 `'void *'`)不是整数别名 → 放弃。 + orig: object | None = getattr(entry, 'OriginalType', None) depth: int = 0 - while base is None and depth < 8: - orig: object | None = getattr(entry, 'OriginalType', None) - if not isinstance(orig, type(base)) and orig is not None and hasattr(orig, 'BaseType'): - entry = orig - base = getattr(entry, 'BaseType', None) - else: - break + while base is None and orig is not None and depth < 8: depth += 1 + if isinstance(orig, str): + cand: object | None = getattr(t, orig, None) + if cand is None: + break + base = cand + break + if hasattr(orig, 'BaseType'): + base = getattr(orig, 'BaseType', None) + orig = getattr(orig, 'OriginalType', None) + continue + break width: int | None = DefineIntWidthOf(base) if width is None: return None @@ -1981,6 +1990,23 @@ def DefineDeclTypeValue(DeclTypes: object | None, Name: str | None, Value: objec return (width, v) +def GlobalDeclShadowsDefine(Gen: object, Name: str | None) -> bool: + """该名字在本模块是否有**已定义**(带初值)的全局 → 视为遮蔽同名 CDefine 常量。 + + 仅 `external global`(**无初值**,典型来自跨模块 stub 注入的 declare)**不算**遮蔽: + 否则 stub 里一条错误的 `@X = external global` 会把 .vpi 里的 CDefine 常量顶掉, + 读路径退化成"加载该全局" → 链接期 undefined symbol(现场:win32file 的 STD_*_HANDLE)。 + 真正的本模块全局在 IR 里带初值/存储,仍按既有优先级遮蔽常量。 + """ + mod: object | None = getattr(Gen, 'module', None) + if mod is None or Name is None: + return False + g: object | None = getattr(mod, 'globals', {}).get(Name) + if g is None: + return False + return getattr(g, 'initializer', None) is not None + + def RequireDefineIntStorable(Value: object, BaseType: object | None, Name: str, AnnotationText: str, Lineno: int, Col: int, FilePath: str, CodeLine: str) -> None: