This commit is contained in:
Andreas Rumpf 2017-03-26 09:30:59 +02:00 • committed by GitHub
commit 1268ca79e5
6 changed files with 26 additions and 9 deletions

View file

@ -229,6 +229,7 @@ proc genDispatcher(methods: TSymSeq, relevantCols: IntSet): PSym =
var base = lastSon(methods[0].ast).sym var base = lastSon(methods[0].ast).sym
result = base result = base
var paramLen = sonsLen(base.typ) var paramLen = sonsLen(base.typ)
var nilchecks = newNodeI(nkStmtList, base.info)
var disp = newNodeI(nkIfStmt, base.info) var disp = newNodeI(nkIfStmt, base.info)
var ands = getSysSym("and") var ands = getSysSym("and")
var iss = getSysSym("of") var iss = getSysSym("of")
@ -239,7 +240,11 @@ proc genDispatcher(methods: TSymSeq, relevantCols: IntSet): PSym =
if contains(relevantCols, col): if contains(relevantCols, col):
var isn = newNodeIT(nkCall, base.info, getSysType(tyBool)) var isn = newNodeIT(nkCall, base.info, getSysType(tyBool))
addSon(isn, newSymNode(iss)) addSon(isn, newSymNode(iss))
addSon(isn, newSymNode(base.typ.n.sons[col].sym)) let param = base.typ.n.sons[col].sym
addSon(isn, newSymNode(param))
if param.typ.skipTypes(abstractInst).kind in {tyRef, tyPtr}:
addSon(nilchecks, newTree(nkCall,
newSymNode(getCompilerProc"chckNilDisp"), newSymNode(param)))
addSon(isn, newNodeIT(nkType, base.info, curr.typ.sons[col])) addSon(isn, newNodeIT(nkType, base.info, curr.typ.sons[col]))
if cond != nil: if cond != nil:
var a = newNodeIT(nkCall, base.info, getSysType(tyBool)) var a = newNodeIT(nkCall, base.info, getSysType(tyBool))
@ -270,7 +275,8 @@ proc genDispatcher(methods: TSymSeq, relevantCols: IntSet): PSym =
addSon(disp, a) addSon(disp, a)
else: else:
disp = ret disp = ret
result.ast.sons[bodyPos] = disp nilchecks.add disp
result.ast.sons[bodyPos] = nilchecks
proc generateMethodDispatchers*(g: ModuleGraph): PNode = proc generateMethodDispatchers*(g: ModuleGraph): PNode =
result = newNode(nkStmtList) result = newNode(nkStmtList)

View file

@ -13,10 +13,6 @@
## ##
## Tested on these OSes: Linux, Windows, OSX ## Tested on these OSes: Linux, Windows, OSX
type
NilAccessError* = object of SystemError ## \
## Raised on dereferences of ``nil`` pointers.
# do allocate memory upfront: # do allocate memory upfront:
var se: ref NilAccessError var se: ref NilAccessError
new(se) new(se)

View file

@ -558,6 +558,10 @@ type
## Raised if it is attempted to send a message to a dead thread. ## Raised if it is attempted to send a message to a dead thread.
## ##
## See the full `exception hierarchy <manual.html#exception-handling-exception-hierarchy>`_. ## See the full `exception hierarchy <manual.html#exception-handling-exception-hierarchy>`_.
NilAccessError* = object of SystemError ## \
## Raised on dereferences of ``nil`` pointers.
##
## This is only raised if the ``segfaults.nim`` module was imported!
{.deprecated: [TObject: RootObj, PObject: RootRef, TEffect: RootEffect, {.deprecated: [TObject: RootObj, PObject: RootRef, TEffect: RootEffect,
FTime: TimeEffect, FIO: IOEffect, FReadIO: ReadIOEffect, FTime: TimeEffect, FIO: IOEffect, FReadIO: ReadIOEffect,
@ -2467,8 +2471,8 @@ template accumulateResult*(iter: untyped) =
const NimStackTrace = compileOption("stacktrace") const NimStackTrace = compileOption("stacktrace")
template coroutinesSupportedPlatform(): bool = template coroutinesSupportedPlatform(): bool =
when defined(sparc) or defined(ELATE) or compileOption("gc", "v2") or when defined(sparc) or defined(ELATE) or compileOption("gc", "v2") or
defined(boehmgc) or defined(gogc) or defined(nogc) or defined(gcStack) or defined(boehmgc) or defined(gogc) or defined(nogc) or defined(gcStack) or
defined(gcMarkAndSweep): defined(gcMarkAndSweep):
false false
else: else:

View file

@ -50,7 +50,11 @@ proc chckRangeF(x, a, b: float): float =
proc chckNil(p: pointer) = proc chckNil(p: pointer) =
if p == nil: if p == nil:
sysFatal(ValueError, "attempt to write to a nil address") sysFatal(NilAccessError, "attempt to write to a nil address")
proc chckNilDisp(p: pointer) {.compilerproc.} =
if p == nil:
sysFatal(NilAccessError, "cannot dispatch; dispatcher is nil")
proc chckObj(obj, subclass: PNimType) {.compilerproc.} = proc chckObj(obj, subclass: PNimType) {.compilerproc.} =
# checks if obj is of type subclass: # checks if obj is of type subclass:

View file

@ -642,6 +642,10 @@ proc toU32*(a: int64): int32 {.asmNoStackFrame, compilerproc.} =
proc nimMin(a, b: int): int {.compilerproc.} = return if a <= b: a else: b proc nimMin(a, b: int): int {.compilerproc.} = return if a <= b: a else: b
proc nimMax(a, b: int): int {.compilerproc.} = return if a >= b: a else: b proc nimMax(a, b: int): int {.compilerproc.} = return if a >= b: a else: b
proc chckNilDisp(p: pointer) {.compilerproc.} =
if p == nil:
sysFatal(NilAccessError, "cannot dispatch; dispatcher is nil")
type NimString = string # hack for hti.nim type NimString = string # hack for hti.nim
include "system/hti" include "system/hti"

View file

@ -42,6 +42,9 @@ Changes affecting backwards compatibility
AST that is the same as what is used to define an enum. Previously the AST AST that is the same as what is used to define an enum. Previously the AST
returned had a repeated ``EnumTy`` node and was missing the initial pragma returned had a repeated ``EnumTy`` node and was missing the initial pragma
node (which is currently empty for an enum). node (which is currently empty for an enum).
- If the dispatcher parameter's value used in multi method is ``nil``,
a ``NilError`` exception is raised. The old behavior was that the method
would be a ``nop`` then.
Library Additions Library Additions