mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-12-07 02:27:11 +01:00
fcl-passrc: pasuseanalyzer: no hint assigned but never used for out argument
git-svn-id: trunk@35720 -
This commit is contained in:
parent
dac17860c4
commit
e71ac95b69
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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,');
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user