mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-25 20:49:43 +02:00
* 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:
parent
d29d9c672c
commit
d23c7980aa
@ -291,17 +291,17 @@ interface
|
|||||||
|
|
||||||
type
|
type
|
||||||
tperformrangecheck = (
|
tperformrangecheck = (
|
||||||
rc_internal, { never at all, internal conversion }
|
rc_internal, { nothing, internal conversion }
|
||||||
rc_explicit, { no, but this is a user conversion and hence can still give warnings in some cases }
|
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_default, { only if range checking is enabled }
|
rc_implicit, { no, but this is an implicit conversion and hence can still give warnings/errors in some cases }
|
||||||
rc_always { always }
|
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 }
|
{ for when used with nf_explicit/nf_internal/cs_check_range nodeflags }
|
||||||
procedure adaptrange(todef : tdef;var l : tconstexprint; internal, explicit: boolean);
|
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
|
if (rangecheck=rc_yes) or
|
||||||
(todef.typ=enumdef) or
|
(todef.typ=enumdef) then
|
||||||
(cs_check_range in current_settings.localswitches) 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;
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
@ -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,hl1,false,false,cs_check_range in current_settings.localswitches);
|
||||||
adaptrange(casedef,hl2,rc_default);
|
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user