This commit is contained in:
Araq
2013-06-13 15:19:55 +02:00
parent 2464da5b26
commit ff1d68c50b
3 changed files with 41 additions and 2 deletions

View File

@@ -345,12 +345,22 @@ proc impliesIn(fact, loc, aSet: PNode): TImplication =
result = geImpliesIn(fact.sons[2], fact.sons[1].pred, aSet)
of mNot, mOr, mAnd: internalError(loc.info, "impliesIn")
else: discard
proc valueIsNil(n: PNode): TImplication =
if n.kind == nkNilLit: impYes
elif n.kind in {nkStrLit..nkTripleStrLit, nkBracket, nkObjConstr}: impNo
else: impUnknown
proc impliesIsNil(fact, eq: PNode): TImplication =
case fact.sons[0].sym.magic
of mIsNil:
if sameTree(fact.sons[1], eq.sons[1]):
result = impYes
of someEq:
if sameTree(fact.sons[1], eq.sons[1]):
result = valueIsNil(fact.sons[2].skipConv)
elif sameTree(fact.sons[2], eq.sons[1]):
result = valueIsNil(fact.sons[1].skipConv)
of mNot, mOr, mAnd: internalError(eq.info, "impliesIsNil")
else: discard
@@ -539,6 +549,13 @@ proc addDiscriminantFact*(m: var TModel, n: PNode) =
fact.sons[2] = n.sons[1]
m.add fact
proc addAsgnFact*(m: var TModel, key, value: PNode) =
var fact = newNodeI(nkCall, key.info, 3)
fact.sons[0] = newSymNode(getSysMagic("==", mEqI))
fact.sons[1] = key
fact.sons[2] = value
m.add fact
proc addCaseBranchFacts*(m: var TModel, n: PNode, i: int) =
let branch = n.sons[i]
if branch.kind == nkOfBranch:

View File

@@ -309,6 +309,12 @@ proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) =
let n = n.skipConv
if paramType != nil and tfNotNil in paramType.flags and
n.typ != nil and tfNotNil notin n.typ.flags:
if n.kind == nkAddr:
# addr(x[]) can't be proven, but addr(x) can:
if not containsNode(n, {nkDerefExpr, nkHiddenDeref}): return
elif n.kind == nkSym and n.sym.kind in RoutineKinds:
# 'p' is not nil obviously:
return
case impliesNotNil(tracked.guards, n)
of impUnknown:
Message(n.info, errGenerated,
@@ -481,6 +487,7 @@ proc track(tracked: PEffects, n: PNode) =
initVar(tracked, n.sons[0])
invalidateFacts(tracked.guards, n.sons[0])
track(tracked, n.sons[0])
addAsgnFact(tracked.guards, n.sons[0], n.sons[1])
notNilCheck(tracked, n.sons[1], n.sons[0].typ)
of nkVarSection:
for child in n:
@@ -489,6 +496,7 @@ proc track(tracked: PEffects, n: PNode) =
track(tracked, last)
for i in 0 .. child.len-3:
initVar(tracked, child.sons[i])
addAsgnFact(tracked.guards, child.sons[i], last)
notNilCheck(tracked, last, child.sons[i].typ)
# since 'var (a, b): T = ()' is not even allowed, there is always type
# inference for (a, b) and thus no nil checking is necessary.
@@ -523,6 +531,7 @@ proc track(tracked: PEffects, n: PNode) =
if sfDiscriminant in x.sons[0].sym.flags:
addDiscriminantFact(tracked.guards, x)
setLen(tracked.guards, oldFacts)
of nkTypeSection: discard
else:
for i in 0 .. <safeLen(n): track(tracked, n.sons[i])

View File

@@ -1,6 +1,6 @@
discard """
errormsg: "'y' is provably nil"
line:25
line:38
"""
import strutils
@@ -10,6 +10,19 @@ type
TObj = object
x, y: int
type
superstring = string not nil
proc q(s: superstring) =
echo s
proc p2() =
var a: string = "I am not nil"
q(a) # but this should and does not
p2()
proc q(x: pointer not nil) =
nil