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:
1 parent
d5b4e9a8b9
commit
4f9c234ea8
3 files changed
+42
-14
No files matched your search
@@ -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,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
@@ -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:
|
||||
|
||||
Reference in new issue
Block a user