Ver Fonte

* in non-TP modes, 'ord_larger_than_256 in set' now always returns
false instead of triggering a range error (mantis #8258,
based on patch provided by Thorsten Engler)

git-svn-id: trunk@6357 -

Jonas Maebe há 18 anos atrás
pai
commit
fc3852e59a
5 ficheiros alterados com 1456 adições e 119 exclusões
  1. 1 0
      .gitattributes
  2. 89 40
      compiler/ncgset.pas
  3. 32 20
      compiler/nset.pas
  4. 78 59
      compiler/x86/nx86set.pas
  5. 1256 0
      tests/webtbs/tw8258.pp

+ 1 - 0
.gitattributes

@@ -8025,6 +8025,7 @@ tests/webtbs/tw8222a.pp svneol=native#text/plain
 tests/webtbs/tw8222b.pp svneol=native#text/plain
 tests/webtbs/tw8229.pp svneol=native#text/plain
 tests/webtbs/tw8232.pp svneol=native#text/plain
+tests/webtbs/tw8258.pp svneol=native#text/plain
 tests/webtbs/tw8264.pp svneol=native#text/plain
 tests/webtbs/ub1873.pp svneol=native#text/plain
 tests/webtbs/ub1883.pp svneol=native#text/plain

+ 89 - 40
compiler/ncgset.pas

@@ -151,8 +151,9 @@ implementation
       { be caught when range checking is on! (JM)                        }
       { cg.a_op_const_reg(list,OP_AND,31,bitnumber);                     }
 
-      if bitsize<>ressize then
+      if tcgsize2unsigned[bitsize]<>tcgsize2unsigned[ressize] then
         begin
+          internalerror(2007020401);
           { FIX ME! We're not allowed to modify the value register here! }
 
           { shift value register "bitnumber" bits to the right }
@@ -232,7 +233,7 @@ implementation
       begin
          { check if we can use smallset operation using btl which is limited
            to 32 bits, the left side may also not contain higher values !! }
-         use_small:=(tsetdef(right.resultdef).settype=smallset) and
+         use_small:=(tsetdef(right.resultdef).settype=smallset) and not is_signed(left.resultdef) and
                     ((left.resultdef.typ=orddef) and (torddef(left.resultdef).high<=32) or
                      (left.resultdef.typ=enumdef) and (tenumdef(left.resultdef).max<=32));
 
@@ -262,17 +263,26 @@ implementation
          pleftreg   : tregister;
          setparts   : Tsetparts;
          opsize     : tcgsize;
+         uopsize    : tcgsize;
+         orgopsize  : tcgsize;
          genjumps,
          use_small  : boolean;
          i,numparts : byte;
-
+         l, l2      : tasmlabel;
+         needslabel : Boolean;
        begin
          { We check first if we can generate jumps, this can be done
            because the resultdef is already set in firstpass }
 
          genjumps := checkgenjumps(setparts,numparts,use_small);
 
-         opsize:=OS_32;
+         orgopsize := def_cgsize(left.resultdef);
+         uopsize := OS_INT;
+         if is_signed(left.resultdef) then
+           opsize := tcgsize(ord(uopsize)+(ord(OS_S8)-ord(OS_8)))
+         else
+           opsize := uopsize;
+         needslabel := false;
 
          { calculate both operators }
          { the complex one first }
@@ -307,7 +317,7 @@ implementation
               { use fact that a <= x <= b <=> aword(x-a) <= aword(b-a) }
               begin
                 { is the range different from all legal values? }
-                if (setparts[i].stop-setparts[i].start <> 255) then
+                if (setparts[i].stop-setparts[i].start <> 255) or not (orgopsize = OS_8) then
                   begin
                     { yes, is the lower bound <> 0? }
                     if (setparts[i].start <> 0) then
@@ -364,7 +374,7 @@ implementation
          {*****************************************************************}
           begin
             { location is always LOC_REGISTER }
-            location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+            location_reset(location, LOC_REGISTER, uopsize{def_cgsize(resultdef)});
 
             { We will now generated code to check the set itself, no jmps,
               handle smallsets separate, because it allows faster checks }
@@ -373,17 +383,17 @@ implementation
                {****************************  SMALL SET **********************}
                if left.nodetype=ordconstn then
                 begin
-                  location_force_reg(current_asmdata.CurrAsmList,right.location,opsize,true);
+                  location_force_reg(current_asmdata.CurrAsmList, right.location, uopsize, true);
                   location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
                   { first SHR the register }
-                  cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,opsize,tordconstnode(left).value and 31,right.location.register,location.register);
+                  cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, uopsize, tordconstnode(left).value and 31, right.location.register, location.register);
                   { then extract the lowest bit }
-                  cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_AND,opsize,1,location.register);
+                  cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_AND, uopsize, 1, location.register);
                 end
                else
                 begin
                   location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,false);
-                  location_force_reg(current_asmdata.CurrAsmList,right.location,opsize,false);
+                  location_force_reg(current_asmdata.CurrAsmList, right.location, uopsize, false);
                   { allocate a register for the result }
                   location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
                   { emit bit test operation }
@@ -409,26 +419,30 @@ implementation
                   else
                     hr := left.location.register;
                   { load right in register }
-                  hr2:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
-                  cg.a_load_const_reg(current_asmdata.CurrAsmList,opsize,right.location.value,hr2);
+                  hr2:=cg.getintregister(current_asmdata.CurrAsmList, uopsize);
+                  cg.a_load_const_reg(current_asmdata.CurrAsmList, uopsize, right.location.value, hr2);
 
                   { emit bit test operation }
-                  emit_bit_test_reg_reg(current_asmdata.CurrAsmList,left.location.size,left.location.register,hr2,opsize,hr2);
+                  emit_bit_test_reg_reg(current_asmdata.CurrAsmList, left.location.size, left.location.register, hr2, uopsize, hr2);
 
                   { if left > 31 then hr := 0 else hr := $ffffffff }
-                  cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SUB,opsize,32,left.location.register,hr);
-                  cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SAR,opsize,31,hr);
+                  cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SUB, uopsize, 32, left.location.register, hr);
+                  cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_SAR, uopsize, 31, hr);
 
                   { if left > 31, then result := 0 else result := result of bit test }
-                  cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_AND,opsize,hr,hr2);
+                  cg.a_op_reg_reg(current_asmdata.CurrAsmList, OP_AND, uopsize, hr, hr2);
                   { allocate a register for the result }
                   location.register := cg.getintregister(current_asmdata.CurrAsmList,location.size);
-                  cg.a_load_reg_reg(current_asmdata.CurrAsmList,opsize,location.size,hr2,location.register);
+                  cg.a_load_reg_reg(current_asmdata.CurrAsmList, uopsize, location.size, hr2, location.register);
                 end { of right.location.loc=LOC_CONSTANT }
                { do search in a normal set which could have >32 elementsm
                  but also used if the left side contains higher values > 32 }
                else if left.nodetype=ordconstn then
                 begin
+                  if (tordconstnode(left).value < 0) or ((tordconstnode(left).value shr 3) >= right.resultdef.size) then
+                    {should be caught earlier }
+                    internalerror(2007020402);
+
                   { use location.register as scratch register here }
                   if (target_info.endian = endian_little) then
                     inc(right.location.reference.offset,tordconstnode(left).value shr 3)
@@ -444,38 +458,73 @@ implementation
                 end
                else
                 begin
-                  location_force_reg(current_asmdata.CurrAsmList,left.location,OS_INT,true);
+                  location_force_reg(current_asmdata.CurrAsmList, left.location, opsize, true);
                   pleftreg := left.location.register;
 
                   location_freetemp(current_asmdata.CurrAsmList,left.location);
-                  hr := cg.getaddressregister(current_asmdata.CurrAsmList);
-                  cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_SHR,OS_INT,5,pleftreg,hr);
-                  cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SHL,OS_INT,2,hr);
-
-                  href := right.location.reference;
-                  if (href.base = NR_NO) then
-                    href.base := hr
-                  else if (right.location.reference.index = NR_NO) then
-                    href.index := hr
-                  else
+
+                  { allocate a register for the result }
+                  location.register := cg.getintregister(current_asmdata.CurrAsmList, uopsize);
+
+                  if (opsize >= OS_S8) or { = if signed }
+                     ((left.resultdef.typ=orddef)  and (torddef(left.resultdef).high >= tsetdef(right.resultdef).setmax)) or
+                     ((left.resultdef.typ=enumdef) and (tenumdef(left.resultdef).max >= tsetdef(right.resultdef).setmax)) then
                     begin
-                      hr2 := cg.getaddressregister(current_asmdata.CurrAsmList);
-                      cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href, hr2);
-                      reference_reset_base(href,hr2,0);
-                      href.index := hr;
+                      current_asmdata.getjumplabel(l);
+                      current_asmdata.getjumplabel(l2);
+                      needslabel := True;
+
+                      cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList, opsize, OC_BE, tsetdef(right.resultdef).setmax, pleftreg, l);
+
+                      cg.a_load_const_reg(current_asmdata.CurrAsmList, opsize, 0, location.register);
+                      cg.a_jmp_always(current_asmdata.CurrAsmList, l2);
+
+                      cg.a_label(current_asmdata.CurrAsmList, l);
                     end;
