summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorBung <crc32@qq.com>2022-11-13 05:57:07 +0800
committerGitHub <noreply@github.com>2022-11-12 22:57:07 +0100
commit1410243d3bd5a5898bea2130e2f3534bd23f5c04 (patch)
tree6c3316bc199af7cffdcc2809eba038b7648a02cc
parent165d523edfcf7e761021ddd2f8b3eeb2257a1293 (diff)
downloadNim-1410243d3bd5a5898bea2130e2f3534bd23f5c04.tar.gz
fix #3505 wrong var {.global.} initialization, asign variable to it (#20812)
* fix #3505 wrong var {.global.} initialization, asign variable to it

* fix #5132 as well

* follow suggestions

* handle all call kinds

* Update tests/global/t3505.nim

* Update compiler/semstmts.nim

* Update compiler/semstmts.nim

* Update compiler/semstmts.nim

* follow suggestion

* Update compiler/semstmts.nim

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
-rw-r--r--compiler/semstmts.nim22
-rw-r--r--tests/global/t3505.nim33
2 files changed, 54 insertions, 1 deletions
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index bf1fe4050..774b50d7b 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -36,6 +36,7 @@ const
   errRecursiveDependencyX = "recursive dependency: '$1'"
   errRecursiveDependencyIteratorX = "recursion is not supported in iterators: '$1'"
   errPragmaOnlyInHeaderOfProcX = "pragmas are only allowed in the header of a proc; redefinition of $1"
+  errCannotAssignToGlobal = "cannot assign local to global variable"
 
 proc semDiscard(c: PContext, n: PNode): PNode =
   result = n
@@ -590,6 +591,24 @@ proc msgSymChoiceUseQualifier(c: PContext; n: PNode; note = errGenerated) =
     inc i
   message(c.config, n.info, note, err)
 
+template isLocalVarSym(n: PNode): bool =
+  n.kind == nkSym and 
+    n.sym.kind in {skVar, skLet} and not 
+    ({sfGlobal, sfPure} <= n.sym.flags or
+      sfCompileTime in n.sym.flags)
+  
+proc usesLocalVar(n: PNode): bool =
+  for z in 1 ..< n.len:
+    if n[z].isLocalVarSym:
+      return true
+    elif n[z].kind in nkCallKinds:
+      if usesLocalVar(n[z]):
+        return true
+
+proc globalVarInitCheck(c: PContext, n: PNode) =
+  if n.isLocalVarSym or n.kind in nkCallKinds and usesLocalVar(n):
+    localError(c.config, n.info, errCannotAssignToGlobal)
+
 proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
   var b: PNode
   result = copyNode(n)
@@ -740,7 +759,8 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
         vm.setupCompileTimeVar(c.module, c.idgen, c.graph, x)
       if v.flags * {sfGlobal, sfThread} == {sfGlobal}:
         message(c.config, v.info, hintGlobalVar)
-
+      if {sfGlobal, sfPure} <= v.flags:
+        globalVarInitCheck(c, def)
       suggestSym(c.graph, v.info, v, c.graph.usageSym)
 
 proc semConst(c: PContext, n: PNode): PNode =
diff --git a/tests/global/t3505.nim b/tests/global/t3505.nim
new file mode 100644
index 000000000..f320ec4f5
--- /dev/null
+++ b/tests/global/t3505.nim
@@ -0,0 +1,33 @@
+discard """
+cmd: "nim check $options --hints:off $file"
+action: "reject"
+nimout: '''
+t3505.nim(22, 22) Error: cannot assign local to global variable
+t3505.nim(31, 28) Error: cannot assign local to global variable
+
+
+
+
+
+'''
+"""
+
+
+
+
+
+
+proc foo =
+  let a = 0
+  var b {.global.} = a
+foo()
+
+# issue #5132
+proc initX(it: float): int = 8
+proc initX2(it: int): int = it
+
+proc main() =
+  var f: float
+  var x {.global.} = initX2(initX(f))
+  
+main()