2
0
Эх сурвалжийг харах

* properly perform (or not) range/overflow checking when performing constant
propagation into inlined routines, regardless of the range/overflow
checking state at the caller site

git-svn-id: trunk@43436 -

Jonas Maebe 5 жил өмнө
parent
commit
d23c7980aa

+ 13 - 12
compiler/defutil.pas

@@ -291,17 +291,17 @@ interface
 
 
   type
   type
     tperformrangecheck = (
     tperformrangecheck = (
-      rc_internal,  { never at all, internal conversion }
-      rc_explicit,  { no, but this is a user conversion and hence can still give warnings in some cases }
-      rc_default,   { only if range checking is enabled }
-      rc_always     { always }
+      rc_internal,  { nothing, internal conversion }
+      rc_explicit,  { no, but this is an explcit user conversion and hence can still give warnings in some cases (or errors in case of enums) }
+      rc_implicit,  { no, but this is an implicit conversion and hence can still give warnings/errors in some cases }
+      rc_yes        { yes }
     );
     );
     {# If @var(l) isn't in the range of todef a range check error (if not explicit) is generated and
     {# If @var(l) isn't in the range of todef a range check error (if not explicit) is generated and
       the value is placed within the range
       the value is placed within the range
     }
     }
     procedure adaptrange(todef : tdef;var l : tconstexprint; rangecheck: tperformrangecheck);
     procedure adaptrange(todef : tdef;var l : tconstexprint; rangecheck: tperformrangecheck);
