fix(decl): stub 跳过联合形态 CDefine + 模块属性访问回退 _all_define_constants
链接报 undefined symbol: STD_INPUT/OUTPUT/ERROR_HANDLE。根因两处:① DeclarationGenerator._generate_global_decl 的 CDefine 跳过判据只认裸 t.CDefine,而 define X: T = V 展开为注解 T | t.CDefine,于是 stub 里写出 @STD_OUTPUT_HANDLE = external global i32(该符号无人定义);② 模块属性访问 win32file.STD_OUTPUT_HANDLE 的 _try_resolve_nested_cdefine 只查 SymbolTable/_define_constants,缺裸名路径已有的 _all_define_constants 回退,解析落空后转去加载那条错误的 stub 全局 → 链接期未定义符号。改为 AnnotationContainsName 判据 + 补 _all_define_constants 回退(仅在本模块无同名全局时,避免遮蔽真实模块全局)。
This commit is contained in:
1 parent
18d753999d
commit
1050e5a23a
2 files changed
+25
-1
No files matched your search
@@ -253,7 +253,13 @@ class DeclarationGenerator:
|
||||
if not isinstance(node.target, ast.Name):
|
||||
return None
|
||||
var_name: str = node.target.id
|
||||
if isinstance(node.annotation, ast.Attribute) and hasattr(node.annotation, 'attr') and node.annotation.attr == 'CDefine':
|
||||
# CDefine 是编译期常量,不是变量:stub 里**不得**生成 external global。
|
||||
# `define X: T = V` 会展开为注解 `T | t.CDefine`,故判据必须能识别**联合形态**——
|
||||
# 原判据只认裸 `t.CDefine`(注解为单个 Attribute),联合注解会漏判 →
|
||||
# stub 出现 `@X = external global i32` → 其他模块引用它时变成未定义符号(链接失败),
|
||||
# 且会遮住跨模块 CDefine 常量回退(同名全局优先于常量)。与 _check_annotation_for_export
|
||||
# 一样用递归判据。
|
||||
if AnnotationContainsName(node.annotation, 'CDefine'):
|
||||
return None
|
||||
if isinstance(node.annotation, ast.Attribute) and hasattr(node.annotation, 'attr') and node.annotation.attr == 'CTypedef':
|
||||
return None
|
||||
|
||||
@@ -2215,6 +2215,24 @@ class ExprAttrHandle(BaseHandle):
|
||||
return ir.Constant(ir.IntType(32), val)
|
||||
elif isinstance(val, float):
|
||||
return ir.Constant(ir.FloatType(), val)
|
||||
# 回退:_all_define_constants(Phase2Translator 从所有 .pyi 预提取的跨模块 CDefine,
|
||||
# 与 _HandleNameLlvm 的裸名回退同源)。此前只覆盖裸名/from-import,**模块属性访问**
|
||||
# (如 `win32file.STD_OUTPUT_HANDLE`)走到这里就落空 → 转去基座求值 + 字段/全局加载,
|
||||
# 命中 stub 里那条错误的 `@STD_OUTPUT_HANDLE = external global`,最终链接期未定义符号。
|
||||
# 与裸名路径同口径:仅当本模块没有同名全局时才用常量(避免遮蔽真正的模块全局)。
|
||||
_mod_globals: Any = getattr(Gen, 'module', None)
|
||||
_has_mod_global: bool = _mod_globals is not None and attr_name in getattr(_mod_globals, 'globals', {})
|
||||
if not _has_mod_global:
|
||||
all_dc: dict[str, Any] = getattr(Gen, '_all_define_constants', None) or getattr(self.Trans, '_all_define_constants', None) or {}
|
||||
for key2 in (attr_name, full_path):
|
||||
if key2 in all_dc:
|
||||
val2: Any = all_dc[key2]
|
||||
if isinstance(val2, int):
|
||||
if val2 > 0x7FFFFFFF or val2 < -0x80000000:
|
||||
return ir.Constant(ir.IntType(64), val2 & 0xFFFFFFFFFFFFFFFF)
|
||||
return ir.Constant(ir.IntType(32), val2)
|
||||
elif isinstance(val2, float):
|
||||
return ir.Constant(ir.FloatType(), val2)
|
||||
return None
|
||||
|
||||
def _try_resolve_cross_module_enum(self, module_alias: str, enum_class_name: str, member_name: str) -> ir.Value | None:
|
||||
|
||||
Reference in new issue
Block a user