Browse Source

compiler:
- add own symbol table for enumeration to store enumeration elements
- reimplement enumeration member traverse using symbol table instead of firstenum/nextenum - that members are removed
- implement TEnum.Element access syntax - element is searched in the enumeration symtable in this case instead of global/local symtables
- implement {$SCOPEDENUM ON/OFF} local switch
+ tests

git-svn-id: trunk@15051 -

paul 15 years ago
parent
commit
1b614b526a

+ 3 - 0
.gitattributes

@@ -8966,6 +8966,9 @@ tests/test/tdispinterface2.pp svneol=native#text/plain
 tests/test/tendian1.pp svneol=native#text/plain
 tests/test/tendian1.pp svneol=native#text/plain
 tests/test/tenum1.pp svneol=native#text/plain
 tests/test/tenum1.pp svneol=native#text/plain
 tests/test/tenum2.pp svneol=native#text/plain
 tests/test/tenum2.pp svneol=native#text/plain
+tests/test/tenum3.pp svneol=native#text/plain
+tests/test/tenum4.pp svneol=native#text/plain
+tests/test/tenum5.pp svneol=native#text/plain
 tests/test/tenumerators1.pp svneol=native#text/pascal
 tests/test/tenumerators1.pp svneol=native#text/pascal
 tests/test/testcmem.pp svneol=native#text/plain
 tests/test/testcmem.pp svneol=native#text/plain
 tests/test/testda1.pp svneol=native#text/plain
 tests/test/testda1.pp svneol=native#text/plain

+ 7 - 9
compiler/browcol.pas

@@ -1259,19 +1259,17 @@ end;
   end;
   end;
   function GetDefinitionStr(def: tdef): string; forward;
   function GetDefinitionStr(def: tdef): string; forward;
   function GetEnumDefStr(def: tenumdef): string;
   function GetEnumDefStr(def: tenumdef): string;
-  var Name: string;
-      esym: tenumsym;
-      Count: integer;
+  var
+    Name: string;
+    esym: tenumsym;
+    i: integer;
   begin
   begin
     Name:='(';
     Name:='(';
-    esym:=tenumsym(def.Firstenum); Count:=0;
-    while (esym<>nil) do
+    for i := 0 to def.symtable.SymList.Count - 1 do
       begin
       begin
-        if Count>0 then
+        if i>0 then
           Name:=Name+', ';
           Name:=Name+', ';
-        Name:=Name+esym.name;
-        esym:=esym.nextenum;
-        Inc(Count);
+        Name:=Name+tenumsym(def.symtable.SymList[i]).name;
       end;
       end;
     Name:=Name+')';
     Name:=Name+')';
     GetEnumDefStr:=Name;
     GetEnumDefStr:=Name;

+ 8 - 3
compiler/dbgdwarf.pas

@@ -1330,6 +1330,7 @@ implementation
     procedure TDebugInfoDwarf.appenddef_enum(list:TAsmList;def:tenumdef);
     procedure TDebugInfoDwarf.appenddef_enum(list:TAsmList;def:tenumdef);
       var
       var
         hp : tenumsym;
         hp : tenumsym;
