From 60a07770f12b60f372d75fd164f1d6b2591e1860 Mon Sep 17 00:00:00 2001
From: svenbarth <pascaldragon@googlemail.com>
Date: Fri, 21 Feb 2014 22:49:19 +0000
Subject: [PATCH] Fix cycling after addition of the new case simplification.

nset.pas, tcasenode.simplify: don't assume a specific order of the case labels

+ added test based on ppu.pas, tppu.getaint where no matching case label was found because of the ordering

git-svn-id: trunk@26825 -
---
 .gitattributes      |  1 +
 compiler/nset.pas   | 35 ++++++++++++++++++++---------------
 tests/tbs/tb0605.pp | 42 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 63 insertions(+), 15 deletions(-)
 create mode 100644 tests/tbs/tb0605.pp

diff --git a/.gitattributes b/.gitattributes
index 650c9abdb0..c909095e70 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -10161,6 +10161,7 @@ tests/tbs/tb0601.pp svneol=native#text/pascal
 tests/tbs/tb0602.pp svneol=native#text/plain
 tests/tbs/tb0603.pp svneol=native#text/pascal
 tests/tbs/tb0604.pp svneol=native#text/pascal
+tests/tbs/tb0605.pp svneol=native#text/pascal
 tests/tbs/tb205.pp svneol=native#text/plain
 tests/tbs/tbs0594.pp svneol=native#text/pascal
 tests/tbs/ub0060.pp svneol=native#text/plain
diff --git a/compiler/nset.pas b/compiler/nset.pas
index 23582e866c..44c2730a6d 100644
--- a/compiler/nset.pas
+++ b/compiler/nset.pas
@@ -844,27 +844,32 @@ implementation
     function tcasenode.simplify(forinline:boolean):tnode;
       var
         tmp: pcaselabel;
+        walkup: boolean;
       begin
         result:=nil;
         if left.nodetype=ordconstn then
           begin
             tmp:=labels;
-            { walk the case labels as long as the upper bound is smaller than
-              the constant }
-            while assigned(tmp) and (tmp^._high<tordconstnode(left).value) do
-              tmp:=tmp^.greater;
-            { check whether the constant is inside the range }
-            if assigned(tmp) and
-                (tmp^._low<=tordconstnode(left).value) and
-                (tmp^._high>=tordconstnode(left).value) then
+            { check all case labels until we find one that fits }
+            walkup:=assigned(tmp^.greater);
+            while assigned(tmp) do
               begin
-                if tmp^.blockid>=blocks.count then
-                  internalerror(2014022101);
-                result:=pcaseblock(blocks[tmp^.blockid])^.statement;
-                if not assigned(result) then
-                  internalerror(2014022102);
-                result:=result.getcopy;
-                exit;
+                if (tmp^._low<=tordconstnode(left).value) and
+                    (tmp^._high>=tordconstnode(left).value) then
+                  begin
+                    if tmp^.blockid>=blocks.count then
+                      internalerror(2014022101);
+                    result:=pcaseblock(blocks[tmp^.blockid])^.statement;
+                    if not assigned(result) then
+                      internalerror(2014022102);
+                    result:=result.getcopy;
+                    exit;
+                  end;
+
+                if walkup then
+                  tmp:=tmp^.greater
+                else
+                  tmp:=tmp^.less;
               end;
             { no label did match; use the else block if available }
             if assigned(elseblock) then
diff --git a/tests/tbs/tb0605.pp b/tests/tbs/tb0605.pp
new file mode 100644
index 0000000000..1fd3936af6
--- /dev/null
+++ b/tests/tbs/tb0605.pp
@@ -0,0 +1,42 @@
+program tb0605;
+
+{$mode objfpc}
+
+type
+  aint = longint;
+
+function getint64: int64;
+begin
+  Result := 64;
+end;
+
+function getlongint: longint;
+begin
+  Result := 32;
+end;
+
+function getword: word;
+begin
+  result := 16;
+end;
+
+function getbyte: byte;
+begin
+  result := 8;
+end;
+
+function getaint: longint;
+begin
+  result:=4;
+  case sizeof(aint) of
+    8: result:=getint64;
+    4: result:=getlongint;
+    2: result:=smallint(getword);
+    1: result:=shortint(getbyte);
+  end;
+end;
+
+begin
+  if getaint <> 32 then
+    Halt(1);
+end.