From 7986f03186d49fb60713420666772ac73a7f7eb5 Mon Sep 17 00:00:00 2001 From: svenbarth Date: Sun, 22 Jan 2012 13:29:12 +0000 Subject: [PATCH] * 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 - --- .gitattributes | 1 + compiler/pgenutil.pas | 27 ++++++++++++------------ compiler/ppu.pas | 2 +- tests/test/tgeneric72.pp | 45 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 14 deletions(-) create mode 100644 tests/test/tgeneric72.pp diff --git a/.gitattributes b/.gitattributes index 1cbbe5f23a..b474e20056 100644 --- a/.gitattributes +++ b/.gitattributes @@ -10340,6 +10340,7 @@ tests/test/tgeneric69.pp svneol=native#text/pascal tests/test/tgeneric7.pp svneol=native#text/plain tests/test/tgeneric70.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/tgeneric9.pp svneol=native#text/plain tests/test/tgoto.pp svneol=native#text/plain diff --git a/compiler/pgenutil.pas b/compiler/pgenutil.pas index b2bbdf4ab9..51b41fe492 100644 --- a/compiler/pgenutil.pas +++ b/compiler/pgenutil.pas @@ -40,7 +40,7 @@ implementation uses { common } - cutils, + cutils,fpccrc, { global } globals,globtype,tokens,verbose, { symtable } @@ -64,7 +64,7 @@ uses first, err : boolean; i, - gencount : longint; + gencount,crc : longint; genericdef : tstoreddef; generictype : ttypesym; genericdeflist : TFPObjectList; @@ -73,9 +73,9 @@ uses oldextendeddefs : TFPHashObjectList; hmodule : tmodule; pu : tused_unit; - prettyname : ansistring; - uspecializename, - countstr,genname,ugenname,specializename : string; + prettyname,specializename : ansistring; + ufinalspecializename, + countstr,genname,ugenname,finalspecializename : string; vmtbuilder : TVMTBuilder; specializest : tsymtable; item : tobject; @@ -165,7 +165,7 @@ uses if assigned(parsedtype) then begin genericdeflist.Add(parsedtype); - specializename:='$'+parsedtype.typesym.realname; + specializename:='$'+parsedtype.typename; prettyname:=parsedtype.typesym.prettyname; end else @@ -189,7 +189,7 @@ uses message(type_e_generics_cannot_reference_itself) else begin - specializename:=specializename+'$'+pt2.resultdef.typesym.realname; + specializename:=specializename+'$'+pt2.resultdef.typename; if first then prettyname:=prettyname+pt2.resultdef.typesym.prettyname else @@ -258,8 +258,9 @@ uses genericdef:=tstoreddef(ttypesym(srsym).typedef); { build the new type's name } - specializename:=genname+specializename; - uspecializename:=upper(specializename); + crc:=UpdateCrc32(0,specializename[1],length(specializename)); + finalspecializename:=genname+'$crc'+hexstr(crc,8); + ufinalspecializename:=upper(finalspecializename); prettyname:=genericdef.typesym.prettyname+'<'+prettyname+'>'; { select the symtable containing the params } @@ -295,7 +296,7 @@ uses { Special case if we are referencing the current defined object } if assigned(current_structdef) and - (current_structdef.objname^=uspecializename) then + (current_structdef.objname^=ufinalspecializename) then tt:=current_structdef; { decide in which symtable to put the specialization } @@ -307,7 +308,7 @@ uses { Can we reuse an already specialized type? } if not assigned(tt) then begin - hashedid.id:=uspecializename; + hashedid.id:=ufinalspecializename; srsym:=tsym(specializest.findwithhash(hashedid)); if assigned(srsym) then @@ -387,7 +388,7 @@ uses { First a new typesym so we can reuse this specialization and references to this specialization can be handled } - srsym:=ttypesym.create(specializename,generrordef); + srsym:=ttypesym.create(finalspecializename,generrordef); specializest.insert(srsym); { specializations are declarations as such it is the wisest to @@ -402,7 +403,7 @@ uses internalerror(200511171); current_scanner.startreplaytokens(genericdef.generictokenbuf, genericdef.change_endian); - read_named_type(tt,specializename,genericdef,generictypelist,false); + read_named_type(tt,finalspecializename,genericdef,generictypelist,false); ttypesym(srsym).typedef:=tt; tt.typesym:=srsym; diff --git a/compiler/ppu.pas b/compiler/ppu.pas index 9f84e49026..306a0d5ea6 100644 --- a/compiler/ppu.pas +++ b/compiler/ppu.pas @@ -43,7 +43,7 @@ type {$endif Test_Double_checksum} const - CurrentPPUVersion = 142; + CurrentPPUVersion = 143; { buffer sizes } maxentrysize = 1024; diff --git a/tests/test/tgeneric72.pp b/tests/test/tgeneric72.pp new file mode 100644 index 0000000000..9db1076cf1 --- /dev/null +++ b/tests/test/tgeneric72.pp @@ -0,0 +1,45 @@ +{ %NORUN } + +{ This tests that the two specializations of TUsedGeneric (once with + TGeneric.TSubType and once with TGeneric.TSubType) inside + TGeneric are unique } + +program tgeneric72; + +{$mode objfpc} + +type + generic TUsedGeneric = class + type + PT = ^T; + var + f: PT; + end; + + generic TGeneric = class + type + TSubType = record + Field: T; + end; + PSubType = ^TSubType; + TMyUsedGeneric = specialize TUsedGeneric; + private + f: PSubType; + public + function GetUsedGeneric: TMyUsedGeneric; + end; + +function TGeneric.GetUsedGeneric: TMyUsedGeneric; +begin + Result := TMyUsedGeneric.Create; + Result.f := f; +end; + +type + TGenericLongInt = specialize TGeneric; + TGenericPointer = specialize TGeneric; + +begin + +end. +