diff options
-rw-r--r-- | compiler/ccgstmts.nim | 48 | ||||
-rw-r--r-- | compiler/cgen.nim | 17 | ||||
-rw-r--r-- | tests/cpp/tconstructor.nim | 24 |
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) |