new feature: ability to turn specific warnings to errors

This commit is contained in:
Andreas Rumpf 2020-04-04 22:56:03 +02:00
commit 9c46927fad
8 changed files with 43 additions and 29 deletions

View file

@ -10,6 +10,7 @@
## Compiler changes
- Specific warnings can now be turned into errors via `--warningAsError[X]:on|off`.
## Tool changes

View file

@ -209,12 +209,18 @@ proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass,
incl(conf.modifiedyNotes, n)
case val
of "on":
incl(conf.notes, n)
incl(conf.mainPackageNotes, n)
if state == wWarningAsError:
incl(conf.warningAsErrors, n)
else:
incl(conf.notes, n)
incl(conf.mainPackageNotes, n)
of "off":
excl(conf.notes, n)
excl(conf.mainPackageNotes, n)
excl(conf.foreignPackageNotes, n)
if state == wWarningAsError:
excl(conf.warningAsErrors, n)
else:
excl(conf.notes, n)
excl(conf.mainPackageNotes, n)
excl(conf.foreignPackageNotes, n)
proc processCompile(conf: ConfigRef; filename: string) =
var found = findFile(conf, filename)
@ -528,6 +534,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
if processOnOffSwitchOrList(conf, {optWarns}, arg, pass, info): listWarnings(conf)
of "warning": processSpecificNote(arg, wWarning, pass, info, switch, conf)
of "hint": processSpecificNote(arg, wHint, pass, info, switch, conf)
of "warningaserror": processSpecificNote(arg, wWarningAsError, pass, info, switch, conf)
of "hints":
if processOnOffSwitchOrList(conf, {optHints}, arg, pass, info): listHints(conf)
of "threadanalysis": processOnOffSwitchG(conf, {optThreadAnalysis}, arg, pass, info)

View file

