diff --git a/packages/fcl-passrc/src/pasresolver.pp b/packages/fcl-passrc/src/pasresolver.pp index df33f5534b..70fedbf63b 100644 --- a/packages/fcl-passrc/src/pasresolver.pp +++ b/packages/fcl-passrc/src/pasresolver.pp @@ -1664,8 +1664,9 @@ function IsValidIdent(const Ident: string; AllowDots: Boolean = False; StrictDot function NoNil(o: TObject): TObject; function dbgs(const Flags: TPasResolverComputeFlags): string; overload; -function dbgs(const a: TResolvedRefAccess): string; +function dbgs(const a: TResolvedRefAccess): string; overload; function dbgs(const Flags: TResolvedReferenceFlags): string; overload; +function dbgs(const a: TPSRefAccess): string; overload; implementation @@ -2152,6 +2153,11 @@ begin Result:='['+Result+']'; end; +function dbgs(const a: TPSRefAccess): string; +begin + str(a,Result); +end; + { TPasProcScopeReference } procedure TPasProcScopeReference.SetElement(const AValue: TPasElement); diff --git a/packages/fcl-passrc/src/pasuseanalyzer.pas b/packages/fcl-passrc/src/pasuseanalyzer.pas index db8ec4ec61..3186b578e2 100644 --- a/packages/fcl-passrc/src/pasuseanalyzer.pas +++ b/packages/fcl-passrc/src/pasuseanalyzer.pas @@ -187,6 +187,7 @@ type function FindOverrideList(El: TPasElement): TPAOverrideList; procedure SetOptions(AValue: TPasAnalyzerOptions); procedure UpdateAccess(IsWrite: Boolean; IsRead: Boolean; Usage: TPAElement); + procedure OnUseProcScopeRef(data, DeclScope: pointer); protected procedure RaiseInconsistency(const Id: int64; Msg: string); procedure RaiseNotSupported(const Id: int64; El: TPasElement; const Msg: string = ''); @@ -238,6 +239,7 @@ type procedure AnalyzeProcRefs(Proc: TPasProcedure); procedure EmitModuleHints(aModule: TPasModule); virtual; function FindElement(El: TPasElement): TPAElement; + function FindUsedElement(El: TPasElement): TPAElement; // utility function IsUsed(El: TPasElement): boolean; // valid after calling Analyze* function IsTypeInfoUsed(El: TPasElement): boolean; // valid after calling Analyze* @@ -248,6 +250,7 @@ type procedure EmitMessage(const Id: int64; const MsgType: TMessageType; MsgNumber: integer; Fmt: String; const Args: array of const; PosEl: TPasElement); procedure EmitMessage(Msg: TPAMessage); + function GetUsedElements: TFPList; virtual; // list of TPAElement property OnMessage: TPAMessageEvent read FOnMessage write FOnMessage; property Options: TPasAnalyzerOptions read FOptions write SetOptions; property Resolver: TPasResolver read FResolver write FResolver; @@ -259,6 +262,7 @@ function CompareElementWithPAElement(El, Id: Pointer): integer; function ComparePAOverrideLists(List1, List2: Pointer): integer; function CompareElementWithPAOverrideList(El, List: Pointer): integer; function GetElModName(El: TPasElement): string; +function dbgs(a: TPAIdentifierAccess): string; overload; implementation @@ -313,6 +317,11 @@ begin Result:=aModule.Name+'.'+Result; end; +function dbgs(a: TPAIdentifierAccess): string; +begin + str(a,Result); +end; + { TPAMessage } constructor TPAMessage.Create; @@ -509,6 +518,28 @@ begin end; end; +procedure TPasAnalyzer.OnUseProcScopeRef(data, DeclScope: pointer); +var + Ref: TPasProcScopeReference absolute data; + Scope: TPasProcedureScope absolute DeclScope; +begin + if Scope=nil then ; + case Ref.Access of + psraNone: ; + psraRead: UseElement(Ref.Element,rraRead,false); + psraWrite: UseElement(Ref.Element,rraAssign,false); + psraReadWrite: UseElement(Ref.Element,rraReadAndAssign,false); + psraWriteRead: + begin + UseElement(Ref.Element,rraAssign,false); + UseElement(Ref.Element,rraRead,false); + end; + psraTypeInfo: UsePublished(Ref.Element); + else + RaiseNotSupported(20180228191928,Ref.Element,dbgs(Ref.Access)); + end; +end; + procedure TPasAnalyzer.RaiseInconsistency(const Id: int64; Msg: string); begin {$IFDEF VerbosePasAnalyzer} @@ -1349,6 +1380,9 @@ begin writeln('TPasAnalyzer.UseProcedure ',GetElModName(Proc)); {$ENDIF} + if ProcScope.References<>nil then + ProcScope.References.ForEachCall(@OnUseProcScopeRef,ProcScope); + UseProcedureType(Proc.ProcType,false); ImplProc:=Proc; @@ -2159,18 +2193,23 @@ begin Result:=TPAElement(Node.Data); end; -function TPasAnalyzer.IsUsed(El: TPasElement): boolean; +function TPasAnalyzer.FindUsedElement(El: TPasElement): TPAElement; var ProcScope: TPasProcedureScope; begin - if not IsIdentifier(El) then exit(true); + if not IsIdentifier(El) then exit(nil); if El is TPasProcedure then begin ProcScope:=El.CustomData as TPasProcedureScope; if ProcScope.DeclarationProc<>nil then El:=ProcScope.DeclarationProc; end; - Result:=FindElement(El)<>nil; + Result:=FindElement(El); +end; + +function TPasAnalyzer.IsUsed(El: TPasElement): boolean; +begin + Result:=FindUsedElement(El)<>nil; end; function TPasAnalyzer.IsTypeInfoUsed(El: TPasElement): boolean; @@ -2294,5 +2333,18 @@ begin end; end; +function TPasAnalyzer.GetUsedElements: TFPList; +var + Node: TAVLTreeNode; +begin + Result:=TFPList.Create; + Node:=FUsedElements.FindLowest; + while Node<>nil do + begin + Result.Add(Node.Data); + Node:=FUsedElements.FindSuccessor(Node); + end; +end; + end.