mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
…his scope
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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",
|
||||
|
||||
54
tests/cpp/t23657.nim
Normal file
54
tests/cpp/t23657.nim
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user