taddr.nim 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. discard """
  2. targets: "c cpp js"
  3. matrix: "; -d:release"
  4. """
  5. type T = object
  6. x: int
  7. s: string
  8. var obj: T
  9. var fieldAddr = addr(obj.x)
  10. var objAddr = addr(obj)
  11. # Integer tests
  12. var field = fieldAddr[]
  13. doAssert field == 0
  14. var objDeref = objAddr[]
  15. doAssert objDeref.x == 0
  16. # Change value
  17. obj.x = 42
  18. doAssert field == 0
  19. doAssert objDeref.x == 0
  20. field = fieldAddr[]
  21. objDeref = objAddr[]
  22. doAssert field == 42
  23. doAssert objDeref.x == 42
  24. # String tests
  25. obj.s = "lorem ipsum dolor sit amet"
  26. when defined(gcArc) or defined(gcOrc):
  27. prepareMutation(obj.s)
  28. var indexAddr = addr(obj.s[2])
  29. doAssert indexAddr[] == 'r'
  30. indexAddr[] = 'd'
  31. doAssert indexAddr[] == 'd'
  32. doAssert obj.s == "lodem ipsum dolor sit amet"
  33. # Bug #2148
  34. var x: array[2, int]
  35. var y = addr x[1]
  36. y[] = 12
  37. doAssert(x[1] == 12)
  38. type
  39. Foo = object
  40. bar: int
  41. var foo: array[2, Foo]
  42. var z = addr foo[1]
  43. z[].bar = 12345
  44. doAssert(foo[1].bar == 12345)
  45. var t : tuple[a, b: int]
  46. var pt = addr t[1]
  47. pt[] = 123
  48. doAssert(t.b == 123)
  49. #block: # Test "untyped" pointer.
  50. proc testPtr(p: pointer, a: int) =
  51. doAssert(a == 5)
  52. (cast[ptr int](p))[] = 124
  53. var i = 123
  54. testPtr(addr i, 5)
  55. doAssert(i == 124)
  56. var someGlobal = 5
  57. proc getSomeGlobalPtr(): ptr int = addr someGlobal
  58. let someGlobalPtr = getSomeGlobalPtr()
  59. doAssert(someGlobalPtr[] == 5)
  60. someGlobalPtr[] = 10
  61. doAssert(someGlobal == 10)
  62. block:
  63. # bug #14576
  64. # lots of these used to give: Error: internal error: genAddr: 2
  65. proc byLent[T](a: T): lent T = a
  66. proc byPtr[T](a: T): ptr T = a.addr
  67. block:
  68. let a = (10,11)
  69. let (x,y) = byLent(a)
  70. doAssert (x,y) == a
  71. block: # (with -d:release) bug #14578
  72. let a = 10
  73. doAssert byLent(a) == 10
  74. let a2 = byLent(a)
  75. doAssert a2 == 10
  76. block:
  77. let a = [11,12]
  78. doAssert byLent(a) == [11,12] # bug #15958
  79. let a2 = (11,)
  80. doAssert byLent(a2) == (11,)
  81. block:
  82. proc byLent2[T](a: seq[T]): lent T = a[1]
  83. var a = @[20,21,22]
  84. doAssert byLent2(a) == 21
  85. block: # sanity checks
  86. proc bar[T](a: var T): var T = a
  87. var a = (10, 11)
  88. let (k,v) = bar(a)
  89. doAssert (k, v) == a
  90. doAssert k == 10
  91. bar(a)[0]+=100
  92. doAssert a == (110, 11)
  93. var a2 = 12
  94. doAssert bar(a2) == a2
  95. bar(a2).inc
  96. doAssert a2 == 13
  97. block: # pending bug #15959
  98. when false:
  99. proc byLent2[T](a: T): lent type(a[0]) = a[0]
  100. proc test14420() = # bug #14420
  101. # s/proc/template/ would hit bug #16005
  102. block:
  103. type Foo = object
  104. x: float
  105. proc fn(a: var Foo): var float =
  106. ## WAS: discard <- turn this into a comment (or a `discard`) and error disappears
  107. # result = a.x # this works
  108. a.x # WAS: Error: limited VM support for 'addr'
  109. proc fn2(a: var Foo): var float =
  110. result = a.x # this works
  111. a.x # WAS: Error: limited VM support for 'addr'
  112. var a = Foo()
  113. discard fn(a)
  114. discard fn2(a)
  115. block:
  116. proc byLent2[T](a: T): lent T =
  117. runnableExamples: discard
  118. a
  119. proc byLent3[T](a: T): lent T =
  120. runnableExamples: discard
  121. result = a
  122. var a = 10
  123. let x3 = byLent3(a) # works
  124. let x2 = byLent2(a) # WAS: Error: internal error: genAddr: nkStmtListExpr
  125. block:
  126. type MyOption[T] = object
  127. case has: bool
  128. of true:
  129. value: T
  130. of false:
  131. discard
  132. func some[T](val: T): MyOption[T] =
  133. result = MyOption[T](has: true, value: val)
  134. func get[T](opt: MyOption[T]): lent T =
  135. doAssert opt.has
  136. # result = opt.value # this was ok
  137. opt.value # this had the bug
  138. let x = some(10)
  139. doAssert x.get() == 10
  140. template test14339() = # bug #14339
  141. block:
  142. type
  143. Node = ref object
  144. val: int
  145. proc bar(c: Node): var int =
  146. var n = c # was: Error: limited VM support for 'addr'
  147. c.val
  148. var a = Node()
  149. discard a.bar()
  150. block:
  151. type
  152. Node = ref object
  153. val: int
  154. proc bar(c: Node): var int =
  155. var n = c
  156. doAssert n.val == n[].val
  157. n.val
  158. var a = Node(val: 3)
  159. a.bar() = 5
  160. when nimvm:
  161. doAssert a.val == 5
  162. else:
  163. when not defined(js): # pending bug #16003
  164. doAssert a.val == 5
  165. template testStatic15464() = # bug #15464
  166. proc access(s: var seq[char], i: int): var char = s[i]
  167. proc access(s: var string, i: int): var char = s[i]
  168. static:
  169. var s = @['a', 'b', 'c']
  170. access(s, 2) = 'C'
  171. doAssert access(s, 2) == 'C'
  172. static:
  173. var s = "abc"
  174. access(s, 2) = 'C'
  175. doAssert access(s, 2) == 'C'
  176. proc test15464() = # bug #15464 (v2)
  177. proc access(s: var seq[char], i: int): var char = s[i]
  178. proc access(s: var string, i: int): var char = s[i]
  179. block:
  180. var s = @['a', 'b', 'c']
  181. access(s, 2) = 'C'
  182. doAssert access(s, 2) == 'C'
  183. block:
  184. var s = "abc"
  185. access(s, 2) = 'C'
  186. doAssert access(s, 2) == 'C'
  187. block: # bug #15939
  188. block:
  189. const foo = "foo"
  190. proc proc1(s: var string) =
  191. if s[^1] notin {'a'..'z'}:
  192. s = ""
  193. proc proc2(f: string): string =
  194. result = f
  195. proc1(result)
  196. const bar = proc2(foo)
  197. doAssert bar == "foo"
  198. template prepareMutationForOrc(x: string) =
  199. when defined(gcArc) or defined(gcOrc):
  200. when nimvm:
  201. discard
  202. else:
  203. prepareMutation(x)
  204. proc test15939() = # bug #15939 (v2)
  205. template fn(a) =
  206. when typeof(a) is string:
  207. prepareMutationForOrc(a)
  208. let pa = a[0].addr
  209. doAssert pa != nil
  210. doAssert pa[] == 'a'
  211. pa[] = 'x'
  212. doAssert pa[] == 'x'
  213. doAssert a == "xbc"
  214. when not defined js: # otherwise overflows
  215. let pa2 = cast[ptr char](cast[int](pa) + 1)
  216. doAssert pa2[] == 'b'
  217. pa2[] = 'B'
  218. doAssert a == "xBc"
  219. # mystring[ind].addr
  220. var a = "abc"
  221. fn(a)
  222. # mycstring[ind].addr
  223. template cstringTest =
  224. var a2 = "abc"
  225. prepareMutationForOrc(a2)
  226. var b2 = a2.cstring
  227. fn(b2)
  228. when nimvm: cstringTest()
  229. else: # can't take address of cstring element in js
  230. when not defined(js): cstringTest()
  231. block: # bug #23499
  232. template volatileStore[T](dest: ptr T, val: T) =
  233. dest[] = val
  234. proc foo =
  235. var ctr = 0
  236. volatileStore(addr ctr, 0)
  237. foo()
  238. template main =
  239. # xxx wrap all other tests here like that so they're also tested in VM
  240. test14420()
  241. test14339()
  242. test15464()
  243. test15939()
  244. testStatic15464()
  245. static: main()
  246. main()