Merge branch 'master' of github.com:Araq/Nimrod into upstream
This commit is contained in:
commit
fca6e31e1d
4 changed files with 29 additions and 7 deletions
|
|
@ -79,6 +79,7 @@ type
|
||||||
exc: PNode # stack of exceptions
|
exc: PNode # stack of exceptions
|
||||||
tags: PNode # list of tags
|
tags: PNode # list of tags
|
||||||
bottom: int
|
bottom: int
|
||||||
|
owner: PSym
|
||||||
|
|
||||||
PEffects = var TEffects
|
PEffects = var TEffects
|
||||||
|
|
||||||
|
|
@ -173,11 +174,16 @@ proc trackTryStmt(tracked: PEffects, n: PNode) =
|
||||||
track(tracked, b.sons[blen-1])
|
track(tracked, b.sons[blen-1])
|
||||||
tracked.bottom = oldBottom
|
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.
|
# 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
|
# Instead we track expressions of type tyProc too. See the manual for
|
||||||
# details:
|
# 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 =
|
proc isForwardedProc(n: PNode): bool =
|
||||||
result = n.kind == nkSym and sfForward in n.sym.flags
|
result = n.kind == nkSym and sfForward in n.sym.flags
|
||||||
|
|
@ -274,7 +280,7 @@ proc track(tracked: PEffects, n: PNode) =
|
||||||
elif effectList.len == 0:
|
elif effectList.len == 0:
|
||||||
if isForwardedProc(a):
|
if isForwardedProc(a):
|
||||||
propagateEffects(tracked, n, a.sym)
|
propagateEffects(tracked, n, a.sym)
|
||||||
elif isIndirectCall(a):
|
elif isIndirectCall(a, tracked.owner):
|
||||||
addEffect(tracked, createRaise(n))
|
addEffect(tracked, createRaise(n))
|
||||||
addTag(tracked, createTag(n))
|
addTag(tracked, createTag(n))
|
||||||
else:
|
else:
|
||||||
|
|
@ -355,6 +361,7 @@ proc trackProc*(s: PSym, body: PNode) =
|
||||||
var t: TEffects
|
var t: TEffects
|
||||||
t.exc = effects.sons[exceptionEffects]
|
t.exc = effects.sons[exceptionEffects]
|
||||||
t.tags = effects.sons[tagEffects]
|
t.tags = effects.sons[tagEffects]
|
||||||
|
t.owner = s
|
||||||
track(t, body)
|
track(t, body)
|
||||||
|
|
||||||
let p = s.ast.sons[pragmasPos]
|
let p = s.ast.sons[pragmasPos]
|
||||||
|
|
|
||||||
|
|
@ -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
|
raise ``system.E_Base`` (the base type of the exception hierarchy) and
|
||||||
thus any exception unless ``T`` has an explicit ``raises`` list.
|
thus any exception unless ``T`` has an explicit ``raises`` list.
|
||||||
However if the call is of the form ``f(...)`` where ``f`` is a parameter
|
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
|
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
|
itself (and not nil) is assumed to be called indirectly somehow and thus
|
||||||
its raises list is added to ``p``'s raises list.
|
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].} =
|
proc doRaise() {.raises: [EIO].} =
|
||||||
raise newException(EIO, "IO")
|
raise newException(EIO, "IO")
|
||||||
|
|
||||||
proc use() =
|
proc use() {.raises: [].} =
|
||||||
|
# doesn't compile! Can raise EIO!
|
||||||
noRaise(doRaise)
|
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
|
So in many cases a callback does not cause the compiler to be overly
|
||||||
conservative in its effect analysis.
|
conservative in its effect analysis.
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ proc innerText*(n: PXmlNode): string =
|
||||||
result = ""
|
result = ""
|
||||||
assert n.k == xnElement
|
assert n.k == xnElement
|
||||||
for i in 0 .. n.s.len-1:
|
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.} =
|
proc tag*(n: PXmlNode): string {.inline.} =
|
||||||
## gets the tag name of `n`. `n` has to be an ``xnElement`` node.
|
## gets the tag name of `n`. `n` has to be an ``xnElement`` node.
|
||||||
|
|
|
||||||
14
tests/reject/teffects5.nim
Normal file
14
tests/reject/teffects5.nim
Normal 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()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue