@@ -216,6 +216,75 @@ proc checkReq(c: var Context; paramMap: Table[SymId, int]; req, call: Cursor): P
216216
217217proc analyseCall (c: var Context ; n: var Cursor )
218218
219+ proc markedNotNil (t: Cursor ): bool =
220+ result = false
221+ case t.typeKind
222+ of PtrT , RefT :
223+ var e = t.firstSon
224+ skip e # base type
225+ if e.kind != ParRi and e.substructureKind == NotnilU :
226+ result = true
227+ of CstringT , PointerT :
228+ let e = t.firstSon
229+ # no base type
230+ if e.kind != ParRi and e.substructureKind == NotnilU :
231+ result = true
232+ else :
233+ discard
234+
235+ proc wantNotNil (c: var Context ; n: Cursor ) =
236+ case n.exprKind
237+ of NilX :
238+ buildErr (c, n.info, " expected non-nil value" )
239+ of AddrX :
240+ discard " fine, addresses are not nil"
241+ else :
242+ let t = getType (c.typeCache, n)
243+ if markedNotNil (t):
244+ discard " fine, per type we know it is not nil"
245+ # elif n.kind
246+ # XXX to implement
247+
248+ proc checkNilMatch (c: var Context ; n: Cursor ; expected: Cursor ) =
249+ if markedNotNil (expected):
250+ wantNotNil c, n
251+
252+ proc analyseOconstr (c: var Context ; n: var Cursor ) =
253+ inc n
254+ skip n # type
255+ while n.kind != ParRi :
256+ assert n.substructureKind == KvU
257+ inc n
258+ let expected = getType (c.typeCache, n)
259+ skip n # field name
260+ checkNilMatch c, n, expected
261+ skip n # value
262+ if n.kind != ParRi :
263+ # optional inheritance
264+ skip n
265+ skipParRi n
266+ skipParRi n
267+
268+ proc analyseArrayConstr (c: var Context ; n: var Cursor ) =
269+ inc n
270+ let expected = n.firstSon # element type of the array
271+ skip n # type
272+ while n.kind != ParRi :
273+ checkNilMatch c, n, expected
274+ skip n
275+ skipParRi n
276+
277+ proc analyseTupConstr (c: var Context ; n: var Cursor ) =
278+ inc n
279+ var expected = n.firstSon # type of the first field
280+ skip n # type
281+ while n.kind != ParRi :
282+ assert expected.kind != ParRi
283+ checkNilMatch c, n, getTupleFieldType (expected)
284+ skip n
285+ skip expected # type of the next field
286+ skipParRi n
287+
219288proc analyseExpr (c: var Context ; pc: var Cursor ) =
220289 # echo "analyseExpr ", toString(pc, false)
221290 var nested = 0
@@ -239,8 +308,27 @@ proc analyseExpr(c: var Context; pc: var Cursor) =
239308 dec nested
240309 inc pc
241310 of ParLe :
242- if pc.exprKind in CallKinds :
311+ case pc.exprKind
312+ of CallKinds :
243313 analyseCall c, pc
314+ of DdotX :
315+ inc pc
316+ wantNotNil c, pc
317+ analyseExpr c, pc # object
318+ skip pc # field name
319+ if pc.kind != ParRi : skip pc # inheritence depth
320+ skipParRi pc
321+ of DerefX :
322+ inc pc
323+ wantNotNil c, pc
324+ analyseExpr c, pc
325+ skipParRi pc
326+ of OconstrX , NewobjX :
327+ analyseOconstr c, pc
328+ of AconstrX :
329+ analyseArrayConstr c, pc
330+ of TupconstrX :
331+ analyseTupConstr c, pc
244332 else :
245333 inc nested
246334 inc pc
@@ -265,6 +353,7 @@ proc analyseCallArgs(c: var Context; n: var Cursor) =
265353 elif pk == VarargsT :
266354 # do not advance formal parameter:
267355 fnType = previousFormalParam
356+ checkNilMatch c, n, param.typ
268357 analyseExpr c, n
269358 while fnType.kind != ParRi : skip fnType
270359 inc fnType # skip ParRi
@@ -493,6 +582,7 @@ proc addAsgnFact(c: var Context; fact: LeXplusC) =
493582
494583proc analyseAsgn (c: var Context ; pc: var Cursor ) =
495584 inc pc # skip asgn instruction
585+ let expected = getType (c.typeCache, pc)
496586 if pc.kind == Symbol :
497587 let symId = pc.symId
498588 let x = getLocalInfo (c.typeCache, symId)
@@ -504,6 +594,7 @@ proc analyseAsgn(c: var Context; pc: var Cursor) =
504594 c.writesTo.add symId
505595 # after `x = 4` we know two facts: `x >= 4` and `x <= 4`
506596 inc pc
597+ checkNilMatch c, pc, expected
507598 if rightHandSide (c, pc, fact):
508599 if fact.a == fact.b:
509600 variableChangedByDiff (c.facts, fact.a, fact.c)
@@ -514,6 +605,7 @@ proc analyseAsgn(c: var Context; pc: var Cursor) =
514605 invalidateFactsAbout (c.facts, fact.a)
515606 else :
516607 analyseExpr c, pc
608+ checkNilMatch c, pc, expected
517609 analyseExpr c, pc
518610 skipParRi pc
519611
0 commit comments