diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index a34e0535c642..c481221a58d5 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -3046,7 +3046,16 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = of nkObjConstr: genObjConstr(p, n, d) of nkCast: genCast(p, n, d) of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, d) - of nkHiddenAddr, nkAddr: genAddr(p, n, d) + of nkHiddenAddr: + if n[0].kind == nkDerefExpr: + # addr ( deref ( x )) --> x + var x = n[0][0] + if n.typ.skipTypes(abstractVar).kind != tyOpenArray: + x.typ = n.typ + expr(p, x, d) + return + genAddr(p, n, d) + of nkAddr: genAddr(p, n, d) of nkBracketExpr: genBracketExpr(p, n, d) of nkDerefExpr, nkHiddenDeref: genDeref(p, n, d) of nkDotExpr: genRecordField(p, n, d) diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 29bfb7df5466..bcabc42ede1d 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -1422,6 +1422,13 @@ proc genAddr(p: PProc, n: PNode, r: var TCompRes) = gen(p, n[0], r) of nkHiddenDeref: gen(p, n[0], r) + of nkDerefExpr: + var x = n[0] + if n.kind == nkHiddenAddr: + x = n[0][0] + if n.typ.skipTypes(abstractVar).kind != tyOpenArray: + x.typ = n.typ + gen(p, x, r) of nkHiddenAddr: gen(p, n[0], r) of nkConv: diff --git a/compiler/transf.nim b/compiler/transf.nim index 738b1a603979..ff480dcf44df 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -459,14 +459,14 @@ proc transformYield(c: PTransf, n: PNode): PNode = for i, child in changeNode: child.info = changeNode.info -proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PNode = +proc transformAddrDeref(c: PTransf, n: PNode, kinds: TNodeKinds): PNode = result = transformSons(c, n) if c.graph.config.backend == backendCpp or sfCompileToCpp in c.module.flags: return var n = result case n[0].kind of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64: var m = n[0][0] - if m.kind == a or m.kind == b: + if m.kind in kinds: # addr ( nkConv ( deref ( x ) ) ) --> nkConv(x) n[0][0] = m[0] result = n[0] @@ -476,7 +476,7 @@ proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PNode = result.typ = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, c.idgen) of nkHiddenStdConv, nkHiddenSubConv, nkConv: var m = n[0][1] - if m.kind == a or m.kind == b: + if m.kind in kinds: # addr ( nkConv ( deref ( x ) ) ) --> nkConv(x) n[0][1] = m[0] result = n[0] @@ -485,7 +485,7 @@ proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PNode = elif n.typ.skipTypes(abstractInst).kind in {tyVar}: result.typ = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, c.idgen) else: - if n[0].kind == a or n[0].kind == b: + if n[0].kind in kinds: # addr ( deref ( x )) --> x result = n[0][0] if n.typ.skipTypes(abstractVar).kind != tyOpenArray: @@ -853,7 +853,7 @@ proc transformCall(c: PTransf, n: PNode): PNode = elif magic == mAddr: result = newTransNode(nkAddr, n, 1) result[0] = n[1] - result = transformAddrDeref(c, result, nkDerefExpr, nkHiddenDeref) + result = transformAddrDeref(c, result, {nkDerefExpr, nkHiddenDeref}) elif magic in {mNBindSym, mTypeOf, mRunnableExamples}: # for bindSym(myconst) we MUST NOT perform constant folding: result = n @@ -1005,10 +1005,12 @@ proc transform(c: PTransf, n: PNode): PNode = of nkBreakStmt: result = transformBreak(c, n) of nkCallKinds: result = transformCall(c, n) - of nkAddr, nkHiddenAddr: - result = transformAddrDeref(c, n, nkDerefExpr, nkHiddenDeref) + of nkHiddenAddr: + result = transformAddrDeref(c, n, {nkHiddenDeref}) + of nkAddr: + result = transformAddrDeref(c, n, {nkDerefExpr, nkHiddenDeref}) of nkDerefExpr, nkHiddenDeref: - result = transformAddrDeref(c, n, nkAddr, nkHiddenAddr) + result = transformAddrDeref(c, n, {nkAddr, nkHiddenAddr}) of nkHiddenStdConv, nkHiddenSubConv, nkConv: result = transformConv(c, n) of nkDiscardStmt: diff --git a/tests/misc/t18079.nim b/tests/misc/t18079.nim new file mode 100644 index 000000000000..352348daf965 --- /dev/null +++ b/tests/misc/t18079.nim @@ -0,0 +1,11 @@ +type + Foo = object + y: int + + Bar = object + x: Foo + +proc baz(state: var Bar):int = + state.x.y = 2 + state.x.y +doAssert baz((ref Bar)(x: (new Foo)[])[]) == 2