summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2012-08-14 07:53:16 +0200
committerAraq <rumpf_a@web.de>2012-08-14 07:53:16 +0200
commit5e570bae479209b60f5cb7c92d60f2e1b1083320 (patch)
tree38a7ea72d6caa3dd1131256943009cf77e354aba
parent991b3096e8fb99d3a1cc06668b724e440c380272 (diff)
downloadNim-5e570bae479209b60f5cb7c92d60f2e1b1083320.tar.gz
more bugfixes for closures
-rw-r--r--compiler/lambdalifting.nim8
-rwxr-xr-xcompiler/semexprs.nim3
-rw-r--r--tests/reject/tinvalidclosure2.nim14
3 files changed, 20 insertions, 5 deletions
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index a42c83af9..68d7e62c2 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -236,7 +236,8 @@ proc dummyClosureParam(o: POuterContext, i: PInnerContext) =
   if i.closureParam == nil: addClosureParam(i, e)
 
 proc illegalCapture(s: PSym): bool {.inline.} =
-  result = skipTypes(s.typ, abstractInst).kind in {tyVar, tyOpenArray} or
+  result = skipTypes(s.typ, abstractInst).kind in 
+                   {tyVar, tyOpenArray, tyVarargs} or
       s.kind == skResult
 
 proc captureVar(o: POuterContext, i: PInnerContext, local: PSym, 
@@ -246,7 +247,8 @@ proc captureVar(o: POuterContext, i: PInnerContext, local: PSym,
   var it = PEnv(IdTableGet(o.localsToEnv, local))
   if it == nil: return
   
-  if illegalCapture(local) or o.fn.id != local.owner.id:
+  if illegalCapture(local) or o.fn.id != local.owner.id or 
+      i.fn.typ.callConv notin {ccClosure, ccDefault}:
     # Currently captures are restricted to a single level of nesting:
     LocalError(info, errIllegalCaptureX, local.name.s)
   i.fn.typ.callConv = ccClosure
@@ -280,7 +282,7 @@ proc interestingVar(s: PSym): bool {.inline.} =
 
 proc semCaptureSym*(s, owner: PSym) =
   if interestingVar(s) and owner.id != s.owner.id:
-    if owner.typ != nil:
+    if owner.typ != nil and not isGenericRoutine(owner):
       owner.typ.callConv = ccClosure
     # since the analysis is not entirely correct, we don't set 'tfCapturesEnv'
     # here
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index a77a34d52..e26826683 100755
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -107,8 +107,6 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
       incl(c.p.owner.flags, sfSideEffect)
     elif s.kind == skParam and s.typ.kind == tyExpr:
       return s.typ.n
-    else:
-      semCaptureSym(s, c.p.owner)
     result = newSymNode(s, n.info)
     # We cannot check for access to outer vars for example because it's still
     # not sure the symbol really ends up being used:
@@ -1415,6 +1413,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   case n.kind
   of nkIdent, nkAccQuoted:
     var s = lookUp(c, n)
+    semCaptureSym(s, c.p.owner)
     result = semSym(c, n, s, flags)
   of nkSym:
     # because of the changed symbol binding, this does not mean that we
diff --git a/tests/reject/tinvalidclosure2.nim b/tests/reject/tinvalidclosure2.nim
new file mode 100644
index 000000000..a84bdafa3
--- /dev/null
+++ b/tests/reject/tinvalidclosure2.nim
@@ -0,0 +1,14 @@
+discard """
+  line: 10
+  errormsg: "invalid capture: 'A'"
+"""
+
+proc outer() = 
+  var A: int
+
+  proc ugh[T](x: T) {.cdecl.} =
+    echo "ugha", A, x
+    
+  ugh[int](12)
+
+outer()