Skip to content

Commit

Permalink
fixes #16331; aliasing of tuple construction within a single assignme… (
Browse files Browse the repository at this point in the history
#22113)

* fixes #16331; aliasing of tuple construction within a single assignment, great coding style

* added test case
  • Loading branch information
Araq committed Jun 16, 2023
1 parent 0de9e6b commit e8d0f1c
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 3 deletions.
21 changes: 18 additions & 3 deletions compiler/ccgexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2679,15 +2679,30 @@ proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
if not handleConstExpr(p, n, d):
let t = n.typ
discard getTypeDesc(p.module, t) # so that any fields are initialized
if d.k == locNone: getTemp(p, t, d)

var tmp: TLoc
# bug #16331
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)

for i in 0..<n.len:
var it = n[i]
if it.kind == nkExprColonExpr: it = it[1]
initLoc(rec, locExpr, it, d.storage)
rec.r = "$1.Field$2" % [rdLoc(d), rope(i)]
initLoc(rec, locExpr, it, dest[].storage)
rec.r = "$1.Field$2" % [rdLoc(dest[]), rope(i)]
rec.flags.incl(lfEnforceDeref)
expr(p, it, rec)

if doesAlias:
if d.k == locNone:
d = tmp
else:
genAssignment(p, d, tmp, {})

proc isConstClosure(n: PNode): bool {.inline.} =
result = n[0].kind == nkSym and isRoutine(n[0].sym) and
n[1].kind == nkNilLit
Expand Down
15 changes: 15 additions & 0 deletions tests/ccgbugs/twrong_tupleconv.nim
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
discard """
targets: "c cpp"
matrix: "--gc:refc; --gc:arc"
"""

# bug #1833
iterator myitems*[T](a: var seq[T]): var T {.inline.} =
## iterates over each item of `a` so that you can modify the yielded value.
Expand All @@ -18,3 +23,13 @@ var ys = @[(1,"a"),(2,"b"),(3,"c")]
for y in myitems(ys):
inc y[0]

# bug #16331
type T1 = tuple[a, b: int]

proc p(b: bool): string =
var x: T1 = (10, 20)
x = if b: (x.b, x.a) else: (-x.b, -x.a)
$x

assert p(false) == "(a: -20, b: -10)"
assert p(true) == "(a: 20, b: 10)"

0 comments on commit e8d0f1c

Please sign in to comment.