diff options
author | Clyybber <darkmine956@gmail.com> | 2021-03-11 14:03:25 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-11 14:03:25 +0100 |
commit | 3cbc80045dfe84e47e28abc4d19f2bbeba82748d (patch) | |
tree | 5f77f08131e2a090c4788e1e28a98b61cea30f2c | |
parent | 3ce27511adac12785b51ecc33dc9d2a2fcd2f0b8 (diff) | |
download | Nim-3cbc80045dfe84e47e28abc4d19f2bbeba82748d.tar.gz |
Fix #14325 (#17308)
* Fix #14325 * Refactor and fix
-rw-r--r-- | compiler/ccgexprs.nim | 52 | ||||
-rw-r--r-- | compiler/renderer.nim | 4 | ||||
-rw-r--r-- | tests/ccgbugs/tlvalueconv.nim (renamed from tests/ccgbugs/t14160.nim) | 17 |
3 files changed, 41 insertions, 32 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 2a8af5c41..ea09b3400 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -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 diff --git a/compiler/renderer.nim b/compiler/renderer.nim index ed1c52bb7..13ff6941f 100644 --- a/compiler/renderer.nim +++ b/compiler/renderer.nim @@ -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: diff --git a/tests/ccgbugs/t14160.nim b/tests/ccgbugs/tlvalueconv.nim index be7088e29..b2cb11eef 100644 --- a/tests/ccgbugs/t14160.nim +++ b/tests/ccgbugs/tlvalueconv.nim @@ -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() + |