From 7384d9a57c3a83d93c0394235e1a9da7012aaa91 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Fri, 2 Oct 2026 17:29:58 +0800 Subject: [PATCH] =?UTF-8?q?fix(parser):=20=E7=B1=BB=E5=9E=8B=E6=B3=A8?= =?UTF-8?q?=E8=A7=A3=E4=BD=8D=E7=9A=84=20=5F=5Fattribute=5F=5F(...)=20?= =?UTF-8?q?=E5=8F=AA=E8=A7=A3=E6=9E=90=E8=B0=83=E7=94=A8=E6=9C=AC=E8=BA=AB?= =?UTF-8?q?=EF=BC=8C=E4=B8=8D=E5=86=8D=E5=90=9E=E6=8E=89=E5=90=8E=E7=BB=AD?= =?UTF-8?q?=20[]T?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原实现用 _parse_test 解析 __attribute__(...) —— 那是通用表达式解析器,解析完调用后 会继续吃 postfix trailer,把紧随的 C 风格前置数组 `[]T` 的 `[]` 当作**合法空下标** 吞掉(_parse_slice 显式支持空下标 T[],见其注释)。后果:ac_node 不再是 Call ⇒ 描述符循环 break(markers 一个都没收集),且 _match_op(Lsqb) 此时看到的是元素类型 ⇒ 数组分支被跳过 ⇒ 整个注解退化成裸元素类型,且**全程零报错**。 现场:TransPyV/App/main.vp:44 V_TPV_VERSION: __attribute__(section(".PRVERSN")) []char = "0.0.5-dev.479" 被解析成 `char`:stub 记 `V_TPV_VERSION: char`、IR 出 `@g = global i8 getelementptr ...`(opt: got 'ptr' but expected 'i8')、段名 ".PRVERSN" 丢失。 改为:_advance 过 `__attribute__` 后用 _parse_call 解析 `( 实参表 )`,postfix 不再被 误吃,`[]char` 交回数组分支脱糖为 t.CArray[char, None] → i8*。 --- ast/parser.vp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/ast/parser.vp b/ast/parser.vp index a37422b..4b5ffc4 100644 --- a/ast/parser.vp +++ b/ast/parser.vp @@ -2631,7 +2631,23 @@ def _parse_type_ann(ps: rawptr[Parser]) -> rawptr[AST]: # 与 const / volatile 同位置、同顺序自由、可混写;每个实参 desugar 成 # `t.attr.`(带调用则保留实参)后并入同一 markers 列表,由 # _PrependDescriptorMarkers 贴到类型联合最左(与 TPC 文本展开同形)。 - ac_node: rawptr[AST] = _parse_test(ps) + # + # ⚠ 只用 _parse_call 解析**这个调用本身**,绝不能用 _parse_test:后者是 + # 通用表达式解析器,解析完 `__attribute__(...)` 会继续吃 postfix trailer, + # 把紧随的 C 风格前置数组 `[]T` 的 `[]` 当作**合法空下标**吞掉 + # (_parse_slice 显式支持空下标 `T[]`,见其注释)——全程**零报错**, + # 但 ac_node 已不是 Call ⇒ 本循环 break、markers 一个都没收集,且 + # `_match_op(Lsqb)` 此时看到的是元素类型 ⇒ 数组分支被跳过 ⇒ 注解整体 + # 退化成裸元素类型。现场:main.vp:44 + # V_TPV_VERSION: __attribute__(section(".PRVERSN")) []char = "…" + # 被解析成 `char`(stub 记 `V_TPV_VERSION: char`、IR 出 + # `global i8 ` 非法、段名 ".PRVERSN" 丢失)。 + mka_lineno: int = _cur_lineno(ps) + mka_col: int = _cur_col(ps) + mka_fn: rawptr[AST] = Name(ps.pool, "__attribute__", ASTCtx.Load) + _set_pos(mka_fn, mka_lineno, mka_col, 0, 0) + _advance(ps) # 消费 `__attribute__` + ac_node: rawptr[AST] = _parse_call(ps, mka_fn) # 只解析 `( 实参表 )` if ac_node is None: break if ac_node.kind() != ASTKind.Call: