diff options
-rw-r--r-- | compiler/ccgcalls.nim | 19 | ||||
-rw-r--r-- | compiler/ccgexprs.nim | 2 | ||||
-rw-r--r-- | tests/destructor/t23748.nim | 31 |
3 files changed, 48 insertions, 4 deletions
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index 81c0fb555..a289e01b7 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -331,7 +331,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: - a = initLocExprSingleUse(p, n[0]) + # 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 + a = initLocExprSingleUse(p, n) + 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] @@ -430,9 +439,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: diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 1f9fbfde9..6db5b3ba8 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -812,6 +812,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]) putIntoDest(p, d, e, addrLoc(p.config, a), a.storage) diff --git a/tests/destructor/t23748.nim b/tests/destructor/t23748.nim new file mode 100644 index 000000000..a3738733e --- /dev/null +++ b/tests/destructor/t23748.nim @@ -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 |