* fixes #10942 * add test * bug build
This commit is contained in:
parent
734da9544d
commit
dc2986789b
5 changed files with 54 additions and 16 deletions
|
|
@ -136,7 +136,7 @@ proc genArg(p: BProc, n: PNode, param: PSym; call: PNode): Rope =
|
||||||
elif skipTypes(param.typ, abstractVar).kind in {tyOpenArray, tyVarargs}:
|
elif skipTypes(param.typ, abstractVar).kind in {tyOpenArray, tyVarargs}:
|
||||||
var n = if n.kind != nkHiddenAddr: n else: n.sons[0]
|
var n = if n.kind != nkHiddenAddr: n else: n.sons[0]
|
||||||
result = openArrayLoc(p, n)
|
result = openArrayLoc(p, n)
|
||||||
elif ccgIntroducedPtr(p.config, param):
|
elif ccgIntroducedPtr(p.config, param, call[0].typ[0]):
|
||||||
initLocExpr(p, n, a)
|
initLocExpr(p, n, a)
|
||||||
result = addrLoc(p.config, a)
|
result = addrLoc(p.config, a)
|
||||||
elif p.module.compileToCpp and param.typ.kind == tyVar and
|
elif p.module.compileToCpp and param.typ.kind == tyVar and
|
||||||
|
|
|
||||||
|
|
@ -249,9 +249,10 @@ proc addAbiCheck(m: BModule, t: PType, name: Rope) =
|
||||||
if isDefined(m.config, "checkabi") and (let size = getSize(m.config, t); size != szUnknownSize):
|
if isDefined(m.config, "checkabi") and (let size = getSize(m.config, t); size != szUnknownSize):
|
||||||
addf(m.s[cfsTypeInfo], "NIM_CHECK_SIZE($1, $2);$n", [name, rope(size)])
|
addf(m.s[cfsTypeInfo], "NIM_CHECK_SIZE($1, $2);$n", [name, rope(size)])
|
||||||
|
|
||||||
proc ccgIntroducedPtr(conf: ConfigRef; s: PSym): bool =
|
proc ccgIntroducedPtr(conf: ConfigRef; s: PSym, retType: PType): bool =
|
||||||
var pt = skipTypes(s.typ, typedescInst)
|
var pt = skipTypes(s.typ, typedescInst)
|
||||||
assert skResult != s.kind
|
assert skResult != s.kind
|
||||||
|
|
||||||
if tfByRef in pt.flags: return true
|
if tfByRef in pt.flags: return true
|
||||||
elif tfByCopy in pt.flags: return false
|
elif tfByCopy in pt.flags: return false
|
||||||
case pt.kind
|
case pt.kind
|
||||||
|
|
@ -261,13 +262,18 @@ proc ccgIntroducedPtr(conf: ConfigRef; s: PSym): bool =
|
||||||
result = true
|
result = true
|
||||||
elif (optByRef in s.options) or (getSize(conf, pt) > conf.target.floatSize * 3):
|
elif (optByRef in s.options) or (getSize(conf, pt) > conf.target.floatSize * 3):
|
||||||
result = true # requested anyway
|
result = true # requested anyway
|
||||||
|
elif retType != nil and retType.kind == tyLent:
|
||||||
|
result = true
|
||||||
elif (tfFinal in pt.flags) and (pt.sons[0] == nil):
|
elif (tfFinal in pt.flags) and (pt.sons[0] == nil):
|
||||||
result = false # no need, because no subtyping possible
|
result = false # no need, because no subtyping possible
|
||||||
else:
|
else:
|
||||||
result = true # ordinary objects are always passed by reference,
|
result = true # ordinary objects are always passed by reference,
|
||||||
# otherwise casting doesn't work
|
# otherwise casting doesn't work
|
||||||
of tyTuple:
|
of tyTuple:
|
||||||
result = (getSize(conf, pt) > conf.target.floatSize*3) or (optByRef in s.options)
|
if retType != nil and retType.kind == tyLent:
|
||||||
|
result = true
|
||||||
|
else:
|
||||||
|
result = (getSize(conf, pt) > conf.target.floatSize*3) or (optByRef in s.options)
|
||||||
else: result = false
|
else: result = false
|
||||||
|
|
||||||
proc fillResult(conf: ConfigRef; param: PNode) =
|
proc fillResult(conf: ConfigRef; param: PNode) =
|
||||||
|
|
@ -404,7 +410,7 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope,
|
||||||
if params != nil: add(params, ~", ")
|
if params != nil: add(params, ~", ")
|
||||||
fillLoc(param.loc, locParam, t.n.sons[i], mangleParamName(m, param),
|
fillLoc(param.loc, locParam, t.n.sons[i], mangleParamName(m, param),
|
||||||
param.paramStorageLoc)
|
param.paramStorageLoc)
|
||||||
if ccgIntroducedPtr(m.config, param):
|
if ccgIntroducedPtr(m.config, param, t.sons[0]):
|
||||||
add(params, getTypeDescWeak(m, param.typ, check))
|
add(params, getTypeDescWeak(m, param.typ, check))
|
||||||
add(params, ~"*")
|
add(params, ~"*")
|
||||||
incl(param.loc.flags, lfIndirect)
|
incl(param.loc.flags, lfIndirect)
|
||||||
|
|
|
||||||
|
|
@ -411,12 +411,12 @@ proc deinitGCFrame(p: BProc): Rope =
|
||||||
result = ropecg(p.module,
|
result = ropecg(p.module,
|
||||||
"if (((NU)&GCFRAME_) < 4096) #nimGCFrame(&GCFRAME_);$n")
|
"if (((NU)&GCFRAME_) < 4096) #nimGCFrame(&GCFRAME_);$n")
|
||||||
|
|
||||||
proc localDebugInfo(p: BProc, s: PSym) =
|
proc localDebugInfo(p: BProc, s: PSym, retType: PType) =
|
||||||
if {optStackTrace, optEndb} * p.options != {optStackTrace, optEndb}: return
|
if {optStackTrace, optEndb} * p.options != {optStackTrace, optEndb}: return
|
||||||
# XXX work around a bug: No type information for open arrays possible:
|
# XXX work around a bug: No type information for open arrays possible:
|
||||||
if skipTypes(s.typ, abstractVar).kind in {tyOpenArray, tyVarargs}: return
|
if skipTypes(s.typ, abstractVar).kind in {tyOpenArray, tyVarargs}: return
|
||||||
var a = "&" & s.loc.r
|
var a = "&" & s.loc.r
|
||||||
if s.kind == skParam and ccgIntroducedPtr(p.config, s): a = s.loc.r
|
if s.kind == skParam and ccgIntroducedPtr(p.config, s, retType): a = s.loc.r
|
||||||
lineF(p, cpsInit,
|
lineF(p, cpsInit,
|
||||||
"FR_.s[$1].address = (void*)$3; FR_.s[$1].typ = $4; FR_.s[$1].name = $2;$n",
|
"FR_.s[$1].address = (void*)$3; FR_.s[$1].typ = $4; FR_.s[$1].name = $2;$n",
|
||||||
[p.maxFrameLen.rope, makeCString(normalize(s.name.s)), a,
|
[p.maxFrameLen.rope, makeCString(normalize(s.name.s)), a,
|
||||||
|
|
@ -447,7 +447,7 @@ proc assignLocalVar(p: BProc, n: PNode) =
|
||||||
let nl = if optLineDir in p.config.options: "" else: "\L"
|
let nl = if optLineDir in p.config.options: "" else: "\L"
|
||||||
let decl = localVarDecl(p, n) & ";" & nl
|
let decl = localVarDecl(p, n) & ";" & nl
|
||||||
line(p, cpsLocals, decl)
|
line(p, cpsLocals, decl)
|
||||||
localDebugInfo(p, n.sym)
|
localDebugInfo(p, n.sym, nil)
|
||||||
|
|
||||||
include ccgthreadvars
|
include ccgthreadvars
|
||||||
|
|
||||||
|
|
@ -501,10 +501,10 @@ proc assignGlobalVar(p: BProc, n: PNode) =
|
||||||
[makeCString(normalize(s.owner.name.s & '.' & s.name.s)),
|
[makeCString(normalize(s.owner.name.s & '.' & s.name.s)),
|
||||||
s.loc.r, genTypeInfo(p.module, s.typ, n.info)])
|
s.loc.r, genTypeInfo(p.module, s.typ, n.info)])
|
||||||
|
|
||||||
proc assignParam(p: BProc, s: PSym) =
|
proc assignParam(p: BProc, s: PSym, retType: PType) =
|
||||||
assert(s.loc.r != nil)
|
assert(s.loc.r != nil)
|
||||||
scopeMangledParam(p, s)
|
scopeMangledParam(p, s)
|
||||||
localDebugInfo(p, s)
|
localDebugInfo(p, s, retType)
|
||||||
|
|
||||||
proc fillProcLoc(m: BModule; n: PNode) =
|
proc fillProcLoc(m: BModule; n: PNode) =
|
||||||
let sym = n.sym
|
let sym = n.sym
|
||||||
|
|
@ -934,7 +934,7 @@ proc genProcAux(m: BModule, prc: PSym) =
|
||||||
returnStmt = ropecg(p.module, "\treturn $1;$n", rdLoc(res.loc))
|
returnStmt = ropecg(p.module, "\treturn $1;$n", rdLoc(res.loc))
|
||||||
else:
|
else:
|
||||||
fillResult(p.config, resNode)
|
fillResult(p.config, resNode)
|
||||||
assignParam(p, res)
|
assignParam(p, res, prc.typ[0])
|
||||||
# We simplify 'unsureAsgn(result, nil); unsureAsgn(result, x)'
|
# We simplify 'unsureAsgn(result, nil); unsureAsgn(result, x)'
|
||||||
# to 'unsureAsgn(result, x)'
|
# to 'unsureAsgn(result, x)'
|
||||||
# Sketch why this is correct: If 'result' points to a stack location
|
# Sketch why this is correct: If 'result' points to a stack location
|
||||||
|
|
@ -952,7 +952,7 @@ proc genProcAux(m: BModule, prc: PSym) =
|
||||||
for i in countup(1, sonsLen(prc.typ.n) - 1):
|
for i in countup(1, sonsLen(prc.typ.n) - 1):
|
||||||
let param = prc.typ.n.sons[i].sym
|
let param = prc.typ.n.sons[i].sym
|
||||||
if param.typ.isCompileTimeOnly: continue
|
if param.typ.isCompileTimeOnly: continue
|
||||||
assignParam(p, param)
|
assignParam(p, param, prc.typ[0])
|
||||||
closureSetup(p, prc)
|
closureSetup(p, prc)
|
||||||
genStmts(p, procBody) # modifies p.locals, p.init, etc.
|
genStmts(p, procBody) # modifies p.locals, p.init, etc.
|
||||||
var generatedProc: Rope
|
var generatedProc: Rope
|
||||||
|
|
|
||||||
|
|
@ -230,8 +230,10 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
|
||||||
let t = n.sym.typ.skipTypes({tyTypeDesc})
|
let t = n.sym.typ.skipTypes({tyTypeDesc})
|
||||||
if t.kind == tyVar: result = arStrange
|
if t.kind == tyVar: result = arStrange
|
||||||
of nkDotExpr:
|
of nkDotExpr:
|
||||||
if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind in
|
let t = skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc})
|
||||||
{tyVar, tyPtr, tyRef}:
|
if t.kind in {tyVar, tyPtr, tyRef}:
|
||||||
|
result = arLValue
|
||||||
|
elif isUnsafeAddr and t.kind == tyLent:
|
||||||
result = arLValue
|
result = arLValue
|
||||||
else:
|
else:
|
||||||
result = isAssignable(owner, n.sons[0], isUnsafeAddr)
|
result = isAssignable(owner, n.sons[0], isUnsafeAddr)
|
||||||
|
|
@ -239,8 +241,10 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
|
||||||
sfDiscriminant in n[1].sym.flags:
|
sfDiscriminant in n[1].sym.flags:
|
||||||
result = arDiscriminant
|
result = arDiscriminant
|
||||||
of nkBracketExpr:
|
of nkBracketExpr:
|
||||||
if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind in
|
let t = skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc})
|
||||||
{tyVar, tyPtr, tyRef}:
|
if t.kind in {tyVar, tyPtr, tyRef}:
|
||||||
|
result = arLValue
|
||||||
|
elif isUnsafeAddr and t.kind == tyLent:
|
||||||
result = arLValue
|
result = arLValue
|
||||||
else:
|
else:
|
||||||
result = isAssignable(owner, n.sons[0], isUnsafeAddr)
|
result = isAssignable(owner, n.sons[0], isUnsafeAddr)
|
||||||
|
|
@ -254,7 +258,8 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
|
||||||
# types that are equal modulo distinction preserve l-value:
|
# types that are equal modulo distinction preserve l-value:
|
||||||
result = isAssignable(owner, n.sons[1], isUnsafeAddr)
|
result = isAssignable(owner, n.sons[1], isUnsafeAddr)
|
||||||
of nkHiddenDeref:
|
of nkHiddenDeref:
|
||||||
if n[0].typ.kind == tyLent: result = arDiscriminant
|
if isUnsafeAddr and n[0].typ.kind == tyLent: result = arLValue
|
||||||
|
elif n[0].typ.kind == tyLent: result = arDiscriminant
|
||||||
else: result = arLValue
|
else: result = arLValue
|
||||||
of nkDerefExpr, nkHiddenAddr:
|
of nkDerefExpr, nkHiddenAddr:
|
||||||
result = arLValue
|
result = arLValue
|
||||||
|
|
@ -266,6 +271,8 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
|
||||||
result = isAssignable(owner, n.sons[1], isUnsafeAddr)
|
result = isAssignable(owner, n.sons[1], isUnsafeAddr)
|
||||||
elif n.typ != nil and n.typ.kind == tyVar:
|
elif n.typ != nil and n.typ.kind == tyVar:
|
||||||
result = arLValue
|
result = arLValue
|
||||||
|
elif isUnsafeAddr and n.typ != nil and n.typ.kind == tyLent:
|
||||||
|
result = arLValue
|
||||||
of nkStmtList, nkStmtListExpr:
|
of nkStmtList, nkStmtListExpr:
|
||||||
if n.typ != nil:
|
if n.typ != nil:
|
||||||
result = isAssignable(owner, n.lastSon, isUnsafeAddr)
|
result = isAssignable(owner, n.lastSon, isUnsafeAddr)
|
||||||
|
|
|
||||||
25
tests/types/tlent_var.nim
Normal file
25
tests/types/tlent_var.nim
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
discard """
|
||||||
|
output: ''''''
|
||||||
|
"""
|
||||||
|
|
||||||
|
type
|
||||||
|
MyObj = object
|
||||||
|
a: int
|
||||||
|
|
||||||
|
proc test_lent(x: MyObj): lent int =
|
||||||
|
x.a
|
||||||
|
|
||||||
|
proc test_var(x: var MyObj): var int =
|
||||||
|
x.a
|
||||||
|
|
||||||
|
var x = MyObj(a: 5)
|
||||||
|
|
||||||
|
doAssert: test_var(x).addr == x.a.addr
|
||||||
|
doAssert: test_lent(x).unsafeAddr == x.a.addr
|
||||||
|
|
||||||
|
proc varProc(x: var int) =
|
||||||
|
x = 100
|
||||||
|
|
||||||
|
doAssert: not compiles(test_lent(x) = 1)
|
||||||
|
doAssert: not compiles(varProc(test_lent(x)))
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue