From e002d4efec779148e046d15433612664d24f2417 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 19 Aug 2022 12:45:32 +0200 Subject: [PATCH] fixes #20107 --- compiler/ccgexprs.nim | 14 ++++++++++++++ tests/ccgbugs/tderefblock.nim | 24 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 tests/ccgbugs/tderefblock.nim diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 4c15101a98283..1f16f458f743b 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -731,7 +731,21 @@ proc isCppRef(p: BProc; typ: PType): bool {.inline.} = skipTypes(typ, abstractInstOwned).kind in {tyVar} and tfVarIsPtr notin skipTypes(typ, abstractInstOwned).flags +proc derefBlock(p: BProc, e: PNode, d: var TLoc) = + # We transform (block: x)[] to (block: x[]) + let e0 = e[0] + var n = shallowCopy(e0) + for i in 0 ..< e0.len - 1: + n[i] = e0[i] + n[e0.len-1] = newTreeIT(nkHiddenDeref, e.info, e.typ, e0[e0.len-1]) + expr p, n, d + proc genDeref(p: BProc, e: PNode, d: var TLoc) = + if e.kind == nkHiddenDeref and e[0].kind in {nkBlockExpr, nkBlockStmt}: + # bug #20107. Watch out to not deref the pointer too late. + derefBlock(p, e, d) + return + let mt = mapType(p.config, e[0].typ, mapTypeChooser(e[0])) if mt in {ctArray, ctPtrToArray} and lfEnforceDeref notin d.flags: # XXX the amount of hacks for C's arrays is incredible, maybe we should diff --git a/tests/ccgbugs/tderefblock.nim b/tests/ccgbugs/tderefblock.nim new file mode 100644 index 0000000000000..55253da108726 --- /dev/null +++ b/tests/ccgbugs/tderefblock.nim @@ -0,0 +1,24 @@ +discard """ + cmd: "nim c -d:release -d:danger $file" + output: "42" +""" + +# bug #20107 + +type Foo = object + a, b, c, d: uint64 + +proc c(i: uint64): Foo = + Foo(a: i, b: i, c: i, d: i) + +func x(f: Foo): lent Foo {.inline.} = + f + +proc m() = + let f = block: + let i = c(42) + x(i) + + echo $f.a + +m()