diff options
author | Araq <rumpf_a@web.de> | 2012-08-14 07:53:16 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-08-14 07:53:16 +0200 |
commit | 5e570bae479209b60f5cb7c92d60f2e1b1083320 (patch) | |
tree | 38a7ea72d6caa3dd1131256943009cf77e354aba | |
parent | 991b3096e8fb99d3a1cc06668b724e440c380272 (diff) | |
download | Nim-5e570bae479209b60f5cb7c92d60f2e1b1083320.tar.gz |
more bugfixes for closures
-rw-r--r-- | compiler/lambdalifting.nim | 8 | ||||
-rwxr-xr-x | compiler/semexprs.nim | 3 | ||||
-rw-r--r-- | tests/reject/tinvalidclosure2.nim | 14 |
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() |