summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2022-08-19 13:42:08 +0200
committerGitHub <noreply@github.com>2022-08-19 13:42:08 +0200
commitb1fe1690c48fc3c24e3db2b2e2d12961f46f36f9 (patch)
tree85e597e1488e451775ed27defe667b73618ad171
parent1c31de361d345c7cfc9ac2ca7a3040bdfa649d9a (diff)
downloadNim-b1fe1690c48fc3c24e3db2b2e2d12961f46f36f9.tar.gz
fixes #20107 (#20246) [backport]
-rw-r--r--compiler/ccgexprs.nim14
-rw-r--r--tests/ccgbugs/tderefblock.nim24
2 files changed, 38 insertions, 0 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 4c15101a9..1f16f458f 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 000000000..55253da10
--- /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()