diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index bf1fe40506165..774b50d7b6579 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 0000000000000..f320ec4f52084 --- /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()