浏览代码

compiler: don't create enum defs for specializations declarations. Enums are stored in the unit symtables and generic declarations already add them there. Therefore specializations should search for enum defs declared by generics and use them instead of own.

git-svn-id: trunk@16686 -
paul 14 年之前
父节点
当前提交
7c33505916
共有 4 个文件被更改,包括 69 次插入9 次删除
  1. 1 0
      .gitattributes
  2. 44 8
      compiler/ptype.pas
  3. 1 1
      tests/test/tgeneric24.pp
  4. 23 0
      tests/test/tgeneric27.pp

+ 1 - 0
.gitattributes

@@ -9415,6 +9415,7 @@ tests/test/tgeneric23.pp svneol=native#text/pascal
 tests/test/tgeneric24.pp svneol=native#text/pascal
 tests/test/tgeneric24.pp svneol=native#text/pascal
 tests/test/tgeneric25.pp svneol=native#text/pascal
 tests/test/tgeneric25.pp svneol=native#text/pascal
 tests/test/tgeneric26.pp svneol=native#text/pascal
 tests/test/tgeneric26.pp svneol=native#text/pascal
+tests/test/tgeneric27.pp svneol=native#text/pascal
 tests/test/tgeneric3.pp svneol=native#text/plain
 tests/test/tgeneric3.pp svneol=native#text/plain
 tests/test/tgeneric4.pp svneol=native#text/plain
 tests/test/tgeneric4.pp svneol=native#text/plain
 tests/test/tgeneric5.pp svneol=native#text/plain
 tests/test/tgeneric5.pp svneol=native#text/plain

+ 44 - 8
compiler/ptype.pas

@@ -1240,10 +1240,13 @@ implementation
         hdef : tdef;
         hdef : tdef;
         pd : tabstractprocdef;
         pd : tabstractprocdef;
         is_func,
         is_func,
-        enumdupmsg, first : boolean;
+        enumdupmsg, first, is_specialize : boolean;
         newtype : ttypesym;
         newtype : ttypesym;
         oldlocalswitches : tlocalswitches;
         oldlocalswitches : tlocalswitches;
         bitpacking: boolean;
         bitpacking: boolean;
+        stitem: psymtablestackitem;
+        sym: tsym;
+        st: tsymtable;
       begin
       begin
          def:=nil;
          def:=nil;
          case token of
          case token of
@@ -1258,8 +1261,37 @@ implementation
                 { allow negativ value_str }
                 { allow negativ value_str }
                 l:=int64(-1);
                 l:=int64(-1);
                 enumdupmsg:=false;
                 enumdupmsg:=false;
-                aktenumdef:=tenumdef.create;
+                { check that we are not adding an enum from specialization
+                  we can't just use current_specializedef because of inner types
+                  like specialize array of record }
+                is_specialize:=false;
+                stitem:=symtablestack.stack;
+                while assigned(stitem) do
+                  begin
+                    { check records, classes and arrays because they can be specialized }
+                    if stitem^.symtable.symtabletype in [recordsymtable,ObjectSymtable,arraysymtable] then
+                      begin
+                        is_specialize:=is_specialize or (df_specialization in tstoreddef(stitem^.symtable.defowner).defoptions);
+                        stitem:=stitem^.next;
+                      end
+                    else
+                      break;
+                  end;
+                if not is_specialize then
+                  aktenumdef:=tenumdef.create
+                else
+                  aktenumdef:=nil;
                 repeat
                 repeat
+                  { if it is a specialization then search the first enum member
+                    and get the member owner instead of just created enumdef }
+                  if not assigned(aktenumdef) then
+                    begin
+                      searchsym(pattern,sym,st);
+                      if sym.typ=enumsym then
+                        aktenumdef:=tenumsym(sym).definition
+                      else
+                        internalerror(201101021);
+                    end;
                   s:=orgpattern;
                   s:=orgpattern;
                   defpos:=current_tokenpos;
                   defpos:=current_tokenpos;
                   consume(_ID);
                   consume(_ID);
@@ -1303,12 +1335,16 @@ implementation
                   else
                   else
                     inc(l.svalue);
                     inc(l.svalue);
                   first:=false;
                   first:=false;
-                  storepos:=current_tokenpos;
-                  current_tokenpos:=defpos;
-                  tenumsymtable(aktenumdef.symtable).insert(tenumsym.create(s,aktenumdef,longint(l.svalue)));
-                  if not (cs_scopedenums in current_settings.localswitches) then
-                    tstoredsymtable(aktenumdef.owner).insert(tenumsym.create(s,aktenumdef,longint(l.svalue)));
-                  current_tokenpos:=storepos;
+                  { don't generate enum members is this is a specialization because aktenumdef is copied from the generic type }
+                  if not is_specialize then
+                    begin
+                      storepos:=current_tokenpos;
+                      current_tokenpos:=defpos;
+                      tenumsymtable(aktenumdef.symtable).insert(tenumsym.create(s,aktenumdef,longint(l.svalue)));
+                      if not (cs_scopedenums in current_settings.localswitches) then
+                        tstoredsymtable(aktenumdef.owner).insert(tenumsym.create(s,aktenumdef,longint(l.svalue)));
+                      current_tokenpos:=storepos;
+                    end;
                 until not try_to_consume(_COMMA);
                 until not try_to_consume(_COMMA);
                 def:=aktenumdef;
                 def:=aktenumdef;
                 consume(_RKLAMMER);
                 consume(_RKLAMMER);

+ 1 - 1
tests/test/tgeneric24.pp

@@ -1,4 +1,4 @@
-program project1;
+program tgeneric24;
 
 
 {$mode objfpc}{$H+}
 {$mode objfpc}{$H+}
 {$apptype console}
 {$apptype console}

+ 23 - 0
tests/test/tgeneric27.pp

@@ -0,0 +1,23 @@
+program tgeneric27;
+
+{ check that specialization does not add enum members to the static symtable and reuses the generic enum definintion }
+
+{$mode objfpc}{$H+}
+type
+  generic TRecArr<T> = array[0..1] of record
+    case enum:(one, two, three) of
+      one: (F: Integer);
+      two: (Z: Byte);
+      three: (Y: PChar);
+  end;
+
+var
+  A: specialize TRecArr<Integer>;
+  B: specialize TRecArr<String>;
+begin
+  A[0].enum := one;
+  B[0].enum := one;
+  if A[0].enum <> B[0].enum then
+    halt(1);
+end.
+