fcl-passrc: no function result not set warning for fieldless record

git-svn-id: trunk@42640 -
This commit is contained in:
Mattias Gaertner 2019-08-10 06:47:35 +00:00
parent 141f2403d3
commit d772890e1f
2 changed files with 71 additions and 18 deletions
packages/fcl-passrc

View File

@ -283,6 +283,7 @@ type
procedure EmitTypeHints(El: TPasType); virtual;
procedure EmitVariableHints(El: TPasVariable); virtual;
procedure EmitProcedureHints(El: TPasProcedure); virtual;
procedure EmitFunctionResultHints(El: TPasFunction); virtual;
public
constructor Create;
destructor Destroy; override;
@ -2620,9 +2621,7 @@ var
Arg: TPasArgument;
Usage: TPAElement;
ProcScope: TPasProcedureScope;
PosEl: TPasElement;
DeclProc, ImplProc: TPasProcedure;
FuncType: TPasFunctionType;
begin
{$IFDEF VerbosePasAnalyzer}
writeln('TPasAnalyzer.EmitProcedureHints ',GetElModName(El));
@ -2689,22 +2688,7 @@ begin
end;
// check result
if (El.ProcType is TPasFunctionType) then
begin
FuncType:=TPasFunctionType(TPasProcedure(El).ProcType);
PosEl:=FuncType.ResultEl;
if (ProcScope.ImplProc<>nil)
and (TPasFunction(ProcScope.ImplProc).FuncType.ResultEl<>nil) then
PosEl:=TPasFunction(ProcScope.ImplProc).FuncType.ResultEl;
Usage:=FindElement(FuncType.ResultEl);
if (Usage=nil) or (Usage.Access in [paiaNone,paiaRead]) then
// result was never used
EmitMessage(20170313214038,mtHint,nPAFunctionResultDoesNotSeemToBeSet,
sPAFunctionResultDoesNotSeemToBeSet,[],PosEl)
else
begin
// result was used
end;
end;
EmitFunctionResultHints(TPasFunction(El));
end;
if El.Body<>nil then
@ -2715,6 +2699,55 @@ begin
end;
end;
procedure TPasAnalyzer.EmitFunctionResultHints(El: TPasFunction);
var
FuncType: TPasFunctionType;
Usage: TPAElement;
TypeEl: TPasType;
Members: TFPList;
i: Integer;
Member: TPasElement;
HasFields: Boolean;
PosEl: TPasResultElement;
ProcScope: TPasProcedureScope;
begin
FuncType:=El.FuncType;
Usage:=FindElement(FuncType.ResultEl);
if (Usage=nil) or (Usage.Access in [paiaNone,paiaRead]) then
begin
// result was never set
TypeEl:=Resolver.ResolveAliasType(FuncType.ResultEl.ResultType);
if TypeEl is TPasRecordType then
begin
Members:=TPasRecordType(TypeEl).Members;
HasFields:=false;
for i:=0 to Members.Count-1 do
begin
Member:=TPasElement(Members[i]);
if Member.ClassType=TPasVariable then
begin
HasFields:=true;
break;
end;
end;
if not HasFields then
// empty record -> no hint
exit;
end;
PosEl:=FuncType.ResultEl;
ProcScope:=El.CustomData as TPasProcedureScope;
if (ProcScope.ImplProc<>nil)
and (TPasFunction(ProcScope.ImplProc).FuncType.ResultEl<>nil) then
PosEl:=TPasFunction(ProcScope.ImplProc).FuncType.ResultEl;
EmitMessage(20170313214038,mtHint,nPAFunctionResultDoesNotSeemToBeSet,
sPAFunctionResultDoesNotSeemToBeSet,[],PosEl)
end
else
begin
// result was used
end;
end;
constructor TPasAnalyzer.Create;
var
m: TPAUseMode;

View File

@ -129,6 +129,7 @@ type
procedure TestM_Hint_FunctionResultDoesNotSeemToBeSet;
procedure TestM_Hint_FunctionResultDoesNotSeemToBeSet_Abstract;
procedure TestM_Hint_FunctionResultRecord;
procedure TestM_Hint_FunctionResultRecordEmpty;
procedure TestM_Hint_FunctionResultPassRecordElement;
procedure TestM_Hint_FunctionResultAssembler;
procedure TestM_Hint_FunctionResultExit;
@ -2198,6 +2199,25 @@ begin
CheckUseAnalyzerUnexpectedHints;
end;
procedure TTestUseAnalyzer.TestM_Hint_FunctionResultRecordEmpty;
begin
StartProgram(true);
Add([
'{$modeswitch AdvancedRecords}',
'type',
' TEmpty = record',
' class function Create: TEmpty; static;',
' end;',
'class function TEmpty.Create: TEmpty;',
'begin',
'end;',
'begin',
' TEmpty.Create;',
'']);
AnalyzeProgram;
CheckUseAnalyzerUnexpectedHints;
end;
procedure TTestUseAnalyzer.TestM_Hint_FunctionResultPassRecordElement;
begin
StartProgram(true);