diff --git a/lib/core/Handles/HandlesExprOps.py b/lib/core/Handles/HandlesExprOps.py index c382ee8..956677a 100644 --- a/lib/core/Handles/HandlesExprOps.py +++ b/lib/core/Handles/HandlesExprOps.py @@ -288,9 +288,26 @@ class ExprOpsHandle(BaseHandle): SubPtr: ir.Value | None = self.Trans.ExprAttrHandle.HandleSubscriptPtrLlvm(Node.operand) if SubPtr and isinstance(SubPtr.type, ir.PointerType): return SubPtr + elif isinstance(Node.operand, ast.Call): + # &() → rvalue 取址。复用上面已求值的 OperandVal,绝不二次求值 + # (构造调用会再跑一遍 __before_init__/__init__)。 + # · 构造调用(_HandleClassNewLlvm)返回的就是临时对象的栈存储指针 + # Ptr(Struct) —— 该指针即"栈构造结构体的地址"本身,原样返回; + # 不能再套 alloca+store(会得到 Ptr(Ptr(Struct)),赋值端还得 + # load 一次回落,语义也从"对象地址"变"槽地址")。 + # · 其它返回值(标量、按值返回的结构体值):入口临时槽承载—— + # allocaEntry 同类型槽 → store → 返回槽地址(与 TransPyV 侧 + # ExprGenOps._addrof_of_call 同口径)。 + OperandType: ir.Type = OperandVal.type + if isinstance(OperandType, ir.PointerType) \ + and isinstance(OperandType.pointee, (ir.IdentifiedStructType, ir.LiteralStructType)): + return OperandVal + TmpSlot: ir.Value = Gen._allocaEntry(OperandType, name="addrof_tmp") + Gen.builder.store(OperandVal, TmpSlot) + return TmpSlot raise TypeError( f"[fast-fail] 单目 '&' 取地址的操作数必须是左值" - f"(Name/Attribute/Subscript),实际为 {type(Node.operand).__name__}" + f"(Name/Attribute/Subscript)或构造调用/函数调用结果,实际为 {type(Node.operand).__name__}" ) return None