-    { for when used with nf_explicit/nf_internal nodeflags }
-    procedure adaptrange(todef : tdef;var l : tconstexprint; internal, explicit: boolean);
+    { for when used with nf_explicit/nf_internal/cs_check_range nodeflags }
+    procedure adaptrange(todef : tdef;var l : tconstexprint; internal, explicit, rangecheckstate: boolean);
 
 
     {# Returns the range of def, where @var(l) is the low-range and @var(h) is
     {# Returns the range of def, where @var(l) is the low-range and @var(h) is
       the high-range.
       the high-range.
@@ -1107,11 +1107,10 @@ implementation
          if (l<lv) or (l>hv) then
          if (l<lv) or (l>hv) then
            begin
            begin
              warned:=false;
              warned:=false;
-             if rangecheck in [rc_default,rc_always] then
+             if rangecheck in [rc_implicit,rc_yes] then
                begin
                begin
-                 if (rangecheck=rc_always) or
-                    (todef.typ=enumdef) or
-                    (cs_check_range in current_settings.localswitches) then
+                 if (rangecheck=rc_yes) or
+                    (todef.typ=enumdef) then
                    Message3(type_e_range_check_error_bounds,tostr(l),tostr(lv),tostr(hv))
                    Message3(type_e_range_check_error_bounds,tostr(l),tostr(lv),tostr(hv))
                  else
                  else
                    Message3(type_w_range_check_error_bounds,tostr(l),tostr(lv),tostr(hv));
                    Message3(type_w_range_check_error_bounds,tostr(l),tostr(lv),tostr(hv));
@@ -1165,14 +1164,16 @@ implementation
       end;
       end;
 
 
 
 
-    procedure adaptrange(todef: tdef; var l: tconstexprint; internal, explicit: boolean);
+    procedure adaptrange(todef: tdef; var l: tconstexprint; internal, explicit, rangecheckstate: boolean);
       begin
       begin
         if internal then
         if internal then
           adaptrange(todef, l, rc_internal)
           adaptrange(todef, l, rc_internal)
         else if explicit then
         else if explicit then
           adaptrange(todef, l, rc_explicit)
           adaptrange(todef, l, rc_explicit)
+        else if not rangecheckstate then
+          adaptrange(todef, l, rc_implicit)
         else
         else
-          adaptrange(todef, l, rc_default)
+          adaptrange(todef, l, rc_yes)
       end;
       end;
 
 
 
 

+ 8 - 7
compiler/nadd.pas

@@ -593,7 +593,7 @@ implementation
                      t := cpointerconstnode.create(qword(v),resultdef)
                      t := cpointerconstnode.create(qword(v),resultdef)
                    else
                    else
                      if is_integer(ld) then
                      if is_integer(ld) then
-                       t := create_simplified_ord_const(v,resultdef,forinline)
+                       t := create_simplified_ord_const(v,resultdef,forinline,cs_check_overflow in localswitches)
                      else
                      else
                        t := cordconstnode.create(v,resultdef,(ld.typ<>enumdef));
                        t := cordconstnode.create(v,resultdef,(ld.typ<>enumdef));
                  end;
                  end;
@@ -618,7 +618,7 @@ implementation
                        t := cpointerconstnode.create(qword(v),resultdef)
                        t := cpointerconstnode.create(qword(v),resultdef)
                    else
                    else
                      if is_integer(ld) then
                      if is_integer(ld) then
-                       t := create_simplified_ord_const(v,resultdef,forinline)
+                       t := create_simplified_ord_const(v,resultdef,forinline,cs_check_overflow in localswitches)
                      else
                      else
                        t:=cordconstnode.create(v,resultdef,(ld.typ<>enumdef));
                        t:=cordconstnode.create(v,resultdef,(ld.typ<>enumdef));
                  end;
                  end;
@@ -632,21 +632,21 @@ implementation
                        t:=genintconstnode(0)
                        t:=genintconstnode(0)
                      end
                      end
                    else
                    else
-                     t := create_simplified_ord_const(v,resultdef,forinline)
+                     t := create_simplified_ord_const(v,resultdef,forinline,cs_check_overflow in localswitches)
                  end;
                  end;
                xorn :
                xorn :
                  if is_integer(ld) then
                  if is_integer(ld) then
-                   t := create_simplified_ord_const(lv xor rv,resultdef,forinline)
+                   t := create_simplified_ord_const(lv xor rv,resultdef,forinline,false)
                  else
                  else
                    t:=cordconstnode.create(lv xor rv,resultdef,true);
                    t:=cordconstnode.create(lv xor rv,resultdef,true);
                orn :
                orn :
                  if is_integer(ld) then
                  if is_integer(ld) then
-                   t:=create_simplified_ord_const(lv or rv,resultdef,forinline)
+                   t:=create_simplified_ord_const(lv or rv,resultdef,forinline,false)
                  else
                  else
                    t:=cordconstnode.create(lv or rv,resultdef,true);
                    t:=cordconstnode.create(lv or rv,resultdef,true);
                andn :
                andn :
                  if is_integer(ld) then
                  if is_integer(ld) then
-                   t:=create_simplified_ord_const(lv and rv,resultdef,forinline)
+                   t:=create_simplified_ord_const(lv and rv,resultdef,forinline,false)
                  else
                  else
                    t:=cordconstnode.create(lv and rv,resultdef,true);
                    t:=cordconstnode.create(lv and rv,resultdef,true);
                ltn :
                ltn :
@@ -671,7 +671,8 @@ implementation
                else
                else
                  internalerror(2008022101);
                  internalerror(2008022101);
              end;
              end;
-             include(t.flags,nf_internal);
+             if not forinline then
+               include(t.flags,nf_internal);
              result:=t;
              result:=t;
              exit;
              exit;
           end
           end

+ 2 - 2
compiler/ncnv.pas

@@ -1488,7 +1488,7 @@ implementation
                     v:=v div 10000;
                     v:=v div 10000;
                  end
                  end
                else if (resultdef.typ in [orddef,enumdef]) then
                else if (resultdef.typ in [orddef,enumdef]) then
-                 adaptrange(resultdef,v,([nf_internal,nf_absolute]*flags)<>[],nf_explicit in flags);
+                 adaptrange(resultdef,v,([nf_internal,nf_absolute]*flags)<>[],nf_explicit in flags,cs_check_range in localswitches);
                result:=cordconstnode.create(v,resultdef,false);
                result:=cordconstnode.create(v,resultdef,false);
              end;
              end;
          end
          end
@@ -3081,7 +3081,7 @@ implementation
                        { for constant values on absolute variables, swapping is required }
                        { for constant values on absolute variables, swapping is required }
                        if (target_info.endian = endian_big) and (nf_absolute in flags) then
                        if (target_info.endian = endian_big) and (nf_absolute in flags) then
                          swap_const_value(tordconstnode(left).value,tordconstnode(left).resultdef.size);
                          swap_const_value(tordconstnode(left).value,tordconstnode(left).resultdef.size);
-                       adaptrange(resultdef,tordconstnode(left).value,([nf_internal,nf_absolute]*flags)<>[],nf_explicit in flags);
+                       adaptrange(resultdef,tordconstnode(left).value,([nf_internal,nf_absolute]*flags)<>[],nf_explicit in flags,cs_check_range in localswitches);
                        { swap value back, but according to new type }
                        { swap value back, but according to new type }
                        if (target_info.endian = endian_big) and (nf_absolute in flags) then
                        if (target_info.endian = endian_big) and (nf_absolute in flags) then
                          swap_const_value(tordconstnode(left).value,resultdef.size);
                          swap_const_value(tordconstnode(left).value,resultdef.size);

+ 1 - 1
compiler/ncon.pas

@@ -619,7 +619,7 @@ implementation
         { only do range checking when explicitly asked for it
         { only do range checking when explicitly asked for it
           and if the type can be range checked, see tests/tbs/tb0539.pp }
           and if the type can be range checked, see tests/tbs/tb0539.pp }
         if (resultdef.typ in [orddef,enumdef]) then
         if (resultdef.typ in [orddef,enumdef]) then
-          adaptrange(resultdef,value,nf_internal in flags, not rangecheck)
+          adaptrange(resultdef,value,nf_internal in flags,not rangecheck,rangecheck)
       end;
       end;
 
 
     function tordconstnode.pass_1 : tnode;
     function tordconstnode.pass_1 : tnode;

+ 3 - 3
compiler/ngtcon.pas

@@ -640,7 +640,7 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
              begin
              begin
                 if is_constboolnode(node) then
                 if is_constboolnode(node) then
                   begin
                   begin
-                    adaptrange(def,tordconstnode(node).value,rc_default);
+                    adaptrange(def,tordconstnode(node).value,false,false,cs_check_range in current_settings.localswitches);
                     ftcb.emit_ord_const(tordconstnode(node).value.svalue,def)
                     ftcb.emit_ord_const(tordconstnode(node).value.svalue,def)
                   end
                   end
                 else
                 else
@@ -674,7 +674,7 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
              begin
              begin
                 if is_constintnode(node) then
                 if is_constintnode(node) then
                   begin
                   begin
-                    adaptrange(def,tordconstnode(node).value,rc_default);
+                    adaptrange(def,tordconstnode(node).value,false,false,cs_check_range in current_settings.localswitches);
                     ftcb.emit_ord_const(tordconstnode(node).value.svalue,def);
                     ftcb.emit_ord_const(tordconstnode(node).value.svalue,def);
                   end
                   end
                 else
                 else
@@ -1087,7 +1087,7 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
             if equal_defs(node.resultdef,def) or
             if equal_defs(node.resultdef,def) or
                is_subequal(node.resultdef,def) then
                is_subequal(node.resultdef,def) then
               begin
               begin
-                adaptrange(def,tordconstnode(node).value,rc_default);
+                adaptrange(def,tordconstnode(node).value,false,false,cs_check_range in current_settings.localswitches);
                 case longint(node.resultdef.size) of
                 case longint(node.resultdef.size) of
                   1 : ftcb.emit_tai(Tai_const.Create_8bit(Byte(tordconstnode(node).value.svalue)),def);
                   1 : ftcb.emit_tai(Tai_const.Create_8bit(Byte(tordconstnode(node).value.svalue)),def);
                   2 : ftcb.emit_tai(Tai_const.Create_16bit(Word(tordconstnode(node).value.svalue)),def);
                   2 : ftcb.emit_tai(Tai_const.Create_16bit(Word(tordconstnode(node).value.svalue)),def);

+ 7 - 7
compiler/ninl.pas

@@ -2283,14 +2283,14 @@ implementation
                case inlinenumber of
                case inlinenumber of
                  in_const_abs :
                  in_const_abs :
                    if vl.signed then
                    if vl.signed then
-                     hp:=create_simplified_ord_const(abs(vl.svalue),resultdef,forinline)
+                     hp:=create_simplified_ord_const(abs(vl.svalue),resultdef,forinline,false)
                    else
                    else
-                     hp:=create_simplified_ord_const(vl.uvalue,resultdef,forinline);
+                     hp:=create_simplified_ord_const(vl.uvalue,resultdef,forinline,false);
                  in_const_sqr:
                  in_const_sqr:
                    if vl.signed then
                    if vl.signed then
-                     hp:=create_simplified_ord_const(sqr(vl.svalue),resultdef,forinline)
+                     hp:=create_simplified_ord_const(sqr(vl.svalue),resultdef,forinline,false)
                    else
                    else
-                     hp:=create_simplified_ord_const(sqr(vl.uvalue),resultdef,forinline);
+                     hp:=create_simplified_ord_const(sqr(vl.uvalue),resultdef,forinline,false);
                  in_const_odd :
                  in_const_odd :
                    hp:=cordconstnode.create(qword(odd(int64(vl))),pasbool1type,true);
                    hp:=cordconstnode.create(qword(odd(int64(vl))),pasbool1type,true);
                  in_const_swap_word :
                  in_const_swap_word :
@@ -2520,7 +2520,7 @@ implementation
                           { the type of the original integer constant is irrelevant,
                           { the type of the original integer constant is irrelevant,
                             it should be automatically adapted to the new value
                             it should be automatically adapted to the new value
                             (except when inlining) }
                             (except when inlining) }
-                          result:=create_simplified_ord_const(vl,resultdef,forinline)
+                          result:=create_simplified_ord_const(vl,resultdef,forinline,cs_check_range in localswitches)
                         else
                         else
                           { check the range for enums, chars, booleans }
                           { check the range for enums, chars, booleans }
                           result:=cordconstnode.create(vl,left.resultdef,not(nf_internal in flags));
                           result:=cordconstnode.create(vl,left.resultdef,not(nf_internal in flags));
@@ -2870,9 +2870,9 @@ implementation
                  (index.left.nodetype = ordconstn) and
                  (index.left.nodetype = ordconstn) and
                  not is_special_array(unpackedarraydef) then
                  not is_special_array(unpackedarraydef) then
                 begin
                 begin
-                  adaptrange(unpackedarraydef,tordconstnode(index.left).value,rc_default);
+                  adaptrange(unpackedarraydef,tordconstnode(index.left).value,false,false,cs_check_range in current_settings.localswitches);
                   tempindex := tordconstnode(index.left).value + packedarraydef.highrange-packedarraydef.lowrange;
                   tempindex := tordconstnode(index.left).value + packedarraydef.highrange-packedarraydef.lowrange;
-                  adaptrange(unpackedarraydef,tempindex,rc_default);
+                  adaptrange(unpackedarraydef,tempindex,false,false,cs_check_range in current_settings.localswitches);
                 end;
                 end;
             end;
             end;
 
 

+ 8 - 8
compiler/nmat.pas

@@ -164,17 +164,17 @@ implementation
                 if nf_isomod in flags then
                 if nf_isomod in flags then
                   begin
                   begin
                     if lv>=0 then
                     if lv>=0 then
-                      result:=create_simplified_ord_const(lv mod rv,resultdef,forinline)
+                      result:=create_simplified_ord_const(lv mod rv,resultdef,forinline,false)
                     else
                     else
                       if ((-lv) mod rv)=0 then
                       if ((-lv) mod rv)=0 then
-                        result:=create_simplified_ord_const((-lv) mod rv,resultdef,forinline)
+                        result:=create_simplified_ord_const((-lv) mod rv,resultdef,forinline,false)
                       else
                       else
-                        result:=create_simplified_ord_const(rv-((-lv) mod rv),resultdef,forinline);
+                        result:=create_simplified_ord_const(rv-((-lv) mod rv),resultdef,forinline,false);
                   end
                   end
                 else
                 else
-                  result:=create_simplified_ord_const(lv mod rv,resultdef,forinline);
+                  result:=create_simplified_ord_const(lv mod rv,resultdef,forinline,false);
               divn:
               divn:
-                result:=create_simplified_ord_const(lv div rv,resultdef,forinline);
+                result:=create_simplified_ord_const(lv div rv,resultdef,forinline,cs_check_overflow in localswitches);
               else
               else
                 internalerror(2019050519);
                 internalerror(2019050519);
             end;
             end;
@@ -729,9 +729,9 @@ implementation
                    lvalue:=tordconstnode(left).value;
                    lvalue:=tordconstnode(left).value;
                  case nodetype of
                  case nodetype of
                     shrn:
                     shrn:
-                      result:=create_simplified_ord_const(lvalue shr rvalue,resultdef,forinline);
+                      result:=create_simplified_ord_const(lvalue shr rvalue,resultdef,forinline,false);
                     shln:
                     shln:
-                      result:=create_simplified_ord_const(lvalue shl rvalue,resultdef,forinline);
+                      result:=create_simplified_ord_const(lvalue shl rvalue,resultdef,forinline,false);
                     else
                     else
                       internalerror(2019050517);
                       internalerror(2019050517);
                  end;
                  end;
@@ -916,7 +916,7 @@ implementation
         { constant folding }
         { constant folding }
         if is_constintnode(left) then
         if is_constintnode(left) then
           begin
           begin
-             result:=create_simplified_ord_const(-tordconstnode(left).value,resultdef,forinline);
+             result:=create_simplified_ord_const(-tordconstnode(left).value,resultdef,forinline,cs_check_overflow in localswitches);
              exit;
              exit;
           end;
           end;
         if is_constrealnode(left) then
         if is_constrealnode(left) then

+ 3 - 3
compiler/nutils.pas

@@ -102,7 +102,7 @@ interface
       which was determined during an earlier typecheck pass (because the value
       which was determined during an earlier typecheck pass (because the value
       may e.g. be a parameter to a call, which needs to be of the declared
       may e.g. be a parameter to a call, which needs to be of the declared
       parameter type) }
       parameter type) }
