diff --git a/packages/fcl-passrc/src/pasresolver.pp b/packages/fcl-passrc/src/pasresolver.pp index 6f034e958b..7f64517b0d 100644 --- a/packages/fcl-passrc/src/pasresolver.pp +++ b/packages/fcl-passrc/src/pasresolver.pp @@ -2209,9 +2209,10 @@ type function IsArrayExpr(Expr: TParamsExpr): TPasArrayType; function IsArrayOperatorAdd(Expr: TPasExpr): boolean; function IsTypeCast(Params: TParamsExpr): boolean; + function IsGenericTemplType(const ResolvedEl: TPasResolverResult): boolean; function GetTypeParameterCount(aType: TPasGenericType): integer; function GetGenericConstraintKeyword(El: TPasExpr): TToken; - function IsGenericTemplType(const ResolvedEl: TPasResolverResult): boolean; + function IsFullySpecialized(El: TPasGenericType): boolean; function IsInterfaceType(const ResolvedEl: TPasResolverResult; IntfType: TPasClassInterfaceType): boolean; overload; function IsInterfaceType(TypeEl: TPasType; IntfType: TPasClassInterfaceType): boolean; overload; @@ -25472,6 +25473,23 @@ begin end; end; +function TPasResolver.IsFullySpecialized(El: TPasGenericType): boolean; +var + GenScope: TPasGenericScope; + Params: TPasTypeArray; + i: Integer; +begin + if (El.GenericTemplateTypes<>nil) and (El.GenericTemplateTypes.Count>0) then + exit(false); + if not (El.CustomData is TPasGenericScope) then exit(true); + GenScope:=TPasGenericScope(El.CustomData); + if GenScope.SpecializedItem=nil then exit(true); + Params:=GenScope.SpecializedItem.Params; + for i:=0 to length(Params)-1 do + if Params[i] is TPasGenericTemplateType then exit(false); + Result:=true; +end; + function TPasResolver.IsInterfaceType(const ResolvedEl: TPasResolverResult; IntfType: TPasClassInterfaceType): boolean; begin diff --git a/packages/fcl-passrc/src/pasuseanalyzer.pas b/packages/fcl-passrc/src/pasuseanalyzer.pas index 7a459335c1..afbaafcfe5 100644 --- a/packages/fcl-passrc/src/pasuseanalyzer.pas +++ b/packages/fcl-passrc/src/pasuseanalyzer.pas @@ -831,7 +831,7 @@ var s: String; E: EPasAnalyzer; begin - s:='['+IntToStr(Id)+']: Element='+GetElModName(El); + s:='['+IntToStr(Id)+']: Element='+GetObjPath(El); if Msg<>'' then S:=S+' '+Msg; E:=EPasAnalyzer.Create(s); E.PasElement:=El; @@ -1065,6 +1065,7 @@ var Prop: TPasProperty; ProcType: TPasProcedureType; ClassEl: TPasClassType; + ArrType: TPasArrayType; begin {$IFDEF VerbosePasAnalyzer} writeln('TPasAnalyzer.UsePublished START ',GetObjName(El)); @@ -1100,10 +1101,13 @@ begin else if C=TPasRangeType then else if C=TPasArrayType then begin - UseSubEl(TPasArrayType(El).ElType); - for i:=0 to length(TPasArrayType(El).Ranges)-1 do + ArrType:=TPasArrayType(El); + if (ScopeModule=nil) and not Resolver.IsFullySpecialized(ArrType) then + RaiseNotSupported(20190817151437,ArrType); + UseSubEl(ArrType.ElType); + for i:=0 to length(ArrType.Ranges)-1 do begin - Member:=TPasArrayType(El).Ranges[i]; + Member:=ArrType.Ranges[i]; Resolver.ComputeElement(Member,MemberResolved,[rcConstant]); UseSubEl(MemberResolved.HiTypeEl); end; @@ -1145,11 +1149,20 @@ begin else if C.InheritsFrom(TPasProcedureType) then begin ProcType:=TPasProcedureType(El); + if (ScopeModule=nil) and not Resolver.IsFullySpecialized(ProcType) then + RaiseNotSupported(20190817151554,ProcType); for i:=0 to ProcType.Args.Count-1 do UseSubEl(TPasArgument(ProcType.Args[i]).ArgType); if El is TPasFunctionType then UseSubEl(TPasFunctionType(El).ResultEl.ResultType); end + else if C=TPasSpecializeType then + UseSubEl(TPasSpecializeType(El).DestType) + else if C=TPasGenericTemplateType then + begin + if ScopeModule=nil then + RaiseNotSupported(20190817110226,El); + end else begin {$IFDEF VerbosePasAnalyzer} @@ -1844,6 +1857,8 @@ begin writeln('TPasAnalyzer.UseProcedureType ',GetElModName(ProcType)); {$ENDIF} if not MarkElementAsUsed(ProcType) then exit; + if (ScopeModule=nil) and not Resolver.IsFullySpecialized(ProcType) then + RaiseNotSupported(20190817151651,ProcType); for i:=0 to ProcType.Args.Count-1 do begin @@ -1861,6 +1876,7 @@ procedure TPasAnalyzer.UseType(El: TPasType; Mode: TPAUseMode); var C: TClass; i: Integer; + ArrType: TPasArrayType; begin if El=nil then exit; @@ -1896,10 +1912,13 @@ begin end else if C=TPasArrayType then begin - if not MarkElementAsUsed(El) then exit; - for i:=0 to length(TPasArrayType(El).Ranges)-1 do - UseExpr(TPasArrayType(El).Ranges[i]); - UseElType(El,TPasArrayType(El).ElType,Mode); + ArrType:=TPasArrayType(El); + if (ScopeModule=nil) and not Resolver.IsFullySpecialized(ArrType) then + RaiseNotSupported(20190817151449,ArrType); + if not MarkElementAsUsed(ArrType) then exit; + for i:=0 to length(ArrType.Ranges)-1 do + UseExpr(ArrType.Ranges[i]); + UseElType(El,ArrType.ElType,Mode); end else if (C=TPasRecordType) or (C=TPasClassType) then UseClassOrRecType(TPasMembersType(El),Mode) @@ -1928,6 +1947,7 @@ begin UseProcedureType(TPasProcedureType(El)) else if C=TPasSpecializeType then UseSpecializeType(TPasSpecializeType(El),Mode) + else if C=TPasGenericTemplateType then else RaiseNotSupported(20170306170315,El); @@ -2001,6 +2021,8 @@ var aClass: TPasClassType; begin FirstTime:=true; + if (ScopeModule=nil) and not Resolver.IsFullySpecialized(El) then + RaiseNotSupported(20190817110919,El); case Mode of paumAllExports: exit; paumAllPasUsable: diff --git a/packages/fcl-passrc/tests/tcresolver.pas b/packages/fcl-passrc/tests/tcresolver.pas index d948d841f0..101e125f7e 100644 --- a/packages/fcl-passrc/tests/tcresolver.pas +++ b/packages/fcl-passrc/tests/tcresolver.pas @@ -5908,8 +5908,8 @@ begin ' if unit1.j1=0 then ;', ' if unitdots.unit1.j1=0 then ;', '']); - CheckResolverException('Duplicate identifier "unitdots.unit1" at unitdots.main1.pas(2,14)', - nDuplicateIdentifier); + CheckParserException('Duplicate identifier "unit1" at token ";" in file unitdots.main1.pas at line 2 column 27', + nParserDuplicateIdentifier); end; procedure TTestResolver.TestUnit_Unit1DotUnit2Fail;