@ -354,7 +354,8 @@ proc handleError(conf: ConfigRef; msg: TMsgKind, eh: TErrorHandling, s: string)
if msg >= fatalMin and msg <= fatalMax:
if conf.cmd == cmdIdeTools: log(s)
quit(conf, msg)
if msg >= errMin and msg <= errMax:
if msg >= errMin and msg <= errMax or
(msg in warnMin..warnMax and msg in conf.warningAsErrors):
inc(conf.errorCounter)
conf.exitcode = 1'i8
if conf.errorCounter >= conf.errorMax:
@ -412,7 +413,7 @@ proc rawMessage*(conf: ConfigRef; msg: TMsgKind, args: openArray[string]) =
sev = Severity.Warning
if not conf.hasWarn(msg): return
writeContext(conf, unknownLineInfo)
title = WarningTitle
title = if msg in conf.warningAsErrors: ErrorTitle else: WarningTitle
color = WarningColor
kind = WarningsToStr[ord(msg) - ord(warnMin)]
inc(conf.warnCounter)
@ -500,7 +501,7 @@ proc liMessage(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
sev = Severity.Warning
ignoreMsg = not conf.hasWarn(msg)
if not ignoreMsg: writeContext(conf, info)
title = WarningTitle
title = if msg in conf.warningAsErrors: ErrorTitle else: WarningTitle
color = WarningColor
kind = WarningsToStr[ord(msg) - ord(warnMin)]
inc(conf.warnCounter)

View file

@ -237,6 +237,7 @@ type
cmdlineNotes*: TNoteKinds # notes that have been set/unset from cmdline
foreignPackageNotes*: TNoteKinds
notes*: TNoteKinds # notes after resolving all logic(defaults, verbosity)/cmdline/configs
warningAsErrors*: TNoteKinds
mainPackageNotes*: TNoteKinds
mainPackageId*: int
errorCounter*: int

View file

@ -330,31 +330,28 @@ proc processDynLib(c: PContext, n: PNode, sym: PSym) =
sym.typ.callConv = ccCDecl
proc processNote(c: PContext, n: PNode) =
template handleNote(toStrArray, msgMin, notes) =
let x = findStr(toStrArray, n[0][1].ident.s)
if x >= 0:
nk = TNoteKind(x + ord(msgMin))
let x = c.semConstBoolExpr(c, n[1])
n[1] = x
if x.kind == nkIntLit and x.intVal != 0: incl(notes, nk)
else: excl(notes, nk)
else:
invalidPragma(c, n)
if n.kind in nkPragmaCallKinds and n.len == 2 and
n[0].kind == nkBracketExpr and
n[0].len == 2 and
n[0][1].kind == nkIdent and n[0][0].kind == nkIdent:
var nk: TNoteKind
case whichKeyword(n[0][0].ident)
of wHint:
var x = findStr(HintsToStr, n[0][1].ident.s)
if x >= 0: nk = TNoteKind(x + ord(hintMin))
else: invalidPragma(c, n); return
of wWarning:
var x = findStr(WarningsToStr, n[0][1].ident.s)
if x >= 0: nk = TNoteKind(x + ord(warnMin))
else: invalidPragma(c, n); return
else:
invalidPragma(c, n)
return
let x = c.semConstBoolExpr(c, n[1])
n[1] = x
if x.kind == nkIntLit and x.intVal != 0: incl(c.config.notes, nk)
else: excl(c.config.notes, nk)
# checkme: honor cmdlineNotes with: c.setNote(nk, x.kind == nkIntLit and x.intVal != 0)
else:
invalidPragma(c, n)
of wHint: handleNote(HintsToStr, hintMin, c.config.notes)
of wWarning: handleNote(WarningsToStr, warnMin, c.config.notes)
of wWarningAsError: handleNote(WarningsToStr, warnMin, c.config.warningAsErrors)
else: invalidPragma(c, n)
else: invalidPragma(c, n)
proc pragmaToOptions(w: TSpecialWord): TOptions {.inline.} =
case w

View file

@ -21,6 +21,7 @@ type
notes*: TNoteKinds
features*: set[Feature]
otherPragmas*: PNode # every pragma can be pushed
warningAsErrors*: TNoteKinds
POptionEntry* = ref TOptionEntry
PProcCon* = ref TProcCon
@ -213,6 +214,7 @@ proc newOptionEntry*(conf: ConfigRef): POptionEntry =
result.defaultCC = ccDefault
result.dynlib = nil
result.notes = conf.notes
result.warningAsErrors = conf.warningAsErrors
proc pushOptionEntry*(c: PContext): POptionEntry =
new(result)
@ -221,12 +223,14 @@ proc pushOptionEntry*(c: PContext): POptionEntry =
result.defaultCC = prev.defaultCC
result.dynlib = prev.dynlib
result.notes = c.config.notes
result.warningAsErrors = c.config.warningAsErrors
result.features = c.features
c.optionStack.add(result)
proc popOptionEntry*(c: PContext) =
c.config.options = c.optionStack[^1].options
c.config.notes = c.optionStack[^1].notes
c.config.warningAsErrors = c.optionStack[^1].warningAsErrors
c.features = c.optionStack[^1].features
c.optionStack.setLen(c.optionStack.len - 1)

View file

@ -44,7 +44,7 @@ type
wAlign, wNodecl, wPure, wSideEffect, wHeader,
wNoSideEffect, wGcSafe, wNoreturn, wNosinks, wMerge, wLib, wDynlib,
wCompilerProc, wCore, wProcVar, wBase, wUsed,
wFatal, wError, wWarning, wHint, wLine, wPush, wPop, wDefine, wUndef,
wFatal, wError, wWarning, wHint, wWarningAsError, wLine, wPush, wPop, wDefine, wUndef,
wLineDir, wStackTrace, wLineTrace, wLink, wCompile,
wLinksys, wDeprecated, wVarargs, wCallconv, wDebugger,
wNimcall, wStdcall, wCdecl, wSafecall, wSyscall, wInline, wNoInline,
@ -131,7 +131,7 @@ const
"requiresinit", "align", "nodecl", "pure", "sideeffect",
"header", "nosideeffect", "gcsafe", "noreturn", "nosinks", "merge", "lib", "dynlib",
"compilerproc", "core", "procvar", "base", "used",
"fatal", "error", "warning", "hint", "line",
"fatal", "error", "warning", "hint", "warningaserror", "line",
"push", "pop", "define", "undef", "linedir", "stacktrace", "linetrace",
"link", "compile", "linksys", "deprecated", "varargs",
"callconv", "debugger", "nimcall", "stdcall",
@ -212,4 +212,5 @@ proc canonPragmaSpelling*(w: TSpecialWord): string =
of wCodegenDecl: "codegenDecl"
of wLiftLocals: "liftLocals"
of wLocalPassc: "localPassc"
of wWarningAsError: "warningAsError"
else: specialWords[w]

View file

@ -38,6 +38,8 @@ Advanced options:
--warning[X]:on|off turn specific warning X on|off
--hints:on|off|list turn all hints on|off or list all available
--hint[X]:on|off turn specific hint X on|off
--warningAsError[X]:on|off
turn specific warning X into an error on|off
--styleCheck:off|hint|error
produce hints or errors for Nim identifiers that
do not adhere to Nim's official style guide