An unnamed break in a block now gives an UnnamedBreak warning (#20901)
* unnamed break in the block now gives an error * bootstrap * fixes * more fixes * break with label * label again * one moee * Delete test5.txt * it now gives a UnnamedBreak warning * change the URL of bump back to the original one
This commit is contained in:
parent
d149727f34
commit
ef29987781
16 changed files with 85 additions and 20 deletions
|
|
@ -148,3 +148,4 @@ proc initDefines*(symbols: StringTableRef) =
|
|||
|
||||
defineSymbol("nimHasOutParams")
|
||||
defineSymbol("nimHasSystemRaisesDefect")
|
||||
defineSymbol("nimHasWarnUnnamedBreak")
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ type
|
|||
warnEffect = "Effect",
|
||||
warnCastSizes = "CastSizes"
|
||||
warnTemplateRedefinition = "TemplateRedefinition",
|
||||
warnUnnamedBreak = "UnnamedBreak",
|
||||
warnUser = "User",
|
||||
# hints
|
||||
hintSuccess = "Success", hintSuccessX = "SuccessX",
|
||||
|
|
@ -181,6 +182,7 @@ const
|
|||
warnEffect: "$1",
|
||||
warnCastSizes: "$1",
|
||||
warnTemplateRedefinition: "template '$1' is implicitly redefined, consider adding an explicit .redefine pragma",
|
||||
warnUnnamedBreak: "Using an unnamed break in a block is deprecated; Use a named block with a named break instead",
|
||||
warnUser: "$1",
|
||||
hintSuccess: "operation successful: $#",
|
||||
# keep in sync with `testament.isSuccess`
|
||||
|
|
|
|||
|
|
@ -27,9 +27,13 @@ define:useStdoutAsStdmsg
|
|||
#gc:markAndSweep
|
||||
|
||||
@if nimHasWarningObservableStores:
|
||||
warning[ObservableStores]: off
|
||||
warning[ObservableStores]:off
|
||||
@end
|
||||
|
||||
@if nimHasWarningAsError:
|
||||
warningAsError:GcUnsafe2:on
|
||||
warningAsError[GcUnsafe2]:on
|
||||
@end
|
||||
|
||||
@if nimHasWarnUnnamedBreak:
|
||||
warningAserror[UnnamedBreak]:on
|
||||
@end
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ type
|
|||
resultSym*: PSym # the result symbol (if we are in a proc)
|
||||
nestedLoopCounter*: int # whether we are in a loop or not
|
||||
nestedBlockCounter*: int # whether we are in a block or not
|
||||
breakInLoop*: bool # whether we are in a loop without block
|
||||
next*: PProcCon # used for stacking procedure contexts
|
||||
mappingExists*: bool
|
||||
mapping*: TIdTable
|
||||
|
|
|
|||
|
|
@ -2640,6 +2640,8 @@ include semobjconstr
|
|||
proc semBlock(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
result = n
|
||||
inc(c.p.nestedBlockCounter)
|
||||
let oldBreakInLoop = c.p.breakInLoop
|
||||
c.p.breakInLoop = false
|
||||
checkSonsLen(n, 2, c.config)
|
||||
openScope(c) # BUGFIX: label is in the scope of block!
|
||||
if n[0].kind != nkEmpty:
|
||||
|
|
@ -2657,6 +2659,7 @@ proc semBlock(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = ni
|
|||
if isEmptyType(n.typ): n.transitionSonsKind(nkBlockStmt)
|
||||
else: n.transitionSonsKind(nkBlockExpr)
|
||||
closeScope(c)
|
||||
c.p.breakInLoop = oldBreakInLoop
|
||||
dec(c.p.nestedBlockCounter)
|
||||
|
||||
proc semExportExcept(c: PContext, n: PNode): PNode =
|
||||
|
|
|
|||
|
|
@ -133,6 +133,8 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
|
|||
typeMismatch(c.config, calli.info, tupleTypeA, tupleTypeB, calli)
|
||||
|
||||
inc(c.p.nestedLoopCounter)
|
||||
let oldBreakInLoop = c.p.breakInLoop
|
||||
c.p.breakInLoop = true
|
||||
if tupleTypeA.kind == tyTuple:
|
||||
var loopBody = n[^1]
|
||||
for i in 0..<tupleTypeA.len:
|
||||
|
|
@ -156,6 +158,7 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
|
|||
semForObjectFields(fc, t.n, n, stmts)
|
||||
if t[0] == nil: break
|
||||
t = skipTypes(t[0], skipPtrs)
|
||||
c.p.breakInLoop = oldBreakInLoop
|
||||
dec(c.p.nestedLoopCounter)
|
||||
# for TR macros this 'while true: ...; break' loop is pretty bad, so
|
||||
# we avoid it now if we can:
|
||||
|
|
|
|||
|
|
@ -73,6 +73,8 @@ proc semBreakOrContinue(c: PContext, n: PNode): PNode =
|
|||
localError(c.config, n.info, errInvalidControlFlowX % s.name.s)
|
||||
else:
|
||||
localError(c.config, n.info, errGenerated, "'continue' cannot have a label")
|
||||
elif c.p.nestedBlockCounter > 0 and n.kind == nkBreakStmt and not c.p.breakInLoop:
|
||||
localError(c.config, n.info, warnUnnamedBreak)
|
||||
elif (c.p.nestedLoopCounter <= 0) and ((c.p.nestedBlockCounter <= 0) or n.kind == nkContinueStmt):
|
||||
localError(c.config, n.info, errInvalidControlFlowX %
|
||||
renderTree(n, {renderNoComments}))
|
||||
|
|
@ -89,7 +91,10 @@ proc semWhile(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
|||
openScope(c)
|
||||
n[0] = forceBool(c, semExprWithType(c, n[0], expectedType = getSysType(c.graph, n.info, tyBool)))
|
||||
inc(c.p.nestedLoopCounter)
|
||||
let oldBreakInLoop = c.p.breakInLoop
|
||||
c.p.breakInLoop = true
|
||||
n[1] = semStmt(c, n[1], flags)
|
||||
c.p.breakInLoop = oldBreakInLoop
|
||||
dec(c.p.nestedLoopCounter)
|
||||
closeScope(c)
|
||||
if n[1].typ == c.enforceVoidContext:
|
||||
|
|
@ -959,11 +964,14 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
|||
if not isDiscardUnderscore(v): addDecl(c, v)
|
||||
elif v.owner == nil: v.owner = getCurrOwner(c)
|
||||
inc(c.p.nestedLoopCounter)
|
||||
let oldBreakInLoop = c.p.breakInLoop
|
||||
c.p.breakInLoop = true
|
||||
openScope(c)
|
||||
n[^1] = semExprBranch(c, n[^1], flags)
|
||||
if efInTypeof notin flags:
|
||||
discardCheck(c, n[^1], flags)
|
||||
closeScope(c)
|
||||
c.p.breakInLoop = oldBreakInLoop
|
||||
dec(c.p.nestedLoopCounter)
|
||||
|
||||
proc implicitIterator(c: PContext, it: string, arg: PNode): PNode =
|
||||
|
|
|
|||
|
|
@ -1457,6 +1457,8 @@ proc semStmtListType(c: PContext, n: PNode, prev: PType): PType =
|
|||
|
||||
proc semBlockType(c: PContext, n: PNode, prev: PType): PType =
|
||||
inc(c.p.nestedBlockCounter)
|
||||
let oldBreakInLoop = c.p.breakInLoop
|
||||
c.p.breakInLoop = false
|
||||
checkSonsLen(n, 2, c.config)
|
||||
openScope(c)
|
||||
if n[0].kind notin {nkEmpty, nkSym}:
|
||||
|
|
@ -1465,6 +1467,7 @@ proc semBlockType(c: PContext, n: PNode, prev: PType): PType =
|
|||
n[1].typ = result
|
||||
n.typ = result
|
||||
closeScope(c)
|
||||
c.p.breakInLoop = oldBreakInLoop
|
||||
dec(c.p.nestedBlockCounter)
|
||||
|
||||
proc semGenericParamInInvocation(c: PContext, n: PNode): PType =
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue