mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-02 11:10:36 +02:00
* pgenutil.pas, generate_specialization:
* When building the typename for a generic use the full typename including it's surrounding object- or abstractrecorddefs. This allows that a nested non-generic type of a generic type A can be used as type arguments for more than one specialization of another generic B (there were some problems when B e.g. defined a pointer to the type argument's type) * Always CRC the constructed specialization name as otherwise it might reach the limit of 255 characters (not yet including unit name, method name or method arguments) Note: Errors like "expected XYZ, but got ABC" will need to be adjusted to use the prettyname... * increased PPU version + added test for above's point 1 git-svn-id: trunk@20149 -
This commit is contained in:
parent
89866cd17e
commit
7986f03186
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -10340,6 +10340,7 @@ tests/test/tgeneric69.pp svneol=native#text/pascal
|
|||||||
tests/test/tgeneric7.pp svneol=native#text/plain
|
tests/test/tgeneric7.pp svneol=native#text/plain
|
||||||
tests/test/tgeneric70.pp svneol=native#text/pascal
|
tests/test/tgeneric70.pp svneol=native#text/pascal
|
||||||
tests/test/tgeneric71.pp svneol=native#text/pascal
|
tests/test/tgeneric71.pp svneol=native#text/pascal
|
||||||
|
tests/test/tgeneric72.pp svneol=native#text/pascal
|
||||||
tests/test/tgeneric8.pp svneol=native#text/plain
|
tests/test/tgeneric8.pp svneol=native#text/plain
|
||||||
tests/test/tgeneric9.pp svneol=native#text/plain
|
tests/test/tgeneric9.pp svneol=native#text/plain
|
||||||
tests/test/tgoto.pp svneol=native#text/plain
|
tests/test/tgoto.pp svneol=native#text/plain
|
||||||
|
@ -40,7 +40,7 @@ implementation
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
{ common }
|
{ common }
|
||||||
cutils,
|
cutils,fpccrc,
|
||||||
{ global }
|
{ global }
|
||||||
globals,globtype,tokens,verbose,
|
globals,globtype,tokens,verbose,
|
||||||
{ symtable }
|
{ symtable }
|
||||||
@ -64,7 +64,7 @@ uses
|
|||||||
first,
|
first,
|
||||||
err : boolean;
|
err : boolean;
|
||||||
i,
|
i,
|
||||||
gencount : longint;
|
gencount,crc : longint;
|
||||||
genericdef : tstoreddef;
|
genericdef : tstoreddef;
|
||||||
generictype : ttypesym;
|
generictype : ttypesym;
|
||||||
genericdeflist : TFPObjectList;
|
genericdeflist : TFPObjectList;
|
||||||
@ -73,9 +73,9 @@ uses
|
|||||||
oldextendeddefs : TFPHashObjectList;
|
oldextendeddefs : TFPHashObjectList;
|
||||||
hmodule : tmodule;
|
hmodule : tmodule;
|
||||||
pu : tused_unit;
|
pu : tused_unit;
|
||||||
prettyname : ansistring;
|
prettyname,specializename : ansistring;
|
||||||
uspecializename,
|
ufinalspecializename,
|
||||||
countstr,genname,ugenname,specializename : string;
|
countstr,genname,ugenname,finalspecializename : string;
|
||||||
vmtbuilder : TVMTBuilder;
|
vmtbuilder : TVMTBuilder;
|
||||||
specializest : tsymtable;
|
specializest : tsymtable;
|
||||||
item : tobject;
|
item : tobject;
|
||||||
@ -165,7 +165,7 @@ uses
|
|||||||
if assigned(parsedtype) then
|
if assigned(parsedtype) then
|
||||||
begin
|
begin
|
||||||
genericdeflist.Add(parsedtype);
|
genericdeflist.Add(parsedtype);
|
||||||
specializename:='$'+parsedtype.typesym.realname;
|
specializename:='$'+parsedtype.typename;
|
||||||
prettyname:=parsedtype.typesym.prettyname;
|
prettyname:=parsedtype.typesym.prettyname;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@ -189,7 +189,7 @@ uses
|
|||||||
message(type_e_generics_cannot_reference_itself)
|
message(type_e_generics_cannot_reference_itself)
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
specializename:=specializename+'$'+pt2.resultdef.typesym.realname;
|
specializename:=specializename+'$'+pt2.resultdef.typename;
|
||||||
if first then
|
if first then
|
||||||
prettyname:=prettyname+pt2.resultdef.typesym.prettyname
|
prettyname:=prettyname+pt2.resultdef.typesym.prettyname
|
||||||
else
|
else
|
||||||
@ -258,8 +258,9 @@ uses
|
|||||||
genericdef:=tstoreddef(ttypesym(srsym).typedef);
|
genericdef:=tstoreddef(ttypesym(srsym).typedef);
|
||||||
|
|
||||||
{ build the new type's name }
|
{ build the new type's name }
|
||||||
specializename:=genname+specializename;
|
crc:=UpdateCrc32(0,specializename[1],length(specializename));
|
||||||
uspecializename:=upper(specializename);
|
finalspecializename:=genname+'$crc'+hexstr(crc,8);
|
||||||
|
ufinalspecializename:=upper(finalspecializename);
|
||||||
prettyname:=genericdef.typesym.prettyname+'<'+prettyname+'>';
|
prettyname:=genericdef.typesym.prettyname+'<'+prettyname+'>';
|
||||||
|
|
||||||
{ select the symtable containing the params }
|
{ select the symtable containing the params }
|
||||||
@ -295,7 +296,7 @@ uses
|
|||||||
|
|
||||||
{ Special case if we are referencing the current defined object }
|
{ Special case if we are referencing the current defined object }
|
||||||
if assigned(current_structdef) and
|
if assigned(current_structdef) and
|
||||||
(current_structdef.objname^=uspecializename) then
|
(current_structdef.objname^=ufinalspecializename) then
|
||||||
tt:=current_structdef;
|
tt:=current_structdef;
|
||||||
|
|
||||||
{ decide in which symtable to put the specialization }
|
{ decide in which symtable to put the specialization }
|
||||||
@ -307,7 +308,7 @@ uses
|
|||||||
{ Can we reuse an already specialized type? }
|
{ Can we reuse an already specialized type? }
|
||||||
if not assigned(tt) then
|
if not assigned(tt) then
|
||||||
begin
|
begin
|
||||||
hashedid.id:=uspecializename;
|
hashedid.id:=ufinalspecializename;
|
||||||
|
|
||||||
srsym:=tsym(specializest.findwithhash(hashedid));
|
srsym:=tsym(specializest.findwithhash(hashedid));
|
||||||
if assigned(srsym) then
|
if assigned(srsym) then
|
||||||
@ -387,7 +388,7 @@ uses
|
|||||||
|
|
||||||
{ First a new typesym so we can reuse this specialization and
|
{ First a new typesym so we can reuse this specialization and
|
||||||
references to this specialization can be handled }
|
references to this specialization can be handled }
|
||||||
srsym:=ttypesym.create(specializename,generrordef);
|
srsym:=ttypesym.create(finalspecializename,generrordef);
|
||||||
specializest.insert(srsym);
|
specializest.insert(srsym);
|
||||||
|
|
||||||
{ specializations are declarations as such it is the wisest to
|
{ specializations are declarations as such it is the wisest to
|
||||||
@ -402,7 +403,7 @@ uses
|
|||||||
internalerror(200511171);
|
internalerror(200511171);
|
||||||
current_scanner.startreplaytokens(genericdef.generictokenbuf,
|
current_scanner.startreplaytokens(genericdef.generictokenbuf,
|
||||||
genericdef.change_endian);
|
genericdef.change_endian);
|
||||||
read_named_type(tt,specializename,genericdef,generictypelist,false);
|
read_named_type(tt,finalspecializename,genericdef,generictypelist,false);
|
||||||
ttypesym(srsym).typedef:=tt;
|
ttypesym(srsym).typedef:=tt;
|
||||||
tt.typesym:=srsym;
|
tt.typesym:=srsym;
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ type
|
|||||||
{$endif Test_Double_checksum}
|
{$endif Test_Double_checksum}
|
||||||
|
|
||||||
const
|
const
|
||||||
CurrentPPUVersion = 142;
|
CurrentPPUVersion = 143;
|
||||||
|
|
||||||
{ buffer sizes }
|
{ buffer sizes }
|
||||||
maxentrysize = 1024;
|
maxentrysize = 1024;
|
||||||
|
45
tests/test/tgeneric72.pp
Normal file
45
tests/test/tgeneric72.pp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
{ %NORUN }
|
||||||
|
|
||||||
|
{ This tests that the two specializations of TUsedGeneric (once with
|
||||||
|
TGeneric<LongInt>.TSubType and once with TGeneric<Pointer>.TSubType) inside
|
||||||
|
TGeneric are unique }
|
||||||
|
|
||||||
|
program tgeneric72;
|
||||||
|
|
||||||
|
{$mode objfpc}
|
||||||
|
|
||||||
|
type
|
||||||
|
generic TUsedGeneric<T> = class
|
||||||
|
type
|
||||||
|
PT = ^T;
|
||||||
|
var
|
||||||
|
f: PT;
|
||||||
|
end;
|
||||||
|
|
||||||
|
generic TGeneric<T> = class
|
||||||
|
type
|
||||||
|
TSubType = record
|
||||||
|
Field: T;
|
||||||
|
end;
|
||||||
|
PSubType = ^TSubType;
|
||||||
|
TMyUsedGeneric = specialize TUsedGeneric<TSubType>;
|
||||||
|
private
|
||||||
|
f: PSubType;
|
||||||
|
public
|
||||||
|
function GetUsedGeneric: TMyUsedGeneric;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TGeneric.GetUsedGeneric: TMyUsedGeneric;
|
||||||
|
begin
|
||||||
|
Result := TMyUsedGeneric.Create;
|
||||||
|
Result.f := f;
|
||||||
|
end;
|
||||||
|
|
||||||
|
type
|
||||||
|
TGenericLongInt = specialize TGeneric<LongInt>;
|
||||||
|
TGenericPointer = specialize TGeneric<Pointer>;
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user