diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index feb5babeacad5..6bbae673a2350 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -146,7 +146,11 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, else: if d.k == locNone: d = getTemp(p, typ.returnType) var list = initLoc(locCall, d.lode, OnUnknown) - list.snippet = extract(result) + var rval = extract(result) + # the function returns T& but the temp is T*, so we need & + if tfVarIsPtr in typ.returnType.flags: + rval = cAddr(rval) + list.snippet = rval genAssignment(p, d, list, {needAssignCall}) # no need for deep copying if canRaise: raiseExit(p) @@ -589,6 +593,8 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) = list.snippet = callIter(rp, pars) else: list.snippet = callProc(rp, pars, rawProc) + if tfVarIsPtr in typ.returnType.flags: + list.snippet = cAddr(list.snippet) genAssignment(p, d, list, {}) # no need for deep copying if canRaise: raiseExit(p) else: @@ -601,6 +607,8 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) = list.snippet = callIter(rp, pars) else: list.snippet = callProc(rp, pars, rawProc) + if tfVarIsPtr in typ.returnType.flags: + list.snippet = cAddr(list.snippet) genAssignment(p, tmp, list, {}) if canRaise: raiseExit(p) genAssignment(p, d, tmp, {}) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index e023eeee7bb85..a3a467d706ad3 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -929,6 +929,13 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc) = # bug #23453 #25265 if e.typ != nil and e.typ.skipTypes(abstractInst).kind == tyObject: discard getTypeDesc(p.module, e.typ) + # C++: genProcParams strips tfVarIsPtr from the signature, so a var T + # return is T&. When used directly (lfSingleUse, a.k == locCall) it's a + # reference and must not be dereferenced. Temps hold T* (via cAddr) and + # still need '*'. The AST type keeps tfVarIsPtr (markResultVarIsPtr), + # so we check a.k to tell the two paths apart. + let isCppCallRef = p.module.compileToCpp and typ.kind in {tyVar} and + tfVarIsPtr in typ.flags and a.k == locCall if d.k == locNone: # dest = *a; <-- We do not know that 'dest' is on the heap! # It is completely wrong to set 'd.storage' here, unless it's not yet @@ -938,7 +945,7 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc) = d.storage = OnHeap of tyVar, tyLent: d.storage = OnUnknown - if tfVarIsPtr notin typ.flags and p.module.compileToCpp and + if (tfVarIsPtr notin typ.flags or isCppCallRef) and p.module.compileToCpp and e.kind == nkHiddenDeref: putIntoDest(p, d, e, rdLoc(a), a.storage) return @@ -947,7 +954,7 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc) = else: internalError(p.config, e.info, "genDeref " & $typ.kind) elif p.module.compileToCpp: - if typ.kind in {tyVar} and tfVarIsPtr notin typ.flags and + if typ.kind in {tyVar} and (tfVarIsPtr notin typ.flags or isCppCallRef) and e.kind == nkHiddenDeref: putIntoDest(p, d, e, rdLoc(a), a.storage) return diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index cd2e325deec76..b63de2df87cad 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -665,7 +665,13 @@ proc genProcParams(m: BModule; t: PType, rettype: var Rope, params: var Builder, if t.returnType == nil or isInvalidReturnType(m.config, t): rettype = CVoid else: - rettype = getTypeDescWeak(m, t.returnType, check, dkResult) + var rt = t.returnType + if m.config.backend == backendCpp and + tfVarIsPtr in rt.flags and + rt.skipTypes(abstractInst).kind == tyVar: + rt = rt.exactReplica(m.idgen) + rt.excl(tfVarIsPtr) + rettype = getTypeDescWeak(m, rt, check, dkResult) var paramBuilder: ProcParamBuilder params.addProcParams(paramBuilder): for i in 1..