summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ccgexprs.nim44
-rw-r--r--compiler/cgen.nim5
-rw-r--r--compiler/semstmts.nim2
-rw-r--r--tests/cpp/tconstructor.nim35
4 files changed, 66 insertions, 20 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index d1c0ac7b1..4521664bf 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -1494,8 +1494,27 @@ proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool =
   else:
     result = false
 
+
+proc genFieldObjConstr(p: BProc; ty: PType; useTemp, isRef: bool; nField, val, check: PNode; d: var TLoc; r: Rope; info: TLineInfo) =
+  var tmp2: TLoc = default(TLoc)
+  tmp2.r = r
+  let field = lookupFieldAgain(p, ty, nField.sym, tmp2.r)
+  if field.loc.r == "": fillObjectFields(p.module, ty)
+  if field.loc.r == "": internalError(p.config, info, "genFieldObjConstr")
+  if check != nil and optFieldCheck in p.options:
+    genFieldCheck(p, check, r, field)
+  tmp2.r.add(".")
+  tmp2.r.add(field.loc.r)
+  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 = val
+  expr(p, val, tmp2)
+
 proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
-  #echo renderTree e, " ", e.isDeepConstExpr
   # inheritance in C++ does not allow struct initialization so
   # we skip this step here:
   if not p.module.compileToCpp and optSeqDestructors notin p.config.globalOptions:
@@ -1534,24 +1553,11 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
   discard getTypeDesc(p.module, t)
   let ty = getUniqueType(t)
   for i in 1..<e.len:
-    let it = e[i]
-    var tmp2: TLoc = default(TLoc)
-    tmp2.r = r
-    let field = lookupFieldAgain(p, ty, it[0].sym, tmp2.r)
-    if field.loc.r == "": fillObjectFields(p.module, ty)
-    if field.loc.r == "": internalError(p.config, e.info, "genObjConstr")
-    if it.len == 3 and optFieldCheck in p.options:
-      genFieldCheck(p, it[2], r, field)
-    tmp2.r.add(".")
-    tmp2.r.add(field.loc.r)
-    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[1]
-    expr(p, it[1], tmp2)
+    var check: PNode = nil
+    if e[i].len == 3 and optFieldCheck in p.options:
+      check = e[i][2]
+    genFieldObjConstr(p, ty, useTemp, isRef, e[i][0], e[i][1], check, d, r, e.info)
+  
   if useTemp:
     if d.k == locNone:
       d = tmp
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 678a15bc9..f8d62e1af 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -1171,6 +1171,11 @@ proc genProcAux*(m: BModule, prc: PSym) =
       returnStmt = ropecg(p.module, "\treturn $1;$n", [rdLoc(res.loc)])
     elif sfConstructor in prc.flags:
       fillLoc(resNode.sym.loc, locParam, resNode, "this", OnHeap)
+      let ty = resNode.sym.typ[0] #generate nim's ctor
+      for i in 1..<resNode.sym.ast.len:
+        let field = resNode.sym.ast[i]
+        genFieldObjConstr(p, ty, useTemp = false, isRef = false, 
+          field[0], field[1], check = nil, resNode.sym.loc, "(*this)", tmpInfo)
     else:
       fillResult(p.config, resNode, prc.typ)
       assignParam(p, res, prc.typ[0])
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 08d6d44e6..5a72632ef 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -1711,6 +1711,8 @@ proc addThis(c: PContext, n: PNode, t: PType, owner: TSymKind) =
   c.p.resultSym = s
   n.add newSymNode(c.p.resultSym)
   addParamOrResult(c, c.p.resultSym, owner)
+  #resolves nim's obj ctor inside cpp ctors see #22669
+  s.ast = c.semExpr(c, newTree(nkCall, t[0].sym.ast[0]))
 
 proc addResult(c: PContext, n: PNode, t: PType, owner: TSymKind) =
   template genResSym(s) =
diff --git a/tests/cpp/tconstructor.nim b/tests/cpp/tconstructor.nim
index b69162661..32fb5e1a2 100644
--- a/tests/cpp/tconstructor.nim
+++ b/tests/cpp/tconstructor.nim
@@ -7,6 +7,15 @@ discard """
 123
 0
 123
+___
+0
+777
+10
+123
+0
+777
+10
+123
 '''
 """
 
@@ -73,4 +82,28 @@ proc main =
     n.x = 123
     echo n.x
 
-main()
\ No newline at end of file
+main()
+#bug:
+echo "___"
+type
+  NimClassWithDefault = object
+    x: int
+    y = 777
+    case kind: bool = true
+    of true:
+      z: int = 10
+    else: discard
+
+proc makeNimClassWithDefault(): NimClassWithDefault {.constructor.} =
+  discard
+
+proc init =
+  for i in 0 .. 1:
+    var n = makeNimClassWithDefault()
+    echo n.x
+    echo n.y
+    echo n.z
+    n.x = 123
+    echo n.x
+
+init()
\ No newline at end of file