* 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 -
This commit is contained in:
Jonas Maebe 2019-11-10 12:00:05 +00:00
parent d29d9c672c
commit d23c7980aa
9 changed files with 49 additions and 47 deletions

View File

@ -291,17 +291,17 @@ interface
type
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
the value is placed within the range
}
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
the high-range.
@ -1107,11 +1107,10 @@ implementation
if (l<lv) or (l>hv) then
begin
warned:=false;
if rangecheck in [rc_default,rc_always] then
if rangecheck in [rc_implicit,rc_yes] then
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))
else
Message3(type_w_range_check_error_bounds,tostr(l),tostr(lv),tostr(hv));
@ -1165,14 +1164,16 @@ implementation
end;
procedure adaptrange(todef: tdef; var l: tconstexprint; internal, explicit: boolean);
procedure adaptrange(todef: tdef; var l: tconstexprint; internal, explicit, rangecheckstate: boolean);
begin
if internal then
adaptrange(todef, l, rc_internal)
else if explicit then
adaptrange(todef, l, rc_explicit)
else if not rangecheckstate then
adaptrange(todef, l, rc_implicit)
else
adaptrange(todef, l, rc_default)
adaptrange(todef, l, rc_yes)
end;

View File

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

View File

@ -1488,7 +1488,7 @@ implementation
v:=v div 10000;
end
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);
end;
end
@ -3081,7 +3081,7 @@ implementation
{ for constant values on absolute variables, swapping is required }
if (target_info.endian = endian_big) and (nf_absolute in flags) then
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 }
if (target_info.endian = endian_big) and (nf_absolute in flags) then
swap_const_value(tordconstnode(left).value,resultdef.size);

View File

@ -619,7 +619,7 @@ implementation
{ only do range checking when explicitly asked for it
and if the type can be range checked, see tests/tbs/tb0539.pp }
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;
function tordconstnode.pass_1 : tnode;

View File

@ -640,7 +640,7 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
begin
if is_constboolnode(node) then
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)
end
else
@ -674,7 +674,7 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
begin
if is_constintnode(node) then
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);
end
else
@ -1087,7 +1087,7 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
if equal_defs(node.resultdef,def) or
is_subequal(node.resultdef,def) then
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
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);

View File

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

View File

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

View File

@ -102,7 +102,7 @@ interface
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
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
containing no code }
@ -1139,12 +1139,12 @@ implementation
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
if not forinline then
result:=genintconstnode(value)
else
result:=cordconstnode.create(value,def,cs_check_range in current_settings.localswitches);
result:=cordconstnode.create(value,def,rangecheck);
end;

View File

@ -223,8 +223,8 @@ implementation
CGMessage(parser_e_case_lower_less_than_upper_bound);
if not casedeferror then
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
else
@ -252,7 +252,7 @@ implementation
begin
hl1:=get_ordinal_value(p);
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);
end;
end;
@ -362,7 +362,7 @@ implementation
begin
if (hp.nodetype=ordconstn) and
(fordef.typ<>errordef) then
adaptrange(fordef,tordconstnode(hp).value,rc_always);
adaptrange(fordef,tordconstnode(hp).value,false,false,true);
end;
function for_loop_create(hloopvar: tnode): tnode;