diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2020-01-15 22:13:31 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-01-15 22:13:31 +0100 |
commit | a5e67071d27a33c7f19d739a6918e9e16b44e4ab (patch) | |
tree | 27360358bdd415011b27357c44c96f11299b596b /tests/arc | |
parent | d88b52c0bc505db42ba6561518c9ee9b21a99e81 (diff) | |
download | Nim-a5e67071d27a33c7f19d739a6918e9e16b44e4ab.tar.gz |
ARC: misc bugfixes (#13156)
* fixes #13102 * closes #13149 * ARC: fixes a move optimizer bug (there are more left regarding array and tuple indexing) * proper fix; fixes #12957 * fixes yet another case object '=' code generation problem
Diffstat (limited to 'tests/arc')
-rw-r--r-- | tests/arc/tcaseobj.nim | 146 | ||||
-rw-r--r-- | tests/arc/tmovebug.nim | 64 |
2 files changed, 210 insertions, 0 deletions
diff --git a/tests/arc/tcaseobj.nim b/tests/arc/tcaseobj.nim new file mode 100644 index 000000000..44daa5979 --- /dev/null +++ b/tests/arc/tcaseobj.nim @@ -0,0 +1,146 @@ +discard """ + valgrind: true + cmd: "nim c --gc:arc -d:useMalloc $file" + output: '''myobj destroyed +myobj destroyed +myobj destroyed +A +B +begin +end +myobj destroyed +''' +""" + +# bug #13102 + +type + D = ref object + R = object + case o: bool + of false: + discard + of true: + field: D + +iterator things(): R = + when true: + var + unit = D() + while true: + yield R(o: true, field: unit) + else: + while true: + var + unit = D() + yield R(o: true, field: unit) + +proc main = + var i = 0 + for item in things(): + discard item.field + inc i + if i == 2: break + +main() + +# bug #13149 + +type + TMyObj = object + p: pointer + len: int + +proc `=destroy`(o: var TMyObj) = + if o.p != nil: + dealloc o.p + o.p = nil + echo "myobj destroyed" + +proc `=`(dst: var TMyObj, src: TMyObj) = + `=destroy`(dst) + dst.p = alloc(src.len) + dst.len = src.len + +proc `=sink`(dst: var TMyObj, src: TMyObj) = + `=destroy`(dst) + dst.p = src.p + dst.len = src.len + +type + TObjKind = enum Z, A, B + TCaseObj = object + case kind: TObjKind + of Z: discard + of A: + x1: int # this int plays important role + x2: TMyObj + of B: + y: TMyObj + +proc testSinks: TCaseObj = + result = TCaseObj(kind: A, x1: 5000, x2: TMyObj(len: 5, p: alloc(5))) + result = TCaseObj(kind: B, y: TMyObj(len: 3, p: alloc(3))) + +proc use(x: TCaseObj) = discard + +proc testCopies(i: int) = + var a: array[2, TCaseObj] + a[i] = TCaseObj(kind: A, x1: 5000, x2: TMyObj(len: 5, p: alloc(5))) + a[i+1] = a[i] # copy, cannot move + use(a[i]) + +let x1 = testSinks() +testCopies(0) + +# bug #12957 + +type + PegKind* = enum + pkCharChoice, + pkSequence + Peg* = object ## type that represents a PEG + case kind: PegKind + of pkCharChoice: charChoice: ref set[char] + else: discard + sons: seq[Peg] + +proc charSet*(s: set[char]): Peg = + ## constructs a PEG from a character set `s` + result = Peg(kind: pkCharChoice) + new(result.charChoice) + result.charChoice[] = s + +proc len(a: Peg): int {.inline.} = return a.sons.len +proc myadd(d: var Peg, s: Peg) {.inline.} = add(d.sons, s) + +proc sequence*(a: openArray[Peg]): Peg = + result = Peg(kind: pkSequence, sons: @[]) + when false: + #works too: + result.myadd(a[0]) + result.myadd(a[1]) + for x in items(a): + # works: + #result.sons.add(x) + # fails: + result.myadd x + if result.len == 1: + result = result.sons[0] # this must not move! + +when true: + # bug #12957 + + proc p = + echo "A" + let x = sequence([charSet({'a'..'z', 'A'..'Z', '_'}), + charSet({'a'..'z', 'A'..'Z', '0'..'9', '_'})]) + echo "B" + p() + + proc testSubObjAssignment = + echo "begin" + # There must be extactly one element in the array constructor! + let x = sequence([charSet({'a'..'z', 'A'..'Z', '_'})]) + echo "end" + testSubObjAssignment() diff --git a/tests/arc/tmovebug.nim b/tests/arc/tmovebug.nim new file mode 100644 index 000000000..98f181b81 --- /dev/null +++ b/tests/arc/tmovebug.nim @@ -0,0 +1,64 @@ +discard """ + cmd: "nim c --gc:arc $file" + output: '''5''' +""" + +# move bug +type + TMyObj = object + p: pointer + len: int + +var destroyCounter = 0 + +proc `=destroy`(o: var TMyObj) = + if o.p != nil: + dealloc o.p + o.p = nil + inc destroyCounter + +proc `=`(dst: var TMyObj, src: TMyObj) = + `=destroy`(dst) + dst.p = alloc(src.len) + dst.len = src.len + +proc `=sink`(dst: var TMyObj, src: TMyObj) = + `=destroy`(dst) + dst.p = src.p + dst.len = src.len + +type + TObjKind = enum Z, A, B + TCaseObj = object + case kind: TObjKind + of Z: discard + of A: + x1: int # this int plays important role + x2: TMyObj + of B: + y: TMyObj + +proc use(a: TCaseObj) = discard + +proc moveBug(i: var int) = + var a: array[2, TCaseObj] + a[i] = TCaseObj(kind: A, x1: 5000, x2: TMyObj(len: 5, p: alloc(5))) # 1 + a[i+1] = a[i] # 2 + inc i + use(a[i-1]) + +var x = 0 +moveBug(x) + +proc moveBug2(): (TCaseObj, TCaseObj) = + var a: array[2, TCaseObj] + a[0] = TCaseObj(kind: A, x1: 5000, x2: TMyObj(len: 5, p: alloc(5))) + a[1] = a[0] # can move 3 + result[0] = TCaseObj(kind: A, x1: 5000, x2: TMyObj(len: 5, p: alloc(5))) # 4 + result[1] = result[0] # 5 + +proc main = + discard moveBug2() + +main() +echo destroyCounter |