-                  { allocate a register for the result }
-                  location.register := cg.getintregister(current_asmdata.CurrAsmList,opsize);
-                  cg.a_load_ref_reg(current_asmdata.CurrAsmList,opsize,opsize,href,location.register);
 
-                  hr := cg.getintregister(current_asmdata.CurrAsmList,opsize);
-                  cg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_AND,opsize,31,pleftreg,hr);
-                  cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_SHR,opsize,hr,location.register);
-                  cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_AND,opsize,1,location.register);
+                  case right.location.loc of
+                    LOC_REGISTER, LOC_CREGISTER :
+                      begin
+                        cg.a_load_reg_reg(current_asmdata.CurrAsmList, uopsize, uopsize, right.location.register, location.register);
+                      end;
+                    LOC_CREFERENCE, LOC_REFERENCE :
+                      begin
+                        hr := cg.getaddressregister(current_asmdata.CurrAsmList);
+                        cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_SHR, uopsize, 5, pleftreg, hr);
+                        cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_SHL, uopsize, 2, hr);
+
+                        href := right.location.reference;
+                        if (href.base = NR_NO) then
+                          href.base := hr
+                        else if (right.location.reference.index = NR_NO) then
+                          href.index := hr
+                        else
+                          begin
+                            hr2 := cg.getaddressregister(current_asmdata.CurrAsmList);
+                            cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList, href, hr2);
+                            reference_reset_base(href, hr2, 0);
+                            href.index := hr;
+                          end;
+                        cg.a_load_ref_reg(current_asmdata.CurrAsmList, uopsize, uopsize, href, location.register);
+                      end
+                    else
+                      internalerror(2007020403);
+                  end;
+
+                  hr := cg.getintregister(current_asmdata.CurrAsmList, uopsize);
+                  cg.a_op_const_reg_reg(current_asmdata.CurrAsmList, OP_AND, uopsize, 31, pleftreg, hr);
+                  cg.a_op_reg_reg(current_asmdata.CurrAsmList, OP_SHR, uopsize, hr, location.register);
+                  cg.a_op_const_reg(current_asmdata.CurrAsmList, OP_AND, uopsize, 1, location.register);
+
+                  if needslabel then
+                    cg.a_label(current_asmdata.CurrAsmList, l2);
                 end;
              end;
           end;
-          location_freetemp(current_asmdata.CurrAsmList,right.location);
+          location_freetemp(current_asmdata.CurrAsmList, right.location);
+
+          location.size := def_cgsize(resultdef);
+          location.register := cg.makeregsize(current_asmdata.CurrAsmList, location.register, location.size);
        end;
 
 {*****************************************************************************

+ 32 - 20
compiler/nset.pas

@@ -240,7 +240,7 @@ implementation
          if not assigned(left.resultdef) then
            internalerror(20021126);
 
-         if (m_fpc in current_settings.modeswitches) then
+         if (m_tp7 in current_settings.modeswitches) then
            begin
              { insert a hint that a range check error might occur on non-byte
                elements with the in operator.
@@ -254,18 +254,20 @@ implementation
                    (left.resultdef.typ = enumdef) and
                    (tenumdef(left.resultdef).maxval > 255)
                  )
-              then
+               then
                  CGMessage(type_h_in_range_check);
 
              { type conversion/check }
              if assigned(tsetdef(right.resultdef).elementdef) then
                inserttypeconv(left,tsetdef(right.resultdef).elementdef);
            end
-         else
+         else if not is_ordinal(left.resultdef) or (left.resultdef.size > uinttype.size) then
            begin
-             { insert explicit type conversion/check }
-             if assigned(tsetdef(right.resultdef).elementdef) then
-               inserttypeconv_internal(left,tsetdef(right.resultdef).elementdef);
+             CGMessage(type_h_in_range_check);
+             if is_signed(left.resultdef) then
+               inserttypeconv(left,sinttype)
+             else
+               inserttypeconv(left,uinttype);
            end;
 
          { empty set then return false }
@@ -280,21 +282,31 @@ implementation
           end;
 
          { constant evaluation }
-         if (left.nodetype=ordconstn) and (right.nodetype=setconstn) then
-          begin
-            t:=cordconstnode.create(byte(tordconstnode(left).value in Tsetconstnode(right).value_set^),
-               booltype,true);
-            typecheckpass(t);
-            result:=t;
-            exit;
-          end;
+         if (left.nodetype=ordconstn) then
+           begin
+             if (right.nodetype=setconstn) then
+               begin
+                 t:=cordconstnode.create(byte(tordconstnode(left).value in Tsetconstnode(right).value_set^),
+                   booltype,true);
+                 typecheckpass(t);
+                 result:=t;
+                 exit;
+               end
+             else
+               begin
+                 if (is_signed(left.resultdef) and (tordconstnode(left).value < 0)) or
+                    (TConstExprUInt(tordconstnode(left).value) > tsetdef(right.resultdef).setmax) then
+                   begin
+                     t:=cordconstnode.create(0, booltype, true);
+                     typecheckpass(t);
+                     result:=t;
+                     exit;
+                   end;
+               end;
+           end;
       end;
 
 
-    { Warning : This is the first pass for the generic version }
-    { the only difference is mainly the result location which  }
-    { is changed, compared to the i386 version.                }
-    { ALSO REGISTER ALLOC IS WRONG?                            }
     function tinnode.pass_1 : tnode;
       begin
          result:=nil;
@@ -316,8 +328,8 @@ implementation
            begin
               { a smallset needs maybe an misc. register }
               if (left.nodetype<>ordconstn) and
-                not(right.expectloc in [LOC_CREGISTER,LOC_REGISTER]) and
-                (right.registersint<1) then
+                 not(right.expectloc in [LOC_CREGISTER,LOC_REGISTER]) and
+                 (right.registersint<1) then
                 inc(registersint);
            end;
       end;

+ 78 - 59
compiler/x86/nx86set.pas

@@ -87,6 +87,7 @@ implementation
          hreg,hreg2,
          pleftreg   : tregister;
          opsize     : tcgsize;
+         orgopsize  : tcgsize;
          setparts   : array[1..8] of Tsetpart;
          i,numparts : byte;
          adjustment : longint;
@@ -144,12 +145,6 @@ implementation
                      setparts[numparts].start:=setparts[numparts].stop;
                      setparts[numparts].stop:=i;
                      ranges := true;
-                     { there's only one compare per range anymore. Only a }
-                     { sub is added, but that's much faster than a        }
-                     { cmp/jcc combo so neglect its effect                }
-{                     inc(compares);
-                     if compares>maxcompares then
-                      exit; }
                    end
                   else
                    begin
@@ -165,8 +160,8 @@ implementation
            because the resultdef is already set in firstpass }
 
          { check if we can use smallset operation using btl which is limited
-           to 32 bits, the left side may also not contain higher values !! }
-         use_small:=(tsetdef(right.resultdef).settype=smallset) and
+           to 32 bits, the left side may also not contain higher values or be signed !! }
+         use_small:=(tsetdef(right.resultdef).settype=smallset) and not is_signed(left.resultdef) and
                     ((left.resultdef.typ=orddef) and (torddef(left.resultdef).high<=32) or
                      (left.resultdef.typ=enumdef) and (tenumdef(left.resultdef).max<=32));
 
@@ -189,42 +184,31 @@ implementation
          if nf_swapped in flags then
           swapleftright;
 
+         orgopsize := def_cgsize(left.resultdef);
+         opsize := OS_INT;
+         if is_signed(left.resultdef) then
+           opsize := tcgsize(ord(opsize)+(ord(OS_S8)-ord(OS_8)));
+
          if not(left.location.loc in [LOC_REGISTER,LOC_CREGISTER,LOC_REFERENCE,LOC_CREFERENCE]) then
-           location_force_reg(current_asmdata.CurrAsmList,left.location,OS_INT,true);
+           location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,true);
+
          if genjumps then
           begin
             { It gives us advantage to check for the set elements
               separately instead of using the SET_IN_BYTE procedure.
               To do: Build in support for LOC_JUMP }
 
-            opsize := def_cgsize(left.resultdef);
-            { If register is used, use only lower 8 bits }
+            { load and zero or sign extend as necessary }
             if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
              begin
-               { for ranges we always need a 32bit register, because then we }
-               { use the register as base in a reference (JM)                }
-               if ranges then
-                 begin
-                   pleftreg:=cg.makeregsize(current_asmdata.CurrAsmList,left.location.register,OS_INT);
-                   cg.a_load_reg_reg(current_asmdata.CurrAsmList,left.location.size,OS_INT,left.location.register,pleftreg);
-                   if opsize<>OS_INT then
-                     cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_AND,OS_INT,255,pleftreg);
-                   opsize:=OS_INT;
-                 end
-               else
-                 { otherwise simply use the lower 8 bits (no "and" }
-                 { necessary this way) (JM)                        }
-                 begin
-                   pleftreg:=cg.makeregsize(current_asmdata.CurrAsmList,left.location.register,OS_8);
-                   opsize := OS_8;
-                 end;
+               pleftreg:=cg.makeregsize(current_asmdata.CurrAsmList,left.location.register,opsize);
+               cg.a_load_reg_reg(current_asmdata.CurrAsmList,left.location.size,opsize,left.location.register,pleftreg);
              end
             else
              begin
                { load the value in a register }
