[bugfix] fixes #11524
This commit is contained in:
parent
0db3c670ac
commit
79c721d418
3 changed files with 40 additions and 5 deletions
|
|
@ -450,6 +450,25 @@ proc passCopyToSink(n: PNode; c: var Con): PNode =
|
||||||
result.add newTree(nkAsgn, tmp, p(n, c))
|
result.add newTree(nkAsgn, tmp, p(n, c))
|
||||||
result.add tmp
|
result.add tmp
|
||||||
|
|
||||||
|
proc isDangerousSeq(t: PType): bool {.inline.} =
|
||||||
|
let t = t.skipTypes(abstractInst)
|
||||||
|
result = t.kind == tySequence and tfHasOwned notin t.sons[0].flags
|
||||||
|
|
||||||
|
proc containsConstSeq(n: PNode): bool =
|
||||||
|
if n.kind == nkBracket and n.len > 0 and n.typ != nil and isDangerousSeq(n.typ):
|
||||||
|
return true
|
||||||
|
result = false
|
||||||
|
case n.kind
|
||||||
|
of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv:
|
||||||
|
result = containsConstSeq(n[1])
|
||||||
|
of nkObjConstr, nkClosure:
|
||||||
|
for i in 1 ..< n.len:
|
||||||
|
if containsConstSeq(n[i]): return true
|
||||||
|
of nkCurly, nkBracket, nkPar, nkTupleConstr:
|
||||||
|
for i in 0 ..< n.len:
|
||||||
|
if containsConstSeq(n[i]): return true
|
||||||
|
else: discard
|
||||||
|
|
||||||
proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
|
proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
|
||||||
template pArgIfTyped(argPart: PNode): PNode =
|
template pArgIfTyped(argPart: PNode): PNode =
|
||||||
# typ is nil if we are in if/case expr branch with noreturn
|
# typ is nil if we are in if/case expr branch with noreturn
|
||||||
|
|
@ -466,7 +485,12 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
|
||||||
result.add arg[0]
|
result.add arg[0]
|
||||||
for i in 1..<arg.len:
|
for i in 1..<arg.len:
|
||||||
result.add pArg(arg[i], c, i < L and isSinkTypeForParam(parameters[i]))
|
result.add pArg(arg[i], c, i < L and isSinkTypeForParam(parameters[i]))
|
||||||
elif arg.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkBracket, nkCharLit..nkTripleStrLit}:
|
elif arg.containsConstSeq:
|
||||||
|
# const sequences are not mutable and so we need to pass a copy to the
|
||||||
|
# sink parameter (bug #11524). Note that the string implemenation is
|
||||||
|
# different and can deal with 'const string sunk into var'.
|
||||||
|
result = passCopyToSink(arg, c)
|
||||||
|
elif arg.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkCharLit..nkTripleStrLit}:
|
||||||
discard "object construction to sink parameter: nothing to do"
|
discard "object construction to sink parameter: nothing to do"
|
||||||
result = arg
|
result = arg
|
||||||
elif arg.kind == nkSym and isSinkParam(arg.sym):
|
elif arg.kind == nkSym and isSinkParam(arg.sym):
|
||||||
|
|
@ -595,7 +619,10 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
|
||||||
result.add branch
|
result.add branch
|
||||||
of nkBracket:
|
of nkBracket:
|
||||||
# array constructor
|
# array constructor
|
||||||
result = genSink(c, dest.typ, dest, ri)
|
if ri.len > 0 and isDangerousSeq(ri.typ):
|
||||||
|
result = genCopy(c, dest.typ, dest, ri)
|
||||||
|
else:
|
||||||
|
result = genSink(c, dest.typ, dest, ri)
|
||||||
let ri2 = copyTree(ri)
|
let ri2 = copyTree(ri)
|
||||||
for i in 0..<ri.len:
|
for i in 0..<ri.len:
|
||||||
# everything that is passed to an array constructor is consumed,
|
# everything that is passed to an array constructor is consumed,
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ ha
|
||||||
@["arg", "asdfklasdfkl", "asdkfj", "dfasj", "klfjl"]
|
@["arg", "asdfklasdfkl", "asdkfj", "dfasj", "klfjl"]
|
||||||
@[1, 2, 3]
|
@[1, 2, 3]
|
||||||
@["red", "yellow", "orange", "rtrt1", "pink"]
|
@["red", "yellow", "orange", "rtrt1", "pink"]
|
||||||
30 30'''
|
a: @[4, 2, 3]
|
||||||
|
35 35'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import allocators
|
import allocators
|
||||||
|
|
@ -169,6 +170,14 @@ proc testWarm =
|
||||||
|
|
||||||
testWarm()
|
testWarm()
|
||||||
|
|
||||||
|
proc mutConstSeq() =
|
||||||
|
# bug #11524
|
||||||
|
var a = @[1,2,3]
|
||||||
|
a[0] = 4
|
||||||
|
echo "a: ", a
|
||||||
|
|
||||||
|
mutConstSeq()
|
||||||
|
|
||||||
#echo s
|
#echo s
|
||||||
let (a, d) = allocCounters()
|
let (a, d) = allocCounters()
|
||||||
discard cprintf("%ld %ld\n", a, d)
|
discard cprintf("%ld %ld\n", a, d)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
discard """
|
discard """
|
||||||
cmd: '''nim c --newruntime $file'''
|
cmd: '''nim c --newruntime $file'''
|
||||||
output: '''442 442'''
|
output: '''443 443'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import strutils, os
|
import strutils, os
|
||||||
|
|
@ -10,7 +10,6 @@ import system / ansi_c
|
||||||
|
|
||||||
# bug #11004
|
# bug #11004
|
||||||
proc retTuple(): (seq[int], int) =
|
proc retTuple(): (seq[int], int) =
|
||||||
# XXX this doesn't allocate yet but probably it should
|
|
||||||
return (@[1], 1)
|
return (@[1], 1)
|
||||||
|
|
||||||
proc nonStaticTests =
|
proc nonStaticTests =
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue