summary refs log tree commit diff stats
path: root/compiler/sempass2.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/sempass2.nim')
-rw-r--r--compiler/sempass2.nim41
1 files changed, 27 insertions, 14 deletions
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim
index fb266ae3a..a00325277 100644
--- a/compiler/sempass2.nim
+++ b/compiler/sempass2.nim
@@ -84,10 +84,10 @@ proc initVar(a: PEffects, n: PNode) =
 proc initVarViaNew(a: PEffects, n: PNode) =
   if n.kind != nkSym: return
   let s = n.sym
-  if {tfNeedsInit, tfNotNil} * s.typ.flags == {tfNotNil}:
+  if {tfNeedsInit, tfNotNil} * s.typ.flags <= {tfNotNil}:
     # 'x' is not nil, but that doesn't mean it's not nil children
     # are initialized:
-    initVarViaNew(a, n)
+    initVar(a, n)
 
 proc useVar(a: PEffects, n: PNode) =
   let s = n.sym
@@ -466,8 +466,7 @@ proc track(tracked: PEffects, n: PNode) =
         mergeEffects(tracked, effectList.sons[exceptionEffects], n)
         mergeTags(tracked, effectList.sons[tagEffects], n)
     for i in 1 .. <len(n): trackOperand(tracked, n.sons[i], paramType(op, i))
-    if a.kind == nkSym and a.sym.magic in {mNew, mNewFinalize, 
-                                           mNewSeq, mShallowCopy}:
+    if a.kind == nkSym and a.sym.magic in {mNew, mNewFinalize, mNewSeq}:
       # may not look like an assignment, but it is:
       initVarViaNew(tracked, n.sons[1])
     for i in 0 .. <safeLen(n):
@@ -477,7 +476,6 @@ proc track(tracked: PEffects, n: PNode) =
     if warnProveField in gNotes: checkFieldAccess(tracked.guards, n)
   of nkTryStmt: trackTryStmt(tracked, n)
   of nkPragma: trackPragmaStmt(tracked, n)
-  of nkMacroDef, nkTemplateDef: discard
   of nkAsgn, nkFastAsgn:
     track(tracked, n.sons[1])
     initVar(tracked, n.sons[0])
@@ -527,7 +525,9 @@ proc track(tracked: PEffects, n: PNode) =
       if sfDiscriminant in x.sons[0].sym.flags:
         addDiscriminantFact(tracked.guards, x)
     setLen(tracked.guards, oldFacts)
-  of nkTypeSection: discard
+  of nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef,
+      nkMacroDef, nkTemplateDef:
+    discard
   else:
     for i in 0 .. <safeLen(n): track(tracked, n.sons[i])
 
@@ -581,22 +581,26 @@ proc setEffectsForProcType*(t: PType, n: PNode) =
     if not isNil(tagsSpec):
       effects.sons[tagEffects] = tagsSpec
 
+proc initEffects(effects: PNode; s: PSym; t: var TEffects) =
+  newSeq(effects.sons, effectListLen)
+  effects.sons[exceptionEffects] = newNodeI(nkArgList, s.info)
+  effects.sons[tagEffects] = newNodeI(nkArgList, s.info)
+  
+  t.exc = effects.sons[exceptionEffects]
+  t.tags = effects.sons[tagEffects]
+  t.owner = s
+  t.init = @[]
+  t.guards = @[]
+  
 proc trackProc*(s: PSym, body: PNode) =
   var effects = s.typ.n.sons[0]
   internalAssert effects.kind == nkEffectList
   # effects already computed?
   if sfForward in s.flags: return
   if effects.len == effectListLen: return
-  newSeq(effects.sons, effectListLen)
-  effects.sons[exceptionEffects] = newNodeI(nkArgList, body.info)
-  effects.sons[tagEffects] = newNodeI(nkArgList, body.info)
   
   var t: TEffects
-  t.exc = effects.sons[exceptionEffects]
-  t.tags = effects.sons[tagEffects]
-  t.owner = s
-  t.init = @[]
-  t.guards = @[]
+  initEffects(effects, s, t)
   track(t, body)
   
   if not isEmptyType(s.typ.sons[0]) and tfNeedsInit in s.typ.sons[0].flags and
@@ -619,3 +623,12 @@ proc trackProc*(s: PSym, body: PNode) =
     # after the check, use the formal spec:
     effects.sons[tagEffects] = tagsSpec
     
+proc trackTopLevelStmt*(module: PSym; n: PNode) =
+  if n.kind in {nkPragma, nkMacroDef, nkTemplateDef, nkProcDef,
+                nkTypeSection, nkConverterDef, nkMethodDef, nkIteratorDef}:
+    return
+  var effects = newNode(nkEffectList, n.info)
+  var t: TEffects
+  initEffects(effects, module, t)
+
+  track(t, n)