mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
implements {.gcsafe.} enforcement as a pragma block
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user