summary refs log tree commit diff stats
path: root/tests/misc/taddr.nim
diff options
context:
space:
mode:
Diffstat (limited to 'tests/misc/taddr.nim')
-rw-r--r--tests/misc/taddr.nim295
1 files changed, 295 insertions, 0 deletions
diff --git a/tests/misc/taddr.nim b/tests/misc/taddr.nim
new file mode 100644
index 000000000..64f95c7e3
--- /dev/null
+++ b/tests/misc/taddr.nim
@@ -0,0 +1,295 @@
+discard """
+  targets: "c cpp js"
+  matrix: "; -d:release"
+"""
+
+type T = object
+  x: int
+  s: string
+
+var obj: T
+var fieldAddr = addr(obj.x)
+var objAddr = addr(obj)
+
+# Integer tests
+var field = fieldAddr[]
+doAssert field == 0
+
+var objDeref = objAddr[]
+doAssert objDeref.x == 0
+
+# Change value
+obj.x = 42
+
+doAssert field == 0
+doAssert objDeref.x == 0
+
+field = fieldAddr[]
+objDeref = objAddr[]
+
+doAssert field == 42
+doAssert objDeref.x == 42
+
+# String tests
+obj.s = "lorem ipsum dolor sit amet"
+when defined(gcArc) or defined(gcOrc):
+  prepareMutation(obj.s)
+
+
+var indexAddr = addr(obj.s[2])
+
+doAssert indexAddr[] == 'r'
+
+indexAddr[] = 'd'
+
+doAssert indexAddr[] == 'd'
+
+doAssert obj.s == "lodem ipsum dolor sit amet"
+
+# Bug #2148
+var x: array[2, int]
+var y = addr x[1]
+
+y[] = 12
+doAssert(x[1] == 12)
+
+type
+  Foo = object
+    bar: int
+
+var foo: array[2, Foo]
+var z = addr foo[1]
+
+z[].bar = 12345
+doAssert(foo[1].bar == 12345)
+
+var t : tuple[a, b: int]
+var pt = addr t[1]
+pt[] = 123
+doAssert(t.b == 123)
+
+#block: # Test "untyped" pointer.
+proc testPtr(p: pointer, a: int) =
+  doAssert(a == 5)
+  (cast[ptr int](p))[] = 124
+var i = 123
+testPtr(addr i, 5)
+doAssert(i == 124)
+
+var someGlobal = 5
+proc getSomeGlobalPtr(): ptr int = addr someGlobal
+let someGlobalPtr = getSomeGlobalPtr()
+doAssert(someGlobalPtr[] == 5)
+someGlobalPtr[] = 10
+doAssert(someGlobal == 10)
+
+block:
+  # bug #14576
+  # lots of these used to give: Error: internal error: genAddr: 2
+  proc byLent[T](a: T): lent T = a
+  proc byPtr[T](a: T): ptr T = a.addr
+
+  block:
+    let a = (10,11)
+    let (x,y) = byLent(a)
+    doAssert (x,y) == a
+
+  block: # (with -d:release) bug #14578
+    let a = 10
+    doAssert byLent(a) == 10
+    let a2 = byLent(a)
+    doAssert a2 == 10
+
+  block:
+    let a = [11,12]
+    doAssert byLent(a) == [11,12] # bug #15958
+    let a2 = (11,)
+    doAssert byLent(a2) == (11,)
+
+  block:
+    proc byLent2[T](a: seq[T]): lent T = a[1]
+    var a = @[20,21,22]
+    doAssert byLent2(a) == 21
+
+  block: # sanity checks
+    proc bar[T](a: var T): var T = a
+    var a = (10, 11)
+    let (k,v) = bar(a)
+    doAssert (k, v) == a
+    doAssert k == 10
+    bar(a)[0]+=100
+    doAssert a == (110, 11)
+    var a2 = 12
+    doAssert bar(a2) == a2
+    bar(a2).inc
+    doAssert a2 == 13
+
+  block: # pending bug #15959
+    when false:
+      proc byLent2[T](a: T): lent type(a[0]) = a[0]
+
+proc test14420() = # bug #14420
+  # s/proc/template/ would hit bug #16005
+  block:
+    type Foo = object
+      x: float
+
+    proc fn(a: var Foo): var float =
+      ## WAS: discard <- turn this into a comment (or a `discard`) and error disappears
+      # result = a.x # this works
+      a.x #  WAS: Error: limited VM support for 'addr'
+
+    proc fn2(a: var Foo): var float =
+      result = a.x # this works
+      a.x #  WAS: Error: limited VM support for 'addr'
+
+    var a = Foo()
+    discard fn(a)
+    discard fn2(a)
+
+  block:
+    proc byLent2[T](a: T): lent T =
+      runnableExamples: discard
+      a
+    proc byLent3[T](a: T): lent T =
+      runnableExamples: discard
+      result = a
+    var a = 10
+    let x3 = byLent3(a) # works
+    let x2 = byLent2(a) # WAS: Error: internal error: genAddr: nkStmtListExpr
+
+  block:
+    type MyOption[T] = object
+      case has: bool
+      of true:
+        value: T
+      of false:
+        discard
+    func some[T](val: T): MyOption[T] =
+      result = MyOption[T](has: true, value: val)
+    func get[T](opt: MyOption[T]): lent T =
+      doAssert opt.has
+      # result = opt.value # this was ok
+      opt.value # this had the bug
+    let x = some(10)
+    doAssert x.get() == 10
+
+template test14339() = # bug #14339
+  block:
+    type
+      Node = ref object
+        val: int
+    proc bar(c: Node): var int =
+      var n = c # was: Error: limited VM support for 'addr'
+      c.val
+    var a = Node()
+    discard a.bar()
+  block:
+    type
+      Node = ref object
+        val: int
+    proc bar(c: Node): var int =
+      var n = c
+      doAssert n.val == n[].val
+      n.val
+    var a = Node(val: 3)
+    a.bar() = 5
+    when nimvm:
+      doAssert a.val == 5
+    else:
+      when not defined(js): # pending bug #16003
+        doAssert a.val == 5
+
+template testStatic15464() = # bug #15464
+  proc access(s: var seq[char], i: int): var char = s[i]
+  proc access(s: var string, i: int): var char = s[i]
+  static:
+    var s = @['a', 'b', 'c']
+    access(s, 2) = 'C'
+    doAssert access(s, 2) == 'C'
+  static:
+    var s = "abc"
+    access(s, 2) = 'C'
+    doAssert access(s, 2) == 'C'
+
+proc test15464() = # bug #15464 (v2)
+  proc access(s: var seq[char], i: int): var char = s[i]
+  proc access(s: var string, i: int): var char = s[i]
+  block:
+    var s = @['a', 'b', 'c']
+    access(s, 2) = 'C'
+    doAssert access(s, 2) == 'C'
+  block:
+    var s = "abc"
+    access(s, 2) = 'C'
+    doAssert access(s, 2) == 'C'
+
+block: # bug #15939
+  block:
+    const foo = "foo"
+    proc proc1(s: var string) =
+      if s[^1] notin {'a'..'z'}:
+        s = ""
+    proc proc2(f: string): string =
+      result = f
+      proc1(result)
+    const bar = proc2(foo)
+    doAssert bar == "foo"
+
+template prepareMutationForOrc(x: string) =
+  when defined(gcArc) or defined(gcOrc):
+    when nimvm:
+      discard
+    else:
+      prepareMutation(x)
+
+proc test15939() = # bug #15939 (v2)
+  template fn(a) =
+    when typeof(a) is string:
+      prepareMutationForOrc(a)
+    let pa = a[0].addr
+    doAssert pa != nil
+    doAssert pa[] == 'a'
+    pa[] = 'x'
+    doAssert pa[] == 'x'
+    doAssert a == "xbc"
+    when not defined js: # otherwise overflows
+      let pa2 = cast[ptr char](cast[int](pa) + 1)
+      doAssert pa2[] == 'b'
+      pa2[] = 'B'
+      doAssert a == "xBc"
+
+  # mystring[ind].addr
+  var a = "abc"
+  fn(a)
+
+  # mycstring[ind].addr
+  template cstringTest =
+    var a2 = "abc"
+    prepareMutationForOrc(a2)
+    var b2 = a2.cstring
+    fn(b2)
+  when nimvm: cstringTest()
+  else: # can't take address of cstring element in js
+    when not defined(js): cstringTest()
+
+block: # bug #23499
+  template volatileStore[T](dest: ptr T, val: T) =
+    dest[] = val
+
+  proc foo =
+    var ctr = 0
+    volatileStore(addr ctr, 0)
+
+  foo()
+
+template main =
+  # xxx wrap all other tests here like that so they're also tested in VM
+  test14420()
+  test14339()
+  test15464()
+  test15939()
+
+testStatic15464()
+static: main()
+main()