2
0
Эх сурвалжийг харах

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 жил өмнө
parent
commit
feeff56099

+ 5 - 0
compiler/psub.pas

@@ -1998,6 +1998,8 @@ implementation
           i  : longint;
           i  : longint;
           hp : tdef;
           hp : tdef;
         begin
         begin
+          if df_methods_specialized in def.defoptions then
+            Exit;
           for i:=0 to def.symtable.DefList.Count-1 do
           for i:=0 to def.symtable.DefList.Count-1 do
             begin
             begin
               hp:=tdef(def.symtable.DefList[i]);
               hp:=tdef(def.symtable.DefList[i]);
@@ -2024,6 +2026,9 @@ implementation
                  { generate code for subtypes as well }
                  { generate code for subtypes as well }
                  process_abstractrecorddef(tabstractrecorddef(hp));
                  process_abstractrecorddef(tabstractrecorddef(hp));
            end;
            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;
         end;
 
 
       begin
       begin

+ 9 - 1
compiler/symconst.pas

@@ -184,7 +184,15 @@ type
     { type is a specialization of a generic type }
     { type is a specialization of a generic type }
     df_specialization,
     df_specialization,
     { def has been copied from another def so symtable is not owned }
     { 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;
   tdefoptions=set of tdefoption;