+        i  : integer;
       begin
       begin
         if assigned(def.typesym) then
         if assigned(def.typesym) then
           append_entry(DW_TAG_enumeration_type,true,[
           append_entry(DW_TAG_enumeration_type,true,[
@@ -1345,15 +1346,19 @@ implementation
         finish_entry;
         finish_entry;
 
 
         { write enum symbols }
         { write enum symbols }
-        hp:=tenumsym(def.firstenum);
-        while assigned(hp) do
+        for i := 0 to def.symtable.SymList.Count - 1 do
           begin
           begin
+            hp:=tenumsym(def.symtable.SymList[i]);
+            if hp.value<def.minval then
+              continue
+            else
+            if hp.value>def.maxval then
+              break;
             append_entry(DW_TAG_enumerator,false,[
             append_entry(DW_TAG_enumerator,false,[
               DW_AT_name,DW_FORM_string,symname(hp)+#0,
               DW_AT_name,DW_FORM_string,symname(hp)+#0,
               DW_AT_const_value,DW_FORM_data4,hp.value
               DW_AT_const_value,DW_FORM_data4,hp.value
             ]);
             ]);
             finish_entry;
             finish_entry;
-            hp:=tenumsym(hp).nextenum;
           end;
           end;
 
 
         finish_children;
         finish_children;

+ 7 - 3
compiler/dbgstabs.pas

@@ -575,7 +575,6 @@ implementation
           result:='@s'+tostr(def.size*8)+';e'
           result:='@s'+tostr(def.size*8)+';e'
         else
         else
           result:='e';
           result:='e';
-        p := tenumsym(def.firstenum);
         { the if-test is required because pred(def.minval) might overflow;
         { the if-test is required because pred(def.minval) might overflow;
           the longint() typecast should be safe because stabs is not
           the longint() typecast should be safe because stabs is not
           supported for 64 bit targets }
           supported for 64 bit targets }
@@ -583,10 +582,15 @@ implementation
           for i:=lowerbound to pred(longint(def.minval)) do
           for i:=lowerbound to pred(longint(def.minval)) do
             result:=result+'<invalid>:'+tostr(i)+',';
             result:=result+'<invalid>:'+tostr(i)+',';
 
 
-        while assigned(p) do
+        for i := 0 to def.symtable.SymList.Count - 1 do
           begin
           begin
+            p := tenumsym(def.symtable.SymList[i]);
+            if p.value<def.minval then
+              continue
+            else
+            if p.value>def.maxval then
+              break;
             result:=result+GetSymName(p)+':'+tostr(p.value)+',';
             result:=result+GetSymName(p)+':'+tostr(p.value)+',';
-            p:=p.nextenum;
           end;
           end;
         { the final ',' is required to have a valid stabs }
         { the final ',' is required to have a valid stabs }
         result:=result+';';
         result:=result+';';

+ 1 - 1
compiler/defcmp.pas

@@ -594,7 +594,7 @@ implementation
                           begin
                           begin
                             { assignment of an enum symbol to an unique type? }
                             { assignment of an enum symbol to an unique type? }
                             if (fromtreetype=ordconstn) and
                             if (fromtreetype=ordconstn) and
-                              (tenumsym(tenumdef(hd1).firstenum)=tenumsym(tenumdef(hd2).firstenum)) then
+                              (tenumsym(tenumdef(hd1).getfirstsym)=tenumsym(tenumdef(hd2).getfirstsym)) then
                               begin
                               begin
                                 { because of packenum they can have different sizes! (JM) }
                                 { because of packenum they can have different sizes! (JM) }
                                 eq:=te_convert_l1;
                                 eq:=te_convert_l1;

+ 1 - 1
compiler/globtype.pas

@@ -110,7 +110,7 @@ interface
          cs_mmx,cs_mmx_saturation,
          cs_mmx,cs_mmx_saturation,
          { parser }
          { parser }
          cs_typed_addresses,cs_strict_var_strings,cs_ansistrings,cs_bitpacking,
          cs_typed_addresses,cs_strict_var_strings,cs_ansistrings,cs_bitpacking,
-         cs_varpropsetter,
+         cs_varpropsetter,cs_scopedenums,
          { macpas specific}
          { macpas specific}
          cs_external_var, cs_externally_visible
          cs_external_var, cs_externally_visible
        );
        );

+ 22 - 10
compiler/ncgrtti.pas

@@ -416,6 +416,7 @@ implementation
 
 
         procedure enumdef_rtti(def:tenumdef);
         procedure enumdef_rtti(def:tenumdef);
         var
         var
+           i  : integer;
            hp : tenumsym;
            hp : tenumsym;
         begin
         begin
           current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkEnumeration));
           current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkEnumeration));
@@ -441,13 +442,16 @@ implementation
             current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.basedef,rt)))
             current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.basedef,rt)))
           else
           else
             current_asmdata.asmlists[al_rtti].concat(Tai_const.create_sym(nil));
             current_asmdata.asmlists[al_rtti].concat(Tai_const.create_sym(nil));
-          { write name list }
-          hp:=tenumsym(def.firstenum);
-          while assigned(hp) do
+          for i := 0 to def.symtable.SymList.Count - 1 do
             begin
             begin
+              hp:=tenumsym(def.symtable.SymList[i]);
+              if hp.value<def.minval then
+                continue
+              else
+              if hp.value>def.maxval then
+                break;
               current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(hp.realname)));
               current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(hp.realname)));
               current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(hp.realname));
               current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(hp.realname));
