summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2023-06-16 20:59:59 +0200
committerGitHub <noreply@github.com>2023-06-16 20:59:59 +0200
commite8d0f1c3aedd8290cc972e3d06f642e88dbe783e (patch)
treefff0c7880eb78749439c3c57fae764978405531d /compiler
parent0de9e6bbf33bd013e39025f0ee81fc86956e70cf (diff)
downloadNim-e8d0f1c3aedd8290cc972e3d06f642e88dbe783e.tar.gz
fixes #16331; aliasing of tuple construction within a single assignme… (#22113)
* fixes #16331; aliasing of tuple construction within a single assignment, great coding style

* added test case
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ccgexprs.nim21
1 files changed, 18 insertions, 3 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 0567fbdf9..978ca8db8 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -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