Skip to content

Commit

Permalink
Perform nil checks during object construction and within compiles()
Browse files Browse the repository at this point in the history
Close #6494
  • Loading branch information
zah authored and Araq committed Apr 1, 2020
1 parent 7b7e42b commit 4f3d309
Show file tree
Hide file tree
Showing 4 changed files with 10 additions and 7 deletions.
2 changes: 1 addition & 1 deletion compiler/sem.nim
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
result = buildEchoStmt(c, result)
if c.config.cmd == cmdIdeTools:
appendToModule(c.module, result)
trackTopLevelStmt(c, c.module, result)
trackStmt(c, c.module, result, isTopLevel = true)

proc recoverContext(c: PContext) =
# clean up in case of a semantic error: We clean up the stacks, etc. This is
Expand Down
5 changes: 4 additions & 1 deletion compiler/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2082,7 +2082,10 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
var err: string
try:
result = semExpr(c, n, flags)
if c.config.errorCounter != oldErrorCount: result = nil
if result != nil:
trackStmt(c, c.module, result, isTopLevel = false)
if c.config.errorCounter != oldErrorCount:
result = nil
except ERecoverableError:
discard
# undo symbol table changes (as far as it's possible):
Expand Down
5 changes: 3 additions & 2 deletions compiler/sempass2.nim
Original file line number Diff line number Diff line change
Expand Up @@ -996,6 +996,7 @@ proc track(tracked: PEffects, n: PNode) =
createTypeBoundOps(tracked, x[1].typ, n.info)

if x.kind == nkExprColonExpr:
notNilCheck(tracked, x[1], x[0].sym.typ)
checkForSink(tracked.config, tracked.owner, x[1])
else:
checkForSink(tracked.config, tracked.owner, x)
Expand Down Expand Up @@ -1260,13 +1261,13 @@ proc trackProc*(c: PContext; s: PSym, body: PNode) =
dataflowAnalysis(s, body)
when false: trackWrites(s, body)

proc trackTopLevelStmt*(c: PContext; module: PSym; n: PNode) =
proc trackStmt*(c: PContext; module: PSym; n: PNode, isTopLevel: bool) =
if n.kind in {nkPragma, nkMacroDef, nkTemplateDef, nkProcDef, nkFuncDef,
nkTypeSection, nkConverterDef, nkMethodDef, nkIteratorDef}:
return
let g = c.graph
var effects = newNode(nkEffectList, n.info)
var t: TEffects
initEffects(g, effects, module, t, c)
t.isTopLevel = true
t.isTopLevel = isTopLevel
track(t, n)
5 changes: 2 additions & 3 deletions tests/constructors/tinvalid_construction.nim
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ type

var x = D
var nilRef: TRefObj
var notNilRef = TRefObj(x: 20)
let notNilRef = TRefObjNotNil(x: 20)

proc makeHasNotNils: ref THasNotNils =
(ref THasNotNils)(a: TRefObj(x: 10),
Expand All @@ -102,8 +102,7 @@ reject TObj(a: 10, f: "") # conflicting fields
accept TObj(choice: E, e1: TRefObj(x: 10), e2: 10)

accept THasNotNils(a: notNilRef, b: notNilRef, c: nilRef)
# XXX: the "not nil" logic in the compiler is not strong enough to catch this one yet:
# reject THasNotNils(a: notNilRef, b: nilRef, c: nilRef)
reject THasNotNils(a: notNilRef, b: nilRef, c: nilRef) # `b` shouldn't be nil
reject THasNotNils(b: notNilRef, c: notNilRef) # there is a missing not nil field
reject THasNotNils() # again, missing fields
accept THasNotNils(a: notNilRef, b: notNilRef) # it's OK to omit a non-mandatory field
Expand Down

0 comments on commit 4f3d309

Please sign in to comment.