Browse Source

Fix for Mantis #24071.

pdecl.pas, types_dec:
  * extract the determination of the nested generic def to a new local function "determine_generic_def"
  * use "determine_generic_def" to determine the generic def in case of a forward def and pass this and the generic type list to "object_dec"

+ added test

git-svn-id: trunk@24572 -
svenbarth 12 years ago
parent
commit
2c792659ce
3 changed files with 78 additions and 40 deletions
  1. 1 0
      .gitattributes
  2. 53 40
      compiler/pdecl.pas
  3. 24 0
      tests/webtbs/tw24071.pp

+ 1 - 0
.gitattributes

@@ -13407,6 +13407,7 @@ tests/webtbs/tw23962.pp svneol=native#text/plain
 tests/webtbs/tw23963.pp svneol=native#text/plain
 tests/webtbs/tw2397.pp svneol=native#text/plain
 tests/webtbs/tw24007.pp svneol=native#text/plain
+tests/webtbs/tw24071.pp svneol=native#text/pascal
 tests/webtbs/tw2409.pp svneol=native#text/plain
 tests/webtbs/tw24131.pp svneol=native#text/plain
 tests/webtbs/tw24197.pp svneol=native#text/plain

+ 53 - 40
compiler/pdecl.pas

@@ -360,6 +360,52 @@ implementation
 
     procedure types_dec(in_structure: boolean);
 
+      function determine_generic_def(name:tidstring):tstoreddef;
+        var
+          hashedid : THashedIDString;
+          pd : tprocdef;
+          sym : tsym;
+        begin
+          result:=nil;
+          { check whether this is a declaration of a type inside a
+            specialization }
+          if assigned(current_structdef) and
+              (df_specialization in current_structdef.defoptions) then
+            begin
+              if not assigned(current_structdef.genericdef) or
+                  not (current_structdef.genericdef.typ in [recorddef,objectdef]) then
+                internalerror(2011052301);
+              hashedid.id:=name;
+              { we could be inside a method of the specialization
+                instead of its declaration, so check that first (as
+                local nested types aren't allowed we don't need to
+                walk the symtablestack to find the localsymtable) }
+              if symtablestack.top.symtabletype=localsymtable then
+                begin
+                  { we are in a method }
+                  if not assigned(symtablestack.top.defowner) or
+                      (symtablestack.top.defowner.typ<>procdef) then
+                    internalerror(2011120701);
+                  pd:=tprocdef(symtablestack.top.defowner);
+                  if not assigned(pd.genericdef) or (pd.genericdef.typ<>procdef) then
+                    internalerror(2011120702);
+                  sym:=tsym(tprocdef(pd.genericdef).localst.findwithhash(hashedid));
+                end
+              else
+                sym:=nil;
+              if not assigned(sym) or not (sym.typ=typesym) then
+                begin
+                  { now search in the declaration of the generic }
+                  sym:=tsym(tabstractrecorddef(current_structdef.genericdef).symtable.findwithhash(hashedid));
+                  if not assigned(sym) or not (sym.typ=typesym) then
+                    internalerror(2011052302);
+                end;
+              { use the corresponding type in the generic's symtable as
+                genericdef for the specialized type }
+              result:=tstoreddef(ttypesym(sym).typedef);
+            end;
+        end;
+
       procedure finalize_class_external_status(od: tobjectdef);
         begin
           if  [oo_is_external,oo_is_forward] <= od.objectoptions then
@@ -389,8 +435,6 @@ implementation
          p:tnode;
          gendef : tstoreddef;
          s : shortstring;
-         pd: tprocdef;
-         hashedid : thashedidstring;
 {$ifdef x86}
          segment_register: string;
 {$endif x86}
@@ -508,8 +552,11 @@ implementation
                         internalerror(200811072);
                     end;
                     consume(token);
+                    { determine the generic def in case we are in a nested type
+                      of a specialization }
+                    gendef:=determine_generic_def(gentypename);
                     { we can ignore the result, the definition is modified }
-                    object_dec(objecttype,genorgtypename,newtype,nil,nil,tobjectdef(ttypesym(sym).typedef),ht_none);
+                    object_dec(objecttype,genorgtypename,newtype,gendef,generictypelist,tobjectdef(ttypesym(sym).typedef),ht_none);
                     newtype:=ttypesym(sym);
                     hdef:=newtype.typedef;
                   end
@@ -564,43 +611,9 @@ implementation
                       sym:=nil;
                     end;
 
-                  { check whether this is a declaration of a type inside a
-                    specialization }
-                  if assigned(current_structdef) and
-                      (df_specialization in current_structdef.defoptions) then
-                    begin
-                      if not assigned(current_structdef.genericdef) or
-                          not (current_structdef.genericdef.typ in [recorddef,objectdef]) then
-                        internalerror(2011052301);
-                      hashedid.id:=gentypename;
-                      { we could be inside a method of the specialization
-                        instead of its declaration, so check that first (as
-                        local nested types aren't allowed we don't need to
-                        walk the symtablestack to find the localsymtable) }
-                      if symtablestack.top.symtabletype=localsymtable then
-                        begin
-                          { we are in a method }
-                          if not assigned(symtablestack.top.defowner) or
-                              (symtablestack.top.defowner.typ<>procdef) then
-                            internalerror(2011120701);
-                          pd:=tprocdef(symtablestack.top.defowner);
-                          if not assigned(pd.genericdef) or (pd.genericdef.typ<>procdef) then
-                            internalerror(2011120702);
-                          sym:=tsym(tprocdef(pd.genericdef).localst.findwithhash(hashedid));
-                        end
-                      else
-                        sym:=nil;
-                      if not assigned(sym) or not (sym.typ=typesym) then
-                        begin
-                          { now search in the declaration of the generic }
-                          sym:=tsym(tabstractrecorddef(current_structdef.genericdef).symtable.findwithhash(hashedid));
-                          if not assigned(sym) or not (sym.typ=typesym) then
-                            internalerror(2011052302);
-                        end;
-                      { use the corresponding type in the generic's symtable as
-                        genericdef for the specialized type }
-                      gendef:=tstoreddef(ttypesym(sym).typedef);
-                    end;
+                  { determine the generic def in case we are in a nested type
+                    of a specialization }
+                  gendef:=determine_generic_def(gentypename);
                 end;
               { insert a new type if we don't reuse an existing symbol }
               if not assigned(newtype) then

+ 24 - 0
tests/webtbs/tw24071.pp

@@ -0,0 +1,24 @@
+{ %NORUN }
+
+program tw24071;
+
+{$mode delphi}
+
+type
+  TA<T> = class
+  end;
+
+  TB<T> = class
+  public
+  type
+    TC = class;
+    TC = class(TA<TC>)
+    private
+      procedure Foo; virtual; abstract;
+    end;
+  end;
+
+var
+  X: TB<Integer>;
+begin
+end.