-    function create_simplified_ord_const(const value: tconstexprint; def: tdef; forinline: boolean): tnode;
+    function create_simplified_ord_const(const value: tconstexprint; def: tdef; forinline, rangecheck: boolean): tnode;
 
 
     { returns true if n is only a tree of administrative nodes
     { returns true if n is only a tree of administrative nodes
       containing no code }
       containing no code }
@@ -1139,12 +1139,12 @@ implementation
       end;
       end;
 
 
 
 
-    function create_simplified_ord_const(const value: tconstexprint; def: tdef; forinline: boolean): tnode;
+    function create_simplified_ord_const(const value: tconstexprint; def: tdef; forinline, rangecheck: boolean): tnode;
       begin
       begin
         if not forinline then
         if not forinline then
           result:=genintconstnode(value)
           result:=genintconstnode(value)
         else
         else
-          result:=cordconstnode.create(value,def,cs_check_range in current_settings.localswitches);
+          result:=cordconstnode.create(value,def,rangecheck);
       end;
       end;
 
 
 
 

+ 4 - 4
compiler/pstatmnt.pas

@@ -223,8 +223,8 @@ implementation
                        CGMessage(parser_e_case_lower_less_than_upper_bound);
                        CGMessage(parser_e_case_lower_less_than_upper_bound);
                      if not casedeferror then
                      if not casedeferror then
                        begin
                        begin
