Procházet zdrojové kódy

* fixed range checking for inc/dec when mixing unsigned and signed types
(mantis #14841)
-> this also makes it impossible now to use constructs such as
inc(qword_var,-1) with range checking enabled, because that would require
a conversion to 128 bit for proper evaluation

git-svn-id: trunk@14260 -

Jonas Maebe před 15 roky
rodič
revize
2c3c6d27d3
5 změnil soubory, kde provedl 32 přidání a 6 odebrání
  1. 1 0
      .gitattributes
  2. 6 4
      compiler/ncginl.pas
  3. 8 1
      compiler/ninl.pas
  4. 12 0
      tests/webtbs/tw14841.pp
  5. 5 1
      tests/webtbs/tw4152.pp

+ 1 - 0
.gitattributes

@@ -10083,6 +10083,7 @@ tests/webtbs/tw1477.pp svneol=native#text/plain
 tests/webtbs/tw1479.pp svneol=native#text/plain
 tests/webtbs/tw14798.pp svneol=native#text/plain
 tests/webtbs/tw14812.pp svneol=native#text/plain
+tests/webtbs/tw14841.pp svneol=native#text/plain
 tests/webtbs/tw1485.pp svneol=native#text/plain
 tests/webtbs/tw1489.pp svneol=native#text/plain
 tests/webtbs/tw14958a.pp svneol=native#text/plain

+ 6 - 4
compiler/ncginl.pas

@@ -491,11 +491,13 @@ implementation
               { Or someone has to rewrite the above to use a_op_const_reg_reg_ov  }
               { and friends in case of overflow checking, and ask everyone to     }
               { implement these methods since they don't exist for all cpus (JM)  }
-              if (cs_check_overflow in current_settings.localswitches) then
+              { Similarly, range checking also has to be handled separately, }
+              { see mantis #14841 (JM)                                       }
+              if ([cs_check_overflow,cs_check_range] * current_settings.localswitches <> []) then
                 internalerror(2006111010);
-    //          cg.g_overflowcheck(current_asmdata.CurrAsmList,tcallparanode(left).left.location,tcallparanode(left).resultdef);
-              cg.g_rangecheck(current_asmdata.CurrAsmList,tcallparanode(left).left.location,tcallparanode(left).left.resultdef,
-                 tcallparanode(left).left.resultdef);
+//              cg.g_overflowcheck(current_asmdata.CurrAsmList,tcallparanode(left).left.location,tcallparanode(left).resultdef);
+//              cg.g_rangecheck(current_asmdata.CurrAsmList,tcallparanode(left).left.location,tcallparanode(left).left.resultdef,
+//                 tcallparanode(left).left.resultdef);
             end;
         end;
 

+ 8 - 1
compiler/ninl.pas

@@ -2205,7 +2205,14 @@ implementation
                              if is_integer(tcallparanode(left).right.resultdef) then
                                begin
                                  set_varstate(tcallparanode(tcallparanode(left).right).left,vs_read,[vsf_must_be_valid]);
-                                 inserttypeconv_internal(tcallparanode(tcallparanode(left).right).left,tcallparanode(left).left.resultdef);
+                                 { when range/overflow checking is on, we
+                                   convert this to a regular add, and for proper
+                                   checking we need the original type }
+                                 if ([cs_check_range,cs_check_overflow]*current_settings.localswitches=[]) then
+                                   if is_integer(tcallparanode(left).left.resultdef) then
+                                     inserttypeconv(tcallparanode(tcallparanode(left).right).left,tcallparanode(left).left.resultdef)
+                                   else
+                                     inserttypeconv_internal(tcallparanode(tcallparanode(left).right).left,tcallparanode(left).left.resultdef);
                                  if assigned(tcallparanode(tcallparanode(left).right).right) then
                                    { should be handled in the parser (JM) }
                                    internalerror(2006020901);

+ 12 - 0
tests/webtbs/tw14841.pp

@@ -0,0 +1,12 @@
+{$r+,o+}
+var
+b: byte;
+s: shortint;
+begin
+  b:=57;
+  s:=-1;
+  inc(b, s);
+  if b<>56 then
+    halt(1);
+end.
+

+ 5 - 1
tests/webtbs/tw4152.pp

@@ -1,7 +1,7 @@
 { Source provided for Free Pascal Bug Report 4152 }
 { Submitted by "C Western" on  2005-07-03 }
 { e-mail: [email protected] }
-{$R+}{$Q+}
+{R+}{Q+}
 var
   p:^Byte;
   c:Byte;
@@ -13,7 +13,11 @@ var
 {$endif}
 begin
   v:=100;
+{$ifdef cpu32}
+  { this gets translated into "v:=v+(-1)", and the compiler would require 128bit
+    arithmetic to calculate this when v is a qword and range checking is on }
   inc(v,-1);
+{$endif cpu32}
   p:=@c;
   Inc(p,-1);  // Gives compile time error: range check error while evaluating constants
   d:=2;