Merge branch 'master' of github.com:Araq/Nimrod into upstream

This commit is contained in:
Zahary Karadjov
2013-05-12 16:14:46 +03:00
4 changed files with 29 additions and 7 deletions

View File

@@ -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]

View File

@@ -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.

View File

@@ -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.

View File

@@ -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()