-              hp:=hp.nextenum;
             end;
             end;
           { write unit name }
           { write unit name }
           current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(current_module.realmodulename^)));
           current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(current_module.realmodulename^)));
@@ -969,9 +973,14 @@ implementation
           sym_count:=0;
           sym_count:=0;
           sym_alloc:=64;
           sym_alloc:=64;
           st:=0;
           st:=0;
-          t:=Tenumsym(def.firstenum);
-          while assigned(t) do
+          for i := 0 to def.symtable.SymList.Count - 1 do
             begin
             begin
+              t:=tenumsym(def.symtable.SymList[i]);
+              if t.value<def.minval then
+                continue
+              else
+              if t.value>def.maxval then
+                break;
               if sym_count>=sym_alloc then
               if sym_count>=sym_alloc then
                 begin
                 begin
                   reallocmem(syms,2*sym_alloc*sizeof(Tenumsym));
                   reallocmem(syms,2*sym_alloc*sizeof(Tenumsym));
@@ -982,7 +991,6 @@ implementation
               offsets[sym_count]:=st;
               offsets[sym_count]:=st;
               inc(sym_count);
               inc(sym_count);
               st:=st+length(t.realname)+1;
               st:=st+length(t.realname)+1;
-              t:=t.nextenum;
             end;
             end;
           {Sort the syms by enum value}
           {Sort the syms by enum value}
           if sym_count>=2 then
           if sym_count>=2 then
@@ -1098,9 +1106,14 @@ implementation
           sym_count:=0;
           sym_count:=0;
           sym_alloc:=64;
           sym_alloc:=64;
           st:=0;
           st:=0;
-          t:=Tenumsym(def.firstenum);
-          while assigned(t) do
+          for i := 0 to def.symtable.SymList.Count - 1 do
             begin
             begin
+              t:=tenumsym(def.symtable.SymList[i]);
+              if t.value<def.minval then
+                continue
+              else
+              if t.value>def.maxval then
+                break;
               if sym_count>=sym_alloc then
               if sym_count>=sym_alloc then
                 begin
                 begin
                   reallocmem(syms,2*sym_alloc*sizeof(Tenumsym));
                   reallocmem(syms,2*sym_alloc*sizeof(Tenumsym));
@@ -1111,7 +1124,6 @@ implementation
               offsets[sym_count]:=st;
               offsets[sym_count]:=st;
               inc(sym_count);
               inc(sym_count);
               st:=st+length(t.realname)+1;
               st:=st+length(t.realname)+1;
-              t:=t.nextenum;
             end;
             end;
           {Sort the syms by enum name}
           {Sort the syms by enum name}
           if sym_count>=2 then
           if sym_count>=2 then

+ 11 - 4
compiler/ninl.pas

@@ -1330,6 +1330,7 @@ implementation
            v    : tconstexprint;
            v    : tconstexprint;
            enum : tenumsym;
            enum : tenumsym;
            hp   : tnode;
            hp   : tnode;
+           i    : integer;
         begin
         begin
            case def.typ of
            case def.typ of
              orddef:
              orddef:
@@ -1346,11 +1347,17 @@ implementation
              enumdef:
              enumdef:
                begin
                begin
                   set_varstate(left,vs_read,[]);
                   set_varstate(left,vs_read,[]);
-                  enum:=tenumsym(tenumdef(def).firstenum);
-                  v:=tenumdef(def).maxval;
                   if inlinenumber=in_high_x then
                   if inlinenumber=in_high_x then
-                    while assigned(enum) and (enum.value <> v) do
-                      enum:=enum.nextenum;
+                    v:=tenumdef(def).maxval
+                  else
+                    v:=tenumdef(def).minval;
+                  enum:=nil;
+                  for i := 0 to tenumdef(def).symtable.SymList.Count - 1 do
+                    if tenumsym(tenumdef(def).symtable.SymList[i]).value=v then
+                      begin
+                        enum:=tenumsym(tenumdef(def).symtable.SymList[i]);
+                        break;
+                      end;
                   if not assigned(enum) then
                   if not assigned(enum) then
                     internalerror(309993)
                     internalerror(309993)
                   else
                   else

