mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-11 22:08:54 +00:00
give hint for forward declarations with unknown raises effects (#24767)
refs #24766 Detect when we track a call to a forward declaration without explicit `raises` effects, then when the `raises` check fails for the proc, give a hint that this forward declaration was tracked as potentially raising any exception.
This commit is contained in:
@@ -110,6 +110,7 @@ type
|
||||
hintSource = "Source", hintPerformance = "Performance", hintStackTrace = "StackTrace",
|
||||
hintGCStats = "GCStats", hintGlobalVar = "GlobalVar", hintExpandMacro = "ExpandMacro",
|
||||
hintUser = "User", hintUserRaw = "UserRaw", hintExtendedContext = "ExtendedContext",
|
||||
hintUnknownRaises = "UnknownRaises",
|
||||
hintMsgOrigin = "MsgOrigin", # since 1.3.5
|
||||
hintDeclaredLoc = "DeclaredLoc", # since 1.5.1
|
||||
|
||||
@@ -236,6 +237,7 @@ const
|
||||
hintUser: "$1",
|
||||
hintUserRaw: "$1",
|
||||
hintExtendedContext: "$1",
|
||||
hintUnknownRaises: "$1 is a forward declaration without explicit .raises, assuming it can raise anything",
|
||||
hintMsgOrigin: "$1",
|
||||
hintDeclaredLoc: "$1"
|
||||
]
|
||||
|
||||
@@ -84,6 +84,7 @@ type
|
||||
gcUnsafe, isRecursive, isTopLevel, hasSideEffect, inEnforcedGcSafe: bool
|
||||
isInnerProc: bool
|
||||
inEnforcedNoSideEffects: bool
|
||||
unknownRaises: seq[(PSym, TLineInfo)]
|
||||
currOptions: TOptions
|
||||
optionsStack: seq[(TOptions, TNoteKinds)]
|
||||
config: ConfigRef
|
||||
@@ -639,6 +640,8 @@ proc importedFromC(n: PNode): bool =
|
||||
proc propagateEffects(tracked: PEffects, n: PNode, s: PSym) =
|
||||
let pragma = s.ast[pragmasPos]
|
||||
let spec = effectSpec(pragma, wRaises)
|
||||
if spec.isNil and sfForward in s.flags:
|
||||
tracked.unknownRaises.add (s, n.info)
|
||||
mergeRaises(tracked, spec, n)
|
||||
|
||||
let tagSpec = effectSpec(pragma, wTags)
|
||||
@@ -1506,7 +1509,7 @@ proc subtypeRelation(g: ModuleGraph; spec, real: PNode): bool =
|
||||
|
||||
proc checkRaisesSpec(g: ModuleGraph; emitWarnings: bool; spec, real: PNode, msg: string, hints: bool;
|
||||
effectPredicate: proc (g: ModuleGraph; a, b: PNode): bool {.nimcall.};
|
||||
hintsArg: PNode = nil; isForbids: bool = false) =
|
||||
hintsArg: PNode = nil; isForbids: bool = false; unknownRaises: seq[(PSym, TLineInfo)] = @[]) =
|
||||
# check that any real exception is listed in 'spec'; mark those as used;
|
||||
# report any unused exception
|
||||
var used = initIntSet()
|
||||
@@ -1523,6 +1526,8 @@ proc checkRaisesSpec(g: ModuleGraph; emitWarnings: bool; spec, real: PNode, msg:
|
||||
pushInfoContext(g.config, spec.info)
|
||||
var rr = if r.kind == nkRaiseStmt: r[0] else: r
|
||||
while rr.kind in {nkStmtList, nkStmtListExpr} and rr.len > 0: rr = rr.lastSon
|
||||
for (s, info) in unknownRaises.items:
|
||||
message(g.config, info, hintUnknownRaises, s.name.s)
|
||||
message(g.config, r.info, if emitWarnings: warnEffect else: errGenerated,
|
||||
renderTree(rr) & " " & msg & typeToString(r.typ))
|
||||
popInfoContext(g.config)
|
||||
@@ -1680,7 +1685,7 @@ proc trackProc*(c: PContext; s: PSym, body: PNode) =
|
||||
if not isNil(raisesSpec):
|
||||
let useWarning = s.name.s == "=destroy"
|
||||
checkRaisesSpec(g, useWarning, raisesSpec, t.exc, "can raise an unlisted exception: ",
|
||||
hints=on, subtypeRelation, hintsArg=s.ast[0])
|
||||
hints=on, subtypeRelation, hintsArg=s.ast[0], unknownRaises = t.unknownRaises)
|
||||
# after the check, use the formal spec:
|
||||
effects[exceptionEffects] = raisesSpec
|
||||
else:
|
||||
|
||||
17
tests/errmsgs/tforwardraises.nim
Normal file
17
tests/errmsgs/tforwardraises.nim
Normal file
@@ -0,0 +1,17 @@
|
||||
discard """
|
||||
action: reject
|
||||
nimout: '''
|
||||
tforwardraises.nim(15, 14) Hint: n is a forward declaration without explicit .raises, assuming it can raise anything [UnknownRaises]
|
||||
tforwardraises.nim(14, 26) template/generic instantiation from here
|
||||
tforwardraises.nim(15, 14) Error: n(0) can raise an unlisted exception: Exception
|
||||
'''
|
||||
"""
|
||||
|
||||
# issue #24766
|
||||
|
||||
proc n(_: int)
|
||||
|
||||
proc s(_: int) {.raises: [CatchableError].} =
|
||||
if false: n(0)
|
||||
|
||||
proc n(_: int) = s(0)
|
||||
Reference in New Issue
Block a user