diff options
author | Zahary Karadjov <zahary@gmail.com> | 2013-05-12 16:14:46 +0300 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.com> | 2013-05-12 16:14:46 +0300 |
commit | fca6e31e1d14dc9a4ba902aa727a008f4fbbf71c (patch) | |
tree | c0393a58efc8d0e73939fa0f19dff03fe6e84795 | |
parent | 1d29d24465ddb9aaea18558f221ff67bf82db0c7 (diff) | |
parent | 37b5be0133815423f785d0779f839fc7f8e09999 (diff) | |
download | Nim-fca6e31e1d14dc9a4ba902aa727a008f4fbbf71c.tar.gz |
Merge branch 'master' of github.com:Araq/Nimrod into upstream
-rw-r--r-- | compiler/sempass2.nim | 13 | ||||
-rw-r--r-- | doc/manual.txt | 7 | ||||
-rw-r--r-- | lib/pure/xmltree.nim | 2 | ||||
-rw-r--r-- | tests/reject/teffects5.nim | 14 |
4 files changed, 29 insertions, 7 deletions
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 9213bd48d..b78e36531 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -79,6 +79,7 @@ type exc: PNode # stack of exceptions tags: PNode # list of tags bottom: int + owner: PSym PEffects = var TEffects @@ -173,11 +174,16 @@ proc trackTryStmt(tracked: PEffects, n: PNode) = track(tracked, b.sons[blen-1]) tracked.bottom = oldBottom -proc isIndirectCall(n: PNode): bool = +proc isIndirectCall(n: PNode, owner: PSym): bool = # we don't count f(...) as an indirect call if 'f' is an parameter. # Instead we track expressions of type tyProc too. See the manual for # details: - result = n.kind != nkSym or n.sym.kind notin (routineKinds+{skParam}) + if n.kind != nkSym: + result = true + elif n.sym.kind == skParam: + result = owner != n.sym.owner or owner == nil + elif n.sym.kind notin routineKinds: + result = true proc isForwardedProc(n: PNode): bool = result = n.kind == nkSym and sfForward in n.sym.flags @@ -274,7 +280,7 @@ proc track(tracked: PEffects, n: PNode) = elif effectList.len == 0: if isForwardedProc(a): propagateEffects(tracked, n, a.sym) - elif isIndirectCall(a): + elif isIndirectCall(a, tracked.owner): addEffect(tracked, createRaise(n)) addTag(tracked, createTag(n)) else: @@ -355,6 +361,7 @@ proc trackProc*(s: PSym, body: PNode) = var t: TEffects t.exc = effects.sons[exceptionEffects] t.tags = effects.sons[tagEffects] + t.owner = s track(t, body) let p = s.ast.sons[pragmasPos] diff --git a/doc/manual.txt b/doc/manual.txt index bc9b81bad..f7b2314c1 100644 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -2910,7 +2910,8 @@ possibly raised exceptions; the algorithm operates on ``p``'s call graph: raise ``system.E_Base`` (the base type of the exception hierarchy) and thus any exception unless ``T`` has an explicit ``raises`` list. However if the call is of the form ``f(...)`` where ``f`` is a parameter - is ignored. Rule 2 compensates for this case. + of the currently analysed routine it is ignored. The call is optimistically + assumed to have no effect. Rule 2 compensates for this case. 2. Every expression of some proc type wihtin a call that is not a call itself (and not nil) is assumed to be called indirectly somehow and thus its raises list is added to ``p``'s raises list. @@ -2933,9 +2934,9 @@ Rules 1-2 ensure the following works: proc doRaise() {.raises: [EIO].} = raise newException(EIO, "IO") - proc use() = + proc use() {.raises: [].} = + # doesn't compile! Can raise EIO! noRaise(doRaise) - # Here the compiler inferes that EIO can be raised. So in many cases a callback does not cause the compiler to be overly conservative in its effect analysis. diff --git a/lib/pure/xmltree.nim b/lib/pure/xmltree.nim index 8cf484bfc..e3fc27237 100644 --- a/lib/pure/xmltree.nim +++ b/lib/pure/xmltree.nim @@ -78,7 +78,7 @@ proc innerText*(n: PXmlNode): string = result = "" assert n.k == xnElement for i in 0 .. n.s.len-1: - if n.s[i].k in {xnText, xnEntity}: result.add(n.fText) + if n.s[i].k in {xnText, xnEntity}: result.add(n.s[i].fText) proc tag*(n: PXmlNode): string {.inline.} = ## gets the tag name of `n`. `n` has to be an ``xnElement`` node. diff --git a/tests/reject/teffects5.nim b/tests/reject/teffects5.nim new file mode 100644 index 000000000..42be115c3 --- /dev/null +++ b/tests/reject/teffects5.nim @@ -0,0 +1,14 @@ +discard """ + errormsg: 'type mismatch' + line: 7 +""" + +proc p(q: proc() ): proc() {.tags: [], raises: [], closure.} = + return proc () = + q() + +let yay = p(proc () = raise newException(EIO, "IO")) + +proc main() {.raises: [], tags: [].} = yay() + +main() |