summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorringabout <43030857+ringabout@users.noreply.github.com>2023-11-20 00:52:42 +0800
committerGitHub <noreply@github.com>2023-11-19 17:52:42 +0100
commit5dafcf4957a225b1f015d131299e51735e7bb1d3 (patch)
tree8a65d81d0ac090abf2af634d63f6f7aec89e4cc9
parent6c5283b194ec238c765c2e0a8f252db003643557 (diff)
downloadNim-5dafcf4957a225b1f015d131299e51735e7bb1d3.tar.gz
fixes #22913; fixes #12985 differently push-ing pragma exportc genera… (#22941)
…tes invalid C identifiers

fixes #22913
fixes #12985 differently


`{.push.} now does not apply to generic instantiations`
-rw-r--r--compiler/pragmas.nim2
-rw-r--r--compiler/seminst.nim6
-rw-r--r--tests/pragmas/tpush.nim39
3 files changed, 46 insertions, 1 deletions
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index 53b4f53a8..d4817ce7a 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -1313,7 +1313,7 @@ proc implicitPragmas*(c: PContext, sym: PSym, info: TLineInfo,
   if sym != nil and sym.kind != skModule:
     for it in c.optionStack:
       let o = it.otherPragmas
-      if not o.isNil and sfFromGeneric notin sym.flags: # see issue #12985
+      if not o.isNil:
         pushInfoContext(c.config, info)
         var i = 0
         while i < o.len:
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index dc25230c2..085769bdd 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -400,11 +400,17 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
     entry.compilesId = c.compilesContextId
     addToGenericProcCache(c, fn, entry)
     c.generics.add(makeInstPair(fn, entry))
+    # bug #12985 bug #22913
+    # TODO: use the context of the declaration of generic functions instead
+    # TODO: consider fixing options as well
+    let otherPragmas = c.optionStack[^1].otherPragmas
+    c.optionStack[^1].otherPragmas = nil
     if n[pragmasPos].kind != nkEmpty:
       pragma(c, result, n[pragmasPos], allRoutinePragmas)
     if isNil(n[bodyPos]):
       n[bodyPos] = copyTree(getBody(c.graph, fn))
     instantiateBody(c, n, fn.typ.n, result, fn)
+    c.optionStack[^1].otherPragmas = otherPragmas
     sideEffectsCheck(c, result)
     if result.magic notin {mSlice, mTypeOf}:
       # 'toOpenArray' is special and it is allowed to return 'openArray':
diff --git a/tests/pragmas/tpush.nim b/tests/pragmas/tpush.nim
index 6d7eade91..6a95f1ca0 100644
--- a/tests/pragmas/tpush.nim
+++ b/tests/pragmas/tpush.nim
@@ -38,3 +38,42 @@ proc main(): void =
   {.push staticBoundChecks: on.}
 
 main()
+
+
+proc timnFoo[T](obj: T) {.noSideEffect.} = discard # BUG
+
+{.push exportc.}
+proc foo1() =
+  var s1 = "bar"
+  timnFoo(s1)
+  var s2 = @[1]
+  timnFoo(s2)
+{.pop.}
+
+
+block: # bug #22913
+  block:
+    type r = object
+
+    template std[T](x: T) =
+      let ttt {.used.} = x
+      result = $ttt
+
+    proc bar[T](x: T): string =
+      std(x)
+
+    {.push exportc: "$1".}
+    proc foo(): r =
+      let s = bar(123)
+    {.pop.}
+
+    discard foo()
+
+  block:
+    type r = object
+    {.push exportc: "$1".}
+    proc foo2(): r =
+      let s = $result
+    {.pop.}
+
+    discard foo2()