fcl-passrc: process TBinaryExpr left lists without stack

This commit is contained in:
mattias 2021-03-22 17:35:19 +00:00
parent 6999e0d475
commit d2eb00eaab
3 changed files with 99 additions and 5 deletions

View File

@ -1488,6 +1488,8 @@ function TResExprEvaluator.EvalBinaryExpr(Expr: TBinaryExpr;
Flags: TResEvalFlags): TResEvalValue;
var
LeftValue, RightValue: TResEvalValue;
Left: TPasExpr;
SubBin: TBinaryExpr;
begin
Result:=nil;
if (Expr.Kind=pekBinary) and (Expr.OpCode=eopSubIdent) then
@ -1498,6 +1500,52 @@ begin
LeftValue:=nil;
RightValue:=nil;
try
if Expr.OpCode=eopAdd then
begin
// handle multi adds without stack
Left:=Expr.left;
while Left.ClassType=TBinaryExpr do
begin
SubBin:=TBinaryExpr(Left);
if SubBin.OpCode<>eopAdd then break;
Left:=SubBin.left;
end;
LeftValue:=Eval(Left,Flags);
while LeftValue<>nil do
begin
SubBin:=TBinaryExpr(Left.Parent);
RightValue:=Eval(SubBin.right,Flags);
if RightValue=nil then exit;
if LeftValue.Kind=revkExternal then
begin
if [refConst,refConstExt]*Flags=[refConst] then
RaiseConstantExprExp(20210321205928,Expr.left);
Result:=LeftValue;
LeftValue:=nil;
exit;
end;
if RightValue.Kind=revkExternal then
begin
if [refConst,refConstExt]*Flags=[refConst] then
RaiseConstantExprExp(20210321205948,Expr.right);
Result:=RightValue;
RightValue:=nil;
exit;
end;
Result:=EvalBinaryAddExpr(SubBin,LeftValue,RightValue);
ReleaseEvalValue(LeftValue);
if SubBin=Expr then exit;
LeftValue:=Result;
Result:=nil;
Left:=SubBin;
end;
exit;
end;
LeftValue:=Eval(Expr.left,Flags);
if LeftValue=nil then exit;
RightValue:=Eval(Expr.right,Flags);

View File

@ -5869,7 +5869,6 @@ begin
end;
end;
constructor TBinaryExpr.Create(AParent : TPasElement; xleft,xright:TPasExpr; AOpCode:TExprOpCode);
begin
inherited Create(AParent,pekBinary, AOpCode);
@ -5889,9 +5888,33 @@ begin
end;
destructor TBinaryExpr.Destroy;
var
El: TPasExpr;
SubBin: TBinaryExpr;
begin
ReleaseAndNil(TPasElement(left){$IFDEF CheckPasTreeRefCount},'TBinaryExpr.left'{$ENDIF});
ReleaseAndNil(TPasElement(right){$IFDEF CheckPasTreeRefCount},'TBinaryExpr.right'{$ENDIF});
// handle left of binary chains without stack
El:=Left;
while El is TBinaryExpr do
begin
SubBin:=TBinaryExpr(El);
El:=SubBin.left;
if (El=nil) or (El.Parent<>SubBin) then
begin
El:=SubBin;
break;
end;
end;
repeat
if El=left then
SubBin:=Self
else
SubBin:=TBinaryExpr(El.Parent);
ReleaseAndNil(TPasElement(SubBin.left){$IFDEF CheckPasTreeRefCount},'TBinaryExpr.left'{$ENDIF});
ReleaseAndNil(TPasElement(SubBin.right){$IFDEF CheckPasTreeRefCount},'TBinaryExpr.left'{$ENDIF});
El:=SubBin;
until El=Self;
inherited Destroy;
end;

View File

@ -1711,6 +1711,8 @@ var
Decl: TPasElement;
ModScope: TPasModuleScope;
Access: TResolvedRefAccess;
Bin: TBinaryExpr;
Left: TPasExpr;
begin
if El=nil then exit;
// Note: expression itself is not marked, but it can reference identifiers
@ -1792,8 +1794,29 @@ begin
// ok
else if C=TBinaryExpr then
begin
UseExpr(TBinaryExpr(El).left);
UseExpr(TBinaryExpr(El).right);
Bin:=TBinaryExpr(El);
if Bin.OpCode=eopAdd then
begin
// handle multi add expressions without stack
Left:=Bin;
while Left.ClassType=TBinaryExpr do
begin
Bin:=TBinaryExpr(Left);
if Bin.OpCode<>eopAdd then break;
Left:=Bin.left;
end;
UseExpr(Left);
repeat
Bin:=TBinaryExpr(Left.Parent);
UseExpr(Bin.right);
Left:=Bin;
until Left=El;
end
else
begin
UseExpr(Bin.left);
UseExpr(Bin.right);
end;
end
else if C=TUnaryExpr then
UseExpr(TUnaryExpr(El).Operand)