+ 2 - 5
compiler/nset.pas

@@ -190,18 +190,15 @@ implementation
         function createsetconst(psd : tsetdef) : pconstset;
         function createsetconst(psd : tsetdef) : pconstset;
         var
         var
           pcs : pconstset;
           pcs : pconstset;
-          pes : tenumsym;
           i : longint;
           i : longint;
         begin
         begin
           new(pcs);
           new(pcs);
           case psd.elementdef.typ of
           case psd.elementdef.typ of
             enumdef :
             enumdef :
               begin
               begin
-                pes:=tenumsym(tenumdef(psd.elementdef).firstenum);
-                while assigned(pes) do
+                for i := 0 to tenumdef(psd.elementdef).symtable.SymList.Count - 1 do
                   begin
                   begin
-                    include(pcs^,pes.value);
-                    pes:=pes.nextenum;
+                    include(pcs^,tenumsym(tenumdef(psd.elementdef).symtable.SymList[i]).value);
                   end;
                   end;
               end;
               end;
             orddef :
             orddef :

+ 22 - 3
compiler/pexpr.pas

@@ -2050,9 +2050,28 @@ implementation
                                   p1.destroy;
                                   p1.destroy;
                                   p1:=cerrornode.create;
                                   p1:=cerrornode.create;
                                 end;
                                 end;
-                             end;
-                           consume(_ID);
-                         end;
+                            end;
+                          consume(_ID);
+                        end;
+                      enumdef:
+                        begin
+                          if token=_ID then
+                            begin
+                              srsym:=tsym(tenumdef(p1.resultdef).symtable.Find(pattern));
+                              p1.destroy;
+                              if assigned(srsym) and (srsym.typ=enumsym) then
+                                begin
+                                  check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg);
+                                  p1:=genenumnode(tenumsym(srsym));
+                                end
+                              else
+                                begin
+                                  Message1(sym_e_id_no_member,orgpattern);
+                                  p1:=cerrornode.create;
+                                end;
+                            end;
+                          consume(_ID);
+                        end;
                        variantdef:
                        variantdef:
                          begin
                          begin
                            { dispatch call? }
                            { dispatch call? }

+ 1 - 1
compiler/ppu.pas

@@ -43,7 +43,7 @@ type
 {$endif Test_Double_checksum}
 {$endif Test_Double_checksum}
 
 
 const
 const
-  CurrentPPUVersion = 116;
+  CurrentPPUVersion = 117;
 
 
 { buffer sizes }
 { buffer sizes }
   maxentrysize = 1024;
   maxentrysize = 1024;

+ 4 - 2
compiler/ptype.pas

@@ -840,7 +840,7 @@ implementation
         pd : tabstractprocdef;
         pd : tabstractprocdef;
         is_func,
         is_func,
         enumdupmsg, first : boolean;
         enumdupmsg, first : boolean;
-        newtype    : ttypesym;
+        newtype : ttypesym;
         oldlocalswitches : tlocalswitches;
         oldlocalswitches : tlocalswitches;
         bitpacking: boolean;
         bitpacking: boolean;
       begin
       begin
@@ -904,7 +904,9 @@ implementation
                   first := false;
                   first := false;
                   storepos:=current_tokenpos;
                   storepos:=current_tokenpos;
                   current_tokenpos:=defpos;
                   current_tokenpos:=defpos;
-                  tstoredsymtable(aktenumdef.owner).insert(tenumsym.create(s,aktenumdef,longint(l.svalue)));
+                  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;
                   current_tokenpos:=storepos;
                 until not try_to_consume(_COMMA);
                 until not try_to_consume(_COMMA);
                 def:=aktenumdef;
                 def:=aktenumdef;

+ 6 - 0
compiler/scandir.pas

@@ -1019,6 +1019,11 @@ unit scandir;
         do_localswitch(cs_fpu_fwait);
         do_localswitch(cs_fpu_fwait);
       end;
       end;
 
 
+    procedure dir_scopedenums;
+      begin
+        do_localswitch(cs_scopedenums);
+      end;
+
     procedure dir_setpeflags;
     procedure dir_setpeflags;
       begin
       begin
         if not (target_info.system in (systems_all_windows)) then
         if not (target_info.system in (systems_all_windows)) then
