|
@@ -252,6 +252,7 @@ type
|
|
function ElementVisited(El: TPasElement; Mode: TPAUseMode): boolean; overload;
|
|
function ElementVisited(El: TPasElement; Mode: TPAUseMode): boolean; overload;
|
|
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;
|
|
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;
|
|
@@ -300,6 +301,7 @@ type
|
|
function IsExport(El: TPasElement): boolean;
|
|
function IsExport(El: TPasElement): boolean;
|
|
function IsIdentifier(El: TPasElement): boolean;
|
|
function IsIdentifier(El: TPasElement): boolean;
|
|
function IsImplBlockEmpty(El: TPasImplBlock): boolean;
|
|
function IsImplBlockEmpty(El: TPasImplBlock): boolean;
|
|
|
|
+ function IsSpecializedGenericType(El: TPasElement): boolean;
|
|
procedure EmitMessage(Id: TMaxPrecInt; MsgType: TMessageType;
|
|
procedure EmitMessage(Id: TMaxPrecInt; MsgType: TMessageType;
|
|
MsgNumber: integer; Fmt: String;
|
|
MsgNumber: integer; Fmt: String;
|
|
const Args: array of {$ifdef pas2js}jsvalue{$else}const{$endif};
|
|
const Args: array of {$ifdef pas2js}jsvalue{$else}const{$endif};
|
|
@@ -1007,6 +1009,27 @@ begin
|
|
CheckImplRef;
|
|
CheckImplRef;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+function TPasAnalyzer.CanSkipGenericType(El: TPasGenericType): boolean;
|
|
|
|
+begin
|
|
|
|
+ Result:=false;
|
|
|
|
+ if ScopeModule=nil then
|
|
|
|
+ begin
|
|
|
|
+ // analyze whole program
|
|
|
|
+ // -> should only reach fully specialized types
|
|
|
|
+ if not Resolver.IsFullySpecialized(El) then
|
|
|
|
+ RaiseNotSupported(20190817151437,El);
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ // analyze a module
|
|
|
|
+ if ((El.GenericTemplateTypes<>nil) and (El.GenericTemplateTypes.Count>0)) then
|
|
|
|
+ // generic template -> analyze
|
|
|
|
+ else if not Resolver.IsFullySpecialized(El) then
|
|
|
|
+ // 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
|
|
@@ -1102,8 +1125,7 @@ begin
|
|
else if C=TPasArrayType then
|
|
else if C=TPasArrayType then
|
|
begin
|
|
begin
|
|
ArrType:=TPasArrayType(El);
|
|
ArrType:=TPasArrayType(El);
|
|
- if (ScopeModule=nil) and not Resolver.IsFullySpecialized(ArrType) then
|
|
|
|
- RaiseNotSupported(20190817151437,ArrType);
|
|
|
|
|
|
+ if CanSkipGenericType(ArrType) then exit;
|
|
UseSubEl(ArrType.ElType);
|
|
UseSubEl(ArrType.ElType);
|
|
for i:=0 to length(ArrType.Ranges)-1 do
|
|
for i:=0 to length(ArrType.Ranges)-1 do
|
|
begin
|
|
begin
|
|
@@ -1117,6 +1139,7 @@ begin
|
|
else if C=TPasClassType then
|
|
else if C=TPasClassType then
|
|
begin
|
|
begin
|
|
ClassEl:=TPasClassType(El);
|
|
ClassEl:=TPasClassType(El);
|
|
|
|
+ if CanSkipGenericType(ClassEl) then exit;
|
|
if ClassEl.ObjKind=okInterface then
|
|
if ClassEl.ObjKind=okInterface then
|
|
begin
|
|
begin
|
|
// mark all used members
|
|
// mark all used members
|
|
@@ -1135,6 +1158,7 @@ begin
|
|
else if C=TPasRecordType then
|
|
else if C=TPasRecordType then
|
|
begin
|
|
begin
|
|
// published record: use all members
|
|
// published record: use all members
|
|
|
|
+ if CanSkipGenericType(TPasRecordType(El)) then exit;
|
|
Members:=TPasRecordType(El).Members;
|
|
Members:=TPasRecordType(El).Members;
|
|
for i:=0 to Members.Count-1 do
|
|
for i:=0 to Members.Count-1 do
|
|
begin
|
|
begin
|
|
@@ -1149,8 +1173,7 @@ begin
|
|
else if C.InheritsFrom(TPasProcedureType) then
|
|
else if C.InheritsFrom(TPasProcedureType) then
|
|
begin
|
|
begin
|
|
ProcType:=TPasProcedureType(El);
|
|
ProcType:=TPasProcedureType(El);
|
|
- if (ScopeModule=nil) and not Resolver.IsFullySpecialized(ProcType) then
|
|
|
|
- RaiseNotSupported(20190817151554,ProcType);
|
|
|
|
|
|
+ if CanSkipGenericType(ProcType) then exit;
|
|
for i:=0 to ProcType.Args.Count-1 do
|
|
for i:=0 to ProcType.Args.Count-1 do
|
|
UseSubEl(TPasArgument(ProcType.Args[i]).ArgType);
|
|
UseSubEl(TPasArgument(ProcType.Args[i]).ArgType);
|
|
if El is TPasFunctionType then
|
|
if El is TPasFunctionType then
|
|
@@ -1913,8 +1936,7 @@ begin
|
|
else if C=TPasArrayType then
|
|
else if C=TPasArrayType then
|
|
begin
|
|
begin
|
|
ArrType:=TPasArrayType(El);
|
|
ArrType:=TPasArrayType(El);
|
|
- if (ScopeModule=nil) and not Resolver.IsFullySpecialized(ArrType) then
|
|
|
|
- RaiseNotSupported(20190817151449,ArrType);
|
|
|
|
|
|
+ if CanSkipGenericType(ArrType) then exit;
|
|
if not MarkElementAsUsed(ArrType) then exit;
|
|
if not MarkElementAsUsed(ArrType) then exit;
|
|
for i:=0 to length(ArrType.Ranges)-1 do
|
|
for i:=0 to length(ArrType.Ranges)-1 do
|
|
UseExpr(ArrType.Ranges[i]);
|
|
UseExpr(ArrType.Ranges[i]);
|
|
@@ -1944,7 +1966,10 @@ begin
|
|
UseElType(El,TPasSetType(El).EnumType,Mode);
|
|
UseElType(El,TPasSetType(El).EnumType,Mode);
|
|
end
|
|
end
|
|
else if C.InheritsFrom(TPasProcedureType) then
|
|
else if C.InheritsFrom(TPasProcedureType) then
|
|
- UseProcedureType(TPasProcedureType(El))
|
|
|
|
|
|
+ begin
|
|
|
|
+ if CanSkipGenericType(TPasProcedureType(El)) then exit;
|
|
|
|
+ UseProcedureType(TPasProcedureType(El));
|
|
|
|
+ end
|
|
else if C=TPasSpecializeType then
|
|
else if C=TPasSpecializeType then
|
|
UseSpecializeType(TPasSpecializeType(El),Mode)
|
|
UseSpecializeType(TPasSpecializeType(El),Mode)
|
|
else if C=TPasGenericTemplateType then
|
|
else if C=TPasGenericTemplateType then
|
|
@@ -2021,8 +2046,7 @@ var
|
|
aClass: TPasClassType;
|
|
aClass: TPasClassType;
|
|
begin
|
|
begin
|
|
FirstTime:=true;
|
|
FirstTime:=true;
|
|
- if (ScopeModule=nil) and not Resolver.IsFullySpecialized(El) then
|
|
|
|
- RaiseNotSupported(20190817110919,El);
|
|
|
|
|
|
+ if CanSkipGenericType(El) then exit;
|
|
case Mode of
|
|
case Mode of
|
|
paumAllExports: exit;
|
|
paumAllExports: exit;
|
|
paumAllPasUsable:
|
|
paumAllPasUsable:
|
|
@@ -2516,7 +2540,6 @@ var
|
|
i: Integer;
|
|
i: Integer;
|
|
Decl: TPasElement;
|
|
Decl: TPasElement;
|
|
Usage: TPAElement;
|
|
Usage: TPAElement;
|
|
- GenScope: TPasGenericScope;
|
|
|
|
begin
|
|
begin
|
|
{$IFDEF VerbosePasAnalyzer}
|
|
{$IFDEF VerbosePasAnalyzer}
|
|
writeln('TPasAnalyzer.EmitDeclarationsHints ',GetElModName(El));
|
|
writeln('TPasAnalyzer.EmitDeclarationsHints ',GetElModName(El));
|
|
@@ -2538,12 +2561,8 @@ begin
|
|
if Usage=nil then
|
|
if Usage=nil then
|
|
begin
|
|
begin
|
|
// declaration was never used
|
|
// declaration was never used
|
|
- if Decl is TPasGenericType then
|
|
|
|
- begin
|
|
|
|
- GenScope:=Decl.CustomData as TPasGenericScope;
|
|
|
|
- if GenScope.SpecializedItem<>nil then
|
|
|
|
- continue;
|
|
|
|
- end;
|
|
|
|
|
|
+ if IsSpecializedGenericType(Decl) then
|
|
|
|
+ continue;
|
|
EmitMessage(20170311231734,mtHint,nPALocalXYNotUsed,
|
|
EmitMessage(20170311231734,mtHint,nPALocalXYNotUsed,
|
|
sPALocalXYNotUsed,[Decl.ElementTypeName,Decl.Name],Decl);
|
|
sPALocalXYNotUsed,[Decl.ElementTypeName,Decl.Name],Decl);
|
|
end;
|
|
end;
|
|
@@ -2558,7 +2577,6 @@ var
|
|
i: Integer;
|
|
i: Integer;
|
|
Member: TPasElement;
|
|
Member: TPasElement;
|
|
Members: TFPList;
|
|
Members: TFPList;
|
|
- GenScope: TPasGenericScope;
|
|
|
|
begin
|
|
begin
|
|
{$IFDEF VerbosePasAnalyzer}
|
|
{$IFDEF VerbosePasAnalyzer}
|
|
writeln('TPasAnalyzer.EmitTypeHints ',GetElModName(El));
|
|
writeln('TPasAnalyzer.EmitTypeHints ',GetElModName(El));
|
|
@@ -2574,12 +2592,7 @@ 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 El is TPasGenericType then
|
|
|
|
- begin
|
|
|
|
- GenScope:=El.CustomData as TPasGenericScope;
|
|
|
|
- if GenScope.SpecializedItem<>nil then
|
|
|
|
- exit;
|
|
|
|
- end;
|
|
|
|
|
|
+ if IsSpecializedGenericType(El) then exit;
|
|
|
|
|
|
EmitMessage(20170312000025,mtHint,nPALocalXYNotUsed,
|
|
EmitMessage(20170312000025,mtHint,nPALocalXYNotUsed,
|
|
sPALocalXYNotUsed,[El.ElementTypeName,El.Name],El);
|
|
sPALocalXYNotUsed,[El.ElementTypeName,El.Name],El);
|
|
@@ -2639,7 +2652,7 @@ begin
|
|
begin
|
|
begin
|
|
// write without read
|
|
// write without read
|
|
if (vmExternal in El.VarModifiers)
|
|
if (vmExternal in El.VarModifiers)
|
|
- or ((El.Parent is TPasClassType) and (TPasClassType(El.Parent).IsExternal)) then
|
|
|
|
|
|
+ or ((El.Parent is TPasClassType) and TPasClassType(El.Parent).IsExternal) then
|
|
exit;
|
|
exit;
|
|
if El.Visibility in [visPrivate,visStrictPrivate] then
|
|
if El.Visibility in [visPrivate,visStrictPrivate] then
|
|
EmitMessage(20170311234159,mtHint,nPAPrivateFieldIsAssignedButNeverUsed,
|
|
EmitMessage(20170311234159,mtHint,nPAPrivateFieldIsAssignedButNeverUsed,
|
|
@@ -2970,6 +2983,19 @@ begin
|
|
Result:=false;
|
|
Result:=false;
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
+function TPasAnalyzer.IsSpecializedGenericType(El: TPasElement): boolean;
|
|
|
|
+var
|
|
|
|
+ GenScope: TPasGenericScope;
|
|
|
|
+begin
|
|
|
|
+ if El is TPasGenericType then
|
|
|
|
+ begin
|
|
|
|
+ GenScope:=El.CustomData as TPasGenericScope;
|
|
|
|
+ if (GenScope<>nil) and (GenScope.SpecializedItem<>nil) then
|
|
|
|
+ exit(true);
|
|
|
|
+ end;
|
|
|
|
+ Result:=false;
|
|
|
|
+end;
|
|
|
|
+
|
|
procedure TPasAnalyzer.EmitMessage(Id: TMaxPrecInt; MsgType: TMessageType;
|
|
procedure TPasAnalyzer.EmitMessage(Id: TMaxPrecInt; MsgType: TMessageType;
|
|
MsgNumber: integer; Fmt: String;
|
|
MsgNumber: integer; Fmt: String;
|
|
const Args: array of {$ifdef pas2js}jsvalue{$else}const{$endif};
|
|
const Args: array of {$ifdef pas2js}jsvalue{$else}const{$endif};
|