summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorringabout <43030857+ringabout@users.noreply.github.com>2024-06-19 14:33:38 +0800
committerGitHub <noreply@github.com>2024-06-19 08:33:38 +0200
commit646bd99d461469f08e656f92ae278d6695b35778 (patch)
tree9929267c811c74c730eea09e30b32415037954de
parente64512036289434c6a7b377f52a50189beae75e8 (diff)
downloadNim-646bd99d461469f08e656f92ae278d6695b35778.tar.gz
[backport] fixes #23711; C code contains backtick`gensym (#23716)
fixes #23711
-rw-r--r--compiler/ast.nim3
-rw-r--r--compiler/evaltempl.nim1
-rw-r--r--compiler/sem.nim4
-rw-r--r--compiler/semstmts.nim2
-rw-r--r--compiler/semtypes.nim12
-rw-r--r--tests/pragmas/tpush.nim25
6 files changed, 40 insertions, 7 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 4de277ba9..8b3c6afcd 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 bd0875213..5895368bb 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 760b83941..d813a791d 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 8c7dda4e7..e4f22f435 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 c79c63a3f..38daa9513 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 8ebbfe3d3..cb411714e 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.}