From d0165951b7aa4d76d464bd17b91e58c3ac07e3c2 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Thu, 8 Oct 2026 20:34:23 +0800 Subject: [PATCH] =?UTF-8?q?test(lifetime):=20NewLifetimeTest=20=E5=A2=9E?= =?UTF-8?q?=E6=9E=90=E6=9E=84=E8=B0=83=E5=BA=A6=E7=94=A8=E4=BE=8B=EF=BC=8C?= =?UTF-8?q?README=20=E8=A1=A5=20escape=20=E9=A1=B9=E7=9B=AE=E8=AF=B4?= =?UTF-8?q?=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 §3.6 用例:DtorPoint.__del__ 计数验证 —— 出口释放恰好 1 次、循环 3 轮(2 次覆盖释放 + 1 次出口)共 3 次;析构与释放点一一对应。 - README:NewLifetimeTest 补析构调度覆盖;NewLifetimeFreeTest 说明手动 del 同样被拒。 --- NewLifetimeTest/App/main.vp | 35 +++++++++++++++++++++++++++++++++++ README.md | 4 ++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/NewLifetimeTest/App/main.vp b/NewLifetimeTest/App/main.vp index 09321b8..2768f8a 100644 --- a/NewLifetimeTest/App/main.vp +++ b/NewLifetimeTest/App/main.vp @@ -107,6 +107,35 @@ def CaseStack() -> int: return 0 +# (9) §3.6 析构调度:slife 释放时**先**调 `__del__`、**再** free(对齐 TPC MemoryOps)。 +# 用一个计数全局量验证析构确实被调度,且每个释放点恰好一次。 +dtor_hits: int = 0 + + +novirtual class DtorPoint: + x: int + + def __del__(self) -> None: + global dtor_hits + dtor_hits += 1 + + +# 出口释放 → 恰好 1 次 __del__ +def CaseDtor() -> int: + p: DtorPoint* = new heap slife DtorPoint(3) + if p.x != 3: return 1 + return 0 + + +# 循环内反复 new → 2 次覆盖释放 + 出口 1 次 = 3 次 __del__(析构跟释放点一一对应) +def CaseDtorOverwrite() -> int: + i: int = 0 + while i < 3: + p: DtorPoint* = new heap slife DtorPoint(i) + i += 1 + return 0 + + def main() -> CInt | CExport: w32.win32console.SetConsoleCP(65001) w32.win32console.SetConsoleOutputCP(65001) @@ -124,6 +153,12 @@ def main() -> CInt | CExport: CaseVoidBare(1) CaseVoidBare(0) + # §3.6 析构调度:出口释放恰好 1 次;循环 3 轮(2 次覆盖 + 1 次出口)共 3 次 + fails += CaseDtor() + if dtor_hits != 1: fails += 1 + fails += CaseDtorOverwrite() + if dtor_hits != 4: fails += 1 + if fails != 0: stdio.printf("NewLifetimeTest FAILED, %d case(s) wrong\n", fails) return 1 diff --git a/README.md b/README.md index a97864b..9fa859e 100644 --- a/README.md +++ b/README.md @@ -131,8 +131,8 @@ | EscapeMethodTest | 仓库根 `EscapeMethodTest/` | **编译失败**:方法 / `__init__` / 嵌套函数交出栈地址 → `LifetimeError`(三用例互斥,一次开一条) | | EscapeXmodTest | 仓库根 `EscapeXmodTest/` | **编译失败**:跨模块摘要(`.vpi` 落盘 `# esc=`)路径 → `LifetimeError` | | NewTest | [Test/NewTest/](NewTest/App/main.vp) | 编译通过并输出 4 行:`stack`(显式 slife) / `heap` / `stack默认slife`(验证**缺省规则**:省略生命期时 stack→slife、heap/memgr→hlife)/ `memgr` | -| NewLifetimeTest | [Test/NewLifetimeTest/](NewLifetimeTest/App/main.vp) | 编译通过、退出码 0(**M3 owned slife RAII**:出口释放 / 循环内覆盖释放 / 别名只释放一次 / 嵌套函数登记隔离 / early return / void 裸 return / 仅分支里 new 时 `free(NULL)` / stack slife 不释放)。**另含 IR 断言**:IR 中必须出现 `llvm.call @free` | -| NewLifetimeFreeTest | [Test/NewLifetimeFreeTest/](NewLifetimeFreeTest/App/main.vp) | **编译失败**:对 `slife` 对象手动 `stdlib.free(p)` → `LifetimeError`(§4.3 判据5,编译器独占释放) | +| NewLifetimeTest | [Test/NewLifetimeTest/](NewLifetimeTest/App/main.vp) | 编译通过、退出码 0(**M3 owned slife RAII**:出口释放 / 循环内覆盖释放 / 别名只释放一次 / 嵌套函数登记隔离 / early return / void 裸 return / 仅分支里 new 时 `free(NULL)` / stack slife 不释放;**§3.6 析构调度**:出口释放恰好 1 次 `__del__`、循环 3 轮共 3 次)。**另含 IR 断言**:IR 中必须出现 `llvm.call @free` | +| NewLifetimeFreeTest | [Test/NewLifetimeFreeTest/](NewLifetimeFreeTest/App/main.vp) | **编译失败**:对 `slife` 对象手动 `stdlib.free(p)` → `LifetimeError`(§4.3 判据5,编译器独占释放;手动 `del p` 同样被拒) | 单独运行(`regression_test.py` 与 `SequentialRegressionTest.py` 都支持):