diff options
author | Araq <rumpf_a@web.de> | 2017-12-15 11:21:49 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2017-12-15 11:21:49 +0100 |
commit | a5e4d2f7a3afdf4e068ae5e6c48392a29c0e8ced (patch) | |
tree | 432ed41b3f691259bcc5064e492f90830a66b173 | |
parent | 196977f623c3e3384e943c08cb85e6e0ded31109 (diff) | |
download | Nim-a5e4d2f7a3afdf4e068ae5e6c48392a29c0e8ced.tar.gz |
fixes #668
-rw-r--r-- | compiler/aliases.nim | 8 | ||||
-rw-r--r-- | compiler/ccgexprs.nim | 22 | ||||
-rw-r--r-- | tests/ccgbugs/tobjconstr_bad_aliasing.nim | 26 |
3 files changed, 51 insertions, 5 deletions
diff --git a/compiler/aliases.nim b/compiler/aliases.nim index c0371e159..cd7e7f19a 100644 --- a/compiler/aliases.nim +++ b/compiler/aliases.nim @@ -179,5 +179,11 @@ proc isPartOf*(a, b: PNode): TAnalysisResult = result = isPartOf(a[0], b) if result == arNo: result = arMaybe else: discard + of nkObjConstr: + result = arNo + for i in 1..<b.len: + let res = isPartOf(a, b[i][1]) + if res != arNo: + result = res + if res == arYes: break else: discard - diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 5f107f21f..1505052cc 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1236,18 +1236,32 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) = else: genAssignment(p, d, tmp, {}) +proc lhsDoesAlias(a, b: PNode): bool = + for y in b: + if isPartOf(a, y) != arNo: return true + proc genSeqConstr(p: BProc, n: PNode, d: var TLoc) = - var arr: TLoc - if d.k == locNone: + var arr, tmp: TLoc + # bug #668 + let doesAlias = lhsDoesAlias(d.lode, n) + let dest = if doesAlias: addr(tmp) else: addr(d) + if doesAlias: + getTemp(p, n.typ, tmp) + elif d.k == locNone: getTemp(p, n.typ, d) # generate call to newSeq before adding the elements per hand: - genNewSeqAux(p, d, intLiteral(sonsLen(n))) + genNewSeqAux(p, dest[], intLiteral(sonsLen(n))) for i in countup(0, sonsLen(n) - 1): initLoc(arr, locExpr, n[i], OnHeap) - arr.r = rfmt(nil, "$1->data[$2]", rdLoc(d), intLiteral(i)) + arr.r = rfmt(nil, "$1->data[$2]", rdLoc(dest[]), intLiteral(i)) arr.storage = OnHeap # we know that sequences are on the heap expr(p, n[i], arr) gcUsage(n) + if doesAlias: + if d.k == locNone: + d = tmp + else: + genAssignment(p, d, tmp, {}) proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) = var elem, a, arr: TLoc diff --git a/tests/ccgbugs/tobjconstr_bad_aliasing.nim b/tests/ccgbugs/tobjconstr_bad_aliasing.nim new file mode 100644 index 000000000..ea51ecacb --- /dev/null +++ b/tests/ccgbugs/tobjconstr_bad_aliasing.nim @@ -0,0 +1,26 @@ +discard """ + output: '''(10, (20, ))''' +""" + +import strutils, sequtils + +# bug #668 + +type + TThing = ref object + data: int + children: seq[TThing] + +proc `$`(t: TThing): string = + result = "($1, $2)" % @[$t.data, join(map(t.children, proc(th: TThing): string = $th), ", ")] + +proc somethingelse(): seq[TThing] = + result = @[TThing(data: 20, children: @[])] + +proc dosomething(): seq[TThing] = + result = somethingelse() + + result = @[TThing(data: 10, children: result)] + +when isMainModule: + echo($dosomething()[0]) |