Pārlūkot izejas kodu

When checking whether the current specialization was already done before we also need to check the globalsymtable if we're currently in the implementation section. Otherwise the specialization will be generated twice and will result in a "duplicate identifier" error. This fixes mantis #20872 .

git-svn-id: trunk@19818 -
svenbarth 13 gadi atpakaļ
vecāks
revīzija
fca525a85b
5 mainītis faili ar 118 papildinājumiem un 2 dzēšanām
  1. 3 0
      .gitattributes
  2. 18 2
      compiler/pgenutil.pas
  3. 30 0
      tests/webtbs/tw20872a.pp
  4. 32 0
      tests/webtbs/tw20872b.pp
  5. 35 0
      tests/webtbs/tw20872c.pp

+ 3 - 0
.gitattributes

@@ -11955,6 +11955,9 @@ tests/webtbs/tw20796b.pp svneol=native#text/pascal
 tests/webtbs/tw20796c.pp svneol=native#text/pascal
 tests/webtbs/tw20821.pp svneol=native#text/pascal
 tests/webtbs/tw20836.pp svneol=native#text/pascal
+tests/webtbs/tw20872a.pp svneol=native#text/pascal
+tests/webtbs/tw20872b.pp svneol=native#text/pascal
+tests/webtbs/tw20872c.pp svneol=native#text/pascal
 tests/webtbs/tw2109.pp svneol=native#text/plain
 tests/webtbs/tw2110.pp svneol=native#text/plain
 tests/webtbs/tw2128.pp svneol=native#text/plain

+ 18 - 2
compiler/pgenutil.pas

@@ -83,6 +83,7 @@ uses
         old_current_genericdef,old_current_specializedef : tstoreddef;
         tempst : tglobalsymtable;
         old_block_type: tblock_type;
+        hashedid: thashedidstring;
       begin
         { retrieve generic def that we are going to replace }
         genericdef:=tstoreddef(tt);
@@ -306,13 +307,28 @@ uses
         { Can we reuse an already specialized type? }
         if not assigned(tt) then
           begin
-            srsym:=tsym(specializest.find(uspecializename));
+            hashedid.id:=uspecializename;
+
+            srsym:=tsym(specializest.findwithhash(hashedid));
             if assigned(srsym) then
               begin
                 if srsym.typ<>typesym then
                   internalerror(200710171);
                 tt:=ttypesym(srsym).typedef;
-              end;
+              end
+            else
+              { the generic could have been specialized in the globalsymtable
+                already, so search there as well }
+              if specializest<>current_module.globalsymtable then
+                begin
+                  srsym:=tsym(current_module.globalsymtable.findwithhash(hashedid));
+                  if assigned(srsym) then
+                    begin
+                      if srsym.typ<>typesym then
+                        internalerror(2011121101);
+                      tt:=ttypesym(srsym).typedef;
+                    end;
+                end;
           end;
 
         if not assigned(tt) then

+ 30 - 0
tests/webtbs/tw20872a.pp

@@ -0,0 +1,30 @@
+unit tw20872a;
+
+{$MODE delphi}
+
+interface
+
+type
+  TWrapper<TValue> = class end;
+
+  TTestClass = class
+  strict private
+    FWrapper: TWrapper<Integer>;  { Using inline specialization }
+  public
+    constructor Create;
+    destructor Destroy; override;
+  end;
+
+implementation
+
+constructor TTestClass.Create;
+begin
+  FWrapper := TWrapper<Integer>.Create;  { Duplicate identifier error here }
+end;
+
+destructor TTestClass.Destroy;
+begin
+  FWrapper.Free;
+end;
+
+end.

+ 32 - 0
tests/webtbs/tw20872b.pp

@@ -0,0 +1,32 @@
+unit tw20872b;
+
+{$MODE delphi}
+
+interface
+
+type
+  TWrapper<TValue> = class end;
+
+  TTestClass = class
+  strict private
+    type TSpecializedWrapper = TWrapper<Integer>;
+  strict private
+    FWrapper: TSpecializedWrapper;  { Using traditional workaround }
+  public
+    constructor Create;
+    destructor Destroy; override;
+  end;
+
+implementation
+
+constructor TTestClass.Create;
+begin
+  FWrapper := TWrapper<Integer>.Create;  { Duplicate identifier error here }
+end;
+
+destructor TTestClass.Destroy;
+begin
+  FWrapper.Free;
+end;
+
+end.

+ 35 - 0
tests/webtbs/tw20872c.pp

@@ -0,0 +1,35 @@
+unit tw20872c;
+
+{$MODE delphi}
+
+interface
+
+type
+  TWrapper<TValue> = class end;
+
+  TTestClass = class
+  strict private
+    type TSpecializedWrapper = TWrapper<Integer>;
+  strict private
+    FWrapper: TSpecializedWrapper;  { Using traditional workaround }
+  public
+    constructor Create;
+    destructor Destroy; override;
+  end;
+
+implementation
+
+constructor TTestClass.Create;
+type
+  TLocalSpecializedWrapper =
+    TWrapper<Integer>;  { Duplicate identifier error here }
+begin
+  FWrapper := TLocalSpecializedWrapper.Create;
+end;
+
+destructor TTestClass.Destroy;
+begin
+  FWrapper.Free;
+end;
+
+end.