From 5cc1eaf8a159d8b52e36fc1ba0df040ad905886c Mon Sep 17 00:00:00 2001 From: mattias Date: Sat, 10 Aug 2019 06:48:04 +0000 Subject: [PATCH] fcl-passrc: no function result not set warning for fieldless record --- .../fcl-passrc/src/pasuseanalyzer.pas | 69 ++++++++++++++----- .../fcl-passrc/tests/tcuseanalyzer.pas | 20 ++++++ 2 files changed, 71 insertions(+), 18 deletions(-) diff --git a/compiler/packages/fcl-passrc/src/pasuseanalyzer.pas b/compiler/packages/fcl-passrc/src/pasuseanalyzer.pas index 038fe23..38b7766 100644 --- a/compiler/packages/fcl-passrc/src/pasuseanalyzer.pas +++ b/compiler/packages/fcl-passrc/src/pasuseanalyzer.pas @@ -281,6 +281,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; @@ -2568,9 +2569,7 @@ var Arg: TPasArgument; Usage: TPAElement; ProcScope: TPasProcedureScope; - PosEl: TPasElement; DeclProc, ImplProc: TPasProcedure; - FuncType: TPasFunctionType; begin {$IFDEF VerbosePasAnalyzer} writeln('TPasAnalyzer.EmitProcedureHints ',GetElModName(El)); @@ -2637,22 +2636,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 @@ -2663,6 +2647,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; diff --git a/compiler/packages/fcl-passrc/tests/tcuseanalyzer.pas b/compiler/packages/fcl-passrc/tests/tcuseanalyzer.pas index d06ebfb..d0fe267 100644 --- a/compiler/packages/fcl-passrc/tests/tcuseanalyzer.pas +++ b/compiler/packages/fcl-passrc/tests/tcuseanalyzer.pas @@ -128,6 +128,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; @@ -2165,6 +2166,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);