[backport] fixes #23748; do not skip materializing temporaries for proc arguments (#23769)

fixes #23748

(cherry picked from commit 4202b606b1)
This commit is contained in:
Alexander Kernozhitsky
2024-06-30 14:10:10 +02:00
committed by narimiran
parent e98c98b46c
commit 3788aa0a99
3 changed files with 48 additions and 4 deletions

View File

@@ -309,7 +309,16 @@ proc genArg(p: BProc, n: PNode, param: PSym; call: PNode; result: var Rope; need
addAddrLoc(p.config, withTmpIfNeeded(p, a, needsTmp), result)
elif p.module.compileToCpp and param.typ.kind in {tyVar} and
n.kind == nkHiddenAddr:
initLocExprSingleUse(p, n[0], a)
# bug #23748: we need to introduce a temporary here. The expression type
# will be a reference in C++ and we cannot create a temporary reference
# variable. Thus, we create a temporary pointer variable instead.
let needsIndirect = mapType(p.config, n[0].typ, mapTypeChooser(n[0]) == skParam) != ctArray
if needsIndirect:
n.typ = n.typ.exactReplica
n.typ.flags.incl tfVarIsPtr
initLocExprSingleUse(p, n, a)
a = withTmpIfNeeded(p, a, needsTmp)
if needsIndirect: a.flags.incl lfIndirect
# if the proc is 'importc'ed but not 'importcpp'ed then 'var T' still
# means '*T'. See posix.nim for lots of examples that do that in the wild.
let callee = call[0]
@@ -407,9 +416,11 @@ proc genParams(p: BProc, ri: PNode, typ: PType; result: var Rope) =
if not needTmp[i - 1]:
needTmp[i - 1] = potentialAlias(n, potentialWrites)
getPotentialWrites(ri[i], false, potentialWrites)
if ri[i].kind in {nkHiddenAddr, nkAddr}:
# Optimization: don't use a temp, if we would only take the address anyway
needTmp[i - 1] = false
when false:
# this optimization is wrong, see bug #23748
if ri[i].kind in {nkHiddenAddr, nkAddr}:
# Optimization: don't use a temp, if we would only take the address anyway
needTmp[i - 1] = false
var oldLen = result.len
for i in 1..<ri.len:

View File

@@ -832,6 +832,8 @@ proc genAddr(p: BProc, e: PNode, d: var TLoc) =
#Message(e.info, warnUser, "HERE NEW &")
elif mapType(p.config, e[0].typ, mapTypeChooser(e[0]) == skParam) == ctArray or isCppRef(p, e.typ):
expr(p, e[0], d)
# bug #19497
d.lode = e
else:
var a: TLoc
initLocExpr(p, e[0], a)

View File

@@ -0,0 +1,31 @@
discard """
matrix: "--gc:refc; --gc:arc"
output: '''
hello 42
hello 42
len = 2
'''
"""
# bug #23748
type
O = ref object
s: string
cb: seq[proc()]
proc push1(o: O, i: int) =
let o = o
echo o.s, " ", i
o.cb.add(proc() = echo o.s, " ", i)
proc push2(o: O, i: int) =
let o = o
echo o.s, " ", i
proc p() = echo o.s, " ", i
o.cb.add(p)
let o = O(s: "hello", cb: @[])
o.push1(42)
o.push2(42)
echo "len = ", o.cb.len