summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ccgexprs.nim48
-rw-r--r--tests/objects/tobjconstr.nim7
-rw-r--r--tests/objects/tobjconstr2.nim7
3 files changed, 45 insertions, 17 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 0a312b4c7..bb9a9f6c6 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -1202,18 +1202,30 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
   # we skip this step here:
   if not p.module.compileToCpp:
     if handleConstExpr(p, e, d): return
-  var tmp: TLoc
   var t = e.typ.skipTypes(abstractInst)
-  getTemp(p, t, tmp)
   let isRef = t.kind == tyRef
-  var r = rdLoc(tmp)
-  if isRef:
-    rawGenNew(p, tmp, nil)
-    t = t.lastSon.skipTypes(abstractInst)
-    r = "(*$1)" % [r]
-    gcUsage(e)
+
+  # check if we need to construct the object in a temporary
+  var useTemp =
+        isRef or
+        (d.k notin {locTemp,locLocalVar,locGlobalVar,locParam,locField}) or
+        (isPartOf(d.lode, e) != arNo)
+
+  var tmp: TLoc
+  var r: Rope
+  if useTemp:
+    getTemp(p, t, tmp)
+    r = rdLoc(tmp)
+    if isRef:
+      rawGenNew(p, tmp, nil)
+      t = t.lastSon.skipTypes(abstractInst)
+      r = "(*$1)" % [r]
+      gcUsage(e)
+    else:
+      constructLoc(p, tmp)
   else:
-    constructLoc(p, tmp)
+    resetLoc(p, d)
+    r = rdLoc(d)
   discard getTypeDesc(p.module, t)
   let ty = getUniqueType(t)
   for i in 1 ..< e.len:
@@ -1227,15 +1239,19 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
       genFieldCheck(p, it.sons[2], r, field)
     add(tmp2.r, ".")
     add(tmp2.r, field.loc.r)
-    tmp2.k = locTemp
+    if useTemp:
+      tmp2.k = locTemp
+      tmp2.storage = if isRef: OnHeap else: OnStack
+    else:
+      tmp2.k = d.k
+      tmp2.storage = if isRef: OnHeap else: d.storage
     tmp2.lode = it.sons[1]
-    tmp2.storage = if isRef: OnHeap else: OnStack
     expr(p, it.sons[1], tmp2)
-
-  if d.k == locNone:
-    d = tmp
-  else:
-    genAssignment(p, d, tmp, {})
+  if useTemp:
+    if d.k == locNone:
+      d = tmp
+    else:
+      genAssignment(p, d, tmp, {})
 
 proc lhsDoesAlias(a, b: PNode): bool =
   for y in b:
diff --git a/tests/objects/tobjconstr.nim b/tests/objects/tobjconstr.nim
index b7da176aa..d1f3c8bdb 100644
--- a/tests/objects/tobjconstr.nim
+++ b/tests/objects/tobjconstr.nim
@@ -15,7 +15,8 @@ discard """
 (y: 678, x: 123)
 (y: 678, x: 123)
 (y: 0, x: 123)
-(y: 678, x: 123)'''
+(y: 678, x: 123)
+(y: 123, x: 678)'''
 """
 
 type
@@ -75,3 +76,7 @@ when true:
   echo b                  # (y: 0, x: 123)
   b=B(y: 678, x: 123)
   echo b                  # (y: 678, x: 123)
+  b=B(y: b.x, x: b.y)
+  echo b                  # (y: 123, x: 678)
+
+GC_fullCollect()
diff --git a/tests/objects/tobjconstr2.nim b/tests/objects/tobjconstr2.nim
index f6805190b..6253edab0 100644
--- a/tests/objects/tobjconstr2.nim
+++ b/tests/objects/tobjconstr2.nim
@@ -1,3 +1,8 @@
+discard """
+  output: '''42
+Foo'''
+"""
+
 type TFoo{.exportc.} = object
  x:int
 
@@ -48,3 +53,5 @@ type NamedGraphic = object of Graphic2
 
 var ngr = NamedGraphic(kind: Koo, radius: 6.9, name: "Foo")
 echo ngr.name
+
+GC_fullCollect()