* Fix #14325
* Refactor and fix
This commit is contained in:
Clyybber
2021-03-11 14:03:25 +01:00
committed by GitHub
parent 3ce27511ad
commit 3cbc80045d
3 changed files with 41 additions and 32 deletions

View File

@@ -2577,40 +2577,32 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
[getTypeDesc(p.module, dest), addrLoc(p.config, a)], a.storage)
proc downConv(p: BProc, n: PNode, d: var TLoc) =
if p.module.compileToCpp:
discard getTypeDesc(p.module, skipTypes(n[0].typ, abstractPtrs))
expr(p, n[0], d) # downcast does C++ for us
else:
var dest = skipTypes(n.typ, abstractPtrs)
var arg = n[0]
while arg.kind == nkObjDownConv: arg = arg[0]
var arg = n[0]
while arg.kind == nkObjDownConv: arg = arg[0]
var src = skipTypes(arg.typ, abstractPtrs)
discard getTypeDesc(p.module, src)
let dest = skipTypes(n.typ, abstractPtrs)
let src = skipTypes(arg.typ, abstractPtrs)
discard getTypeDesc(p.module, src)
let isRef = skipTypes(arg.typ, abstractInstOwned).kind in {tyRef, tyPtr, tyVar, tyLent}
if isRef and d.k == locNone and n.typ.skipTypes(abstractInstOwned).kind in {tyRef, tyPtr} and n.isLValue:
# it can happen that we end up generating '&&x->Sup' here, so we pack
# the '&x->Sup' into a temporary and then those address is taken
# (see bug #837). However sometimes using a temporary is not correct:
# init(TFigure(my)) # where it is passed to a 'var TFigure'. We test
# this by ensuring the destination is also a pointer:
var a: TLoc
initLocExpr(p, arg, a)
var r = rdLoc(a)
let isRef = skipTypes(arg.typ, abstractInstOwned).kind in {tyRef, tyPtr, tyVar, tyLent}
if isRef:
r.add("->Sup")
else:
r.add(".Sup")
putIntoDest(p, d, n,
"(*(($1*) (&($2))))" % [getTypeDesc(p.module, n.typ), rdLoc(a)], a.storage)
elif p.module.compileToCpp:
# C++ implicitly downcasts for us
expr(p, arg, d)
else:
var a: TLoc
initLocExpr(p, arg, a)
var r = rdLoc(a) & (if isRef: "->Sup" else: ".Sup")
for i in 2..abs(inheritanceDiff(dest, src)): r.add(".Sup")
if isRef:
# it can happen that we end up generating '&&x->Sup' here, so we pack
# the '&x->Sup' into a temporary and then those address is taken
# (see bug #837). However sometimes using a temporary is not correct:
# init(TFigure(my)) # where it is passed to a 'var TFigure'. We test
# this by ensuring the destination is also a pointer:
if d.k == locNone and skipTypes(n.typ, abstractInstOwned).kind in {tyRef, tyPtr, tyVar, tyLent}:
getTemp(p, n.typ, d)
linefmt(p, cpsStmts, "$1 = &$2;$n", [rdLoc(d), r])
else:
r = "&" & r
putIntoDest(p, d, n, r, a.storage)
else:
putIntoDest(p, d, n, r, a.storage)
putIntoDest(p, d, n, if isRef: "&" & r else: r, a.storage)
proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
let t = n.typ

View File

@@ -1143,9 +1143,9 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
gcomma(g, n)
put(g, tkParRi, ")")
of nkObjDownConv, nkObjUpConv:
let typ = if (n.typ != nil) and (n.typ.sym != nil): n.typ.sym.name.s else: ""
put(g, tkParLe, typ & "(")
if n.len >= 1: gsub(g, n[0])
put(g, tkParLe, "(")
gcomma(g, n, 1)
put(g, tkParRi, ")")
of nkClosedSymChoice, nkOpenSymChoice:
if renderIds in g.flags:

View File

@@ -1,3 +1,9 @@
discard """
matrix: "--gc:refc; --gc:arc"
"""
# bug #14160
type
TPassContext = object of RootObj
PPassContext = ref TPassContext
@@ -11,5 +17,16 @@ type
proc main() =
var g = ModuleGraph(vm: new(Pctx))
PCtx(g.vm) = nil #This generates invalid C code
doAssert g.vm == nil
main()
# bug #14325
proc main2() =
var g = ModuleGraph(vm: new(Pctx))
PPassContext(PCtx(g.vm)) = nil #This compiles, but crashes at runtime with gc:arc
doAssert g.vm == nil
main2()