@@ -1447,6 +1452,7 @@ unit scandir;
         AddDirective('RESOURCE',directive_all, @dir_resource);
         AddDirective('RESOURCE',directive_all, @dir_resource);
         AddDirective('SATURATION',directive_all, @dir_saturation);
         AddDirective('SATURATION',directive_all, @dir_saturation);
         AddDirective('SAFEFPUEXCEPTIONS',directive_all, @dir_safefpuexceptions);
         AddDirective('SAFEFPUEXCEPTIONS',directive_all, @dir_safefpuexceptions);
+        AddDirective('SCOPEDENUMS',directive_all, @dir_scopedenums);
         AddDirective('SETPEFLAGS', directive_all, @dir_setpeflags);
         AddDirective('SETPEFLAGS', directive_all, @dir_setpeflags);
         AddDirective('SCREENNAME',directive_all, @dir_screenname);
         AddDirective('SCREENNAME',directive_all, @dir_screenname);
         AddDirective('SMARTLINK',directive_all, @dir_smartlink);
         AddDirective('SMARTLINK',directive_all, @dir_smartlink);

+ 2 - 1
compiler/symconst.pas

@@ -419,7 +419,8 @@ type
     ObjectSymtable,recordsymtable,
     ObjectSymtable,recordsymtable,
     localsymtable,parasymtable,
     localsymtable,parasymtable,
     withsymtable,stt_excepTSymtable,
     withsymtable,stt_excepTSymtable,
-    exportedmacrosymtable, localmacrosymtable
+    exportedmacrosymtable, localmacrosymtable,
+    enumsymtable
   );
   );
 
 
 
 

+ 59 - 26
compiler/symdef.pas

@@ -579,21 +579,23 @@ interface
           function  getvardef:longint;override;
           function  getvardef:longint;override;
        end;
        end;
 
 
+       { tenumdef }
+
        tenumdef = class(tstoreddef)
        tenumdef = class(tstoreddef)
           minval,
           minval,
           maxval    : aint;
           maxval    : aint;
           has_jumps : boolean;
           has_jumps : boolean;
-          firstenum : tsym;  {tenumsym}
           basedef   : tenumdef;
           basedef   : tenumdef;
           basedefderef : tderef;
           basedefderef : tderef;
+          symtable  : TSymtable;
           constructor create;
           constructor create;
           constructor create_subrange(_basedef:tenumdef;_min,_max:aint);
           constructor create_subrange(_basedef:tenumdef;_min,_max:aint);
           constructor ppuload(ppufile:tcompilerppufile);
           constructor ppuload(ppufile:tcompilerppufile);
+          destructor destroy;override;
           function getcopy : tstoreddef;override;
           function getcopy : tstoreddef;override;
           procedure ppuwrite(ppufile:tcompilerppufile);override;
           procedure ppuwrite(ppufile:tcompilerppufile);override;
           procedure buildderef;override;
           procedure buildderef;override;
           procedure deref;override;
           procedure deref;override;
-          procedure derefimpl;override;
           function  GetTypeName:string;override;
           function  GetTypeName:string;override;
           function  is_publishable : boolean;override;
           function  is_publishable : boolean;override;
           procedure calcsavesize;
           procedure calcsavesize;
@@ -602,6 +604,7 @@ interface
           procedure setmin(_min:aint);
           procedure setmin(_min:aint);
           function  min:aint;
           function  min:aint;
           function  max:aint;
           function  max:aint;
+          function  getfirstsym:tsym;
        end;
        end;
 
 
        tsetdef = class(tstoreddef)
        tsetdef = class(tstoreddef)
@@ -1392,7 +1395,7 @@ implementation
          calcsavesize;
          calcsavesize;
          has_jumps:=false;
          has_jumps:=false;
          basedef:=nil;
          basedef:=nil;
-         firstenum:=nil;
+         symtable:=tenumsymtable.create(self);
       end;
       end;
 
 
 
 
@@ -1404,21 +1407,37 @@ implementation
          basedef:=_basedef;
          basedef:=_basedef;
          calcsavesize;
          calcsavesize;
          has_jumps:=false;
          has_jumps:=false;
