Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 21 additions & 6 deletions compiler/ccgcalls.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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:
Expand All @@ -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, {})
Expand Down Expand Up @@ -872,11 +880,18 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
genAssignment(p, d, tmp, {}) # no need for deep copying
else:
pl.add("]")
if d.k == locNone: d = getTemp(p, typ.returnType)
assert(d.t != nil) # generate an assignment to d:
var list: TLoc = initLoc(locCall, ri, OnUnknown)
list.snippet = extract(pl)
genAssignment(p, d, list, {}) # no need for deep copying
if p.module.compileToCpp and typ.returnType != nil and
typ.returnType.skipTypes(abstractInst).kind == tyVar:
d = getTempCpp(p, typ.returnType, extract(pl))
else:
if d.k == locNone: d = getTemp(p, typ.returnType)
assert(d.t != nil) # generate an assignment to d:
var list: TLoc = initLoc(locCall, ri, OnUnknown)
var rval = extract(pl)
if tfVarIsPtr in typ.returnType.flags:
rval = cAddr(rval)
list.snippet = rval
genAssignment(p, d, list, {}) # no need for deep copying
Comment thread
nimamasl114514 marked this conversation as resolved.
Outdated
else:
pl.add("]")
p.s(cpsStmts).addStmt():
Expand Down
8 changes: 7 additions & 1 deletion compiler/ccgtypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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..<t.n.len:
Expand Down
13 changes: 10 additions & 3 deletions compiler/cgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -746,10 +746,14 @@ proc getTempCpp(p: BProc, t: PType, value: Rope): TLoc =
inc(p.labels)
result = TLoc(snippet: "T" & rope(p.labels) & "_", k: locTemp, lode: lodeTyp t,
storage: OnStack, flags: {})
let isVarRet = p.module.compileToCpp and
t.skipTypes(abstractInst).kind == tyVar
let tmpTyp = if isVarRet: getTypeDesc(p.module, t, dkVar) else: "auto"
let initVal = if isVarRet and tfVarIsPtr in t.flags: cAddr(value) else: value
p.s(cpsStmts).addVar(kind = Local,
name = result.snippet,
typ = "auto",
initializer = value)
typ = tmpTyp,
initializer = initVal)

proc getIntTemp(p: BProc): TLoc =
inc(p.labels)
Expand Down Expand Up @@ -1520,7 +1524,10 @@ proc genProcLvl3*(m: BModule, prc: PSym) =
else:
initLocalVar(p, res, immediateAsgn=false)
var returnBuilder = newBuilder("\t")
let rres = rdLoc(res.loc)
var rres = rdLoc(res.loc)
if m.compileToCpp and res.typ.skipTypes(abstractInst).kind == tyVar and
tfVarIsPtr in res.typ.flags:
rres = cDeref(rres)
returnBuilder.addReturn(rres)
returnStmt = extract(returnBuilder)
elif sfConstructor in prc.flags:
Expand Down
54 changes: 54 additions & 0 deletions tests/proc/tprocvar_var_ret.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
discard """
targets: "c cpp"
"""

proc testVarRet(x: var int): var int = x

proc testProcTypeParam(prc: proc (x: var int): var int {.nimcall.}) =
var x = 123
prc(x) = 321
doAssert x == 321

testProcTypeParam(testVarRet)

var v = 42
doAssert testVarRet(v) == 42
testVarRet(v) = 99
doAssert v == 99

var pVarRet = testVarRet
var testVar = 1234
pVarRet(testVar) = 5678
doAssert testVar == 5678

proc testVarRetStr(x: var string): var string = x

proc testProcTypeParamStr(prc: proc (x: var string): var string {.nimcall.}) =
var x = "foo"
prc(x) = "bar"
doAssert x == "bar"

testProcTypeParamStr(testVarRetStr)

type
FooObj = object
x, y: int

proc testVarRetObj(x: var FooObj): var FooObj = x

proc testProcTypeParamObj(prc: proc (x: var FooObj): var FooObj {.nimcall.}) =
var x = FooObj(x: 111, y: 222)
prc(x) = FooObj(x: 333, y: 444)
doAssert x == FooObj(x: 333, y: 444)

testProcTypeParamObj(testVarRetObj)

proc testProcTypeParamChain(prc: proc (x: var int): var int {.nimcall.}) =
var x = 100
var y = 200
prc(x) = prc(y)
doAssert x == 200

testProcTypeParamChain(testVarRet)

echo "ok"
Loading