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 ## Compiler changes
- Specific warnings can now be turned into errors via `--warningAsError[X]:on|off`.
## Tool changes ## Tool changes

View file

@ -209,12 +209,18 @@ proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass,
incl(conf.modifiedyNotes, n) incl(conf.modifiedyNotes, n)
case val case val
of "on": of "on":
incl(conf.notes, n) if state == wWarningAsError:
incl(conf.mainPackageNotes, n) incl(conf.warningAsErrors, n)
else:
incl(conf.notes, n)
incl(conf.mainPackageNotes, n)
of "off": of "off":
excl(conf.notes, n) if state == wWarningAsError:
excl(conf.mainPackageNotes, n) excl(conf.warningAsErrors, n)
excl(conf.foreignPackageNotes, n) else:
excl(conf.notes, n)
excl(conf.mainPackageNotes, n)
excl(conf.foreignPackageNotes, n)
proc processCompile(conf: ConfigRef; filename: string) = proc processCompile(conf: ConfigRef; filename: string) =
var found = findFile(conf, filename) 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) if processOnOffSwitchOrList(conf, {optWarns}, arg, pass, info): listWarnings(conf)
of "warning": processSpecificNote(arg, wWarning, pass, info, switch, conf) of "warning": processSpecificNote(arg, wWarning, pass, info, switch, conf)
of "hint": processSpecificNote(arg, wHint, pass, info, switch, conf) of "hint": processSpecificNote(arg, wHint, pass, info, switch, conf)
of "warningaserror": processSpecificNote(arg, wWarningAsError, pass, info, switch, conf)
of "hints": of "hints":
if processOnOffSwitchOrList(conf, {optHints}, arg, pass, info): listHints(conf) if processOnOffSwitchOrList(conf, {optHints}, arg, pass, info): listHints(conf)
of "threadanalysis": processOnOffSwitchG(conf, {optThreadAnalysis}, arg, pass, info) 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 msg >= fatalMin and msg <= fatalMax:
if conf.cmd == cmdIdeTools: log(s) if conf.cmd == cmdIdeTools: log(s)
quit(conf, msg) 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) inc(conf.errorCounter)
conf.exitcode = 1'i8 conf.exitcode = 1'i8
if conf.errorCounter >= conf.errorMax: if conf.errorCounter >= conf.errorMax:
@ -412,7 +413,7 @@ proc rawMessage*(conf: ConfigRef; msg: TMsgKind, args: openArray[string]) =
sev = Severity.Warning sev = Severity.Warning
if not conf.hasWarn(msg): return if not conf.hasWarn(msg): return
writeContext(conf, unknownLineInfo) writeContext(conf, unknownLineInfo)
title = WarningTitle title = if msg in conf.warningAsErrors: ErrorTitle else: WarningTitle
color = WarningColor color = WarningColor
kind = WarningsToStr[ord(msg) - ord(warnMin)] kind = WarningsToStr[ord(msg) - ord(warnMin)]
inc(conf.warnCounter) inc(conf.warnCounter)
@ -500,7 +501,7 @@ proc liMessage(conf: ConfigRef; info: TLineInfo, msg: TMsgKind, arg: string,
sev = Severity.Warning sev = Severity.Warning
ignoreMsg = not conf.hasWarn(msg) ignoreMsg = not conf.hasWarn(msg)
if not ignoreMsg: writeContext(conf, info) if not ignoreMsg: writeContext(conf, info)
title = WarningTitle title = if msg in conf.warningAsErrors: ErrorTitle else: WarningTitle
color = WarningColor color = WarningColor
kind = WarningsToStr[ord(msg) - ord(warnMin)] kind = WarningsToStr[ord(msg) - ord(warnMin)]
inc(conf.warnCounter) inc(conf.warnCounter)

View file

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

View file

@ -330,31 +330,28 @@ proc processDynLib(c: PContext, n: PNode, sym: PSym) =
sym.typ.callConv = ccCDecl sym.typ.callConv = ccCDecl
proc processNote(c: PContext, n: PNode) = 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 if n.kind in nkPragmaCallKinds and n.len == 2 and
n[0].kind == nkBracketExpr and n[0].kind == nkBracketExpr and
n[0].len == 2 and n[0].len == 2 and
n[0][1].kind == nkIdent and n[0][0].kind == nkIdent: n[0][1].kind == nkIdent and n[0][0].kind == nkIdent:
var nk: TNoteKind var nk: TNoteKind
case whichKeyword(n[0][0].ident) case whichKeyword(n[0][0].ident)
of wHint: of wHint: handleNote(HintsToStr, hintMin, c.config.notes)
var x = findStr(HintsToStr, n[0][1].ident.s) of wWarning: handleNote(WarningsToStr, warnMin, c.config.notes)
if x >= 0: nk = TNoteKind(x + ord(hintMin)) of wWarningAsError: handleNote(WarningsToStr, warnMin, c.config.warningAsErrors)
else: invalidPragma(c, n); return else: invalidPragma(c, n)
of wWarning: else: invalidPragma(c, n)
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)
proc pragmaToOptions(w: TSpecialWord): TOptions {.inline.} = proc pragmaToOptions(w: TSpecialWord): TOptions {.inline.} =
case w case w

View file

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

View file

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

View file

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