fcl-passrc: pasuseanalyzer: no hint assigned but never used for out argument

git-svn-id: trunk@35720 -
This commit is contained in:
Mattias Gaertner 2017-04-03 15:52:36 +00:00
parent dac17860c4
commit e71ac95b69
4 changed files with 121 additions and 34 deletions

View File

@ -5209,6 +5209,7 @@ begin
if (Ref.Access=Access) then exit;
if Access in [rraNone,rraParamToUnknownProc] then
exit;
if Expr=nil then ;
case Ref.Access of
rraNone,rraParamToUnknownProc:
@ -5228,31 +5229,6 @@ begin
else
RaiseInternalError(20170403163727);
end;
if (Expr.ClassType=TSelfExpr)
or ((Expr.ClassType=TPrimitiveExpr) and (TPrimitiveExpr(Expr).Kind=pekIdent)) then
begin
if Ref.WithExprScope<>nil then
begin
if Ref.WithExprScope.Scope is TPasRecordScope then
begin
// a record member was accessed -> access the record too
AccessExpr(Ref.WithExprScope.Expr,Access);
exit;
end;
end;
if (Ref.Declaration is TPasVariable)
and (Expr.Parent is TBinaryExpr)
and (TBinaryExpr(Expr.Parent).right=Expr) then
begin
if ((Ref.Declaration.Parent is TPasRecordType)
or (Ref.Declaration.Parent is TPasVariant)) then
begin
// a record member was accessed -> access the record too
AccessExpr(TBinaryExpr(Expr.Parent).left,Access);
end;
end;
end;
end;
procedure TPasResolver.AccessExpr(Expr: TPasExpr;
@ -5297,6 +5273,8 @@ begin
pekSet:
if Access<>rraRead then
RaiseMsg(20170306112306,nVariableIdentifierExpected,sVariableIdentifierExpected,[],Expr);
else
RaiseNotYetImplemented(20170403173831,Params);
end;
end
else if (C=TSelfExpr) or ((C=TPrimitiveExpr) and (TPrimitiveExpr(Expr).Kind=pekIdent)) then

View File

@ -193,6 +193,8 @@ type
procedure UseImplBlock(Block: TPasImplBlock; Mark: boolean); virtual;
procedure UseImplElement(El: TPasImplElement); virtual;
procedure UseExpr(El: TPasExpr); virtual;
procedure UseExprRef(Expr: TPasExpr; Access: TResolvedRefAccess;
UseFull: boolean); virtual;
procedure UseProcedure(Proc: TPasProcedure); virtual;
procedure UseProcedureType(ProcType: TPasProcedureType; Mark: boolean); virtual;
procedure UseType(El: TPasType; Mode: TPAUseMode); virtual;
@ -877,13 +879,39 @@ var
i: Integer;
begin
if El=nil then exit;
// expression are not marked
// expressions are not marked
if El.CustomData is TResolvedReference then
begin
// this is a reference -> mark target
Ref:=TResolvedReference(El.CustomData);
UseElement(Ref.Declaration,Ref.Access,false);
if (El.ClassType=TSelfExpr)
or ((El.ClassType=TPrimitiveExpr) and (TPrimitiveExpr(El).Kind=pekIdent)) then
begin
if Ref.WithExprScope<>nil then
begin
if Ref.WithExprScope.Scope is TPasRecordScope then
begin
// a record member was accessed -> access the record too
UseExprRef(Ref.WithExprScope.Expr,Ref.Access,false);
exit;
end;
end;
if (Ref.Declaration is TPasVariable)
and (El.Parent is TBinaryExpr)
and (TBinaryExpr(El.Parent).right=El) then
begin
if ((Ref.Declaration.Parent is TPasRecordType)
or (Ref.Declaration.Parent is TPasVariant)) then
begin
// a record member was accessed -> access the record too
UseExprRef(TBinaryExpr(El.Parent).left,Ref.Access,false);
end;
end;
end;
end;
UseExpr(El.format1);
UseExpr(El.format2);
@ -911,6 +939,65 @@ begin
RaiseNotSupported(20170307085444,El);
end;
procedure TPasAnalyzer.UseExprRef(Expr: TPasExpr; Access: TResolvedRefAccess;
UseFull: boolean);
var
Ref: TResolvedReference;
C: TClass;
Bin: TBinaryExpr;
Params: TParamsExpr;
ValueResolved: TPasResolverResult;
begin
if (Expr.CustomData is TResolvedReference) then
begin
Ref:=TResolvedReference(Expr.CustomData);
UseElement(Ref.Declaration,Access,UseFull);
end;
C:=Expr.ClassType;
if C=TBinaryExpr then
begin
Bin:=TBinaryExpr(Expr);
if Bin.OpCode in [eopSubIdent,eopNone] then
UseExprRef(Bin.right,Access,UseFull);
end
else if C=TParamsExpr then
begin
Params:=TParamsExpr(Expr);
case Params.Kind of
pekFuncParams:
if Resolver.IsTypeCast(Params) then
UseExprRef(Params.Params[0],Access,UseFull)
else
UseExprRef(Params.Value,Access,UseFull);
pekArrayParams:
begin
Resolver.ComputeElement(Params.Value,ValueResolved,[]);
if not Resolver.IsDynArray(ValueResolved.TypeEl) then
UseExprRef(Params.Value,Access,UseFull);
end;
pekSet: ;
else
RaiseNotSupported(20170403173817,Params);
end;
end
else if (C=TSelfExpr) or ((C=TPrimitiveExpr) and (TPrimitiveExpr(Expr).Kind=pekIdent)) then
// ok
else if (Access=rraRead)
and ((C=TPrimitiveExpr)
or (C=TNilExpr)
or (C=TBoolConstExpr)
or (C=TUnaryExpr)) then
// ok
else
begin
{$IFDEF VerbosePasResolver}
writeln('TPasResolver.UseExprRef Expr=',GetObjName(Expr),' Access=',Access,' Declaration="',Expr.GetDeclaration(false),'"');
{$ENDIF}
RaiseNotSupported(20170306102158,Expr);
end;
end;
procedure TPasAnalyzer.UseProcedure(Proc: TPasProcedure);
procedure UseOverrides(CurProc: TPasProcedure);
@ -1531,7 +1618,7 @@ begin
else
begin
// parameter was used
if Usage.Access=paiaWrite then
if (Usage.Access=paiaWrite) and (Arg.Access<>argOut) then
EmitMessage(20170312095348,mtHint,nPAValueParameterIsAssignedButNeverUsed,
sPAValueParameterIsAssignedButNeverUsed,[Arg.Name],Arg);
end;

View File

@ -4046,8 +4046,8 @@ begin
Add('begin');
Add(' DoIt({#r1_read}r.{#r_a1_read}a,');
Add(' {#r2_read}r.{#r_a2_read}a,');
Add(' {#r3_readandassign}r.{#r_a3_var}a,');
Add(' {#r4_readandassign}r.{#r_a4_out}a);');
Add(' {#r3_read}r.{#r_a3_var}a,');
Add(' {#r4_read}r.{#r_a4_out}a);');
Add(' with r do');
Add(' DoIt({#w_a1_read}a,');
Add(' {#w_a2_read}a,');

View File

@ -92,6 +92,7 @@ type
procedure TestM_Hint_FunctionResultDoesNotSeemToBeSet;
procedure TestM_Hint_FunctionResultRecord;
procedure TestM_Hint_FunctionResultPassRecordElement;
procedure TestM_Hint_OutParam_No_AssignedButNeverUsed;
// whole program optimization
procedure TestWP_LocalVar;
@ -233,13 +234,19 @@ begin
while i>=0 do
begin
Msg:=PAMessages[i];
if (Msg.MsgType=MsgType)
and (Msg.MsgNumber=MsgNumber)
and (Msg.MsgText=MsgText) then
if (Msg.MsgNumber=MsgNumber) then
begin
if Has then
exit;
break;
begin
// must have -> message type and text must match exactly
if (Msg.MsgType=MsgType) and (Msg.MsgText=MsgText) then
exit;
end
else
begin
// must not have -> matching number is enough
break;
end;
end;
dec(i);
end;
@ -1168,6 +1175,21 @@ begin
sPAFunctionResultDoesNotSeemToBeSet,false);
end;
procedure TTestUseAnalyzer.TestM_Hint_OutParam_No_AssignedButNeverUsed;
begin
StartProgram(true);
Add('procedure DoIt(out x: longint);');
Add('begin');
Add(' x:=3;');
Add('end;');
Add('var i: longint;');
Add('begin');
Add(' DoIt(i);');
AnalyzeProgram;
CheckHasHint(mtHint,nPAValueParameterIsAssignedButNeverUsed,
sPAValueParameterIsAssignedButNeverUsed,false);
end;
procedure TTestUseAnalyzer.TestWP_LocalVar;
begin
StartProgram(false);