-         firstenum:=basedef.firstenum;
-         while assigned(firstenum) and (tenumsym(firstenum).value<>minval) do
-           firstenum:=tenumsym(firstenum).nextenum;
-      end;
+         symtable:=basedef.symtable.getcopy;
+         include(defoptions, df_copied_def);
+       end;
 
 
 
 
     constructor tenumdef.ppuload(ppufile:tcompilerppufile);
     constructor tenumdef.ppuload(ppufile:tcompilerppufile);
       begin
       begin
          inherited ppuload(enumdef,ppufile);
          inherited ppuload(enumdef,ppufile);
-         ppufile.getderef(basedefderef);
          minval:=ppufile.getaint;
          minval:=ppufile.getaint;
          maxval:=ppufile.getaint;
          maxval:=ppufile.getaint;
          savesize:=ppufile.getaint;
          savesize:=ppufile.getaint;
          has_jumps:=false;
          has_jumps:=false;
-         firstenum:=Nil;
+         if df_copied_def in defoptions then
+           begin
+             symtable:=nil;
+             ppufile.getderef(basedefderef);
+           end
+         else
+           begin
+             // create with nil defowner first to prevent values changes on insert
+             symtable:=tenumsymtable.create(nil);
+             tenumsymtable(symtable).ppuload(ppufile);
+             symtable.defowner:=self;
+           end;
+      end;
+
+    destructor tenumdef.destroy;
+      begin
+        symtable.free;
+        symtable:=nil;
+        inherited destroy;
       end;
       end;
 
 
 
 
@@ -1431,10 +1450,13 @@ implementation
             result:=tenumdef.create;
             result:=tenumdef.create;
             tenumdef(result).minval:=minval;
             tenumdef(result).minval:=minval;
             tenumdef(result).maxval:=maxval;
             tenumdef(result).maxval:=maxval;
+            tenumdef(result).symtable.free;
+            tenumdef(result).symtable:=symtable.getcopy;
+            tenumdef(result).basedef:=self;
           end;
           end;
         tenumdef(result).has_jumps:=has_jumps;
         tenumdef(result).has_jumps:=has_jumps;
-        tenumdef(result).firstenum:=firstenum;
         tenumdef(result).basedefderef:=basedefderef;
         tenumdef(result).basedefderef:=basedefderef;
+        include(tenumdef(result).defoptions,df_copied_def);
       end;
       end;
 
 
 
 
@@ -1501,43 +1523,54 @@ implementation
         max:=maxval;
         max:=maxval;
       end;
       end;
 
 
+    function tenumdef.getfirstsym: tsym;
+      var
+        i:integer;
+      begin
+        for i := 0 to symtable.SymList.Count - 1 do
+          begin
+            result:=tsym(symtable.SymList[i]);
+            if tenumsym(result).value=minval then
+              exit;
+          end;
+        result:=nil;
+      end;
+
 
 
     procedure tenumdef.buildderef;
     procedure tenumdef.buildderef;
       begin
       begin
         inherited buildderef;
         inherited buildderef;
-        basedefderef.build(basedef);
+        if df_copied_def in defoptions then
+          basedefderef.build(basedef)
+        else
+          tenumsymtable(symtable).buildderef;
       end;
       end;
 
 
 
 
     procedure tenumdef.deref;
     procedure tenumdef.deref;
       begin
       begin
         inherited deref;
         inherited deref;
-        basedef:=tenumdef(basedefderef.resolve);
-        { restart ordering }
-        firstenum:=nil;
-      end;
-
-
-    procedure tenumdef.derefimpl;
-      begin
-        if assigned(basedef) and
-           (firstenum=nil) then
+        if df_copied_def in defoptions then
           begin
           begin
-            firstenum:=basedef.firstenum;
-            while assigned(firstenum) and (tenumsym(firstenum).value<>minval) do
-              firstenum:=tenumsym(firstenum).nextenum;
-          end;
+            basedef:=tenumdef(basedefderef.resolve);
+            symtable:=basedef.symtable.getcopy;
+          end
+        else
+          tenumsymtable(symtable).deref;
       end;
       end;
 
 
 
 
     procedure tenumdef.ppuwrite(ppufile:tcompilerppufile);
     procedure tenumdef.ppuwrite(ppufile:tcompilerppufile);
       begin
       begin
          inherited ppuwrite(ppufile);
          inherited ppuwrite(ppufile);