-                         adaptrange(casedef,hl1,rc_default);
-                         adaptrange(casedef,hl2,rc_default);
+                         adaptrange(casedef,hl1,false,false,cs_check_range in current_settings.localswitches);
+                         adaptrange(casedef,hl2,false,false,cs_check_range in current_settings.localswitches);
                        end;
                        end;
                    end
                    end
                  else
                  else
@@ -252,7 +252,7 @@ implementation
                    begin
                    begin
                      hl1:=get_ordinal_value(p);
                      hl1:=get_ordinal_value(p);
                      if not casedeferror then
                      if not casedeferror then
-                       adaptrange(casedef,hl1,rc_default);
+                       adaptrange(casedef,hl1,false,false,cs_check_range in current_settings.localswitches);
                      casenode.addlabel(blockid,hl1,hl1);
                      casenode.addlabel(blockid,hl1,hl1);
                    end;
                    end;
                end;
                end;
@@ -362,7 +362,7 @@ implementation
           begin
           begin
             if (hp.nodetype=ordconstn) and
             if (hp.nodetype=ordconstn) and
                (fordef.typ<>errordef) then
                (fordef.typ<>errordef) then
-              adaptrange(fordef,tordconstnode(hp).value,rc_always);
+              adaptrange(fordef,tordconstnode(hp).value,false,false,true);
           end;
           end;
 
 
         function for_loop_create(hloopvar: tnode): tnode;
         function for_loop_create(hloopvar: tnode): tnode;