-               pleftreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
-               opsize:=OS_32;
-               cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_8,OS_32,left.location.reference,pleftreg);
+               pleftreg:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+               cg.a_load_ref_reg(current_asmdata.CurrAsmList,left.location.size,opsize,left.location.reference,pleftreg);
              end;
 
             { Get a label to jump to the end }
@@ -248,17 +232,16 @@ implementation
               { use fact that a <= x <= b <=> cardinal(x-a) <= cardinal(b-a) }
               begin
                 { is the range different from all legal values? }
-                if (setparts[i].stop-setparts[i].start <> 255) then
+                if (setparts[i].stop-setparts[i].start <> 255) or not (orgopsize = OS_8) then
                   begin
                     { yes, is the lower bound <> 0? }
                     if (setparts[i].start <> 0) then
                       begin
                         if (left.location.loc = LOC_CREGISTER) then
                           begin
-                            hreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
-                            cg.a_load_reg_reg(current_asmdata.CurrAsmList,opsize,OS_INT,pleftreg,hreg);
+                            hreg:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+                            cg.a_load_reg_reg(current_asmdata.CurrAsmList,opsize,opsize,pleftreg,hreg);
                             pleftreg:=hreg;
-                            opsize:=OS_INT;
                           end;
                         cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,opsize,setparts[i].start-adjustment,pleftreg);
                       end;
@@ -296,7 +279,7 @@ implementation
                 { if the last one was a range, the carry flag is already }
                 { set appropriately                                      }
                 not(setparts[numparts].range) then
-               current_asmdata.CurrAsmList.concat(taicpu.op_none(A_CLC,S_NO));
+                  current_asmdata.CurrAsmList.concat(taicpu.op_none(A_CLC,S_NO));
              { To compensate for not doing a second pass }
              right.location.reference.symbol:=nil;
              { Now place the end label }
@@ -384,15 +367,15 @@ implementation
 
                   { load constants to a register }
                   if left.nodetype=ordconstn then
-                    location_force_reg(current_asmdata.CurrAsmList,left.location,OS_INT,true);
+                    location_force_reg(current_asmdata.CurrAsmList,left.location,opsize,true);
 
                   case left.location.loc of
                      LOC_REGISTER,
                      LOC_CREGISTER:
                        begin
-                          hreg:=cg.makeregsize(current_asmdata.CurrAsmList,left.location.register,OS_32);
-                          cg.a_load_reg_reg(current_asmdata.CurrAsmList,left.location.size,OS_32,left.location.register,hreg);
-                          cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_32,OC_BE,31,hreg,l);
+                          hreg:=cg.makeregsize(current_asmdata.CurrAsmList,left.location.register,opsize);
+                          cg.a_load_reg_reg(current_asmdata.CurrAsmList,left.location.size,opsize,left.location.register,hreg);
+                          cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,OC_BE,31,hreg,l);
                           { reset carry flag }
                           current_asmdata.CurrAsmList.concat(taicpu.op_none(A_CLC,S_NO));
                           cg.a_jmp_always(current_asmdata.CurrAsmList,l2);
@@ -405,18 +388,7 @@ implementation
                        end;
                   else
                     begin
-{$ifdef CORRECT_SET_IN_FPC}
-                          if m_tp in current_settings.modeswitches then
-                            begin
-                              {***WARNING only correct if
-                                reference is 32 bits (PM) *****}
-                               emit_const_ref(A_CMP,S_L,31,reference_copy(left.location.reference));
-                            end
-                          else
-{$endif CORRECT_SET_IN_FPC}
-                            begin
-                               emit_const_ref(A_CMP,S_B,31,left.location.reference);
-                            end;
+                       emit_const_ref(A_CMP,TCGSize2OpSize[orgopsize],31,left.location.reference);
                        cg.a_jmp_flags(current_asmdata.CurrAsmList,F_BE,l);
                        { reset carry flag }
                        current_asmdata.CurrAsmList.concat(taicpu.op_none(A_CLC,S_NO));
@@ -434,9 +406,13 @@ implementation
                   cg.a_label(current_asmdata.CurrAsmList,l2);
                 end { of right.location.loc=LOC_CONSTANT }
                { do search in a normal set which could have >32 elementsm
-                 but also used if the left side contains higher values > 32 }
+                 but also used if the left side contains values > 32 or < 0 }
                else if left.nodetype=ordconstn then
                 begin
+                  if (tordconstnode(left).value < 0) or ((tordconstnode(left).value shr 3) >= right.resultdef.size) then
+                    {should be caught earlier }
+                    internalerror(2007020201);
+
                   location.resflags:=F_NE;
                   inc(right.location.reference.offset,tordconstnode(left).value shr 3);
                   emit_const_ref(A_TEST,S_B,1 shl (tordconstnode(left).value and 7),right.location.reference);
@@ -444,14 +420,57 @@ implementation
                else
                 begin
                   if (left.location.loc=LOC_REGISTER) then
-                    pleftreg:=cg.makeregsize(current_asmdata.CurrAsmList,left.location.register,OS_32)
+                    pleftreg:=cg.makeregsize(current_asmdata.CurrAsmList,left.location.register,opsize)
                   else
-                    pleftreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
-                  cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_32,left.location,pleftreg);
+                    pleftreg:=cg.getintregister(current_asmdata.CurrAsmList,opsize);
+
+                  cg.a_load_loc_reg(current_asmdata.CurrAsmList,opsize,left.location,pleftreg);
                   location_freetemp(current_asmdata.CurrAsmList,left.location);
-                  emit_reg_ref(A_BT,S_L,pleftreg,right.location.reference);
-                  { tg.ungetiftemp(current_asmdata.CurrAsmList,right.location.reference) happens below }
-                  location.resflags:=F_C;
+
+                  if (opsize >= OS_S8) or { = if signed }
+                    ((left.resultdef.typ=orddef)  and (torddef(left.resultdef).high >= tsetdef(right.resultdef).setmax)) or
+                    ((left.resultdef.typ=enumdef) and (tenumdef(left.resultdef).max >= tsetdef(right.resultdef).setmax)) then
+                   begin
+
+                    { we have to check if the value is < 0 or > setmax }
+
+                    current_asmdata.getjumplabel(l);
+                    current_asmdata.getjumplabel(l2);
+
+                    { BE will be false for negative values }
+                    cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,opsize,OC_BE,tsetdef(right.resultdef).setmax,pleftreg,l);
+                    { reset carry flag }
+                    current_asmdata.CurrAsmList.concat(taicpu.op_none(A_CLC,S_NO));
+                    cg.a_jmp_always(current_asmdata.CurrAsmList,l2);
+
+                    cg.a_label(current_asmdata.CurrAsmList,l);
+
+                    case right.location.loc of
+                      LOC_REGISTER, LOC_CREGISTER :
+                        emit_reg_reg(A_BT,S_L,pleftreg,right.location.register);
+                      LOC_CREFERENCE, LOC_REFERENCE :
+                        emit_reg_ref(A_BT,S_L,pleftreg,right.location.reference);
+                    else
+                      internalerror(2007020301);
+                    end;
+
+                    cg.a_label(current_asmdata.CurrAsmList,l2);
+
+                    location.resflags:=F_C;
+
+                   end
+                  else
+                   begin
+                      case right.location.loc of
+                        LOC_REGISTER, LOC_CREGISTER :
+                          emit_reg_reg(A_BT,S_L,pleftreg,right.location.register);
+                        LOC_CREFERENCE, LOC_REFERENCE :
+                          emit_reg_ref(A_BT,S_L,pleftreg,right.location.reference);
+                      else
+                        internalerror(2007020302);
+                      end;
+                      location.resflags:=F_C;
+                   end;
                 end;
              end;
           end;

+ 1256 - 0
tests/webtbs/tw8258.pp

