fix(gen): 跨模块 vpi 查询只在加载成功时记"已加载"备忘(修漏检回归)
A2 引入的 lookup_ret_kind_via_vpi 会在 life_of_expr(判右值生命期,可能在极早的翻译阶段) 里触发对方模块 vpi 的按需加载,但它沿用 _vpi_escape_packed 的旧写法:**无论加载成功与否** 都把该模块记入 _vpi_escape_module_loaded 备忘。于是当那个时刻 vpi 还没生成/打不开时, 该模块被毒化成"已加载",之后所有共用这条备忘的跨模块查询(逃逸摘要 esc=、willFree wf=) 都跳过真正的加载 → 缓存恒空 → 判据静默失效。 现场:EscapeXmodTest(跨模块 esc)与 NewLifetimeWillFreeTest(跨模块 wf)双双漏检, 即"应拒绝却通过"。同模块用例不受影响,故更隐蔽。 修法:两处加载点都改为 _ensure_vpi_ret_annot_loaded 返回非 0(= 真加载/已缓存)才 _vpi_escape_mark_module;失败直接返回 0,留给后续查询重试。 - lookup_ret_kind_via_vpi(新代码,回归根源) - _vpi_escape_packed(既有同款隐患,一并修)。
This commit is contained in:
1 parent
a3a627f513
commit
948e1855a6
1 file changed
+9
-2
@@ -802,7 +802,9 @@ novirtual class CallGenBase:
|
||||
if sha1 is None or method_name is None: return 0
|
||||
if VpiReader._vpi_escape_module_loaded(sha1) == 0:
|
||||
if self.Gen.CallGenBase.TempDir is None or self.Gen.CallGenBase.TempDirLen == 0: return 0
|
||||
VpiReader._ensure_vpi_ret_annot_loaded(sha1, self.Gen.CallGenBase.TempDir)
|
||||
# ⚠ 同 lookup_ret_kind_via_vpi:**加载成功才记备忘**。失败也记会把该模块毒化成"已加载",
|
||||
# 使之后所有跨模块查询(含 willFree 的 _vpi_willfree,它共用这条备忘)永远查空。
|
||||
if VpiReader._ensure_vpi_ret_annot_loaded(sha1, self.Gen.CallGenBase.TempDir) == 0: return 0
|
||||
VpiReader._vpi_escape_mark_module(sha1)
|
||||
return VpiReader._lookup_vpi_escape_packed(sha1, cls_name, method_name)
|
||||
|
||||
@@ -823,7 +825,12 @@ novirtual class CallGenBase:
|
||||
if func_name is None or cls_sha1 is None: return 0
|
||||
if VpiReader._vpi_escape_module_loaded(cls_sha1) == 0:
|
||||
if self.Gen.CallGenBase.TempDir is None or self.Gen.CallGenBase.TempDirLen == 0: return 0
|
||||
VpiReader._ensure_vpi_ret_annot_loaded(cls_sha1, self.Gen.CallGenBase.TempDir)
|
||||
# ⚠ 只有**加载成功**才能记入"已加载"备忘。_ensure 失败(该模块的 vpi 此刻还没生成 /
|
||||
# 打不开)时若也记上,后续所有跨模块查询(逃逸摘要 / willFree / ret)都会**跳过真正的
|
||||
# 加载** → 缓存恒空 → 判据静默失效。现场:本查询可能在极早的翻译阶段先跑(life_of_expr
|
||||
# 判右值生命期),把尚无 vpi 的模块毒化成"已加载" → EscapeXmodTest(esc)/
|
||||
# NewLifetimeWillFreeTest(wf)双双漏检。
|
||||
if VpiReader._ensure_vpi_ret_annot_loaded(cls_sha1, self.Gen.CallGenBase.TempDir) == 0: return 0
|
||||
VpiReader._vpi_escape_mark_module(cls_sha1)
|
||||
return VpiReader._lookup_vpi_escape_dir(cls_sha1, class_name, func_name, 2)
|
||||
|
||||
|
||||
Reference in new issue
Block a user