summary refs log tree commit diff stats
path: root/tests/arc
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2020-01-15 22:13:31 +0100
committerGitHub <noreply@github.com>2020-01-15 22:13:31 +0100
commita5e67071d27a33c7f19d739a6918e9e16b44e4ab (patch)
tree27360358bdd415011b27357c44c96f11299b596b /tests/arc
parentd88b52c0bc505db42ba6561518c9ee9b21a99e81 (diff)
downloadNim-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.nim146
-rw-r--r--tests/arc/tmovebug.nim64
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