-         ppufile.putderef(basedefderef);
          ppufile.putaint(min);
          ppufile.putaint(min);
          ppufile.putaint(max);
          ppufile.putaint(max);
          ppufile.putaint(savesize);
          ppufile.putaint(savesize);
+         if df_copied_def in defoptions then
+           ppufile.putderef(basedefderef);
          ppufile.writeentry(ibenumdef);
          ppufile.writeentry(ibenumdef);
+         if not (df_copied_def in defoptions) then
+           tenumsymtable(symtable).ppuwrite(ppufile);
       end;
       end;
 
 
 
 

+ 0 - 50
compiler/symsym.pas

@@ -277,13 +277,11 @@ interface
           value      : longint;
           value      : longint;
           definition : tenumdef;
           definition : tenumdef;
           definitionderef : tderef;
           definitionderef : tderef;
-          nextenum   : tenumsym;
           constructor create(const n : string;def : tenumdef;v : longint);
           constructor create(const n : string;def : tenumdef;v : longint);
           constructor ppuload(ppufile:tcompilerppufile);
           constructor ppuload(ppufile:tcompilerppufile);
           procedure ppuwrite(ppufile:tcompilerppufile);override;
           procedure ppuwrite(ppufile:tcompilerppufile);override;
           procedure buildderef;override;
           procedure buildderef;override;
           procedure deref;override;
           procedure deref;override;
-          procedure order;
        end;
        end;
 
 
        tsyssym = class(Tstoredsym)
        tsyssym = class(Tstoredsym)
@@ -1774,26 +1772,6 @@ implementation
          inherited create(enumsym,n);
          inherited create(enumsym,n);
          definition:=def;
          definition:=def;
          value:=v;
          value:=v;
-         { First entry? Then we need to set the minval }
-         if def.firstenum=nil then
-           begin
-             if v>0 then
-               def.has_jumps:=true;
-             def.setmin(v);
-             def.setmax(v);
-           end
-         else
-           begin
-             { check for jumps }
-             if v>def.max+1 then
-              def.has_jumps:=true;
-             { update low and high }
-             if def.min>v then
-               def.setmin(v);
-             if def.max<v then
-               def.setmax(v);
-           end;
-         order;
       end;
       end;
 
 
 
 
@@ -1802,7 +1780,6 @@ implementation
          inherited ppuload(enumsym,ppufile);
          inherited ppuload(enumsym,ppufile);
          ppufile.getderef(definitionderef);
          ppufile.getderef(definitionderef);
          value:=ppufile.getlongint;
          value:=ppufile.getlongint;
-         nextenum := Nil;
       end;
       end;
 
 
 
 
@@ -1815,33 +1792,6 @@ implementation
     procedure tenumsym.deref;
     procedure tenumsym.deref;
       begin
       begin
          definition:=tenumdef(definitionderef.resolve);
          definition:=tenumdef(definitionderef.resolve);
-         order;
-      end;
-
-   procedure tenumsym.order;
-      var
-         sym : tenumsym;
-      begin
-         sym := tenumsym(definition.firstenum);
-         if sym = nil then
-          begin
-            definition.firstenum := self;
-            nextenum := nil;
-            exit;
-          end;
-         { reorder the symbols in increasing value }
-         if value < sym.value then
-          begin
-            nextenum := sym;
-            definition.firstenum := self;
-          end
-         else
-          begin
-            while (sym.value <= value) and assigned(sym.nextenum) do
-             sym := sym.nextenum;
-            nextenum := sym.nextenum;
-            sym.nextenum := self;
-          end;
       end;
       end;
 
 
     procedure tenumsym.ppuwrite(ppufile:tcompilerppufile);
     procedure tenumsym.ppuwrite(ppufile:tcompilerppufile);

+ 51 - 0
compiler/symtable.pas

@@ -173,6 +173,14 @@ interface
           constructor create(exported: boolean);
           constructor create(exported: boolean);
        end;
        end;
 
 
+       { tenumsymtable }
+
+       tenumsymtable = class(tstoredsymtable)
+       public
+          procedure insert(sym: TSymEntry; checkdup: boolean = true); override;
+          constructor create(adefowner:tdef);
+       end;
+
     var
     var
        systemunit     : tglobalsymtable; { pointer to the system unit }
        systemunit     : tglobalsymtable; { pointer to the system unit }
 
 
