Browse Source

We need to flag specializations of record-/objectdef once we have generated their methods otherwise an interesting situation might occur:
The classes in "fgl.pas" implement an enumerator in the generic class "TFPGListEnumerator" and "specialize" that inside themselves. If we now specialize one of the generic classes (e.g. "TFPGList") the "TFPGListEnumerator" is really specialized as well. That means a def is added to the global symtable (the local one in case of a program or library file). If we now use the enumerator class in the same file (e.g. by using a "for ... in", which has a temporary variable of that type) then the methods of the enumerator are specialized again (the def itself is not). To avoid this (and time consuming searches for existing method specializations) we flag the specialized def as "done" once we're finished.

symconst.pas
* add a new flag "df_methods_specialized" to the "tdefoption" enumeration

psub.pas, process_abstractrecorddef
* check the def for the "df_methods_specialized" flag and continue only if that is not set
* set the "df_methods_specialized" flag before leaving the function

git-svn-id: branches/svenbarth/generics@19432 -

svenbarth 14 years ago
parent
commit
feeff56099
2 changed files with 14 additions and 1 deletions
  1. 5 0
      compiler/psub.pas
  2. 9 1
      compiler/symconst.pas

+ 5 - 0
compiler/psub.pas

@@ -1998,6 +1998,8 @@ implementation
           i  : longint;
           hp : tdef;
         begin
+          if df_methods_specialized in def.defoptions then
+            Exit;
           for i:=0 to def.symtable.DefList.Count-1 do
             begin
               hp:=tdef(def.symtable.DefList[i]);
@@ -2024,6 +2026,9 @@ implementation
                  { generate code for subtypes as well }
                  process_abstractrecorddef(tabstractrecorddef(hp));
            end;
+          { we need to flag the def, so that we know the next time that we
+            already specialized the methods }
+          Include(def.defoptions, df_methods_specialized);
         end;
 
       begin

+ 9 - 1
compiler/symconst.pas

@@ -184,7 +184,15 @@ type
     { type is a specialization of a generic type }
     df_specialization,
     { def has been copied from another def so symtable is not owned }
-    df_copied_def
+    df_copied_def,
+    { this flag is set when the methods for a spezialization where already
+      generated; this is for example needed in case of the enumerator in the
+      generic lists of fgl.pp: the enumerator is specialized as part of the
+      surrounding class and if the class and the enumerator are used in the
+      same unit the methods of the enumerator are generated twice, once as part
+      of the class and once as part of the temporary variable that holds the
+      enumerator }
+    df_methods_specialized
   );
   tdefoptions=set of tdefoption;