fixes #21540; deref block at transf phase to make injectdestructors function properly (#21688)

* fixes #21540; deref block at transf phase to make injectdestructors function properly

* add a test case

* add one more test

* fixes the type of block

* transform block
This commit is contained in:
ringabout
2023-04-19 17:55:54 +08:00
committed by GitHub
parent 0d6b994bee
commit 9cb06d357e
3 changed files with 69 additions and 17 deletions

View File

@@ -752,21 +752,8 @@ 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)
n.typ = e.typ
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
assert e[0].kind notin {nkBlockExpr, nkBlockStmt}, "it should have been transformed in transf"
let mt = mapType(p.config, e[0].typ, mapTypeChooser(e[0]))
if mt in {ctArray, ctPtrToArray} and lfEnforceDeref notin d.flags:

View File

@@ -941,6 +941,15 @@ proc commonOptimizations*(g: ModuleGraph; idgen: IdGenerator; c: PSym, n: PNode)
else:
result = n
proc transformDerefBlock(c: PTransf, n: PNode): PNode =
# We transform (block: x)[] to (block: x[])
let e0 = n[0]
result = shallowCopy(e0)
result.typ = n.typ
for i in 0 ..< e0.len - 1:
result[i] = e0[i]
result[e0.len-1] = newTreeIT(nkHiddenDeref, n.info, n.typ, e0[e0.len-1])
proc transform(c: PTransf, n: PNode): PNode =
when false:
var oldDeferAnchor: PNode
@@ -1012,7 +1021,12 @@ proc transform(c: PTransf, n: PNode): PNode =
of nkAddr:
result = transformAddrDeref(c, n, {nkDerefExpr, nkHiddenDeref})
of nkDerefExpr, nkHiddenDeref:
result = transformAddrDeref(c, n, {nkAddr, nkHiddenAddr})
if n[0].kind in {nkBlockExpr, nkBlockStmt}:
# bug #20107 bug #21540. Watch out to not deref the pointer too late.
let e = transformDerefBlock(c, n)
result = transformBlock(c, e)
else:
result = transformAddrDeref(c, n, {nkAddr, nkHiddenAddr})
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
result = transformConv(c, n)
of nkDiscardStmt:

View File

@@ -1,6 +1,5 @@
discard """
cmd: "nim c -d:release -d:danger $file"
matrix: ";--gc:orc"
matrix: "--mm:refc -d:release -d:danger;--mm:orc -d:useMalloc -d:release -d:danger"
output: "42"
"""
@@ -23,3 +22,55 @@ proc m() =
echo $f.a
m()
block: # bug #21540
type
Option = object
val: string
has: bool
proc some(val: string): Option =
result.has = true
result.val = val
# Remove lent and it works
proc get(self: Option): lent string =
result = self.val
type
StringStream = ref object
data: string
pos: int
proc readAll(s: StringStream): string =
result = newString(s.data.len)
copyMem(addr(result[0]), addr(s.data[0]), s.data.len)
proc newStringStream(s: string = ""): StringStream =
new(result)
result.data = s
proc parseJson(s: string): string =
let stream = newStringStream(s)
result = stream.readAll()
proc main =
let initialFEN = block:
let initialFEN = some parseJson("startpos")
initialFEN.get
doAssert initialFEN == "startpos"
main()
import std/[
json,
options
]
block: # bug #21540
let cheek = block:
let initialFEN = some("""{"initialFen": "startpos"}""".parseJson{"initialFen"}.getStr)
initialFEN.get
doAssert cheek == "startpos"