Browse Source

fcl-passrc: useanalyzer: mark needed typeinfo

git-svn-id: trunk@35793 -
Mattias Gaertner 8 years ago
parent
commit
a0482df6df
1 changed files with 92 additions and 8 deletions
  1. 92 8
      packages/fcl-passrc/src/pasuseanalyzer.pas

+ 92 - 8
packages/fcl-passrc/src/pasuseanalyzer.pas

@@ -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;