fcl-passrc: useanalyzer: mark needed typeinfo

git-svn-id: trunk@35793 -
This commit is contained in:
Mattias Gaertner 2017-04-14 15:52:31 +00:00
parent 5a8578cfaa
commit a0482df6df

View File

@ -147,15 +147,15 @@ type
end;
TPasAnalyzerOption = (
paoKeepPublished, // when a class is used, all its published members are used as well
paoOnlyExports // default: use all class members accessible from outside (protected, but not private)
);
TPasAnalyzerOptions = set of TPasAnalyzerOption;
TPAUseMode = (
paumElement, // mark element
paumAllPublic, // mark element and descend into children and mark public identifiers
paumAllExports // do not mark element and descend into children and mark exports
paumElement, // Mark element. Do not descend into children.
paumAllPublic, // Mark element and descend into children and mark public identifiers
paumAllExports, // Do not mark element. Descend into children and mark exports.
paumPublished // Mark element and its type and descend into children and mark published identifiers
);
TPAUseModes = set of TPAUseMode;
@ -188,6 +188,7 @@ type
function ElementVisited(El: TPasElement; Mode: TPAUseMode): boolean;
procedure UseElement(El: TPasElement; Access: TResolvedRefAccess;
UseFull: boolean); virtual;
procedure UsePublished(El: TPasElement); virtual;
procedure UseModule(aModule: TPasModule; Mode: TPAUseMode); virtual;
procedure UseSection(Section: TPasSection; Mode: TPAUseMode); virtual;
procedure UseImplBlock(Block: TPasImplBlock; Mark: boolean); virtual;
@ -221,6 +222,7 @@ type
function FindElement(El: TPasElement): TPAElement;
// utility
function IsUsed(El: TPasElement): boolean; // valid after calling Analyze*
function IsTypeInfoUsed(El: TPasElement): boolean; // valid after calling Analyze*
function IsModuleInternal(El: TPasElement): boolean;
function IsExport(El: TPasElement): boolean;
function IsIdentifier(El: TPasElement): boolean;
@ -615,6 +617,80 @@ begin
RaiseNotSupported(20170307090947,El);
end;
procedure TPasAnalyzer.UsePublished(El: TPasElement);
// mark typeinfo, do not
var
C: TClass;
Members: TFPList;
i: Integer;
Member: TPasElement;
MemberResolved: TPasResolverResult;
Prop: TPasProperty;
ProcType: TPasProcedureType;
begin
{$IFDEF VerbosePasAnalyzer}
writeln('TPasAnalyzer.UsePublished START ',GetObjName(El));
{$ENDIF}
if ElementVisited(El,paumPublished) then exit;
C:=El.ClassType;
if C=TPasUnresolvedSymbolRef then
else if (C=TPasVariable) or (C=TPasConst) then
UsePublished(TPasVariable(El).VarType)
else if C=TPasProperty then
begin
// published property
Prop:=TPasProperty(El);
for i:=0 to Prop.Args.Count-1 do
UsePublished(TPasArgument(Prop.Args[i]).ArgType);
UsePublished(Prop.VarType);
// Note: read, write and index don't need extra typeinfo
// stored and defaultvalue are only used when published -> mark as used
UseElement(Prop.StoredAccessor,rraRead,false);
UseElement(Prop.DefaultExpr,rraRead,false);
end
else if (C=TPasAliasType) or (C=TPasTypeAliasType) then
UsePublished(TPasAliasType(El).DestType)
else if C=TPasSetType then
UsePublished(TPasSetType(El).EnumType)
else if C=TPasArrayType then
begin
UsePublished(TPasArrayType(El).ElType);
for i:=0 to length(TPasArrayType(El).Ranges)-1 do
begin
Member:=TPasArrayType(El).Ranges[i];
Resolver.ComputeElement(Member,MemberResolved,[rcConstant]);
UsePublished(MemberResolved.TypeEl);
end;
end
else if C=TPasPointerType then
UsePublished(TPasPointerType(El).DestType)
else if C=TPasClassType then
else if C=TPasClassOfType then
else if C=TPasRecordType then
begin
// published record: use all members
Members:=TPasRecordType(El).Members;
for i:=0 to Members.Count-1 do
begin
UsePublished(TPasElement(Members[i]));
UseElement(Member,rraNone,true);
end;
end
else if C.InheritsFrom(TPasProcedure) then
UsePublished(TPasProcedure(El).ProcType)
else if C.InheritsFrom(TPasProcedureType) then
begin
ProcType:=TPasProcedureType(El);
for i:=0 to ProcType.Args.Count-1 do
UsePublished(TPasArgument(ProcType.Args[i]).ArgType);
if El is TPasFunctionType then
UsePublished(TPasFunctionType(El).ResultEl.ResultType);
end
else
RaiseNotSupported(20170414153904,El);
end;
procedure TPasAnalyzer.UseModule(aModule: TPasModule; Mode: TPAUseMode);
procedure UseInitFinal(aSection: TPasImplBlock);
@ -1158,7 +1234,7 @@ procedure TPasAnalyzer.UseClassType(El: TPasClassType; Mode: TPAUseMode);
var
i: Integer;
Member: TPasElement;
UsePublished, FirstTime: Boolean;
AllPublished, FirstTime: Boolean;
ProcScope: TPasProcedureScope;
ClassScope: TPasClassScope;
Ref: TResolvedReference;
@ -1178,6 +1254,8 @@ begin
end;
paumElement:
if not MarkElementAsUsed(El) then exit;
else
RaiseInconsistency(20170414152143,IntToStr(ord(Mode)));
end;
{$IFDEF VerbosePasAnalyzer}
writeln('TPasAnalyzer.UseClassType ',GetElModName(El),' ',Mode,' First=',FirstTime);
@ -1199,7 +1277,7 @@ begin
UseType(TPasType(El.Interfaces[i]),paumElement);
end;
// members
UsePublished:=(Mode<>paumAllExports) and (paoKeepPublished in Options);
AllPublished:=(Mode<>paumAllExports);
for i:=0 to El.Members.Count-1 do
begin
Member:=TPasElement(El.Members[i]);
@ -1209,10 +1287,11 @@ begin
if ProcScope.OverriddenProc<>nil then
AddOverride(ProcScope.OverriddenProc,Member);
end;
if UsePublished and (Member.Visibility=visPublished) then
if AllPublished and (Member.Visibility=visPublished) then
begin
// include published
if not FirstTime then continue;
UsePublished(Member);
end
else if Mode=paumElement then
continue
@ -1763,6 +1842,11 @@ begin
Result:=FindElement(El)<>nil;
end;
function TPasAnalyzer.IsTypeInfoUsed(El: TPasElement): boolean;
begin
Result:=FChecked[paumPublished].Find(El)<>nil;
end;
function TPasAnalyzer.IsModuleInternal(El: TPasElement): boolean;
begin
if El=nil then
@ -1772,7 +1856,7 @@ begin
if IsExport(El) then exit(false);
case El.Visibility of
visPrivate,visStrictPrivate: exit(true);
visPublished: if paoKeepPublished in Options then exit(false);
visPublished: exit(false);
end;
Result:=IsModuleInternal(El.Parent);
end;