summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorOscar NihlgÄrd <oscarnihlgard@gmail.com>2018-02-24 14:56:17 +0100
committerAndreas Rumpf <rumpf_a@web.de>2018-02-24 14:56:17 +0100
commite4515f304abf9b9ce029b634b38fce2a398a16fc (patch)
tree6d37b5c7fddaa27c4fdb1bf80b8c091dec80f383 /compiler
parentba6e11fc888c0e8171797f5af731e6ac6b16c8e6 (diff)
downloadNim-e4515f304abf9b9ce029b634b38fce2a398a16fc.tar.gz
Improve semchecking for duplicate cases in case statements (#7176)
* Improve semchecking for duplicate cases in case statements

* Revert to previous solution

* Improve test
Diffstat (limited to 'compiler')
-rw-r--r--compiler/nimsets.nim5
-rw-r--r--compiler/semtypes.nim15
2 files changed, 16 insertions, 4 deletions
diff --git a/compiler/nimsets.nim b/compiler/nimsets.nim
index 94507adf0..bda753e85 100644
--- a/compiler/nimsets.nim
+++ b/compiler/nimsets.nim
@@ -151,6 +151,11 @@ proc complement*(a: PNode): PNode =
   for i in countup(0, high(x)): x[i] = not x[i]
   result = toTreeSet(x, a.typ, a.info)
 
+proc deduplicate*(a: PNode): PNode =
+  var x: TBitSet
+  toBitSet(a, x)
+  result = toTreeSet(x, a.typ, a.info)
+
 proc cardSet(s: PNode): BiggestInt =
   # here we can do better than converting it into a compact set
   # we just count the elements directly
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index df274c7db..50c2e287e 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -497,8 +497,8 @@ proc semCaseBranchSetElem(c: PContext, t, b: PNode,
 
 proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
                    covered: var BiggestInt) =
-
-  for i in countup(0, sonsLen(branch) - 2):
+  let lastIndex = sonsLen(branch) - 2
+  for i in 0..lastIndex:
     var b = branch.sons[i]
     if b.kind == nkRange:
       branch.sons[i] = b
@@ -516,14 +516,21 @@ proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
         branch.sons[i] = skipConv(fitNode(c, t.sons[0].typ, r, r.info))
         inc(covered)
       else:
+        if r.kind == nkCurly:
+          r = r.deduplicate
+
         # first element is special and will overwrite: branch.sons[i]:
         branch.sons[i] = semCaseBranchSetElem(c, t, r[0], covered)
+
         # other elements have to be added to ``branch``
         for j in 1 ..< r.len:
           branch.add(semCaseBranchSetElem(c, t, r[j], covered))
           # caution! last son of branch must be the actions to execute:
-          var L = branch.len
-          swap(branch.sons[L-2], branch.sons[L-1])
+          swap(branch.sons[^2], branch.sons[^1])
+    checkForOverlap(c, t, i, branchIndex)
+
+  # Elements added above needs to be checked for overlaps.
+  for i in lastIndex.succ..(sonsLen(branch) - 2):
     checkForOverlap(c, t, i, branchIndex)
 
 proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,