summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ccgstmts.nim48
-rw-r--r--compiler/cgen.nim17
-rw-r--r--tests/cpp/tconstructor.nim24
3 files changed, 68 insertions, 21 deletions
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index b57864b46..1ed546256 100644
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -288,15 +288,32 @@ proc potentialValueInit(p: BProc; v: PSym; value: PNode; result: var Rope) =
     #echo "New code produced for ", v.name.s, " ", p.config $ value.info
     genBracedInit(p, value, isConst = false, v.typ, result)
 
+proc genCppVarForConstructor(p: BProc, v: PSym; vn, value: PNode; decl: var Rope) =
+  var params = newRopeAppender()
+  var argsCounter = 0
+  let typ = skipTypes(value[0].typ, abstractInst)
+  assert(typ.kind == tyProc)
+  for i in 1..<value.len:
+    assert(typ.len == typ.n.len)
+    genOtherArg(p, value, i, typ, params, argsCounter)
+  if params.len == 0:
+    decl = runtimeFormat("$#;\n", [decl])
+  else:
+    decl = runtimeFormat("$#($#);\n", [decl, params])
+
 proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
   if sfGoto in v.flags:
     # translate 'var state {.goto.} = X' into 'goto LX':
     genGotoVar(p, value)
     return
+  let imm = isAssignedImmediately(p.config, value)
+  let isCppConstructorCall = p.module.compileToCpp and imm and
+    value.kind in nkCallKinds and value[0].kind == nkSym and
+    v.typ.kind != tyPtr and sfConstructor in value[0].sym.flags
   var targetProc = p
   var valueAsRope = ""
   potentialValueInit(p, v, value, valueAsRope)
-  if sfGlobal in v.flags:
+  if sfGlobal in v.flags:  
     if v.flags * {sfImportc, sfExportc} == {sfImportc} and
         value.kind == nkEmpty and
         v.loc.flags * {lfHeader, lfNoDecl} != {}:
@@ -304,7 +321,11 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
     if sfPure in v.flags:
       # v.owner.kind != skModule:
       targetProc = p.module.preInitProc
-    assignGlobalVar(targetProc, vn, valueAsRope)
+    if isCppConstructorCall and not containsHiddenPointer(v.typ):
+      callGlobalVarCppConstructor(targetProc, v, vn, value)
+    else:
+      assignGlobalVar(targetProc, vn, valueAsRope)
+
     # XXX: be careful here.
     # Global variables should not be zeromem-ed within loops
     # (see bug #20).
@@ -313,7 +334,6 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
     # global variables will be initialized to zero.
     if valueAsRope.len == 0:
       var loc = v.loc
-
       # When the native TLS is unavailable, a global thread-local variable needs
       # one more layer of indirection in order to access the TLS block.
       # Only do this for complex types that may need a call to `objectInit`
@@ -327,7 +347,6 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
       genVarPrototype(p.module.g.generatedHeader, vn)
     registerTraverseProc(p, v)
   else:
-    let imm = isAssignedImmediately(p.config, value)
     if imm and p.module.compileToCpp and p.splitDecls == 0 and
         not containsHiddenPointer(v.typ) and
         nimErrorFlagAccessed notin p.flags:
@@ -335,21 +354,11 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
       # parameterless constructor followed by an assignment operator. So we
       # generate better code here: 'Foo f = x;'
       genLineDir(p, vn)
-      let decl = localVarDecl(p, vn)
+      var decl = localVarDecl(p, vn)
       var tmp: TLoc
-      if value.kind in nkCallKinds and value[0].kind == nkSym and
-           sfConstructor in value[0].sym.flags:
-        var params = newRopeAppender()
-        var argsCounter = 0
-        let typ = skipTypes(value[0].typ, abstractInst)
-        assert(typ.kind == tyProc)
-        for i in 1..<value.len:
-          assert(typ.len == typ.n.len)
-          genOtherArg(p, value, i, typ, params, argsCounter)
-        if params.len == 0:
-          lineF(p, cpsStmts, "$#;\n", [decl])
-        else:
-          lineF(p, cpsStmts, "$#($#);\n", [decl, params])
+      if isCppConstructorCall:
+        genCppVarForConstructor(p, v, vn, value, decl)
+        line(p, cpsStmts, decl)
       else:
         initLocExprSingleUse(p, value, tmp)
         lineF(p, cpsStmts, "$# = $#;\n", [decl, tmp.rdLoc])
@@ -379,7 +388,8 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
     startBlock(targetProc)
   if value.kind != nkEmpty and valueAsRope.len == 0:
     genLineDir(targetProc, vn)
-    loadInto(targetProc, vn, value, v.loc)
+    if not isCppConstructorCall:
+      loadInto(targetProc, vn, value, v.loc)
   if forHcr:
     endBlock(targetProc)
 
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 4b2d4fe09..6ceda109f 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -643,7 +643,20 @@ proc genGlobalVarDecl(p: BProc, n: PNode; td, value: Rope; decl: var Rope) =
       decl = runtimeFormat(s.cgDeclFrmt & " = $#;$n", [td, s.loc.r, value])
     else:
       decl = runtimeFormat(s.cgDeclFrmt & ";$n", [td, s.loc.r])
-    
+
+proc genCppVarForConstructor(p: BProc, v: PSym; vn, value: PNode; decl: var Rope) 
+
+proc callGlobalVarCppConstructor(p: BProc; v: PSym; vn, value: PNode) =
+  let s = vn.sym
+  fillBackendName(p.module, s)
+  fillLoc(s.loc, locGlobalVar, vn, OnHeap)
+  var decl: Rope
+  let td = getTypeDesc(p.module, vn.sym.typ, dkVar)
+  genGlobalVarDecl(p, vn, td, "", decl)
+  decl.add " " & $s.loc.r
+  genCppVarForConstructor(p, v, vn, value, decl)
+  p.module.s[cfsVars].add decl
+
 proc assignGlobalVar(p: BProc, n: PNode; value: Rope) =
   let s = n.sym
   if s.loc.k == locNone:
@@ -669,7 +682,7 @@ proc assignGlobalVar(p: BProc, n: PNode; value: Rope) =
         internalError(p.config, n.info, ".threadvar variables cannot have a value")
     else:
       var decl: Rope = ""
-      var td = getTypeDesc(p.module, s.loc.t, dkVar)
+      let td = getTypeDesc(p.module, s.loc.t, dkVar)
       genGlobalVarDecl(p, n, td, value, decl)
       if s.constraint.isNil:
         if value != "":
diff --git a/tests/cpp/tconstructor.nim b/tests/cpp/tconstructor.nim
new file mode 100644
index 000000000..8489c71d3
--- /dev/null
+++ b/tests/cpp/tconstructor.nim
@@ -0,0 +1,24 @@
+discard """
+  targets: "cpp"
+  cmd: "nim cpp $file"
+"""
+
+{.emit:"""/*TYPESECTION*/
+struct CppClass {
+  int x;
+  int y;
+  CppClass(int inX, int inY) {
+    this->x = inX;
+    this->y = inY;
+  }
+  //CppClass() = default;
+};
+""".}
+
+type  CppClass* {.importcpp.} = object
+  x: int32
+  y: int32
+
+proc makeCppClass(x, y: int32): CppClass {.importcpp: "CppClass(@)", constructor.}
+
+var shouldCompile = makeCppClass(1, 2)