diff options
author | Juan M Gómez <info@jmgomez.me> | 2024-06-02 14:15:03 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-02 15:15:03 +0200 |
commit | cb0ebecb2045143f71b7be40b853672a987fa4d1 (patch) | |
tree | 8a056febed7c21afa12af9e7d4282210cf1761e8 | |
parent | 08f1eac8ac46baccd1701715feb8aca7b00e0be7 (diff) | |
download | Nim-cb0ebecb2045143f71b7be40b853672a987fa4d1.tar.gz |
#Fixes #23657 C++ compilation fails with: 'T1_' was not declared in t… (#23666)
…his scope
-rw-r--r-- | compiler/ccgstmts.nim | 31 | ||||
-rw-r--r-- | compiler/ccgtypes.nim | 9 | ||||
-rw-r--r-- | compiler/cgen.nim | 31 | ||||
-rw-r--r-- | compiler/lineinfos.nim | 2 | ||||
-rw-r--r-- | tests/cpp/t23657.nim | 54 |
5 files changed, 103 insertions, 24 deletions
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 345639d94..a55512466 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -289,7 +289,7 @@ 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 genCppParamsForCtor(p: BProc; call: PNode): string = +proc genCppParamsForCtor(p: BProc; call: PNode; didGenTemp: var bool): string = result = "" var argsCounter = 0 let typ = skipTypes(call[0].typ, abstractInst) @@ -298,12 +298,23 @@ proc genCppParamsForCtor(p: BProc; call: PNode): string = #if it's a type we can just generate here another initializer as we are in an initializer context if call[i].kind == nkCall and call[i][0].kind == nkSym and call[i][0].sym.kind == skType: if argsCounter > 0: result.add "," - result.add genCppInitializer(p.module, p, call[i][0].sym.typ) + result.add genCppInitializer(p.module, p, call[i][0].sym.typ, didGenTemp) else: + #We need to test for temp in globals, see: #23657 + let param = + if typ[i].kind in {tyVar} and call[i].kind == nkHiddenAddr: + call[i][0] + else: + call[i] + if param.kind != nkBracketExpr or param.typ.kind in + {tyRef, tyPtr, tyUncheckedArray, tyArray, tyOpenArray, + tyVarargs, tySequence, tyString, tyCstring, tyTuple}: + let tempLoc = initLocExprSingleUse(p, param) + didGenTemp = didGenTemp or tempLoc.k == locTemp genOtherArg(p, call, i, typ, result, argsCounter) -proc genCppVarForCtor(p: BProc; call: PNode; decl: var Rope) = - let params = genCppParamsForCtor(p, call) +proc genCppVarForCtor(p: BProc; call: PNode; decl: var Rope, didGenTemp: var bool) = + let params = genCppParamsForCtor(p, call, didGenTemp) if params.len == 0: decl = runtimeFormat("$#;\n", [decl]) else: @@ -330,7 +341,14 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) = # v.owner.kind != skModule: targetProc = p.module.preInitProc if isCppCtorCall and not containsHiddenPointer(v.typ): - callGlobalVarCppCtor(targetProc, v, vn, value) + var didGenTemp = false + callGlobalVarCppCtor(targetProc, v, vn, value, didGenTemp) + if didGenTemp: + message(p.config, vn.info, warnGlobalVarConstructorTemporary, vn.sym.name.s) + #We fail to call the constructor in the global scope so we do the call inside the main proc + assignGlobalVar(targetProc, vn, valueAsRope) + var loc = initLocExprSingleUse(targetProc, value) + genAssignment(targetProc, v.loc, loc, {}) else: assignGlobalVar(targetProc, vn, valueAsRope) @@ -365,7 +383,8 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) = var decl = localVarDecl(p, vn) var tmp: TLoc if isCppCtorCall: - genCppVarForCtor(p, value, decl) + var didGenTemp = false + genCppVarForCtor(p, value, decl, didGenTemp) line(p, cpsStmts, decl) else: tmp = initLocExprSingleUse(p, value) diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 927b56bba..75b520f3a 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -678,9 +678,9 @@ proc hasCppCtor(m: BModule; typ: PType): bool = if sfConstructor in prc.flags: return true -proc genCppParamsForCtor(p: BProc; call: PNode): string +proc genCppParamsForCtor(p: BProc; call: PNode; didGenTemp: var bool): string -proc genCppInitializer(m: BModule, prc: BProc; typ: PType): string = +proc genCppInitializer(m: BModule, prc: BProc; typ: PType; didGenTemp: var bool): string = #To avoid creating a BProc per test when called inside a struct nil BProc is allowed result = "{}" if typ.itemId in m.g.graph.initializersPerType: @@ -689,7 +689,7 @@ proc genCppInitializer(m: BModule, prc: BProc; typ: PType): string = var p = prc if p == nil: p = BProc(module: m) - result = "{" & genCppParamsForCtor(p, call) & "}" + result = "{" & genCppParamsForCtor(p, call, didGenTemp) & "}" if prc == nil: assert p.blocks.len == 0, "BProc belongs to a struct doesnt have blocks" @@ -759,7 +759,8 @@ proc genRecordFieldsAux(m: BModule; n: PNode, # tyGenericInst for C++ template support let noInit = sfNoInit in field.flags or (field.typ.sym != nil and sfNoInit in field.typ.sym.flags) if not noInit and (fieldType.isOrHasImportedCppType() or hasCppCtor(m, field.owner.typ)): - var initializer = genCppInitializer(m, nil, fieldType) + var didGenTemp = false + var initializer = genCppInitializer(m, nil, fieldType, didGenTemp) result.addf("\t$1$3 $2$4;$n", [getTypeDescAux(m, field.loc.t, check, dkField), sname, noAlias, initializer]) else: result.addf("\t$1$3 $2;$n", [getTypeDescAux(m, field.loc.t, check, dkField), sname, noAlias]) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 287a6f5e4..c69e12a20 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -562,8 +562,9 @@ proc getTemp(p: BProc, t: PType, needsInit=false): TLoc = result = TLoc(r: "T" & rope(p.labels) & "_", k: locTemp, lode: lodeTyp t, storage: OnStack, flags: {}) if p.module.compileToCpp and isOrHasImportedCppType(t): + var didGenTemp = false linefmt(p, cpsLocals, "$1 $2$3;$n", [getTypeDesc(p.module, t, dkVar), result.r, - genCppInitializer(p.module, p, t)]) + genCppInitializer(p.module, p, t, didGenTemp)]) else: linefmt(p, cpsLocals, "$1 $2;$n", [getTypeDesc(p.module, t, dkVar), result.r]) constructLoc(p, result, not needsInit) @@ -620,7 +621,8 @@ proc assignLocalVar(p: BProc, n: PNode) = let nl = if optLineDir in p.config.options: "" else: "\n" var decl = localVarDecl(p, n) if p.module.compileToCpp and isOrHasImportedCppType(n.typ): - decl.add genCppInitializer(p.module, p, n.typ) + var didGenTemp = false + decl.add genCppInitializer(p.module, p, n.typ, didGenTemp) decl.add ";" & nl line(p, cpsLocals, decl) @@ -655,18 +657,7 @@ proc genGlobalVarDecl(p: BProc, n: PNode; td, value: Rope; decl: var Rope) = else: decl = runtimeFormat(s.cgDeclFrmt & ";$n", [td, s.loc.r]) -proc genCppVarForCtor(p: BProc; call: PNode; decl: var Rope) - -proc callGlobalVarCppCtor(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 - genCppVarForCtor(p, value, decl) - p.module.s[cfsVars].add decl +proc genCppVarForCtor(p: BProc; call: PNode; decl: var Rope; didGenTemp: var bool) proc assignGlobalVar(p: BProc, n: PNode; value: Rope) = let s = n.sym @@ -722,6 +713,18 @@ proc assignGlobalVar(p: BProc, n: PNode; value: Rope) = # fixes tests/run/tzeroarray: resetLoc(p, s.loc) +proc callGlobalVarCppCtor(p: BProc; v: PSym; vn, value: PNode; didGenTemp: var bool) = + 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 + genCppVarForCtor(p, value, decl, didGenTemp) + if didGenTemp: return # generated in the caller + p.module.s[cfsVars].add decl + proc assignParam(p: BProc, s: PSym, retType: PType) = assert(s.loc.r != "") scopeMangledParam(p, s) diff --git a/compiler/lineinfos.nim b/compiler/lineinfos.nim index dc0b6c360..b48252ace 100644 --- a/compiler/lineinfos.nim +++ b/compiler/lineinfos.nim @@ -95,6 +95,7 @@ type warnGenericsIgnoredInjection = "GenericsIgnoredInjection", warnStdPrefix = "StdPrefix" warnUser = "User", + warnGlobalVarConstructorTemporary = "GlobalVarConstructorTemporary", # hints hintSuccess = "Success", hintSuccessX = "SuccessX", hintCC = "CC", @@ -200,6 +201,7 @@ const warnGenericsIgnoredInjection: "$1", warnStdPrefix: "$1 needs the 'std' prefix", warnUser: "$1", + warnGlobalVarConstructorTemporary: "global variable '$1' initialization requires a temporary variable", hintSuccess: "operation successful: $#", # keep in sync with `testament.isSuccess` hintSuccessX: "$build\n$loc lines; ${sec}s; $mem; proj: $project; out: $output", diff --git a/tests/cpp/t23657.nim b/tests/cpp/t23657.nim new file mode 100644 index 000000000..63deb7fb0 --- /dev/null +++ b/tests/cpp/t23657.nim @@ -0,0 +1,54 @@ +discard """ + targets: "cpp" + cmd: "nim cpp -r $file" + output: ''' +1.0 +1.0 +''' + +""" +{.emit:"""/*TYPESECTION*/ +struct Point { + float x, y, z; + Point(float x, float y, float z): x(x), y(y), z(z) {} + Point() = default; +}; +struct Direction { + float x, y, z; + Direction(float x, float y, float z): x(x), y(y), z(z) {} + Direction() = default; +}; +struct Axis { + Point origin; + Direction direction; + Axis(Point origin, Direction direction): origin(origin), direction(direction) {} + Axis() = default; +}; + +""".} + +type + Point {.importcpp.} = object + x, y, z: float + + Direction {.importcpp.} = object + x, y, z: float + + Axis {.importcpp.} = object + origin: Point + direction: Direction + +proc makeAxis(origin: Point, direction: Direction): Axis {. constructor, importcpp:"Axis(@)".} +proc makePoint(x, y, z: float): Point {. constructor, importcpp:"Point(@)".} +proc makeDirection(x, y, z: float): Direction {. constructor, importcpp:"Direction(@)".} + +var axis1 = makeAxis(Point(x: 1.0, y: 2.0, z: 3.0), Direction(x: 4.0, y: 5.0, z: 6.0)) #Triggers the error (T1) +var axis2Ctor = makeAxis(makePoint(1.0, 2.0, 3.0), makeDirection(4.0, 5.0, 6.0)) #Do not triggers + +proc main() = #Do not triggers as Tx are inside the body + let test = makeAxis(Point(x: 1.0, y: 2.0, z: 3.0), Direction(x: 4.0, y: 5.0, z: 6.0)) + echo test.origin.x + +main() + +echo $axis1.origin.x #Make sures it's init \ No newline at end of file |