fix #19580; add warning for bare except: clause (#21099)

* fix #19580; add warning for bare except: clause

* fixes some easy ones

* Update doc/manual.md

* fixes docs

* Update changelog.md

* addition

* Apply suggestions from code review

Co-authored-by: Jacek Sieka <arnetheduck@gmail.com>

* Update doc/tut2.md

Co-authored-by: Jacek Sieka <arnetheduck@gmail.com>
This commit is contained in:
ringabout 2022-12-15 13:45:36 +08:00 • committed by GitHub
commit 91ce8c385d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 50 additions and 26 deletions

View file

@ -151,3 +151,4 @@ proc initDefines*(symbols: StringTableRef) =
defineSymbol("nimHasWarnUnnamedBreak")
defineSymbol("nimHasGenericDefine")
defineSymbol("nimHasDefineAliases")
defineSymbol("nimHasWarnBareExcept")

View file

@ -1746,7 +1746,7 @@ proc commandJson*(cache: IdentCache, conf: ConfigRef) =
let filename = getOutFile(conf, RelativeFile conf.projectName, JsonExt)
try:
writeFile(filename, content)
except:
except IOError:
rawMessage(conf, errCannotOpenFile, filename.string)
proc commandTags*(cache: IdentCache, conf: ConfigRef) =
@ -1768,7 +1768,7 @@ proc commandTags*(cache: IdentCache, conf: ConfigRef) =
let filename = getOutFile(conf, RelativeFile conf.projectName, TagsExt)
try:
writeFile(filename, content)
except:
except IOError:
rawMessage(conf, errCannotOpenFile, filename.string)
proc commandBuildIndex*(conf: ConfigRef, dir: string, outFile = RelativeFile"") =
@ -1789,7 +1789,7 @@ proc commandBuildIndex*(conf: ConfigRef, dir: string, outFile = RelativeFile"")
try:
writeFile(filename, code)
except:
except IOError:
rawMessage(conf, errCannotOpenFile, filename.string)
proc commandBuildIndexJson*(conf: ConfigRef, dir: string, outFile = RelativeFile"") =
@ -1803,5 +1803,5 @@ proc commandBuildIndexJson*(conf: ConfigRef, dir: string, outFile = RelativeFile
try:
writeFile(filename, $body)
except:
except IOError:
rawMessage(conf, errCannotOpenFile, filename.string)

View file

@ -528,7 +528,7 @@ proc ccHasSaneOverflow*(conf: ConfigRef): bool =
var exe = getConfigVar(conf, conf.cCompiler, ".exe")
if exe.len == 0: exe = CC[conf.cCompiler].compilerExe
# NOTE: should we need the full version, use -dumpfullversion
let (s, exitCode) = try: execCmdEx(exe & " -dumpversion") except: ("", 1)
let (s, exitCode) = try: execCmdEx(exe & " -dumpversion") except IOError, OSError, ValueError: ("", 1)
if exitCode == 0:
var major: int
discard parseInt(s, major)
@ -1018,7 +1018,7 @@ proc changeDetectedViaJsonBuildInstructions*(conf: ConfigRef; jsonFile: Absolute
proc runJsonBuildInstructions*(conf: ConfigRef; jsonFile: AbsoluteFile) =
var bcache: BuildCache
try: bcache.fromJson(jsonFile.string.parseFile)
except:
except ValueError, KeyError, JsonKindError:
let e = getCurrentException()
conf.quitOrRaise "\ncaught exception:\n$#\nstacktrace:\n$#error evaluating JSON file: $#" %
[e.msg, e.getStackTrace(), jsonFile.string]

View file

@ -86,6 +86,7 @@ type
warnImplicitTemplateRedefinition = "ImplicitTemplateRedefinition",
warnUnnamedBreak = "UnnamedBreak",
warnStmtListLambda = "StmtListLambda",
warnBareExcept = "BareExcept",
warnUser = "User",
# hints
hintSuccess = "Success", hintSuccessX = "SuccessX",
@ -185,6 +186,7 @@ const
warnImplicitTemplateRedefinition: "template '$1' is implicitly redefined; this is deprecated, add an explicit .redefine pragma",
warnUnnamedBreak: "Using an unnamed break in a block is deprecated; Use a named block with a named break instead",
warnStmtListLambda: "statement list expression assumed to be anonymous proc; this is deprecated, use `do (): ...` or `proc () = ...` instead",
warnBareExcept: "$1",
warnUser: "$1",
hintSuccess: "operation successful: $#",
# keep in sync with `testament.isSuccess`

View file

@ -38,3 +38,7 @@ define:useStdoutAsStdmsg
@if nimHasWarnUnnamedBreak:
warningAserror[UnnamedBreak]:on
@end
@if nimHasWarnBareExcept:
warningAserror[BareExcept]:on
@end

View file

@ -210,6 +210,8 @@ proc semTry(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil)
isImported = true
elif not isException(typ):
localError(c.config, typeNode.info, errExprCannotBeRaised)
elif not isDefectOrCatchableError(typ):
message(c.config, a.info, warnBareExcept, "catch a more precise Exception deriving from CatchableError or Defect.")
if containsOrIncl(check, typ.id):
localError(c.config, typeNode.info, errExceptionAlreadyHandled)
@ -251,7 +253,8 @@ proc semTry(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil)
elif a.len == 1:
# count number of ``except: body`` blocks
inc catchAllExcepts
message(c.config, a.info, warnBareExcept,
"The bare except clause is deprecated; use `except CatchableError:` instead")
else:
# support ``except KeyError, ValueError, ... : body``
if catchAllExcepts > 0:

View file

@ -1721,6 +1721,18 @@ proc isDefectException*(t: PType): bool =
t = skipTypes(t[0], abstractPtrs)
return false
proc isDefectOrCatchableError*(t: PType): bool =
var t = t.skipTypes(abstractPtrs)
while t.kind == tyObject:
if t.sym != nil and t.sym.owner != nil and
sfSystemModule in t.sym.owner.flags and
(t.sym.name.s == "Defect" or
t.sym.name.s == "CatchableError"):
return true
if t[0] == nil: break
t = skipTypes(t[0], abstractPtrs)
return false
proc isSinkTypeForParam*(t: PType): bool =
# a parameter like 'seq[owned T]' must not be used only once, but its
# elements must, so we detect this case here: