mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-10-21 21:41:37 +02:00
+ tfornode.simply which removes for loops being never executed
* handle function results correctly in life dfa * handle for loops with at least one iteration better in life dfa o resolves #8151 git-svn-id: trunk@11624 -
This commit is contained in:
parent
512ffe26f5
commit
1c0bd054f4
8
.gitattributes
vendored
8
.gitattributes
vendored
@ -8111,6 +8111,8 @@ tests/webtbf/tw11295b.pp svneol=native#text/plain
|
||||
tests/webtbf/tw1157a.pp svneol=native#text/plain
|
||||
tests/webtbf/tw11619b.pp svneol=native#text/plain
|
||||
tests/webtbf/tw11632.pp svneol=native#text/plain
|
||||
tests/webtbf/tw11846.pp svneol=native#text/plain
|
||||
tests/webtbf/tw11846c.pp svneol=native#text/plain
|
||||
tests/webtbf/tw11848a.pp svneol=native#text/plain
|
||||
tests/webtbf/tw11849a.pp svneol=native#text/plain
|
||||
tests/webtbf/tw11862a.pp svneol=native#text/plain
|
||||
@ -8300,6 +8302,8 @@ tests/webtbf/tw8150c.pp svneol=native#text/plain
|
||||
tests/webtbf/tw8150e.pp svneol=native#text/plain
|
||||
tests/webtbf/tw8150f.pp svneol=native#text/plain
|
||||
tests/webtbf/tw8150g.pp svneol=native#text/plain
|
||||
tests/webtbf/tw8151b.pp svneol=native#text/plain
|
||||
tests/webtbf/tw8151c.pp svneol=native#text/plain
|
||||
tests/webtbf/tw8264a.pp svneol=native#text/plain
|
||||
tests/webtbf/tw8398.pp svneol=native#text/plain
|
||||
tests/webtbf/tw8451.pp svneol=native#text/plain
|
||||
@ -8549,7 +8553,8 @@ tests/webtbs/tw1157.pp svneol=native#text/plain
|
||||
tests/webtbs/tw1157b.pp svneol=native#text/plain
|
||||
tests/webtbs/tw11619.pp svneol=native#text/plain
|
||||
tests/webtbs/tw1181.pp svneol=native#text/plain
|
||||
tests/webtbs/tw11846.pp svneol=native#text/plain
|
||||
tests/webtbs/tw11846a.pp svneol=native#text/plain
|
||||
tests/webtbs/tw11846b.pp svneol=native#text/plain
|
||||
tests/webtbs/tw11848.pp svneol=native#text/plain
|
||||
tests/webtbs/tw11849.pp svneol=native#text/plain
|
||||
tests/webtbs/tw11852.pp svneol=native#text/plain
|
||||
@ -9315,6 +9320,7 @@ tests/webtbs/tw8145.pp svneol=native#text/plain
|
||||
tests/webtbs/tw8148.pp svneol=native#text/plain
|
||||
tests/webtbs/tw8150a.pp svneol=native#text/plain
|
||||
tests/webtbs/tw8150d.pp svneol=native#text/plain
|
||||
tests/webtbs/tw8151a.pp svneol=native#text/plain
|
||||
tests/webtbs/tw8153.pp svneol=native#text/plain
|
||||
tests/webtbs/tw8153a.pp svneol=native#text/plain
|
||||
tests/webtbs/tw8155.pp svneol=native#text/plain
|
||||
|
@ -101,6 +101,7 @@ interface
|
||||
procedure loop_var_access(not_type:Tnotification_flag;symbol:Tsym);
|
||||
function pass_typecheck:tnode;override;
|
||||
function pass_1 : tnode;override;
|
||||
function simplify : tnode;override;
|
||||
end;
|
||||
tfornodeclass = class of tfornode;
|
||||
|
||||
@ -764,6 +765,26 @@ implementation
|
||||
Tabstractvarsym(symbol).unregister_notification(loopvar_notid);
|
||||
end;
|
||||
|
||||
|
||||
function tfornode.simplify : tnode;
|
||||
begin
|
||||
result:=nil;
|
||||
if (t1.nodetype=ordconstn) and
|
||||
(right.nodetype=ordconstn) and
|
||||
(
|
||||
(
|
||||
(lnf_backward in loopflags) and
|
||||
(tordconstnode(right).value<tordconstnode(t1).value)
|
||||
) or
|
||||
(
|
||||
not(lnf_backward in loopflags) and
|
||||
(tordconstnode(right).value>tordconstnode(t1).value)
|
||||
)
|
||||
) then
|
||||
result:=cnothingnode.create;
|
||||
end;
|
||||
|
||||
|
||||
function tfornode.pass_typecheck:tnode;
|
||||
var
|
||||
unrollres : tnode;
|
||||
|
@ -204,8 +204,20 @@ unit optdfa;
|
||||
end
|
||||
else
|
||||
begin
|
||||
l:=n.optinfo^.use;
|
||||
DFASetIncludeSet(l,n.optinfo^.life);
|
||||
{ last node, not exit or raise node and function? }
|
||||
if assigned(resultnode) and
|
||||
not(node.nodetype in [raisen,exitn]) then
|
||||
begin
|
||||
{ if yes, result lifes }
|
||||
DFASetDiff(l,resultnode.optinfo^.life,n.optinfo^.def);
|
||||
DFASetIncludeSet(l,n.optinfo^.use);
|
||||
DFASetIncludeSet(l,n.optinfo^.life);
|
||||
end
|
||||
else
|
||||
begin
|
||||
l:=n.optinfo^.use;
|
||||
DFASetIncludeSet(l,n.optinfo^.life);
|
||||
end;
|
||||
end;
|
||||
updatelifeinfo(n,l);
|
||||
end;
|
||||
@ -275,7 +287,9 @@ unit optdfa;
|
||||
t1: to
|
||||
t2: body
|
||||
}
|
||||
calclife(node);
|
||||
{ take care of the sucessor if it's possible that we don't have one execution of the body }
|
||||
if not((tfornode(node).right.nodetype=ordconstn) and (tfornode(node).t1.nodetype=ordconstn)) then
|
||||
calclife(node);
|
||||
node.allocoptinfo;
|
||||
if not(assigned(node.optinfo^.def)) and
|
||||
not(assigned(node.optinfo^.use)) then
|
||||
@ -287,9 +301,11 @@ unit optdfa;
|
||||
foreachnodestatic(pm_postprocess,tfornode(node).right,@AddDefUse,@dfainfo);
|
||||
foreachnodestatic(pm_postprocess,tfornode(node).t1,@AddDefUse,@dfainfo);
|
||||
end;
|
||||
calclife(node);
|
||||
{ take care of the sucessor if it's possible that we don't have one execution of the body }
|
||||
if not((tfornode(node).right.nodetype=ordconstn) and (tfornode(node).t1.nodetype=ordconstn)) then
|
||||
calclife(node);
|
||||
|
||||
{ create life the body }
|
||||
{ create life for the body }
|
||||
CreateInfo(tfornode(node).t2);
|
||||
|
||||
{ update for node }
|
||||
@ -360,7 +376,12 @@ unit optdfa;
|
||||
DFASetIncludeSet(l,tifnode(node).t1.optinfo^.life)
|
||||
else
|
||||
if assigned(node.successor) then
|
||||
DFASetIncludeSet(l,node.successor.optinfo^.life);
|
||||
DFASetIncludeSet(l,node.successor.optinfo^.life)
|
||||
{ last node and function? }
|
||||
else
|
||||
if assigned(resultnode) then
|
||||
DFASetIncludeSet(l,resultnode.optinfo^.life);
|
||||
|
||||
{ add use info from the cond. expression }
|
||||
DFASetIncludeSet(l,tifnode(node).optinfo^.use);
|
||||
{ finally, update the life info of the node }
|
||||
@ -397,7 +418,11 @@ unit optdfa;
|
||||
DFASetIncludeSet(l,tcasenode(node).elseblock.optinfo^.life)
|
||||
else
|
||||
if assigned(node.successor) then
|
||||
DFASetIncludeSet(l,node.successor.optinfo^.life);
|
||||
DFASetIncludeSet(l,node.successor.optinfo^.life)
|
||||
{ last node and function? }
|
||||
else
|
||||
if assigned(resultnode) then
|
||||
DFASetIncludeSet(l,resultnode.optinfo^.life);
|
||||
|
||||
{ add use info from the "case" expression }
|
||||
DFASetIncludeSet(l,tcasenode(node).optinfo^.use);
|
||||
@ -502,6 +527,7 @@ unit optdfa;
|
||||
dfarec.def:=@resultnode.optinfo^.def;
|
||||
dfarec.map:=map;
|
||||
AddDefUse(resultnode,@dfarec);
|
||||
resultnode.optinfo^.life:=resultnode.optinfo^.use;
|
||||
end
|
||||
else
|
||||
resultnode:=nil;
|
||||
@ -530,40 +556,13 @@ unit optdfa;
|
||||
|
||||
|
||||
procedure TDFABuilder.createdfainfo(node : tnode);
|
||||
{
|
||||
var
|
||||
lastnode : tnode;
|
||||
fakeexitnode : texitnode;
|
||||
}
|
||||
begin
|
||||
if not(assigned(nodemap)) then
|
||||
nodemap:=TIndexedNodeSet.Create;
|
||||
{ add controll flow information }
|
||||
SetNodeSucessors(node);
|
||||
{
|
||||
{ create an exit node for functions to get
|
||||
the function result at the end handled properly }
|
||||
if not(is_void(current_procinfo.procdef.returndef)) and
|
||||
not(current_procinfo.procdef.proctypeoption=potype_constructor) then
|
||||
begin
|
||||
lastnode:=node;
|
||||
while assigned(lastnode.successor) do
|
||||
lastnode:=lastnode.successor;
|
||||
fakeexitnode:=cexitnode.create(nil);
|
||||
lastnode.successor:=fakeexitnode;
|
||||
end
|
||||
else
|
||||
fakeexitnode:=nil;
|
||||
}
|
||||
{ now, collect life information }
|
||||
CreateLifeInfo(node,nodemap);
|
||||
{
|
||||
if assigned(fakeexitnode) then
|
||||
begin
|
||||
lastnode.successor.free;
|
||||
lastnode.successor:=nil;
|
||||
end;
|
||||
}
|
||||
end;
|
||||
|
||||
|
||||
|
14
tests/webtbf/tw11846.pp
Normal file
14
tests/webtbf/tw11846.pp
Normal file
@ -0,0 +1,14 @@
|
||||
{ %OPT=-Sew -Oodfa }
|
||||
{ %NORUN }
|
||||
{ %fail }
|
||||
{$mode objfpc}
|
||||
function Test(a: integer): boolean;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
for i:=1 to a do
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
begin
|
||||
end.
|
14
tests/webtbf/tw11846c.pp
Normal file
14
tests/webtbf/tw11846c.pp
Normal file
@ -0,0 +1,14 @@
|
||||
{ %OPT=-Sew -Oodfa }
|
||||
{ %NORUN }
|
||||
{ %fail }
|
||||
{$mode objfpc}
|
||||
function Test(a: integer): boolean;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
for i:=2 to 1 do
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
begin
|
||||
end.
|
21
tests/webtbf/tw8151b.pp
Normal file
21
tests/webtbf/tw8151b.pp
Normal file
@ -0,0 +1,21 @@
|
||||
{ %opt=-Oodfa -Sew } program FunctionResultAnalysisWrong;
|
||||
{ %fail }
|
||||
{$IFDEF FPC}
|
||||
{$mode delphi}
|
||||
{$ENDIF}
|
||||
|
||||
uses
|
||||
SysUtils;
|
||||
|
||||
var
|
||||
I : longint;
|
||||
|
||||
function Test3: Integer;
|
||||
begin
|
||||
if i > 0 then
|
||||
raise Exception.Create('')
|
||||
end; {SHOULD generate "Warning: Function result does not seem to be set", and does in both delphi and FPC}
|
||||
|
||||
begin
|
||||
i:=1;
|
||||
end.
|
22
tests/webtbf/tw8151c.pp
Normal file
22
tests/webtbf/tw8151c.pp
Normal file
@ -0,0 +1,22 @@
|
||||
{ %opt=-Oodfa -Sew } program FunctionResultAnalysisWrong;
|
||||
{ %fail }
|
||||
{$IFDEF FPC}
|
||||
{$mode delphi}
|
||||
{$ENDIF}
|
||||
|
||||
uses
|
||||
SysUtils;
|
||||
|
||||
var
|
||||
I : longint;
|
||||
|
||||
function Test5: Integer;
|
||||
begin
|
||||
if i > 0 then
|
||||
Result := 0;
|
||||
end; {SHOULD generate "Warning: Function result does not seem to be set", does in delphi, not in FPC }
|
||||
|
||||
|
||||
begin
|
||||
i:=1;
|
||||
end.
|
14
tests/webtbs/tw11846b.pp
Normal file
14
tests/webtbs/tw11846b.pp
Normal file
@ -0,0 +1,14 @@
|
||||
{ %OPT=-Sew -Oodfa }
|
||||
{ %NORUN }
|
||||
{$mode objfpc}
|
||||
function Test(a: integer): boolean;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
for i:=2 to 1 do
|
||||
Result:=true;
|
||||
Result:=true;
|
||||
end;
|
||||
|
||||
begin
|
||||
end.
|
36
tests/webtbs/tw8151a.pp
Normal file
36
tests/webtbs/tw8151a.pp
Normal file
@ -0,0 +1,36 @@
|
||||
{ %opt=-Oodfa -Sew } program FunctionResultAnalysisWrong;
|
||||
{ %norun }
|
||||
{$IFDEF FPC}
|
||||
{$mode delphi}
|
||||
{$ENDIF}
|
||||
|
||||
uses
|
||||
SysUtils;
|
||||
|
||||
var
|
||||
I : longint;
|
||||
|
||||
function Test1: Integer;
|
||||
begin
|
||||
raise Exception.Create('');
|
||||
end; {should NOT generate "Warning: Function result does not seem to be set" (doesn't in delphi, does in FPC) }
|
||||
|
||||
function Test2: Integer;
|
||||
begin
|
||||
if i > 0 then
|
||||
raise Exception.Create('')
|
||||
else
|
||||
raise Exception.Create('');
|
||||
end; {should NOT generate "Warning: Function result does not seem to be set" (doesn't in delphi, does in FPC) }
|
||||
|
||||
function Test4: Integer;
|
||||
begin
|
||||
if i > 0 then
|
||||
raise Exception.Create('')
|
||||
else
|
||||
Result := 0;
|
||||
end; {should NOT generate "Warning: Function result does not seem to be set" (doesn't in delphi and FPC) }
|
||||
|
||||
begin
|
||||
i:=1;
|
||||
end.
|
Loading…
Reference in New Issue
Block a user