From 646bd99d461469f08e656f92ae278d6695b35778 Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Wed, 19 Jun 2024 14:33:38 +0800 Subject: [PATCH] [backport] fixes #23711; C code contains backtick`gensym (#23716) fixes #23711 --- compiler/ast.nim | 3 ++- compiler/evaltempl.nim | 1 + compiler/sem.nim | 4 +++- compiler/semstmts.nim | 2 +- compiler/semtypes.nim | 12 ++++++++---- tests/pragmas/tpush.nim | 25 +++++++++++++++++++++++++ 6 files changed, 40 insertions(+), 7 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 4de277ba9a23..8b3c6afcde33 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -41,7 +41,7 @@ type TNodeKinds* = set[TNodeKind] type - TSymFlag* = enum # 51 flags! + TSymFlag* = enum # 52 flags! sfUsed, # read access of sym (for warnings) or simply used sfExported, # symbol is exported from module sfFromGeneric, # symbol is instantiation of a generic; this is needed @@ -126,6 +126,7 @@ type sfByCopy # param is marked as pass bycopy sfMember # proc is a C++ member of a type sfCodegenDecl # type, proc, global or proc param is marked as codegenDecl + sfWasGenSym # symbol was 'gensym'ed TSymFlags* = set[TSymFlag] diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim index bd0875213fc8..5895368bb56b 100644 --- a/compiler/evaltempl.nim +++ b/compiler/evaltempl.nim @@ -56,6 +56,7 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) = # internalAssert c.config, false idTablePut(c.mapping, s, x) if sfGenSym in s.flags: + # TODO: getIdent(c.ic, "`" & x.name.s & "`gensym" & $c.instID) result.add newIdentNode(getIdent(c.ic, x.name.s & "`gensym" & $c.instID), if c.instLines: actual.info else: templ.info) else: diff --git a/compiler/sem.nim b/compiler/sem.nim index 760b83941d10..d813a791d2a9 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -254,6 +254,8 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym = result.owner = getCurrOwner(c) else: result = newSym(kind, considerQuotedIdent(c, n), c.idgen, getCurrOwner(c), n.info) + if find(result.name.s, '`') >= 0: + result.flags.incl sfWasGenSym #if kind in {skForVar, skLet, skVar} and result.owner.kind == skModule: # incl(result.flags, sfGlobal) when defined(nimsuggest): @@ -263,7 +265,7 @@ proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, allowed: TSymFlags): PSym # identifier with visibility proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode, - allowed: TSymFlags): PSym + allowed: TSymFlags, fromTopLevel = false): PSym proc typeAllowedCheck(c: PContext; info: TLineInfo; typ: PType; kind: TSymKind; flags: TTypeAllowedFlags = {}) = diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 8c7dda4e7c2c..e4f22f4359eb 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -480,7 +480,7 @@ proc identWithin(n: PNode, s: PIdent): bool = proc semIdentDef(c: PContext, n: PNode, kind: TSymKind, reportToNimsuggest = true): PSym = if isTopLevel(c): - result = semIdentWithPragma(c, kind, n, {sfExported}) + result = semIdentWithPragma(c, kind, n, {sfExported}, fromTopLevel = true) incl(result.flags, sfGlobal) #if kind in {skVar, skLet}: # echo "global variable here ", n.info, " ", result.name.s diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index c79c63a3f268..38daa9513441 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -540,7 +540,7 @@ proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, result = newSymG(kind, n, c) proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode, - allowed: TSymFlags): PSym = + allowed: TSymFlags, fromTopLevel = false): PSym = if n.kind == nkPragmaExpr: checkSonsLen(n, 2, c.config) result = semIdentVis(c, kind, n[0], allowed) @@ -555,11 +555,15 @@ proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode, else: discard else: result = semIdentVis(c, kind, n, allowed) + let invalidPragmasForPush = if fromTopLevel and sfWasGenSym notin result.flags: + {} + else: + {wExportc, wExportCpp, wDynlib} case kind of skField: implicitPragmas(c, result, n.info, fieldPragmas) - of skVar: implicitPragmas(c, result, n.info, varPragmas) - of skLet: implicitPragmas(c, result, n.info, letPragmas) - of skConst: implicitPragmas(c, result, n.info, constPragmas) + of skVar: implicitPragmas(c, result, n.info, varPragmas-invalidPragmasForPush) + of skLet: implicitPragmas(c, result, n.info, letPragmas-invalidPragmasForPush) + of skConst: implicitPragmas(c, result, n.info, constPragmas-invalidPragmasForPush) else: discard proc checkForOverlap(c: PContext, t: PNode, currentEx, branchIndex: int) = diff --git a/tests/pragmas/tpush.nim b/tests/pragmas/tpush.nim index 8ebbfe3d3d6f..cb411714e2dd 100644 --- a/tests/pragmas/tpush.nim +++ b/tests/pragmas/tpush.nim @@ -99,3 +99,28 @@ block: # bug #23019 k(w) {.pop.} {.pop.} + +{.push exportC.} + +block: + proc foo11() = + const factor = [1, 2, 3, 4] + doAssert factor[0] == 1 + proc foo21() = + const factor = [1, 2, 3, 4] + doAssert factor[0] == 1 + + foo11() + foo21() + +template foo31() = + let factor = [1, 2, 3, 4] + doAssert factor[0] == 1 +template foo41() = + let factor = [1, 2, 3, 4] + doAssert factor[0] == 1 + +foo31() +foo41() + +{.pop.}