@@ -0,0 +1,1256 @@
+program SetTests;
+
+{$APPTYPE CONSOLE}
+
+{$IFDEF FPC}
+  {$mode delphi}
+{$ENDIF}
+
+{$R+}
+{$Q+}
+
+uses
+  SysUtils;
+
+var
+  u8      : Byte;
+  s8      : ShortInt;
+  u16     : Word;
+  s16     : SmallInt;
+  u32     : LongWord;
+  s32     : LongInt;
+  u64     : QWord;
+  s64     : Int64;
+
+  LargeSet : set of Byte;
+  SmallSet : set of 0..31;
+
+  Error    : Boolean;
+
+procedure CheckResult(const s: string; aIs, aExpected: Boolean); overload;
+begin
+  if aIs <> aExpected then begin
+    WriteLn(s, aIs, ' <> ', aExpected, '   * * * ERROR * * * ERROR * * * ERROR * * *');
+    Error := True;
+  end else
+    WriteLn(s, aIs);
+end;
+
+procedure CheckResult(const s: string; aIs: Boolean); overload;
+begin
+  WriteLn(s, aIs, ' <> EXCEPTION   * * * ERROR * * * ERROR * * * ERROR * * *');
+  Error := True;
+end;
+
+
+begin
+  Error := False;
+
+  WriteLn('--- Variable against constant set [0, 2, 8..20, 99..192] ---' );
+  WriteLn;
+
+  u8  := 100;
+  s8  := 100;
+  u16 := 100;
+  s16 := 100;
+  u32 := 100;
+  s32 := 100;
+  u64 := 100;
+  s64 := 100;
+
+  WriteLn('100, should be true');
+  CheckResult(' u8 -> ',  u8 in [0, 2, 8..20, 99..192], True);
+  CheckResult(' s8 -> ',  s8 in [0, 2, 8..20, 99..192], True);
+  CheckResult('u16 -> ', u16 in [0, 2, 8..20, 99..192], True);
+  CheckResult('s16 -> ', s16 in [0, 2, 8..20, 99..192], True);
+  CheckResult('u32 -> ', u32 in [0, 2, 8..20, 99..192], True);
+  CheckResult('s32 -> ', s32 in [0, 2, 8..20, 99..192], True);
+  CheckResult('u64 -> ', u64 in [0, 2, 8..20, 99..192], True);
+  CheckResult('s64 -> ', s64 in [0, 2, 8..20, 99..192], True);
+  WriteLn;
+
+  u8  := 98;
+  s8  := 98;
+  u16 := 98;
+  s16 := 98;
+  u32 := 98;
+  s32 := 98;
+  u64 := 98;
+  s64 := 98;
+
+  WriteLn('98, should be false');
+  CheckResult(' u8 -> ',  u8 in [0, 2, 8..20, 99..192], False);
+  CheckResult(' s8 -> ',  s8 in [0, 2, 8..20, 99..192], False);
+  CheckResult('u16 -> ', u16 in [0, 2, 8..20, 99..192], False);
+  CheckResult('s16 -> ', s16 in [0, 2, 8..20, 99..192], False);
+  CheckResult('u32 -> ', u32 in [0, 2, 8..20, 99..192], False);
+  CheckResult('s32 -> ', s32 in [0, 2, 8..20, 99..192], False);
+  CheckResult('u64 -> ', u64 in [0, 2, 8..20, 99..192], False);
+  CheckResult('s64 -> ', s64 in [0, 2, 8..20, 99..192], False);
+  WriteLn;
+
+  u8  := 193;
+//  s8  := 193;
+  u16 := 193;
+  s16 := 193;
+  u32 := 193;
+  s32 := 193;
+  u64 := 193;
+  s64 := 193;
+
+  WriteLn('193, should be false');
+  CheckResult(' u8 -> ',  u8 in [0, 2, 8..20, 99..192], False);
+//  CheckResult(' s8 -> ',  s8 in [0, 2, 8..20, 99..192], False);
+  CheckResult('u16 -> ', u16 in [0, 2, 8..20, 99..192], False);
+  CheckResult('s16 -> ', s16 in [0, 2, 8..20, 99..192], False);
+  CheckResult('u32 -> ', u32 in [0, 2, 8..20, 99..192], False);
+  CheckResult('s32 -> ', s32 in [0, 2, 8..20, 99..192], False);
+  CheckResult('u64 -> ', u64 in [0, 2, 8..20, 99..192], False);
+  CheckResult('s64 -> ', s64 in [0, 2, 8..20, 99..192], False);
+  WriteLn;
+
+//  u8  := 256;
+//  s8  := 256;
+  u16 := 256;
+  s16 := 256;
+  u32 := 256;
+  s32 := 256;
+  u64 := 256;
+  s64 := 256;
+
+  WriteLn('256, should be false');
+//  CheckResult(' u8 -> ',  u8 in [0, 2, 8..20, 99..192], False);
+//  CheckResult(' s8 -> ',  s8 in [0, 2, 8..20, 99..192], False);
+  CheckResult('u16 -> ', u16 in [0, 2, 8..20, 99..192], False);
+  CheckResult('s16 -> ', s16 in [0, 2, 8..20, 99..192], False);
+  CheckResult('u32 -> ', u32 in [0, 2, 8..20, 99..192], False);
+  CheckResult('s32 -> ', s32 in [0, 2, 8..20, 99..192], False);
+  CheckResult('u64 -> ', u64 in [0, 2, 8..20, 99..192], False);
+  CheckResult('s64 -> ', s64 in [0, 2, 8..20, 99..192], False);
+  WriteLn;
+
+  u8  := High(u8);
+  s8  := High(s8);
+  u16 := High(u16);
+  s16 := High(s16);
+  u32 := High(u32);
+  s32 := High(s32);
+  u64 := High(u64);
+  s64 := High(s64);
+
+  WriteLn('High(type), s8 should be true, u64/s64 should cause range check');
+  CheckResult(' u8 -> ',  u8 in [0, 2, 8..20, 99..192], False);
+  CheckResult(' s8 -> ',  s8 in [0, 2, 8..20, 99..192], True);
+  CheckResult('u16 -> ', u16 in [0, 2, 8..20, 99..192], False);
+  CheckResult('s16 -> ', s16 in [0, 2, 8..20, 99..192], False);
+  CheckResult('u32 -> ', u32 in [0, 2, 8..20, 99..192], False);
+  CheckResult('s32 -> ', s32 in [0, 2, 8..20, 99..192], False);
+  try
+    CheckResult('u64 -> ', u64 in [0, 2, 8..20, 99..192]);
+  except
+    on E: Exception do
+      WriteLn('u64 -> ', E.Classname,': ',E.Message);
+  end;
+  try
+    CheckResult('s64 -> ', s64 in [0, 2, 8..20, 99..192]);
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+  u8  := Low(u8);
+  s8  := Low(s8);
+  u16 := Low(u16);
+  s16 := Low(s16);
+  u32 := Low(u32);
+  s32 := Low(s32);
+  u64 := Low(u64);
+  s64 := Low(s64);
+
+  WriteLn('Low(type), all unsigned true, all signed false, except s64 -> range check error');
+  CheckResult('u8  -> ',  u8 in [0, 2, 8..20, 99..192], True);
+  CheckResult('s8  -> ',  s8 in [0, 2, 8..20, 99..192], False);
+  CheckResult('u16 -> ', u16 in [0, 2, 8..20, 99..192], True);
+  CheckResult('s16 -> ', s16 in [0, 2, 8..20, 99..192], False);
+  CheckResult('u32 -> ', u32 in [0, 2, 8..20, 99..192], True);
+  CheckResult('s32 -> ', s32 in [0, 2, 8..20, 99..192], False);
+  CheckResult('u64 -> ', u64 in [0, 2, 8..20, 99..192], True);
+
+  try
+    CheckResult('s64 -> ', s64 in [0, 2, 8..20, 99..192]);
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+  WriteLn('--- Variable against set of byte with value [0, 2, 8..20, 99..192] ---' );
+  WriteLn;
+
+  LargeSet := [0, 2, 8..20, 99..192];
+
+  u8  := 100;
+  s8  := 100;
+  u16 := 100;
+  s16 := 100;
+  u32 := 100;
+  s32 := 100;
+  u64 := 100;
+  s64 := 100;
+
+  WriteLn('100, should be true');
+  CheckResult(' u8 -> ',  u8 in LargeSet, True);
+  CheckResult(' s8 -> ',  s8 in LargeSet, True);
+  CheckResult('u16 -> ', u16 in LargeSet, True);
+  CheckResult('s16 -> ', s16 in LargeSet, True);
+  CheckResult('u32 -> ', u32 in LargeSet, True);
+  CheckResult('s32 -> ', s32 in LargeSet, True);
+  CheckResult('u64 -> ', u64 in LargeSet, True);
+  CheckResult('s64 -> ', s64 in LargeSet, True);
+  WriteLn;
+
+  u8  := 98;
+  s8  := 98;
+  u16 := 98;
+  s16 := 98;
+  u32 := 98;
+  s32 := 98;
+  u64 := 98;
+  s64 := 98;
+
+  WriteLn('98, should be false');
+  CheckResult(' u8 -> ',  u8 in LargeSet, False);
+  CheckResult(' s8 -> ',  s8 in LargeSet, False);
+  CheckResult('u16 -> ', u16 in LargeSet, False);
+  CheckResult('s16 -> ', s16 in LargeSet, False);
+  CheckResult('u32 -> ', u32 in LargeSet, False);
+  CheckResult('s32 -> ', s32 in LargeSet, False);
+  CheckResult('u64 -> ', u64 in LargeSet, False);
+  CheckResult('s64 -> ', s64 in LargeSet, False);
+  WriteLn;
+
+  u8  := 193;
+//  s8  := 193;
+  u16 := 193;
+  s16 := 193;
+  u32 := 193;
+  s32 := 193;
+  u64 := 193;
+  s64 := 193;
+
+  WriteLn('193, should be false');
+  CheckResult(' u8 -> ',  u8 in LargeSet, False);
+//  CheckResult(' s8 -> ',  s8 in LargeSet, False);
+  CheckResult('u16 -> ', u16 in LargeSet, False);
+  CheckResult('s16 -> ', s16 in LargeSet, False);
+  CheckResult('u32 -> ', u32 in LargeSet, False);
+  CheckResult('s32 -> ', s32 in LargeSet, False);
+  CheckResult('u64 -> ', u64 in LargeSet, False);
+  CheckResult('s64 -> ', s64 in LargeSet, False);
+  WriteLn;
+
+//  u8  := 256;
+//  s8  := 256;
+  u16 := 256;
+  s16 := 256;
+  u32 := 256;
+  s32 := 256;
+  u64 := 256;
+  s64 := 256;
+
+  WriteLn('256, should be false');
+//  CheckResult(' u8 -> ',  u8 in LargeSet, False);
+//  CheckResult(' s8 -> ',  s8 in LargeSet, False);
+  CheckResult('u16 -> ', u16 in LargeSet, False);
+  CheckResult('s16 -> ', s16 in LargeSet, False);
+  CheckResult('u32 -> ', u32 in LargeSet, False);
+  CheckResult('s32 -> ', s32 in LargeSet, False);
+  CheckResult('u64 -> ', u64 in LargeSet, False);
+  CheckResult('s64 -> ', s64 in LargeSet, False);
+  WriteLn;
+
+  u8  := High(u8);
+  s8  := High(s8);
+  u16 := High(u16);
+  s16 := High(s16);
+  u32 := High(u32);
+  s32 := High(s32);
+  u64 := High(u64);
+  s64 := High(s64);
+
+  WriteLn('High(type), s8 should be true, u64/s64 should cause range check');
+  CheckResult(' u8 -> ',  u8 in LargeSet, False);
+  CheckResult(' s8 -> ',  s8 in LargeSet, True);
+  CheckResult('u16 -> ', u16 in LargeSet, False);
+  CheckResult('s16 -> ', s16 in LargeSet, False);
+  CheckResult('u32 -> ', u32 in LargeSet, False);
+  CheckResult('s32 -> ', s32 in LargeSet, False);
+  try
+    CheckResult('u64 -> ', u64 in LargeSet);
+  except
+    on E: Exception do
+      WriteLn('u64 -> ', E.Classname,': ',E.Message);
+  end;
+  try
+    CheckResult('s64 -> ', s64 in LargeSet);
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+  u8  := Low(u8);
+  s8  := Low(s8);
+  u16 := Low(u16);
+  s16 := Low(s16);
+  u32 := Low(u32);
+  s32 := Low(s32);
+  u64 := Low(u64);
+  s64 := Low(s64);
+
+  WriteLn('Low(type), all unsigned true, all signed false, except s64 -> range check error');
+  CheckResult('u8  -> ',  u8 in LargeSet, True);
+  CheckResult('s8  -> ',  s8 in LargeSet, False);
+  CheckResult('u16 -> ', u16 in LargeSet, True);
+  CheckResult('s16 -> ', s16 in LargeSet, False);
+  CheckResult('u32 -> ', u32 in LargeSet, True);
+  CheckResult('s32 -> ', s32 in LargeSet, False);
+  CheckResult('u64 -> ', u64 in LargeSet, True);
+
+  try
+    CheckResult('s64 -> ', s64 in LargeSet);
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+  WriteLn('--- constant value against constant set [0, 2, 8..20, 99..192] ---' );
+  WriteLn;
+
+  WriteLn('100, should be true');
+  CheckResult('100 -> ', 100 in [0, 2, 8..20, 99..192], True);
+  WriteLn;
+
+  WriteLn('98, should be false');
+  CheckResult(' 98 -> ', 98 in [0, 2, 8..20, 99..192], False);
+  WriteLn;
+
+  WriteLn('193, should be false');
+  CheckResult('193 -> ', 193 in [0, 2, 8..20, 99..192], False);
+  WriteLn;
+
+  WriteLn('256, should be false');
+  CheckResult('256 -> ', 256 in [0, 2, 8..20, 99..192], False);
+  WriteLn;
+
+  WriteLn('High(type), s8 should be true, u64/s64 should cause range check at compile time');
+  CheckResult(' u8 -> ', High(u8)  in [0, 2, 8..20, 99..192], False);
+  CheckResult(' s8 -> ', High(s8)  in [0, 2, 8..20, 99..192], True);
+  CheckResult('u16 -> ', High(u16) in [0, 2, 8..20, 99..192], False);
+  CheckResult('s16 -> ', High(s16) in [0, 2, 8..20, 99..192], False);
+  CheckResult('u32 -> ', High(u32) in [0, 2, 8..20, 99..192], False);
+  CheckResult('s32 -> ', High(s32) in [0, 2, 8..20, 99..192], False);
+  try
+//    CheckResult('u64 -> ', High(u64) in [0, 2, 8..20, 99..192]);
+    WriteLn('u64 -> Error: range check error while evaluating constants');
+  except
+    on E: Exception do
+      WriteLn('u64 -> ', E.Classname,': ',E.Message);
+  end;
+  try
+//    CheckResult('s64 -> ', High(s64) in [0, 2, 8..20, 99..192]);
+    WriteLn('s64 -> Error: range check error while evaluating constants');
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+  WriteLn('Low(type), all unsigned true, all signed false, except s64 -> range check error at compile time');
+  CheckResult('u8  -> ',  Low(u8) in [0, 2, 8..20, 99..192], True);
+  CheckResult('s8  -> ',  Low(s8) in [0, 2, 8..20, 99..192], False);
+  CheckResult('u16 -> ', Low(u16) in [0, 2, 8..20, 99..192], True);
+  CheckResult('s16 -> ', Low(s16) in [0, 2, 8..20, 99..192], False);
+  CheckResult('u32 -> ', Low(u32) in [0, 2, 8..20, 99..192], True);
+  CheckResult('s32 -> ', Low(s32) in [0, 2, 8..20, 99..192], False);
+  CheckResult('u64 -> ', Low(u64) in [0, 2, 8..20, 99..192], True);
+
+  try
+//    CheckResult('s64 -> ', Low(s64) in [0, 2, 8..20, 99..192]);
+    WriteLn('s64 -> Error: range check error while evaluating constants');
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+  WriteLn('--- constant value against set of byte with value [0, 2, 8..20, 99..192] ---' );
+  WriteLn;
+
+  LargeSet := [0, 2, 8..20, 99..192];
+
+  WriteLn('100, should be true');
+  CheckResult('100 -> ', 100 in LargeSet, True);
+  WriteLn;
+
+  WriteLn('98, should be false');
+  CheckResult(' 98 -> ',  98 in LargeSet, False);
+  WriteLn;
+
+  WriteLn('193, should be false');
+  CheckResult('193 -> ', 193 in LargeSet, False);
+  WriteLn;
+
+  WriteLn('256, should be false');
+  CheckResult('256 -> ', 256 in LargeSet, False);
+  WriteLn;
+
+  WriteLn('High(type), s8 should be true, u64/s64 should cause range check at compile time');
+  CheckResult(' u8 -> ',  High(u8) in LargeSet, False);
+  CheckResult(' s8 -> ',  High(s8) in LargeSet, True);
+  CheckResult('u16 -> ', High(u16) in LargeSet, False);
+  CheckResult('s16 -> ', High(s16) in LargeSet, False);
+  CheckResult('u32 -> ', High(u32) in LargeSet, False);
+  CheckResult('s32 -> ', High(s32) in LargeSet, False);
+  try
+//    CheckResult('u64 -> ', High(u64) in LargeSet);
+    WriteLn('u64 -> Error: range check error while evaluating constants');
+  except
+    on E: Exception do
+      WriteLn('u64 -> ', E.Classname,': ',E.Message);
+  end;
+  try
+//    CheckResult('s64 -> ', High(s64) in LargeSet);
+    WriteLn('s64 -> Error: range check error while evaluating constants');
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+
+  WriteLn('Low(type), all unsigned true, all signed false, except s64 -> range check error at compile time');
+  CheckResult(' u8 -> ',  Low(u8) in LargeSet, True);
+  CheckResult(' s8 -> ',  Low(s8) in LargeSet, False);
+  CheckResult('u16 -> ', Low(u16) in LargeSet, True);
+  CheckResult('s16 -> ', Low(s16) in LargeSet, False);
+  CheckResult('u32 -> ', Low(u32) in LargeSet, True);
+  CheckResult('s32 -> ', Low(s32) in LargeSet, False);
+  CheckResult('u64 -> ', Low(u64) in LargeSet, True);
+  try
+//    CheckResult('s64 -> ', Low(s64) in LargeSet);
+    WriteLn('s64 -> Error: range check error while evaluating constants');
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+  WriteLn('--- Variable against constant set [0, 2, 8..20] ---' );
+  WriteLn;
+
+  u8  := 10;
+  s8  := 10;
+  u16 := 10;
+  s16 := 10;
+  u32 := 10;
+  s32 := 10;
+  u64 := 10;
+  s64 := 10;
+
+  WriteLn('10, should be true');
+  CheckResult(' u8 -> ',  u8 in [0, 2, 8..20], True);
+  CheckResult(' s8 -> ',  s8 in [0, 2, 8..20], True);
+  CheckResult('u16 -> ', u16 in [0, 2, 8..20], True);
+  CheckResult('s16 -> ', s16 in [0, 2, 8..20], True);
+  CheckResult('u32 -> ', u32 in [0, 2, 8..20], True);
+  CheckResult('s32 -> ', s32 in [0, 2, 8..20], True);
+  CheckResult('u64 -> ', u64 in [0, 2, 8..20], True);
+  CheckResult('s64 -> ', s64 in [0, 2, 8..20], True);
+  WriteLn;
+
+  u8  := 7;
+  s8  := 7;
+  u16 := 7;
+  s16 := 7;
+  u32 := 7;
+  s32 := 7;
+  u64 := 7;
+  s64 := 7;
+
+  WriteLn('7, should be false');
+  CheckResult(' u8 -> ',  u8 in [0, 2, 8..20], False);
+  CheckResult(' s8 -> ',  s8 in [0, 2, 8..20], False);
+  CheckResult('u16 -> ', u16 in [0, 2, 8..20], False);
+  CheckResult('s16 -> ', s16 in [0, 2, 8..20], False);
+  CheckResult('u32 -> ', u32 in [0, 2, 8..20], False);
+  CheckResult('s32 -> ', s32 in [0, 2, 8..20], False);
+  CheckResult('u64 -> ', u64 in [0, 2, 8..20], False);
+  CheckResult('s64 -> ', s64 in [0, 2, 8..20], False);
+  WriteLn;
+
+  u8  := 30;
+  s8  := 30;
+  u16 := 30;
+  s16 := 30;
+  u32 := 30;
+  s32 := 30;
+  u64 := 30;
+  s64 := 30;
+
+  WriteLn('30, should be false');
+  CheckResult(' u8 -> ',  u8 in [0, 2, 8..20], False);
+  CheckResult(' s8 -> ',  s8 in [0, 2, 8..20], False);
+  CheckResult('u16 -> ', u16 in [0, 2, 8..20], False);
+  CheckResult('s16 -> ', s16 in [0, 2, 8..20], False);
+  CheckResult('u32 -> ', u32 in [0, 2, 8..20], False);
+  CheckResult('s32 -> ', s32 in [0, 2, 8..20], False);
+  CheckResult('u64 -> ', u64 in [0, 2, 8..20], False);
+  CheckResult('s64 -> ', s64 in [0, 2, 8..20], False);
+  WriteLn;
+
+//  u8  := 256;
+//  s8  := 256;
+  u16 := 256;
+  s16 := 256;
+  u32 := 256;
+  s32 := 256;
+  u64 := 256;
+  s64 := 256;
+
+  WriteLn('256, should be false');
+//  CheckResult(' u8 -> ',  u8 in [0, 2, 8..20], False);
+//  CheckResult(' s8 -> ',  s8 in [0, 2, 8..20], False);
+  CheckResult('u16 -> ', u16 in [0, 2, 8..20], False);
+  CheckResult('s16 -> ', s16 in [0, 2, 8..20], False);
+  CheckResult('u32 -> ', u32 in [0, 2, 8..20], False);
+  CheckResult('s32 -> ', s32 in [0, 2, 8..20], False);
+  CheckResult('u64 -> ', u64 in [0, 2, 8..20], False);
+  CheckResult('s64 -> ', s64 in [0, 2, 8..20], False);
+  WriteLn;
+
+  u8  := High(u8);
+  s8  := High(s8);
+  u16 := High(u16);
+  s16 := High(s16);
+  u32 := High(u32);
+  s32 := High(s32);
+  u64 := High(u64);
+  s64 := High(s64);
+
+  WriteLn('High(type), should be false, u64/s64 should cause range check');
+  CheckResult(' u8 -> ',  u8 in [0, 2, 8..20], False);
+  CheckResult(' s8 -> ',  s8 in [0, 2, 8..20], False);
+  CheckResult('u16 -> ', u16 in [0, 2, 8..20], False);
+  CheckResult('s16 -> ', s16 in [0, 2, 8..20], False);
+  CheckResult('u32 -> ', u32 in [0, 2, 8..20], False);
+  CheckResult('s32 -> ', s32 in [0, 2, 8..20], False);
+  try
+    CheckResult('u64 -> ', u64 in [0, 2, 8..20]);
+  except
+    on E: Exception do
+      WriteLn('u64 -> ', E.Classname,': ',E.Message);
+  end;
+  try
+    CheckResult('s64 -> ', s64 in [0, 2, 8..20]);
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+  u8  := Low(u8);
+  s8  := Low(s8);
+  u16 := Low(u16);
+  s16 := Low(s16);
+  u32 := Low(u32);
+  s32 := Low(s32);
+  u64 := Low(u64);
+  s64 := Low(s64);
+
+  WriteLn('Low(type), all unsigned true, all signed false, except s64 -> range check error');
+  CheckResult('u8  -> ',  u8 in [0, 2, 8..20], True);
+  CheckResult('s8  -> ',  s8 in [0, 2, 8..20], False);
+  CheckResult('u16 -> ', u16 in [0, 2, 8..20], True);
+  CheckResult('s16 -> ', s16 in [0, 2, 8..20], False);
+  CheckResult('u32 -> ', u32 in [0, 2, 8..20], True);
+  CheckResult('s32 -> ', s32 in [0, 2, 8..20], False);
+  CheckResult('u64 -> ', u64 in [0, 2, 8..20], True);
+
+  try
+    CheckResult('s64 -> ', s64 in [0, 2, 8..20]);
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+  WriteLn('--- Variable against set of 0..31 with value [0, 2, 8..20] ---' );
+  WriteLn;
+
+  SmallSet := [0, 2, 8..20];
+
+  u8  := 10;
+  s8  := 10;
+  u16 := 10;
+  s16 := 10;
+  u32 := 10;
+  s32 := 10;
+  u64 := 10;
+  s64 := 10;
+
+  WriteLn('10, should be true');
+  CheckResult(' u8 -> ',  u8 in SmallSet, True);
+  CheckResult(' s8 -> ',  s8 in SmallSet, True);
+  CheckResult('u16 -> ', u16 in SmallSet, True);
+  CheckResult('s16 -> ', s16 in SmallSet, True);
+  CheckResult('u32 -> ', u32 in SmallSet, True);
+  CheckResult('s32 -> ', s32 in SmallSet, True);
+  CheckResult('u64 -> ', u64 in SmallSet, True);
+  CheckResult('s64 -> ', s64 in SmallSet, True);
+  WriteLn;
+
+  u8  := 7;
+  s8  := 7;
+  u16 := 7;
+  s16 := 7;
+  u32 := 7;
+  s32 := 7;
+  u64 := 7;
+  s64 := 7;
+
+  WriteLn('7, should be false');
+  CheckResult(' u8 -> ',  u8 in SmallSet, False);
+  CheckResult(' s8 -> ',  s8 in SmallSet, False);
+  CheckResult('u16 -> ', u16 in SmallSet, False);
+  CheckResult('s16 -> ', s16 in SmallSet, False);
+  CheckResult('u32 -> ', u32 in SmallSet, False);
+  CheckResult('s32 -> ', s32 in SmallSet, False);
+  CheckResult('u64 -> ', u64 in SmallSet, False);
+  CheckResult('s64 -> ', s64 in SmallSet, False);
+  WriteLn;
+
+  u8  := 30;
+  s8  := 30;
+  u16 := 30;
+  s16 := 30;
+  u32 := 30;
+  s32 := 30;
+  u64 := 30;
+  s64 := 30;
+
+  WriteLn('30, should be false');
+  CheckResult(' u8 -> ',  u8 in SmallSet, False);
+  CheckResult(' s8 -> ',  s8 in SmallSet, False);
+  CheckResult('u16 -> ', u16 in SmallSet, False);
+  CheckResult('s16 -> ', s16 in SmallSet, False);
+  CheckResult('u32 -> ', u32 in SmallSet, False);
+  CheckResult('s32 -> ', s32 in SmallSet, False);
+  CheckResult('u64 -> ', u64 in SmallSet, False);
+  CheckResult('s64 -> ', s64 in SmallSet, False);
+  WriteLn;
+
+//  u8  := 256;
+//  s8  := 256;
+  u16 := 256;
+  s16 := 256;
+  u32 := 256;
+  s32 := 256;
+  u64 := 256;
+  s64 := 256;
+
+  WriteLn('256, should be false');
+//  CheckResult(' u8 -> ',  u8 in SmallSet, False);
+//  CheckResult(' s8 -> ',  s8 in SmallSet, False);
+  CheckResult('u16 -> ', u16 in SmallSet, False);
+  CheckResult('s16 -> ', s16 in SmallSet, False);
+  CheckResult('u32 -> ', u32 in SmallSet, False);
+  CheckResult('s32 -> ', s32 in SmallSet, False);
+  CheckResult('u64 -> ', u64 in SmallSet, False);
+  CheckResult('s64 -> ', s64 in SmallSet, False);
+  WriteLn;
+
+  u8  := High(u8);
+  s8  := High(s8);
+  u16 := High(u16);
+  s16 := High(s16);
+  u32 := High(u32);
+  s32 := High(s32);
+  u64 := High(u64);
+  s64 := High(s64);
+
+  WriteLn('High(type), should be false, u64/s64 should cause range check');
+  CheckResult(' u8 -> ',  u8 in SmallSet, False);
+  CheckResult(' s8 -> ',  s8 in SmallSet, False);
+  CheckResult('u16 -> ', u16 in SmallSet, False);
+  CheckResult('s16 -> ', s16 in SmallSet, False);
+  CheckResult('u32 -> ', u32 in SmallSet, False);
+  CheckResult('s32 -> ', s32 in SmallSet, False);
+  try
+    CheckResult('u64 -> ', u64 in SmallSet);
+  except
+    on E: Exception do
+      WriteLn('u64 -> ', E.Classname,': ',E.Message);
+  end;
+  try
+    CheckResult('s64 -> ', s64 in SmallSet);
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+  u8  := Low(u8);
+  s8  := Low(s8);
+  u16 := Low(u16);
+  s16 := Low(s16);
+  u32 := Low(u32);
+  s32 := Low(s32);
+  u64 := Low(u64);
+  s64 := Low(s64);
+
+  WriteLn('Low(type), all unsigned true, all signed false, except s64 -> range check error');
+  CheckResult('u8  -> ',  u8 in SmallSet, True);
+  CheckResult('s8  -> ',  s8 in SmallSet, False);
+  CheckResult('u16 -> ', u16 in SmallSet, True);
+  CheckResult('s16 -> ', s16 in SmallSet, False);
+  CheckResult('u32 -> ', u32 in SmallSet, True);
+  CheckResult('s32 -> ', s32 in SmallSet, False);
+  CheckResult('u64 -> ', u64 in SmallSet, True);
+
+  try
+    CheckResult('s64 -> ', s64 in SmallSet);
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+  WriteLn('--- constant value against constant set [0, 2, 8..20] ---' );
+  WriteLn;
+
+  WriteLn('10, should be true');
+  CheckResult('10 -> ', 10 in [0, 2, 8..20], True);
+  WriteLn;
+
+  WriteLn('7, should be false');
+  CheckResult(' 7 -> ', 7 in [0, 2, 8..20], False);
+  WriteLn;
+
+  WriteLn('30, should be false');
+  CheckResult('30 -> ', 30 in [0, 2, 8..20], False);
+  WriteLn;
+
+  WriteLn('256, should be false');
+  CheckResult('256 -> ', 256 in [0, 2, 8..20], False);
+  WriteLn;
+
+  WriteLn('High(type), should be false, u64/s64 should cause range check at compile time');
+  CheckResult(' u8 -> ', High(u8)  in [0, 2, 8..20], False);
+  CheckResult(' s8 -> ', High(s8)  in [0, 2, 8..20], False);
+  CheckResult('u16 -> ', High(u16) in [0, 2, 8..20], False);
+  CheckResult('s16 -> ', High(s16) in [0, 2, 8..20], False);
+  CheckResult('u32 -> ', High(u32) in [0, 2, 8..20], False);
+  CheckResult('s32 -> ', High(s32) in [0, 2, 8..20], False);
+  try
+//    CheckResult('u64 -> ', High(u64) in [0, 2, 8..20]);
+    WriteLn('u64 -> Error: range check error while evaluating constants');
+  except
+    on E: Exception do
+      WriteLn('u64 -> ', E.Classname,': ',E.Message);
+  end;
+  try
+//    CheckResult('s64 -> ', High(s64) in [0, 2, 8..20]);
+    WriteLn('s64 -> Error: range check error while evaluating constants');
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+  WriteLn('Low(type), all unsigned true, all signed false, except s64 -> range check error at compile time');
+  CheckResult('u8  -> ',  Low(u8) in [0, 2, 8..20], True);
+  CheckResult('s8  -> ',  Low(s8) in [0, 2, 8..20], False);
+  CheckResult('u16 -> ', Low(u16) in [0, 2, 8..20], True);
+  CheckResult('s16 -> ', Low(s16) in [0, 2, 8..20], False);
+  CheckResult('u32 -> ', Low(u32) in [0, 2, 8..20], True);
+  CheckResult('s32 -> ', Low(s32) in [0, 2, 8..20], False);
+  CheckResult('u64 -> ', Low(u64) in [0, 2, 8..20], True);
+
+  try
+//    CheckResult('s64 -> ', Low(s64) in [0, 2, 8..20]);
+    WriteLn('s64 -> Error: range check error while evaluating constants');
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+  WriteLn('--- constant value against set of 0..31 with value [0, 2, 8..20] ---' );
+  WriteLn;
+
+  SmallSet := [0, 2, 8..20];
+
+  WriteLn('10, should be true');
+  CheckResult('10 -> ', 10 in SmallSet, True);
+  WriteLn;
+
+  WriteLn('7, should be false');
+  CheckResult(' 7 -> ',  7 in SmallSet, False);
+  WriteLn;
+
+  WriteLn('30, should be false');
+  CheckResult('30 -> ', 30 in SmallSet, False);
+  WriteLn;
+
+  WriteLn('256, should be false');
+  CheckResult('256 -> ', 256 in SmallSet, False);
+  WriteLn;
+
+  WriteLn('High(type), all false, u64/s64 should cause range check at compile time');
+  CheckResult(' u8 -> ',  High(u8) in SmallSet, False);
+  CheckResult(' s8 -> ',  High(s8) in SmallSet, False);
+  CheckResult('u16 -> ', High(u16) in SmallSet, False);
+  CheckResult('s16 -> ', High(s16) in SmallSet, False);
+  CheckResult('u32 -> ', High(u32) in SmallSet, False);
+  CheckResult('s32 -> ', High(s32) in SmallSet, False);
+  try
+//    CheckResult('u64 -> ', High(u64) in SmallSet);
+    WriteLn('u64 -> Error: range check error while evaluating constants');
+  except
+    on E: Exception do
+      WriteLn('u64 -> ', E.Classname,': ',E.Message);
+  end;
+  try
+//    CheckResult('s64 -> ', High(s64) in SmallSet);
+    WriteLn('s64 -> Error: range check error while evaluating constants');
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+
+  WriteLn('Low(type), all unsigned true, all signed false, except s64 -> range check error at compile time');
+  CheckResult(' u8 -> ',  Low(u8) in SmallSet, True);
+  CheckResult(' s8 -> ',  Low(s8) in SmallSet, False);
+  CheckResult('u16 -> ', Low(u16) in SmallSet, True);
+  CheckResult('s16 -> ', Low(s16) in SmallSet, False);
+  CheckResult('u32 -> ', Low(u32) in SmallSet, True);
+  CheckResult('s32 -> ', Low(s32) in SmallSet, False);
+  CheckResult('u64 -> ', Low(u64) in SmallSet, True);
+  try
+//    CheckResult('s64 -> ', Low(s64) in SmallSet);
+    WriteLn('s64 -> Error: range check error while evaluating constants');
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+  WriteLn('--- Variable against constant set [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41] ---' );
+  WriteLn;
+
+  u8  := 25;
+  s8  := 25;
+  u16 := 25;
+  s16 := 25;
+  u32 := 25;
+  s32 := 25;
+  u64 := 25;
+  s64 := 25;
+
+  WriteLn('25, should be true');
+  CheckResult(' u8 -> ',  u8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], True);
+  CheckResult(' s8 -> ',  s8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], True);
+  CheckResult('u16 -> ', u16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], True);
+  CheckResult('s16 -> ', s16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], True);
+  CheckResult('u32 -> ', u32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], True);
+  CheckResult('s32 -> ', s32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], True);
+  CheckResult('u64 -> ', u64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], True);
+  CheckResult('s64 -> ', s64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], True);
+  WriteLn;
+
+  u8  := 26;
+  s8  := 26;
+  u16 := 26;
+  s16 := 26;
+  u32 := 26;
+  s32 := 26;
+  u64 := 26;
+  s64 := 26;
+
+  WriteLn('26, should be false');
+  CheckResult(' u8 -> ',  u8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult(' s8 -> ',  s8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('u16 -> ', u16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('s16 -> ', s16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('u32 -> ', u32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('s32 -> ', s32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('u64 -> ', u64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('s64 -> ', s64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  WriteLn;
+
+  u8  := 49;
+  s8  := 49;
+  u16 := 49;
+  s16 := 49;
+  u32 := 49;
+  s32 := 49;
+  u64 := 49;
+  s64 := 49;
+
+  WriteLn('49, should be false');
+  CheckResult(' u8 -> ',  u8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult(' s8 -> ',  s8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('u16 -> ', u16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('s16 -> ', s16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('u32 -> ', u32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('s32 -> ', s32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('u64 -> ', u64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('s64 -> ', s64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  WriteLn;
+
+//  u8  := 256;
+//  s8  := 256;
+  u16 := 256;
+  s16 := 256;
+  u32 := 256;
+  s32 := 256;
+  u64 := 256;
+  s64 := 256;
+
+  WriteLn('256, should be false');
+//  CheckResult(' u8 -> ',  u8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+//  CheckResult(' s8 -> ',  s8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('u16 -> ', u16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('s16 -> ', s16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('u32 -> ', u32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('s32 -> ', s32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('u64 -> ', u64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('s64 -> ', s64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  WriteLn;
+
+  u8  := High(u8);
+  s8  := High(s8);
+  u16 := High(u16);
+  s16 := High(s16);
+  u32 := High(u32);
+  s32 := High(s32);
+  u64 := High(u64);
+  s64 := High(s64);
+
+  WriteLn('High(type), should be false, u64/s64 should cause range check');
+  CheckResult(' u8 -> ',  u8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult(' s8 -> ',  s8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('u16 -> ', u16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('s16 -> ', s16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('u32 -> ', u32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('s32 -> ', s32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  try
+    CheckResult('u64 -> ', u64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41]);
+  except
+    on E: Exception do
+      WriteLn('u64 -> ', E.Classname,': ',E.Message);
+  end;
+  try
+    CheckResult('s64 -> ', s64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41]);
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+  u8  := Low(u8);
+  s8  := Low(s8);
+  u16 := Low(u16);
+  s16 := Low(s16);
+  u32 := Low(u32);
+  s32 := Low(s32);
+  u64 := Low(u64);
+  s64 := Low(s64);
+
+  WriteLn('Low(type), all false, except s64 -> range check error');
+  CheckResult('u8  -> ',  u8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('s8  -> ',  s8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('u16 -> ', u16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('s16 -> ', s16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('u32 -> ', u32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('s32 -> ', s32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('u64 -> ', u64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+
+  try
+    CheckResult('s64 -> ', s64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41]);
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+  WriteLn('--- constant value against constant set [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41] ---' );
+  WriteLn;
+
+  WriteLn('25, should be true');
+  CheckResult('25 -> ', 25 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], True);
+  WriteLn;
+
+  WriteLn('26, should be false');
+  CheckResult(' 26 -> ', 26 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  WriteLn;
+
+  WriteLn('49, should be false');
+  CheckResult('49 -> ', 49 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  WriteLn;
+
+  WriteLn('256, should be false');
+  CheckResult('256 -> ', 256 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  WriteLn;
+
+  WriteLn('High(type), should be false, u64/s64 should cause range check at compile time');
+  CheckResult(' u8 -> ', High(u8)  in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult(' s8 -> ', High(s8)  in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('u16 -> ', High(u16) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('s16 -> ', High(s16) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('u32 -> ', High(u32) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('s32 -> ', High(s32) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  try
+//    CheckResult('u64 -> ', High(u64) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+    WriteLn('u64 -> Error: range check error while evaluating constants');
+  except
+    on E: Exception do
+      WriteLn('u64 -> ', E.Classname,': ',E.Message);
+  end;
+  try
+//    CheckResult('s64 -> ', High(s64) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+    WriteLn('s64 -> Error: range check error while evaluating constants');
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+  WriteLn('Low(type), all false, except s64 -> range check error at compile time');
+  CheckResult('u8  -> ',  Low(u8) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('s8  -> ',  Low(s8) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('u16 -> ', Low(u16) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('s16 -> ', Low(s16) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('u32 -> ', Low(u32) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('s32 -> ', Low(s32) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+  CheckResult('u64 -> ', Low(u64) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+
+  try
+//    CheckResult('s64 -> ', Low(s64) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41], False);
+    WriteLn('s64 -> Error: range check error while evaluating constants');
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+  WriteLn('--- Variable against constant set [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29] ---' );
+  WriteLn;
+
+  u8  := 25;
+  s8  := 25;
+  u16 := 25;
+  s16 := 25;
+  u32 := 25;
+  s32 := 25;
+  u64 := 25;
+  s64 := 25;
+
+  WriteLn('25, should be true');
+  CheckResult(' u8 -> ',  u8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], True);
+  CheckResult(' s8 -> ',  s8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], True);
+  CheckResult('u16 -> ', u16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], True);
+  CheckResult('s16 -> ', s16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], True);
+  CheckResult('u32 -> ', u32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], True);
+  CheckResult('s32 -> ', s32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], True);
+  CheckResult('u64 -> ', u64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], True);
+  CheckResult('s64 -> ', s64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], True);
+  WriteLn;
+
+  u8  := 26;
+  s8  := 26;
+  u16 := 26;
+  s16 := 26;
+  u32 := 26;
+  s32 := 26;
+  u64 := 26;
+  s64 := 26;
+
+  WriteLn('26, should be false');
+  CheckResult(' u8 -> ',  u8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult(' s8 -> ',  s8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('u16 -> ', u16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('s16 -> ', s16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('u32 -> ', u32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('s32 -> ', s32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('u64 -> ', u64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('s64 -> ', s64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  WriteLn;
+
+  u8  := 30;
+  s8  := 30;
+  u16 := 30;
+  s16 := 30;
+  u32 := 30;
+  s32 := 30;
+  u64 := 30;
+  s64 := 30;
+
+  WriteLn('30, should be false');
+  CheckResult(' u8 -> ',  u8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult(' s8 -> ',  s8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('u16 -> ', u16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('s16 -> ', s16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('u32 -> ', u32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('s32 -> ', s32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('u64 -> ', u64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('s64 -> ', s64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  WriteLn;
+
+//  u8  := 256;
+//  s8  := 256;
+  u16 := 256;
+  s16 := 256;
+  u32 := 256;
+  s32 := 256;
+  u64 := 256;
+  s64 := 256;
+
+  WriteLn('256, should be false');
+//  CheckResult(' u8 -> ',  u8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+//  CheckResult(' s8 -> ',  s8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('u16 -> ', u16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('s16 -> ', s16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('u32 -> ', u32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('s32 -> ', s32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('u64 -> ', u64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('s64 -> ', s64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  WriteLn;
+
+  u8  := High(u8);
+  s8  := High(s8);
+  u16 := High(u16);
+  s16 := High(s16);
+  u32 := High(u32);
+  s32 := High(s32);
+  u64 := High(u64);
+  s64 := High(s64);
+
+  WriteLn('High(type), should be false, u64/s64 should cause range check');
+  CheckResult(' u8 -> ',  u8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult(' s8 -> ',  s8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('u16 -> ', u16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('s16 -> ', s16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('u32 -> ', u32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('s32 -> ', s32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  try
+    CheckResult('u64 -> ', u64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29]);
+  except
+    on E: Exception do
+      WriteLn('u64 -> ', E.Classname,': ',E.Message);
+  end;
+  try
+    CheckResult('s64 -> ', s64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29]);
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+  u8  := Low(u8);
+  s8  := Low(s8);
+  u16 := Low(u16);
+  s16 := Low(s16);
+  u32 := Low(u32);
+  s32 := Low(s32);
+  u64 := Low(u64);
+  s64 := Low(s64);
+
+  WriteLn('Low(type), all false, except s64 -> range check error');
+  CheckResult('u8  -> ',  u8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('s8  -> ',  s8 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('u16 -> ', u16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('s16 -> ', s16 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('u32 -> ', u32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('s32 -> ', s32 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('u64 -> ', u64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+
+  try
+    CheckResult('s64 -> ', s64 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29]);
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+  WriteLn('--- constant value against constant set [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29] ---' );
+  WriteLn;
+
+  WriteLn('25, should be true');
+  CheckResult('25 -> ', 25 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], True);
+  WriteLn;
+
+  WriteLn('26, should be false');
+  CheckResult(' 26 -> ', 26 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  WriteLn;
+
+  WriteLn('30, should be false');
+  CheckResult('30 -> ', 30 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  WriteLn;
+
+  WriteLn('256, should be false');
+  CheckResult('256 -> ', 256 in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  WriteLn;
+
+  WriteLn('High(type), should be false, u64/s64 should cause range check at compile time');
+  CheckResult(' u8 -> ', High(u8)  in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult(' s8 -> ', High(s8)  in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('u16 -> ', High(u16) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('s16 -> ', High(s16) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('u32 -> ', High(u32) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('s32 -> ', High(s32) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  try
+//    CheckResult('u64 -> ', High(u64) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+    WriteLn('u64 -> Error: range check error while evaluating constants');
+  except
+    on E: Exception do
+      WriteLn('u64 -> ', E.Classname,': ',E.Message);
+  end;
+  try
+//    CheckResult('s64 -> ', High(s64) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+    WriteLn('s64 -> Error: range check error while evaluating constants');
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+  WriteLn('Low(type), all false, except s64 -> range check error at compile time');
+  CheckResult('u8  -> ',  Low(u8) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('s8  -> ',  Low(s8) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('u16 -> ', Low(u16) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('s16 -> ', Low(s16) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('u32 -> ', Low(u32) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('s32 -> ', Low(s32) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+  CheckResult('u64 -> ', Low(u64) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+
+  try
+//    CheckResult('s64 -> ', Low(s64) in [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29], False);
+    WriteLn('s64 -> Error: range check error while evaluating constants');
+  except
+    on E: Exception do
+      WriteLn('s64 -> ', E.Classname,': ',E.Message);
+  end;
+  WriteLn;
+
+  if Error then begin
+    WriteLn('* * * ERROR * * * ERROR * * * ERROR * * * ERROR * * * ERROR * * * ERROR * * *');
+    Halt(1);
+  end else
+    Halt(0);
+end.