fixes #12766
This commit is contained in:
parent
a114a40b57
commit
b688250202
3 changed files with 96 additions and 8 deletions
|
|
@ -239,7 +239,7 @@ proc getTemp(c: var Con; typ: PType; info: TLineInfo): PNode =
|
||||||
proc genWasMoved(n: PNode; c: var Con): PNode =
|
proc genWasMoved(n: PNode; c: var Con): PNode =
|
||||||
result = newNodeI(nkCall, n.info)
|
result = newNodeI(nkCall, n.info)
|
||||||
result.add(newSymNode(createMagic(c.graph, "wasMoved", mWasMoved)))
|
result.add(newSymNode(createMagic(c.graph, "wasMoved", mWasMoved)))
|
||||||
result.add n #mWasMoved does not take the address
|
result.add copyTree(n) #mWasMoved does not take the address
|
||||||
|
|
||||||
proc genDefaultCall(t: PType; c: Con; info: TLineInfo): PNode =
|
proc genDefaultCall(t: PType; c: Con; info: TLineInfo): PNode =
|
||||||
result = newNodeI(nkCall, info)
|
result = newNodeI(nkCall, info)
|
||||||
|
|
@ -401,6 +401,7 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
|
||||||
# different and can deal with 'const string sunk into var'.
|
# different and can deal with 'const string sunk into var'.
|
||||||
result = passCopyToSink(arg, c)
|
result = passCopyToSink(arg, c)
|
||||||
elif arg.kind in nkLiterals:
|
elif arg.kind in nkLiterals:
|
||||||
|
# literals are save to share accross ASTs (for now!)
|
||||||
result = arg # literal to sink parameter: nothing to do
|
result = arg # literal to sink parameter: nothing to do
|
||||||
elif arg.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkClosure}:
|
elif arg.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkClosure}:
|
||||||
# object construction to sink parameter: nothing to do
|
# object construction to sink parameter: nothing to do
|
||||||
|
|
@ -497,19 +498,22 @@ proc p(n: PNode; c: var Con; consumed = false): PNode =
|
||||||
of nkCallKinds:
|
of nkCallKinds:
|
||||||
let parameters = n[0].typ
|
let parameters = n[0].typ
|
||||||
let L = if parameters != nil: parameters.len else: 0
|
let L = if parameters != nil: parameters.len else: 0
|
||||||
|
result = shallowCopy(n)
|
||||||
for i in 1..<n.len:
|
for i in 1..<n.len:
|
||||||
n[i] = pArg(n[i], c, i < L and isSinkTypeForParam(parameters[i]))
|
result[i] = pArg(n[i], c, i < L and isSinkTypeForParam(parameters[i]))
|
||||||
result = n
|
if n[0].kind == nkSym and n[0].sym.magic in {mNew, mNewFinalize}:
|
||||||
if result[0].kind == nkSym and result[0].sym.magic in {mNew, mNewFinalize}:
|
result[0] = copyTree(n[0])
|
||||||
if c.graph.config.selectedGC in {gcHooks, gcDestructors}:
|
if c.graph.config.selectedGC in {gcHooks, gcDestructors}:
|
||||||
let destroyOld = genDestroy(c, result[1])
|
let destroyOld = genDestroy(c, result[1])
|
||||||
result = newTree(nkStmtList, destroyOld, result)
|
result = newTree(nkStmtList, destroyOld, result)
|
||||||
else:
|
else:
|
||||||
result[0] = pArg(result[0], c, isSink = false)
|
result[0] = pArg(n[0], c, isSink = false)
|
||||||
of nkDiscardStmt: # Small optimization
|
of nkDiscardStmt: # Small optimization
|
||||||
|
result = shallowCopy(n)
|
||||||
if n[0].kind != nkEmpty:
|
if n[0].kind != nkEmpty:
|
||||||
n[0] = pArg(n[0], c, false)
|
result[0] = pArg(n[0], c, false)
|
||||||
result = n
|
else:
|
||||||
|
result[0] = copyNode(n[0])
|
||||||
of nkBracket:
|
of nkBracket:
|
||||||
result = copyTree(n)
|
result = copyTree(n)
|
||||||
for i in 0..<n.len:
|
for i in 0..<n.len:
|
||||||
|
|
@ -580,7 +584,7 @@ proc p(n: PNode; c: var Con; consumed = false): PNode =
|
||||||
result = moveOrCopy(n[0], n[1], c)
|
result = moveOrCopy(n[0], n[1], c)
|
||||||
else:
|
else:
|
||||||
result = copyNode(n)
|
result = copyNode(n)
|
||||||
result.add n[0]
|
result.add copyTree(n[0])
|
||||||
result.add p(n[1], c)
|
result.add p(n[1], c)
|
||||||
of nkRaiseStmt:
|
of nkRaiseStmt:
|
||||||
if optOwnedRefs in c.graph.config.globalOptions and n[0].kind != nkEmpty:
|
if optOwnedRefs in c.graph.config.globalOptions and n[0].kind != nkEmpty:
|
||||||
|
|
|
||||||
77
tests/destructor/const_smart_ptr.nim
Normal file
77
tests/destructor/const_smart_ptr.nim
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
type
|
||||||
|
ConstPtr*[T] = object
|
||||||
|
val: ptr T
|
||||||
|
|
||||||
|
proc `=destroy`*[T](p: var ConstPtr[T]) =
|
||||||
|
if p.val != nil:
|
||||||
|
`=destroy`(p.val[])
|
||||||
|
dealloc(p.val)
|
||||||
|
p.val = nil
|
||||||
|
|
||||||
|
proc `=`*[T](dest: var ConstPtr[T], src: ConstPtr[T]) {.error.}
|
||||||
|
|
||||||
|
proc `=sink`*[T](dest: var ConstPtr[T], src: ConstPtr[T]) {.inline.} =
|
||||||
|
if dest.val != nil and dest.val != src.val:
|
||||||
|
`=destroy`(dest)
|
||||||
|
dest.val = src.val
|
||||||
|
|
||||||
|
proc newConstPtr*[T](val: sink T): ConstPtr[T] {.inline.} =
|
||||||
|
result.val = cast[type(result.val)](alloc(sizeof(result.val[])))
|
||||||
|
reset(result.val[])
|
||||||
|
result.val[] = val
|
||||||
|
|
||||||
|
converter convertConstPtrToObj*[T](p: ConstPtr[T]): lent T =
|
||||||
|
result = p.val[]
|
||||||
|
|
||||||
|
|
||||||
|
#-------------------------------------------------------------
|
||||||
|
|
||||||
|
type
|
||||||
|
MySeqNonCopyable* = object
|
||||||
|
len: int
|
||||||
|
data: ptr UncheckedArray[float]
|
||||||
|
|
||||||
|
proc `=destroy`*(m: var MySeqNonCopyable) {.inline.} =
|
||||||
|
if m.data != nil:
|
||||||
|
deallocShared(m.data)
|
||||||
|
m.data = nil
|
||||||
|
|
||||||
|
proc `=`*(m: var MySeqNonCopyable, m2: MySeqNonCopyable) {.error.}
|
||||||
|
|
||||||
|
proc `=sink`*(m: var MySeqNonCopyable, m2: MySeqNonCopyable) {.inline.} =
|
||||||
|
if m.data != m2.data:
|
||||||
|
if m.data != nil:
|
||||||
|
`=destroy`(m)
|
||||||
|
m.len = m2.len
|
||||||
|
m.data = m2.data
|
||||||
|
|
||||||
|
proc len*(m: MySeqNonCopyable): int {.inline.} = m.len
|
||||||
|
|
||||||
|
proc `[]`*(m: MySeqNonCopyable; i: int): float {.inline.} =
|
||||||
|
m.data[i.int]
|
||||||
|
|
||||||
|
proc `[]=`*(m: var MySeqNonCopyable; i: int, val: float) {.inline.} =
|
||||||
|
m.data[i.int] = val
|
||||||
|
|
||||||
|
proc setTo(s: var MySeqNonCopyable, val: float) =
|
||||||
|
for i in 0..<s.len.int:
|
||||||
|
s.data[i] = val
|
||||||
|
|
||||||
|
proc newMySeq*(size: int, initial_value = 0.0): MySeqNonCopyable =
|
||||||
|
result.len = size
|
||||||
|
if size > 0:
|
||||||
|
result.data = cast[ptr UncheckedArray[float]](createShared(float, size))
|
||||||
|
result.setTo(initial_value)
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
proc test*(x1: int): ConstPtr[MySeqNonCopyable] {.inline.} = # remove inline here to make it work as expected
|
||||||
|
if x1 == 0:
|
||||||
|
let x = newMySeq(1, 0.0)
|
||||||
|
result = newConstPtr(x)
|
||||||
|
else:
|
||||||
|
let y = newMySeq(x1, 0.0)
|
||||||
|
result = newConstPtr(y)
|
||||||
|
|
||||||
|
discard test(10)
|
||||||
7
tests/destructor/tconst_smart_ptr.nim
Normal file
7
tests/destructor/tconst_smart_ptr.nim
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
discard """
|
||||||
|
action: "compile"
|
||||||
|
"""
|
||||||
|
|
||||||
|
import const_smart_ptr
|
||||||
|
|
||||||
|
discard test(0)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue