|
@@ -53,7 +53,7 @@ uses
|
|
{$ifdef pas2js}
|
|
{$ifdef pas2js}
|
|
js,
|
|
js,
|
|
{$else}
|
|
{$else}
|
|
- AVL_Tree,
|
|
|
|
|
|
+ AVL_Tree, contnrs,
|
|
{$endif}
|
|
{$endif}
|
|
Classes, SysUtils, Types,
|
|
Classes, SysUtils, Types,
|
|
PasTree, PScanner, PasResolveEval, PasResolver;
|
|
PasTree, PScanner, PasResolveEval, PasResolver;
|
|
@@ -253,6 +253,7 @@ type
|
|
function ElementVisited(El: TPasElement; OtherCheck: TPAOtherCheckedEl): boolean; overload;
|
|
function ElementVisited(El: TPasElement; OtherCheck: TPAOtherCheckedEl): boolean; overload;
|
|
procedure MarkImplScopeRef(El, RefEl: TPasElement; Access: TPSRefAccess);
|
|
procedure MarkImplScopeRef(El, RefEl: TPasElement; Access: TPSRefAccess);
|
|
function CanSkipGenericType(El: TPasGenericType): boolean;
|
|
function CanSkipGenericType(El: TPasGenericType): boolean;
|
|
|
|
+ function CanSkipGenericProc(DeclProc: TPasProcedure): boolean;
|
|
procedure UseElement(El: TPasElement; Access: TResolvedRefAccess;
|
|
procedure UseElement(El: TPasElement; Access: TResolvedRefAccess;
|
|
UseFull: boolean); virtual;
|
|
UseFull: boolean); virtual;
|
|
procedure UseTypeInfo(El: TPasElement); virtual;
|
|
procedure UseTypeInfo(El: TPasElement); virtual;
|
|
@@ -1043,7 +1044,7 @@ begin
|
|
else
|
|
else
|
|
begin
|
|
begin
|
|
// analyze a module
|
|
// analyze a module
|
|
- if ((El.GenericTemplateTypes<>nil) and (El.GenericTemplateTypes.Count>0)) then
|
|
|
|
|
|
+ if (El.GenericTemplateTypes<>nil) and (El.GenericTemplateTypes.Count>0) then
|
|
// generic template -> analyze
|
|
// generic template -> analyze
|
|
else if not Resolver.IsFullySpecialized(El) then
|
|
else if not Resolver.IsFullySpecialized(El) then
|
|
// half specialized -> skip
|
|
// half specialized -> skip
|
|
@@ -1051,6 +1052,52 @@ begin
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+function TPasAnalyzer.CanSkipGenericProc(DeclProc: TPasProcedure): boolean;
|
|
|
|
+
|
|
|
|
+ procedure RaiseHalfSpecialized;
|
|
|
|
+ var
|
|
|
|
+ Templates: TFPList;
|
|
|
|
+ ProcScope: TPasProcedureScope;
|
|
|
|
+ Item: TPRSpecializedItem;
|
|
|
|
+ begin
|
|
|
|
+ Templates:=Resolver.GetProcTemplateTypes(DeclProc);
|
|
|
|
+ if (Templates<>nil) and (Templates.Count>0) then
|
|
|
|
+ RaiseNotSupported(20191016132828,DeclProc);
|
|
|
|
+ if not (DeclProc.CustomData is TPasProcedureScope) then
|
|
|
|
+ RaiseNotSupported(20191016132836,DeclProc,GetObjName(DeclProc.CustomData));
|
|
|
|
+ ProcScope:=TPasProcedureScope(DeclProc.CustomData);
|
|
|
|
+ Item:=ProcScope.SpecializedFromItem;
|
|
|
|
+ if Item=nil then
|
|
|
|
+ RaiseNotSupported(20191016133013,DeclProc);
|
|
|
|
+ if Item.SpecializedEl=nil then
|
|
|
|
+ RaiseNotSupported(20191016133017,DeclProc);
|
|
|
|
+ if Item.FirstSpecialize=nil then
|
|
|
|
+ RaiseNotSupported(20191016133019,DeclProc);
|
|
|
|
+ RaiseNotSupported(20191016133022,DeclProc,'SpecializedAt:'+GetObjPath(Item.FirstSpecialize)+' '+Resolver.GetElementSourcePosStr(Item.FirstSpecialize));
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+var
|
|
|
|
+ Templates: TFPList;
|
|
|
|
+begin
|
|
|
|
+ Result:=false;
|
|
|
|
+ if ScopeModule=nil then
|
|
|
|
+ begin
|
|
|
|
+ // analyze whole program
|
|
|
|
+ if not Resolver.IsFullySpecialized(DeclProc) then
|
|
|
|
+ RaiseHalfSpecialized;
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ // analyze a module
|
|
|
|
+ Templates:=Resolver.GetProcTemplateTypes(DeclProc);
|
|
|
|
+ if (Templates<>nil) and (Templates.Count>0) then
|
|
|
|
+ // generic template -> analyze
|
|
|
|
+ else if not Resolver.IsFullySpecialized(DeclProc) then
|
|
|
|
+ // half specialized -> skip
|
|
|
|
+ exit(true);
|
|
|
|
+ end;
|
|
|
|
+end;
|
|
|
|
+
|
|
procedure TPasAnalyzer.UseElement(El: TPasElement; Access: TResolvedRefAccess;
|
|
procedure TPasAnalyzer.UseElement(El: TPasElement; Access: TResolvedRefAccess;
|
|
UseFull: boolean);
|
|
UseFull: boolean);
|
|
var
|
|
var
|
|
@@ -1864,6 +1911,7 @@ begin
|
|
ProcScope:=Proc.CustomData as TPasProcedureScope;
|
|
ProcScope:=Proc.CustomData as TPasProcedureScope;
|
|
if ProcScope.DeclarationProc<>nil then
|
|
if ProcScope.DeclarationProc<>nil then
|
|
exit; // skip implementation, Note:PasResolver always refers the declaration
|
|
exit; // skip implementation, Note:PasResolver always refers the declaration
|
|
|
|
+ if CanSkipGenericProc(Proc) then exit;
|
|
|
|
|
|
if not MarkElementAsUsed(Proc) then exit;
|
|
if not MarkElementAsUsed(Proc) then exit;
|
|
{$IFDEF VerbosePasAnalyzer}
|
|
{$IFDEF VerbosePasAnalyzer}
|
|
@@ -1932,7 +1980,7 @@ begin
|
|
writeln('TPasAnalyzer.UseProcedureType ',GetElModName(ProcType));
|
|
writeln('TPasAnalyzer.UseProcedureType ',GetElModName(ProcType));
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
if not MarkElementAsUsed(ProcType) then exit;
|
|
if not MarkElementAsUsed(ProcType) then exit;
|
|
- if (ScopeModule=nil) and not Resolver.IsFullySpecialized(ProcType) then
|
|
|
|
|
|
+ if CanSkipGenericType(ProcType) then
|
|
RaiseNotSupported(20190817151651,ProcType);
|
|
RaiseNotSupported(20190817151651,ProcType);
|
|
|
|
|
|
for i:=0 to ProcType.Args.Count-1 do
|
|
for i:=0 to ProcType.Args.Count-1 do
|
|
@@ -2630,8 +2678,10 @@ var
|
|
C: TClass;
|
|
C: TClass;
|
|
Usage: TPAElement;
|
|
Usage: TPAElement;
|
|
i: Integer;
|
|
i: Integer;
|
|
- Member: TPasElement;
|
|
|
|
|
|
+ Member, SpecEl: TPasElement;
|
|
Members: TFPList;
|
|
Members: TFPList;
|
|
|
|
+ GenScope: TPasGenericScope;
|
|
|
|
+ SpecializedItems: TObjectList;
|
|
begin
|
|
begin
|
|
{$IFDEF VerbosePasAnalyzer}
|
|
{$IFDEF VerbosePasAnalyzer}
|
|
writeln('TPasAnalyzer.EmitTypeHints ',GetElModName(El));
|
|
writeln('TPasAnalyzer.EmitTypeHints ',GetElModName(El));
|
|
@@ -2640,6 +2690,21 @@ begin
|
|
if Usage=nil then
|
|
if Usage=nil then
|
|
begin
|
|
begin
|
|
// the whole type was never used
|
|
// the whole type was never used
|
|
|
|
+ if IsSpecializedGenericType(El) then
|
|
|
|
+ exit; // no hints for not used specializations
|
|
|
|
+ if (El.CustomData is TPasGenericScope) then
|
|
|
|
+ begin
|
|
|
|
+ GenScope:=TPasGenericScope(El.CustomData);
|
|
|
|
+ SpecializedItems:=GenScope.SpecializedItems;
|
|
|
|
+ if SpecializedItems<>nil then
|
|
|
|
+ for i:=0 to SpecializedItems.Count-1 do
|
|
|
|
+ begin
|
|
|
|
+ SpecEl:=TPRSpecializedItem(SpecializedItems[i]).SpecializedEl;
|
|
|
|
+ if FindElement(SpecEl)<>nil then
|
|
|
|
+ exit; // a specialization of this generic type is used
|
|
|
|
+ end;
|
|
|
|
+ end;
|
|
|
|
+
|
|
if (El.Visibility in [visPrivate,visStrictPrivate]) then
|
|
if (El.Visibility in [visPrivate,visStrictPrivate]) then
|
|
EmitMessage(20170312000020,mtHint,nPAPrivateTypeXNeverUsed,
|
|
EmitMessage(20170312000020,mtHint,nPAPrivateTypeXNeverUsed,
|
|
sPAPrivateTypeXNeverUsed,[El.FullName],El)
|
|
sPAPrivateTypeXNeverUsed,[El.FullName],El)
|
|
@@ -2647,10 +2712,9 @@ begin
|
|
begin
|
|
begin
|
|
if (El is TPasClassType) and (TPasClassType(El).ObjKind=okInterface) then
|
|
if (El is TPasClassType) and (TPasClassType(El).ObjKind=okInterface) then
|
|
exit;
|
|
exit;
|
|
- if IsSpecializedGenericType(El) then exit;
|
|
|
|
|
|
|
|
EmitMessage(20170312000025,mtHint,nPALocalXYNotUsed,
|
|
EmitMessage(20170312000025,mtHint,nPALocalXYNotUsed,
|
|
- sPALocalXYNotUsed,[El.ElementTypeName,El.Name],El);
|
|
|
|
|
|
+ sPALocalXYNotUsed,[El.ElementTypeName,GetElementNameAndParams(El)],El);
|
|
end;
|
|
end;
|
|
exit;
|
|
exit;
|
|
end;
|
|
end;
|
|
@@ -2726,6 +2790,8 @@ var
|
|
Usage: TPAElement;
|
|
Usage: TPAElement;
|
|
ProcScope: TPasProcedureScope;
|
|
ProcScope: TPasProcedureScope;
|
|
DeclProc, ImplProc: TPasProcedure;
|
|
DeclProc, ImplProc: TPasProcedure;
|
|
|
|
+ SpecializedItems: TObjectList;
|
|
|
|
+ SpecEl: TPasElement;
|
|
begin
|
|
begin
|
|
{$IFDEF VerbosePasAnalyzer}
|
|
{$IFDEF VerbosePasAnalyzer}
|
|
writeln('TPasAnalyzer.EmitProcedureHints ',GetElModName(El));
|
|
writeln('TPasAnalyzer.EmitProcedureHints ',GetElModName(El));
|
|
@@ -2746,15 +2812,26 @@ begin
|
|
if not PAElementExists(DeclProc) then
|
|
if not PAElementExists(DeclProc) then
|
|
begin
|
|
begin
|
|
// procedure never used
|
|
// procedure never used
|
|
- if ProcScope.DeclarationProc=nil then
|
|
|
|
- begin
|
|
|
|
- if El.Visibility in [visPrivate,visStrictPrivate] then
|
|
|
|
- EmitMessage(20170312093348,mtHint,nPAPrivateMethodIsNeverUsed,
|
|
|
|
- sPAPrivateMethodIsNeverUsed,[El.FullName],El)
|
|
|
|
- else
|
|
|
|
- EmitMessage(20170312093418,mtHint,nPALocalXYNotUsed,
|
|
|
|
- sPALocalXYNotUsed,[El.ElementTypeName,El.Name],El);
|
|
|
|
- end;
|
|
|
|
|
|
+ if ProcScope.DeclarationProc<>nil then
|
|
|
|
+ exit;
|
|
|
|
+
|
|
|
|
+ if ProcScope.SpecializedFromItem<>nil then
|
|
|
|
+ exit; // no hint for not used specialized procedure
|
|
|
|
+ SpecializedItems:=ProcScope.SpecializedItems;
|
|
|
|
+ if SpecializedItems<>nil then
|
|
|
|
+ for i:=0 to SpecializedItems.Count-1 do
|
|
|
|
+ begin
|
|
|
|
+ SpecEl:=TPRSpecializedItem(SpecializedItems[i]).SpecializedEl;
|
|
|
|
+ if FindElement(SpecEl)<>nil then
|
|
|
|
+ exit; // a specialization of this generic procedure is used
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ if El.Visibility in [visPrivate,visStrictPrivate] then
|
|
|
|
+ EmitMessage(20170312093348,mtHint,nPAPrivateMethodIsNeverUsed,
|
|
|
|
+ sPAPrivateMethodIsNeverUsed,[El.FullName],El)
|
|
|
|
+ else
|
|
|
|
+ EmitMessage(20170312093418,mtHint,nPALocalXYNotUsed,
|
|
|
|
+ sPALocalXYNotUsed,[El.ElementTypeName,El.Name],El);
|
|
exit;
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
|