fix(cdef): external 声明不再遮蔽同名 CDefine 常量;补 t 类名别名解析

两处:① 现场证据(_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)。
This commit is contained in:
TermiNexus committed 2026-10-10 21:25:33 +08:00
1 parent d5b4e9a8b9
commit 4f9c234ea8
3 files changed
+42 -14

No files matched your search

+3 -2
View File
@@ -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]
+5 -4
View File
@@ -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):
+34 -8
View File
@@ -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: