From b8ce3a41753fa3aeeeee1e91401e9909d63cfbe7 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 12 Aug 2014 08:47:31 +0200 Subject: fixes 'gcsafe' --- compiler/astalgo.nim | 11 +++++++++++ compiler/options.nim | 2 +- compiler/sempass2.nim | 29 +++++++++++++++++------------ lib/system.nim | 12 ++++++------ tests/effects/teffects1.nim | 2 +- tests/effects/tgcsafe.nim | 16 ++++++++++++++++ todo.txt | 2 -- web/news.txt | 4 ++++ 8 files changed, 56 insertions(+), 22 deletions(-) create mode 100644 tests/effects/tgcsafe.nim diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index dbf13f764..3431aaf41 100644 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -124,6 +124,17 @@ proc skipConv*(n: PNode): PNode = result = n.sons[1] else: result = n +proc skipConvAndClosure*(n: PNode): PNode = + result = n + while true: + case result.kind + of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64, + nkClosure: + result = result.sons[0] + of nkHiddenStdConv, nkHiddenSubConv, nkConv: + result = result.sons[1] + else: break + proc skipConvTakeType*(n: PNode): PNode = result = n.skipConv result.typ = n.typ diff --git a/compiler/options.nim b/compiler/options.nim index 58a340d21..02719cacc 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -95,7 +95,7 @@ var optBoundsCheck, optOverflowCheck, optAssert, optWarns, optHints, optStackTrace, optLineTrace, optPatterns, optNilCheck} - gGlobalOptions*: TGlobalOptions = {} + gGlobalOptions*: TGlobalOptions = {optThreadAnalysis} gExitcode*: int8 gCmd*: TCommands = cmdNone # the command gSelectedGC* = gcRefc # the selected GC diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index c8ce5e787..acc2425f1 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -115,7 +115,7 @@ proc useVar(a: PEffects, n: PNode) = a.addUse(copyNode(n)) if (tfHasGCedMem in s.typ.flags or s.typ.isGCedMem) and tfGcSafe notin s.typ.flags: - message(n.info, warnGcUnsafe, renderTree(n)) + if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n)) a.gcUnsafe = true type @@ -332,7 +332,7 @@ proc propagateEffects(tracked: PEffects, n: PNode, s: PSym) = mergeTags(tracked, tagSpec, n) if notGcSafe(s.typ) and sfImportc notin s.flags: - message(n.info, warnGcUnsafe, renderTree(n)) + if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n)) tracked.gcUnsafe = true when trackGlobals: @@ -358,7 +358,7 @@ proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) = of impYes: discard proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) = - let op = n.typ + let op = skipConvAndClosure(n).typ if op != nil and op.kind == tyProc and n.kind != nkNilLit: internalAssert op.n.sons[0].kind == nkEffectList var effectList = op.n.sons[0] @@ -367,21 +367,24 @@ proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) = propagateEffects(tracked, n, s.sym) elif effectList.len == 0: if isForwardedProc(n): + # we have no explicit effects but it's a forward declaration and so it's + # stated there are no additional effects, so simply propagate them: propagateEffects(tracked, n, n.sym) else: + # we have no explicit effects so assume the worst: addEffect(tracked, createRaise(n)) addTag(tracked, createTag(n)) when trackGlobals: addUse(tracked, createAnyGlobal(n)) - # assume GcUnsafe unless in its type: - if notGcSafe(op): - message(n.info, warnGcUnsafe, renderTree(n)) + # assume GcUnsafe unless in its type; 'forward' does not matter: + if notGcSafe(op): + if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n)) tracked.gcUnsafe = true else: mergeEffects(tracked, effectList.sons[exceptionEffects], n) mergeTags(tracked, effectList.sons[tagEffects], n) when trackGlobals: mergeUses(tracked, effectList.sons[usesEffects], n) if notGcSafe(op): - message(n.info, warnGcUnsafe, renderTree(n)) + if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n)) tracked.gcUnsafe = true notNilCheck(tracked, n, paramType) @@ -510,9 +513,6 @@ proc track(tracked: PEffects, n: PNode) = if op != nil and op.kind == tyProc and op.n.sons[0].kind == nkEffectList: if a.kind == nkSym and a.sym == tracked.owner: tracked.isRecursive = true - elif notGcSafe(op) and not importedFromC(a): - message(n.info, warnGcUnsafe, renderTree(n)) - tracked.gcUnsafe = true var effectList = op.n.sons[0] if a.kind == nkSym and a.sym.kind == skMethod: propagateEffects(tracked, n, a.sym) @@ -528,6 +528,11 @@ proc track(tracked: PEffects, n: PNode) = mergeEffects(tracked, effectList.sons[exceptionEffects], n) mergeTags(tracked, effectList.sons[tagEffects], n) when trackGlobals: mergeUses(tracked, effectList.sons[usesEffects], n) + if notGcSafe(op) and not importedFromC(a): + # and it's not a recursive call: + if not (a.kind == nkSym and a.sym == tracked.owner): + message(n.info, warnGcUnsafe, renderTree(n)) + tracked.gcUnsafe = true for i in 1 ..