diff options
-rw-r--r-- | compiler/sempass2.nim | 16 | ||||
-rw-r--r-- | tests/method/t20515.nim | 20 |
2 files changed, 32 insertions, 4 deletions
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 34490f492..42c463cd9 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -259,10 +259,15 @@ proc listGcUnsafety(s: PSym; onlyWarning: bool; cycleCheck: var IntSet; conf: Co of routineKinds: # recursive call *always* produces only a warning so the full error # message is printed: - listGcUnsafety(u, true, cycleCheck, conf) - message(conf, s.info, msgKind, - "'$#' is not GC-safe as it calls '$#'" % - [s.name.s, u.name.s]) + if u.kind == skMethod and {sfBase, sfThread} * u.flags == {sfBase}: + message(conf, u.info, msgKind, + "Base method '$#' requires explicit '{.gcsafe.}' to be GC-safe" % + [u.name.s]) + else: + listGcUnsafety(u, true, cycleCheck, conf) + message(conf, s.info, msgKind, + "'$#' is not GC-safe as it calls '$#'" % + [s.name.s, u.name.s]) of skParam, skForVar: message(conf, s.info, msgKind, "'$#' is not GC-safe as it performs an indirect call via '$#'" % @@ -836,6 +841,9 @@ proc trackCall(tracked: PEffects; n: PNode) = discard var effectList = op.n[0] if a.kind == nkSym and a.sym.kind == skMethod: + if {sfBase, sfThread} * a.sym.flags == {sfBase}: + if tracked.config.hasWarn(warnGcUnsafe): warnAboutGcUnsafe(n, tracked.config) + markGcUnsafe(tracked, a) propagateEffects(tracked, n, a.sym) elif isNoEffectList(effectList): if isForwardedProc(a): diff --git a/tests/method/t20515.nim b/tests/method/t20515.nim new file mode 100644 index 000000000..1921f2e46 --- /dev/null +++ b/tests/method/t20515.nim @@ -0,0 +1,20 @@ +discard """ + errormsg: "Base method 'zzz' requires explicit '{.gcsafe.}' to be GC-safe" + line: 10 +""" + +type + A = ref object of RootObj + B = ref object of A + +method zzz(a: A) {.base.} = + discard + +var s: seq[int] +method zzz(a: B) = + echo s + +proc xxx(someObj: A) {.gcsafe.} = + someObj.zzz() + +xxx(B()) |