bugfix: overlap checking for 'case'
This commit is contained in:
parent
0758508895
commit
d5a5c2291f
4 changed files with 25 additions and 10 deletions
|
|
@ -47,9 +47,9 @@ proc inSet(s: PNode, elem: PNode): bool =
|
||||||
proc overlap(a, b: PNode): bool =
|
proc overlap(a, b: PNode): bool =
|
||||||
if a.kind == nkRange:
|
if a.kind == nkRange:
|
||||||
if b.kind == nkRange:
|
if b.kind == nkRange:
|
||||||
|
# X..Y and C..D overlap iff (X <= D and C <= Y)
|
||||||
result = leValue(a.sons[0], b.sons[1]) and
|
result = leValue(a.sons[0], b.sons[1]) and
|
||||||
leValue(b.sons[1], a.sons[1]) or
|
leValue(b.sons[0], a.sons[1])
|
||||||
leValue(a.sons[0], b.sons[0]) and leValue(b.sons[0], a.sons[1])
|
|
||||||
else:
|
else:
|
||||||
result = leValue(a.sons[0], b) and leValue(b, a.sons[1])
|
result = leValue(a.sons[0], b) and leValue(b, a.sons[1])
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -311,11 +311,12 @@ proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
|
||||||
else:
|
else:
|
||||||
result = semIdentVis(c, kind, n, allowed)
|
result = semIdentVis(c, kind, n, allowed)
|
||||||
|
|
||||||
proc checkForOverlap(c: PContext, t, ex: PNode, branchIndex: int) =
|
proc checkForOverlap(c: PContext, t: PNode, currentEx, branchIndex: int) =
|
||||||
let ex = ex.skipConv
|
let ex = t[branchIndex][currentEx].skipConv
|
||||||
for i in countup(1, branchIndex - 1):
|
for i in countup(1, branchIndex):
|
||||||
for j in countup(0, sonsLen(t.sons[i]) - 2):
|
for j in countup(0, sonsLen(t.sons[i]) - 2):
|
||||||
if overlap(t.sons[i].sons[j].skipConv, ex):
|
if i == branchIndex and j == currentEx: break
|
||||||
|
if overlap(t.sons[i].sons[j].skipConv, ex):
|
||||||
LocalError(ex.info, errDuplicateCaseLabel)
|
LocalError(ex.info, errDuplicateCaseLabel)
|
||||||
|
|
||||||
proc semBranchRange(c: PContext, t, a, b: PNode, covered: var biggestInt): PNode =
|
proc semBranchRange(c: PContext, t, a, b: PNode, covered: var biggestInt): PNode =
|
||||||
|
|
@ -373,8 +374,8 @@ proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
|
||||||
# caution! last son of branch must be the actions to execute:
|
# caution! last son of branch must be the actions to execute:
|
||||||
var L = branch.len
|
var L = branch.len
|
||||||
swap(branch.sons[L-2], branch.sons[L-1])
|
swap(branch.sons[L-2], branch.sons[L-1])
|
||||||
checkForOverlap(c, t, branch.sons[i], branchIndex)
|
checkForOverlap(c, t, i, branchIndex)
|
||||||
|
|
||||||
proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
||||||
father: PNode, rectype: PSym)
|
father: PNode, rectype: PSym)
|
||||||
proc semRecordCase(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
proc semRecordCase(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
||||||
|
|
@ -397,6 +398,7 @@ proc semRecordCase(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
||||||
var chckCovered = true
|
var chckCovered = true
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
var b = copyTree(n.sons[i])
|
var b = copyTree(n.sons[i])
|
||||||
|
addSon(a, b)
|
||||||
case n.sons[i].kind
|
case n.sons[i].kind
|
||||||
of nkOfBranch:
|
of nkOfBranch:
|
||||||
checkMinSonsLen(b, 2)
|
checkMinSonsLen(b, 2)
|
||||||
|
|
@ -407,7 +409,6 @@ proc semRecordCase(c: PContext, n: PNode, check: var TIntSet, pos: var int,
|
||||||
else: illFormedAst(n)
|
else: illFormedAst(n)
|
||||||
delSon(b, sonsLen(b) - 1)
|
delSon(b, sonsLen(b) - 1)
|
||||||
semRecordNodeAux(c, lastSon(n.sons[i]), check, pos, b, rectype)
|
semRecordNodeAux(c, lastSon(n.sons[i]), check, pos, b, rectype)
|
||||||
addSon(a, b)
|
|
||||||
if chckCovered and (covered != lengthOrd(a.sons[0].typ)):
|
if chckCovered and (covered != lengthOrd(a.sons[0].typ)):
|
||||||
localError(a.info, errNotAllCasesCovered)
|
localError(a.info, errNotAllCasesCovered)
|
||||||
addSon(father, a)
|
addSon(father, a)
|
||||||
|
|
|
||||||
15
tests/reject/tcaseoverlaprange.nim
Normal file
15
tests/reject/tcaseoverlaprange.nim
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
discard """
|
||||||
|
line: 13
|
||||||
|
errormsg: "duplicate case label"
|
||||||
|
"""
|
||||||
|
|
||||||
|
type
|
||||||
|
TE = enum A, B, C, D
|
||||||
|
|
||||||
|
var
|
||||||
|
e: TE
|
||||||
|
|
||||||
|
case e
|
||||||
|
of A..D, B..C:
|
||||||
|
echo "redundant"
|
||||||
|
else: nil
|
||||||
1
todo.txt
1
todo.txt
|
|
@ -4,7 +4,6 @@ version 0.9.2
|
||||||
- implement constructors + full 'not nil' checking
|
- implement constructors + full 'not nil' checking
|
||||||
- ``restrict`` pragma + backend support
|
- ``restrict`` pragma + backend support
|
||||||
- fix: 'result' is not properly cleaned for NRVO
|
- fix: 'result' is not properly cleaned for NRVO
|
||||||
- fix: exhaustive checking in case statements
|
|
||||||
|
|
||||||
version 0.9.4
|
version 0.9.4
|
||||||
=============
|
=============
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue