From 975ca268f0989344ac5c4b051a4e58e37301a376 Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Fri, 23 May 2025 22:15:55 +0800 Subject: [PATCH] fixes #24940; fixes #17552; lifts `{.global.}` in `injectDestructorCalls` (#24962) fixes #24940 fixes #17552 Collects `{.global.}` (i.e. if it was changed into a hook call: `=copy`, `=sink`) in `injectDestructorCalls` and generates it in the init sections in cgen (cherry picked from commit 3c0446b0828e0a64eb55ea38459e214d871d8ac1) --- compiler/cgen.nim | 3 +++ compiler/injectdestructors.nim | 13 ++++++++++++- compiler/modulegraphs.nim | 2 ++ tests/global/tglobal3.nim | 30 ++++++++++++++++++++++++++++++ 4 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 tests/global/tglobal3.nim diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 8a68b765f2..fe622f7ea8 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -2183,6 +2183,9 @@ proc genTopLevelStmt*(m: BModule; n: PNode) = else: genProcBody(m.initProc, transformedN) + for g in m.g.graph.procGlobals: + genStmts(m.preInitProc, g) + proc shouldRecompile(m: BModule; code: Rope, cfile: Cfile): bool = if optForceFullMake notin m.config.globalOptions: if not moduleHasChanged(m.g.graph, m.module): diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index 7e8d4250b1..93d03a5737 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -936,6 +936,9 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing of nkVarSection, nkLetSection: # transform; var x = y to var x; x op y where op is a move or copy result = newNodeI(nkStmtList, n.info) + + let isInProc = c.owner.kind in {skProc, skFunc, skMethod, skIterator, skConverter} + for it in n: var ri = it[^1] if it.kind == nkVarTuple and hasDestructor(c, ri.typ): @@ -951,7 +954,15 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing s.locals.add v.sym pVarTopLevel(v, c, s, result) if ri.kind != nkEmpty: - result.add moveOrCopy(v, ri, c, s, if v.kind == nkSym: {IsDecl} else: {}) + let isGlobalPragma = v.kind == nkSym and + {sfPure, sfGlobal} <= v.sym.flags and + isInProc + + let value = moveOrCopy(v, ri, c, s, if v.kind == nkSym: {IsDecl} else: {}) + if isGlobalPragma: + c.graph.procGlobals.add value + else: + result.add value elif ri.kind == nkEmpty and c.inLoop > 0: let skipInit = v.kind == nkDotExpr and # Closure var sfNoInit in v[1].sym.flags diff --git a/compiler/modulegraphs.nim b/compiler/modulegraphs.nim index dd6a590e4f..25ca73ad1f 100644 --- a/compiler/modulegraphs.nim +++ b/compiler/modulegraphs.nim @@ -136,6 +136,8 @@ type cachedFiles*: StringTableRef + procGlobals*: seq[PNode] + TPassContext* = object of RootObj # the pass's context idgen*: IdGenerator PPassContext* = ref TPassContext diff --git a/tests/global/tglobal3.nim b/tests/global/tglobal3.nim new file mode 100644 index 0000000000..10a40798f2 --- /dev/null +++ b/tests/global/tglobal3.nim @@ -0,0 +1,30 @@ +discard """ + matrix: "--mm:refc; --mm:orc" + targets: "c cpp" +""" + +block: # bug #17552 + proc main: string = + var tc {.global.} = "hi" + tc &= "hi" + result = tc + + doAssert main() == "hihi" + doAssert main() == "hihihi" + doAssert main() == "hihihihi" + +# bug #24940 +var v: int + +proc ccc(): ref int = + let tmp = new int + v += 1 + tmp[] = v + tmp + +proc f(v: static string): int = + let xxx {.global.} = ccc() + xxx[] + +doAssert f("1") == 1 +doAssert f("1") == 1 \ No newline at end of file