implements {.gcsafe.} enforcement as a pragma block

This commit is contained in:
Andreas Rumpf
2017-01-18 12:55:33 +01:00
parent b6b5a11be7
commit 2f08fdf623
3 changed files with 27 additions and 16 deletions

View File

@@ -38,7 +38,7 @@ const
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
wTags, wLocks, wGcSafe, wExportNims}
exprPragmas* = {wLine, wLocks, wNoRewrite}
exprPragmas* = {wLine, wLocks, wNoRewrite, wGcSafe}
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks,
wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError,
@@ -775,9 +775,12 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
if sym.typ.callConv == ccClosure: sym.typ.callConv = ccDefault
of wGcSafe:
noVal(it)
if sym.kind != skType: incl(sym.flags, sfThread)
if sym.typ != nil: incl(sym.typ.flags, tfGcSafe)
else: invalidPragma(it)
if sym != nil:
if sym.kind != skType: incl(sym.flags, sfThread)
if sym.typ != nil: incl(sym.typ.flags, tfGcSafe)
else: invalidPragma(it)
else:
discard "no checking if used as a code block"
of wPacked:
noVal(it)
if sym.typ == nil: invalidPragma(it)

View File

@@ -59,7 +59,7 @@ type
init: seq[int] # list of initialized variables
guards: TModel # nested guards
locked: seq[PNode] # locked locations
gcUnsafe, isRecursive, isToplevel, hasSideEffect: bool
gcUnsafe, isRecursive, isToplevel, hasSideEffect, inEnforcedGcSafe: bool
maxLockLevel, currLockLevel: TLockLevel
PEffects = var TEffects
@@ -180,17 +180,19 @@ proc warnAboutGcUnsafe(n: PNode) =
message(n.info, warnGcUnsafe, renderTree(n))
proc markGcUnsafe(a: PEffects; reason: PSym) =
a.gcUnsafe = true
if a.owner.kind in routineKinds: a.owner.gcUnsafetyReason = reason
if not a.inEnforcedGcSafe:
a.gcUnsafe = true
if a.owner.kind in routineKinds: a.owner.gcUnsafetyReason = reason
proc markGcUnsafe(a: PEffects; reason: PNode) =
a.gcUnsafe = true
if a.owner.kind in routineKinds:
if reason.kind == nkSym:
a.owner.gcUnsafetyReason = reason.sym
else:
a.owner.gcUnsafetyReason = newSym(skUnknown, getIdent("<unknown>"),
a.owner, reason.info)
if not a.inEnforcedGcSafe:
a.gcUnsafe = true
if a.owner.kind in routineKinds:
if reason.kind == nkSym:
a.owner.gcUnsafetyReason = reason.sym
else:
a.owner.gcUnsafetyReason = newSym(skUnknown, getIdent("<unknown>"),
a.owner, reason.info)
when true:
template markSideEffect(a: PEffects; reason: typed) =
@@ -803,10 +805,16 @@ proc track(tracked: PEffects, n: PNode) =
let pragmaList = n.sons[0]
let oldLocked = tracked.locked.len
let oldLockLevel = tracked.currLockLevel
var enforcedGcSafety = false
for i in 0 .. <pragmaList.len:
if whichPragma(pragmaList.sons[i]) == wLocks:
let pragma = whichPragma(pragmaList.sons[i])
if pragma == wLocks:
lockLocations(tracked, pragmaList.sons[i])
elif pragma == wGcSafe:
enforcedGcSafety = true
if enforcedGcSafety: tracked.inEnforcedGcSafe = true
track(tracked, n.lastSon)
if enforcedGcSafety: tracked.inEnforcedGcSafe = false
setLen(tracked.locked, oldLocked)
tracked.currLockLevel = oldLockLevel
of nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef,

View File

@@ -1444,7 +1444,7 @@ proc semPragmaBlock(c: PContext, n: PNode): PNode =
for i in 0 .. <pragmaList.len:
case whichPragma(pragmaList.sons[i])
of wLine: setLine(result, pragmaList.sons[i].info)
of wLocks:
of wLocks, wGcSafe:
result = n
result.typ = n.sons[1].typ
of wNoRewrite: