diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index a217052082..85e850834a 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -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) diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 8aa8f15c8b..437a458178 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -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(""), - 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(""), + 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 ..