tmovebug.nim 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. discard """
  2. cmd: "nim c --gc:arc $file"
  3. output: '''5
  4. (w: 5)
  5. (w: -5)
  6. c.text = hello
  7. c.text = hello
  8. p.text = hello
  9. p.toks = @["hello"]
  10. c.text = hello
  11. c[].text = hello
  12. pA.text = hello
  13. pA.toks = @["hello"]
  14. c.text = hello
  15. c.text = hello
  16. pD.text = hello
  17. pD.toks = @["hello"]
  18. c.text = hello
  19. c.text = hello
  20. pOD.text = hello
  21. pOD.toks = @["hello"]
  22. fff
  23. fff
  24. 2
  25. fff
  26. fff
  27. 2
  28. fff
  29. fff
  30. 2
  31. mmm
  32. fff
  33. fff
  34. fff
  35. 3
  36. mmm
  37. sink me (sink)
  38. assign me (not sink)
  39. sink me (not sink)
  40. sinked and not optimized to a bitcopy
  41. sinked and not optimized to a bitcopy
  42. sinked and not optimized to a bitcopy
  43. '''
  44. """
  45. # move bug
  46. type
  47. TMyObj = object
  48. p: pointer
  49. len: int
  50. var destroyCounter = 0
  51. proc `=destroy`(o: var TMyObj) =
  52. if o.p != nil:
  53. dealloc o.p
  54. o.p = nil
  55. inc destroyCounter
  56. proc `=`(dst: var TMyObj, src: TMyObj) =
  57. `=destroy`(dst)
  58. dst.p = alloc(src.len)
  59. dst.len = src.len
  60. proc `=sink`(dst: var TMyObj, src: TMyObj) =
  61. `=destroy`(dst)
  62. dst.p = src.p
  63. dst.len = src.len
  64. type
  65. TObjKind = enum Z, A, B
  66. TCaseObj = object
  67. case kind: TObjKind
  68. of Z: discard
  69. of A:
  70. x1: int # this int plays important role
  71. x2: TMyObj
  72. of B:
  73. y: TMyObj
  74. proc use(a: TCaseObj) = discard
  75. proc moveBug(i: var int) =
  76. var a: array[2, TCaseObj]
  77. a[i] = TCaseObj(kind: A, x1: 5000, x2: TMyObj(len: 5, p: alloc(5))) # 1
  78. a[i+1] = a[i] # 2
  79. inc i
  80. use(a[i-1])
  81. var x = 0
  82. moveBug(x)
  83. proc moveBug2(): (TCaseObj, TCaseObj) =
  84. var a: array[2, TCaseObj]
  85. a[0] = TCaseObj(kind: A, x1: 5000, x2: TMyObj(len: 5, p: alloc(5)))
  86. a[1] = a[0] # can move 3
  87. result[0] = TCaseObj(kind: A, x1: 5000, x2: TMyObj(len: 5, p: alloc(5))) # 4
  88. result[1] = result[0] # 5
  89. proc main =
  90. discard moveBug2()
  91. main()
  92. echo destroyCounter
  93. # bug #13314
  94. type
  95. O = object
  96. v: int
  97. R = ref object
  98. w: int
  99. proc `$`(r: R): string = $r[]
  100. proc tbug13314 =
  101. var t5 = R(w: 5)
  102. var execute = proc () =
  103. echo t5
  104. execute()
  105. t5.w = -5
  106. execute()
  107. tbug13314()
  108. #-------------------------------------------------------------------------
  109. # bug #13368
  110. import strutils
  111. proc procStat() =
  112. for line in @["a b", "c d", "e f"]:
  113. let cols = line.splitWhitespace(maxSplit=1)
  114. let x = cols[0]
  115. let (nm, rest) = (cols[0], cols[1])
  116. procStat()
  117. # bug #14269
  118. import sugar, strutils
  119. type
  120. Cursor = object
  121. text: string
  122. Parsed = object
  123. text: string
  124. toks: seq[string]
  125. proc tokenize(c: var Cursor): seq[string] =
  126. dump c.text
  127. return c.text.splitWhitespace()
  128. proc parse(): Parsed =
  129. var c = Cursor(text: "hello")
  130. dump c.text
  131. return Parsed(text: c.text, toks: c.tokenize) # note: c.tokenized uses c.text
  132. let p = parse()
  133. dump p.text
  134. dump p.toks
  135. proc tokenizeA(c: ptr Cursor): seq[string] =
  136. dump c[].text
  137. return c[].text.splitWhitespace()
  138. proc parseA(): Parsed =
  139. var c = Cursor(text: "hello")
  140. dump c.text
  141. return Parsed(text: c.text, toks: c.addr.tokenizeA) # note: c.tokenized uses c.text
  142. let pA = parseA()
  143. dump pA.text
  144. dump pA.toks
  145. proc tokenizeD(c: Cursor): seq[string] =
  146. dump c.text
  147. return c.text.splitWhitespace()
  148. proc parseD(): Parsed =
  149. var c = cast[ptr Cursor](alloc0(sizeof(Cursor)))
  150. c[] = Cursor(text: "hello")
  151. dump c.text
  152. return Parsed(text: c.text, toks: c[].tokenizeD) # note: c.tokenized uses c.text
  153. let pD = parseD()
  154. dump pD.text
  155. dump pD.toks
  156. # Bug would only pop up with owned refs
  157. proc tokenizeOD(c: Cursor): seq[string] =
  158. dump c.text
  159. return c.text.splitWhitespace()
  160. proc parseOD(): Parsed =
  161. var c = new Cursor
  162. c[] = Cursor(text: "hello")
  163. dump c.text
  164. return Parsed(text: c.text, toks: c[].tokenizeOD) # note: c.tokenized uses c.text
  165. let pOD = parseOD()
  166. dump pOD.text
  167. dump pOD.toks
  168. when false:
  169. # Bug would only pop up with owned refs and implicit derefs, but since they don't work together..
  170. {.experimental: "implicitDeref".}
  171. proc tokenizeOHD(c: Cursor): seq[string] =
  172. dump c.text
  173. return c.text.splitWhitespace()
  174. proc parseOHD(): Parsed =
  175. var c = new Cursor
  176. c[] = Cursor(text: "hello")
  177. dump c.text
  178. return Parsed(text: c.text, toks: c.tokenizeOHD) # note: c.tokenized uses c.text
  179. let pOHD = parseOHD()
  180. dump pOHD.text
  181. dump pOHD.toks
  182. # bug #13456
  183. iterator combinations[T](s: openarray[T], k: int): seq[T] =
  184. let n = len(s)
  185. assert k >= 0 and k <= n
  186. var pos = newSeq[int](k)
  187. var current = newSeq[T](k)
  188. for i in 0..k-1:
  189. pos[k-i-1] = i
  190. var done = false
  191. while not done:
  192. for i in 0..k-1:
  193. current[i] = s[pos[k-i-1]]
  194. yield current
  195. var i = 0
  196. while i < k:
  197. pos[i] += 1
  198. if pos[i] < n-i:
  199. for j in 0..i-1:
  200. pos[j] = pos[i] + i - j
  201. break
  202. i += 1
  203. if i >= k:
  204. break
  205. type
  206. UndefEx = object of ValueError
  207. proc main2 =
  208. var delayedSyms = @[1, 2, 3]
  209. var unp: seq[int]
  210. block myb:
  211. for a in 1 .. 2:
  212. if delayedSyms.len > a:
  213. unp = delayedSyms
  214. for t in unp.combinations(a + 1):
  215. try:
  216. var h = false
  217. for k in t:
  218. echo "fff"
  219. if h: continue
  220. if true:
  221. raise newException(UndefEx, "forward declaration")
  222. break myb
  223. except UndefEx:
  224. echo t.len
  225. echo "mmm"
  226. main2()
  227. type ME = object
  228. who: string
  229. proc `=`(x: var ME, y: ME) =
  230. if y.who.len > 0: echo "assign ",y.who
  231. proc `=sink`(x: var ME, y: ME) =
  232. if y.who.len > 0: echo "sink ",y.who
  233. var dump: ME
  234. template use(x) = dump = x
  235. template def(x) = x = dump
  236. var c = true
  237. proc shouldSink() =
  238. var x = ME(who: "me (sink)")
  239. use(x) # we analyse this
  240. if c: def(x)
  241. else: def(x)
  242. use(x) # ok, with the [else] part.
  243. shouldSink()
  244. dump = ME()
  245. proc shouldNotSink() =
  246. var x = ME(who: "me (not sink)")
  247. use(x) # we analyse this
  248. if c: def(x)
  249. use(x) # Not ok without the '[else]'
  250. shouldNotSink()
  251. # bug #14568
  252. import os
  253. type O2 = object
  254. s: seq[int]
  255. proc `=sink`(dest: var O2, src: O2) =
  256. echo "sinked and not optimized to a bitcopy"
  257. var testSeq: O2
  258. proc update() =
  259. # testSeq.add(0) # uncommenting this line fixes the leak
  260. testSeq = O2(s: @[])
  261. testSeq.s.add(0)
  262. for i in 1..3:
  263. update()