@@ -1508,6 +1516,49 @@ implementation
         symtablelevel:=main_program_level;
         symtablelevel:=main_program_level;
       end;
       end;
 
 
+{****************************************************************************
+                          TEnumSymtable
+****************************************************************************}
+
+    procedure tenumsymtable.insert(sym: TSymEntry; checkdup: boolean);
+      var
+        value: longint;
+        def: tenumdef;
+      begin
+        // defowner = nil only when we are loading from ppu
+        if defowner<>nil then
+          begin
+            { First entry? Then we need to set the minval }
+            value:=tenumsym(sym).value;
+            def:=tenumdef(defowner);
+            if SymList.count=0 then
+              begin
+                if value>0 then
+                  def.has_jumps:=true;
+                def.setmin(value);
+                def.setmax(value);
+              end
+            else
+              begin
+                { check for jumps }
+                if value>def.max+1 then
+                  def.has_jumps:=true;
+                { update low and high }
+                if def.min>value then
+                  def.setmin(value);
+                if def.max<value then
+                  def.setmax(value);
+              end;
+          end;
+        inherited insert(sym, checkdup);
+      end;
+
+    constructor tenumsymtable.create(adefowner: tdef);
+      begin
+        inherited Create('');
+        symtabletype:=enumsymtable;
+        defowner:=adefowner;
+      end;
 
 
 {*****************************************************************************
 {*****************************************************************************
                              Helper Routines
                              Helper Routines

+ 39 - 0
tests/test/tenum3.pp

@@ -0,0 +1,39 @@
+// test that enumeration members are retrieved from the right enumeration types
+// test enumeration.element syntax
+// test scropedenums directive
+program tenum3;
+uses
+  typinfo;
+type
+{$SCOPEDENUMS ON}
+  TEnum1 = (first, second, third);
+{$SCOPEDENUMS OFF}
+  TEnum2 = (zero, first, second, third);
+  TRange1 = first..second;
+var
+  En1: TEnum1;
+  En2: TEnum2;
+  R1: TRange1;
+begin
+  En1 := TEnum1.first;
+  if GetEnumName(TypeInfo(TEnum1), Ord(En1)) <> 'first' then
+    halt(1);
+  if Ord(En1) <> 0 then
+    halt(2);
+  En2 := first;
+  if GetEnumName(TypeInfo(TEnum2), Ord(En2)) <> 'first' then
+    halt(3);
+  if ord(En2) <> 1 then
+    halt(4);
+  En2 := TEnum2.second;
+  if GetEnumName(TypeInfo(TEnum2), Ord(En2)) <> 'second' then
+    halt(5);
+  if ord(En2) <> 2 then
+    halt(6);
+  R1 := TRange1.second;
+  if GetEnumName(TypeInfo(TRange1), Ord(R1)) <> 'second' then
+    halt(7);
+  if ord(R1) <> 2 then
+    halt(8);
+  writeln('ok');
+end.

+ 18 - 0
tests/test/tenum4.pp

@@ -0,0 +1,18 @@
+{ %fail}
+{ %norun}
+
+// test checks that enumeration memebers are not present in the global/local symtables 
+// if enumeration is defined with scopedenums directive
+
+program tenum4;
+type
+{$SCOPEDENUMS ON}
+  TEnum1 = (first, second, third);
+{$SCOPEDENUMS OFF}
+  TEnum2 = (zero, first, second, third);
+var
+  En1: TEnum1;
+begin
+  // this is not possible since first belongs to TEnum2
+  En1 := first;
+end.

+ 17 - 0
tests/test/tenum5.pp

@@ -0,0 +1,17 @@
+{ %fail}
+{ %norun}
+
+// test checks that enumeration searches symbols only in the own symbol list 
+// if they are prefixed by the enumeration name
+
+program tenum5;
+type
+{$SCOPEDENUMS ON}
+  TEnum1 = (first, second, third);
+{$SCOPEDENUMS OFF}
+  TEnum2 = (zero, first, second, third);
+var
+  En1: TEnum1;
+begin
+  En1 := TEnum1.zero;
+end.