Browse Source

* Changed names of procedures flags
* Changed VMT generation

daniel 25 years ago
parent
commit
a511be87c4

+ 278 - 120
compiler/new/symtable/defs.pas

@@ -45,18 +45,12 @@ type    Targconvtyp=(act_convertable,act_equal,act_exact);
 
         Tvarspez=(vs_value,vs_const,vs_var);
 
-        Tobjprop=(sp_public,sp_private,sp_protected,sp_published,sp_static);
-        Tobjpropset=set of Tobjprop;
-
         Tobjoption=(oo_has_abstract,         {The object/class has
                                              an abstract method => no
                                              instances can be created.}
                     oo_is_class,            {The object is a class.}
                     oo_has_virtual,         {The object/class has
                                              virtual methods.}
-                    oo_has_private,         {The object has private members.}
-                    oo_has_protected,       {The obejct has protected
-                                             members.}
                     oo_isforward,           {The class is only a forward
                                              declared yet.}
                     oo_can_have_published,  {True, if the class has rtti, i.e.
@@ -66,7 +60,8 @@ type    Targconvtyp=(act_convertable,act_equal,act_exact);
                     oo_has_destructor,      {The object/class has a
                                              destructor.}
 
-                    oo_has_vmt,             {The object/class has a vmt.}
+                    {When has_virtual is set, has_vmt is also set....
+                    oo_has_vmt,             The object/class has a vmt.}
                     oo_has_msgstr,
                     oo_has_msgint,
                     oo_cppvmt);             {The object/class uses an C++
@@ -76,58 +71,64 @@ type    Targconvtyp=(act_convertable,act_equal,act_exact);
         Tobjoptionset=set of Tobjoption;
 
         {Calling convention for tprocdef and Tprocvardef.}
-        Tproccalloption=(pocall_none,
-                         pocall_clearstack,     {Use IBM flat calling
+        Tproccalloption=(po_call_none,
+                         po_call_clearstack,    {Use IBM flat calling
                                                  convention. (Used by GCC.)}
-                         pocall_leftright,      {Push parameters from left to
+                         po_call_leftright,     {Push parameters from left to
                                                  right.}
-                         pocall_cdecl,          {Procedure uses C styled
+                         po_call_cdecl,         {Procedure uses C styled
                                                  calling.}
-                         pocall_register,       {Procedure uses register
+                         po_call_register,      {Procedure uses register
                                                  (fastcall) calling.}
-                         pocall_stdcall,        {Procedure uses stdcall
+                         po_call_stdcall,       {Procedure uses stdcall
                                                  call.}
-                         pocall_safecall,       {Safe call calling
+                         po_call_safecall,      {Safe call calling
                                                  conventions.}
-                         pocall_palmossyscall,  {Procedure is a PalmOS
+                         po_call_palmossyscall, {Procedure is a PalmOS
                                                  system call.}
-                         pocall_system,
-                         pocall_inline,         {Procedure is an assembler
+                         po_call_system,
+                         po_call_inline,        {Procedure is an assembler
                                                  macro.}
-                         pocall_internproc,     {Procedure has compiler
+                         po_call_internproc,    {Procedure has compiler
                                                  magic.}
-                         pocall_internconst);   {Procedure has constant
+                         po_call_internconst);  {Procedure has constant
                                                  evaluator intern.}
         Tproccalloptionset=set of Tproccalloption;
 
         {Basic type for tprocdef and tprocvardef }
-        Tproctypeoption=(potype_none,
-                         potype_proginit,       {Program initialization.}
-                         potype_unitinit,       {Unit initialization.}
-                         potype_unitfinalize,   {Unit finalization.}
-                         potype_constructor,    {Procedure is a constructor.}
-                         potype_destructor,     {Procedure is a destructor.}
-                         potype_operator);      {Procedure defines an
+        Tproctypeoption=(po_type_none,
+                         po_type_proginit,      {Program initialization.}
+                         po_type_unitinit,      {Unit initialization.}
+                         po_type_unitfinalize,  {Unit finalization.}
+                         po_type_constructor,   {Procedure is a constructor.}
+                         po_type_destructor,    {Procedure is a destructor.}
+                         po_type_operator);     {Procedure defines an
                                                  operator.}
 
         {Other options for Tprocdef and Tprocvardef.}
         Tprocoption=(po_none,
-            poclassmethod,          {Class method.}
-            povirtualmethod,        {Procedure is a virtual method.}
-            poabstractmethod,       {Procedure is an abstract method.}
-            postaticmethod,         {Static method.}
-            pooverridingmethod,     {Method with override directive.}
-            pomethodpointer,        {Method pointer, only in procvardef, also used for 'with object do'.}
-            pocontainsself,         {Self is passed explicit to the compiler.}
-            pointerrupt,            {Procedure is an interrupt handler.}
-            poiocheck,              {IO checking should be done after a call to the procedure.}
-            poassembler,            {Procedure is written in assembler.}
-            pomsgstr,               {Method for string message handling.}
-            pomsgint,               {Method for int message handling.}
-            poexports,              {Procedure has export directive (needed for OS/2).}
-            poexternal,             {Procedure is external (in other object or lib).}
-            posavestdregs,          {Save std regs cdecl and stdcall need that !}
-            posaveregisters);       {Save all registers }
+            po_classmethod,         {Class method.}
+            po_virtualmethod,       {Procedure is a virtual method.}
+            po_abstractmethod,      {Procedure is an abstract method.}
+            po_staticmethod,        {Static method.}
+            po_overridingmethod,    {Method with override directive.}
+            po_methodpointer,       {Method pointer, only in procvardef, also
+                                     used for 'with object do'.}
+            po_containsself,        {Self is passed explicit to the
+                                     compiler.}
+            po_interrupt,           {Procedure is an interrupt handler.}
+            po_iocheck,             {IO checking should be done after a call
+                                     to the procedure.}
+            po_assembler,           {Procedure is written in assembler.}
+            po_msgstr,              {Method for string message handling.}
+            po_msgint,              {Method for int message handling.}
+            po_exports,             {Procedure has export directive (needed
+                                     for OS/2).}
+            po_external,            {Procedure is external (in other object
+                                     or lib).}
+            po_savestdregs,         {Save std regs cdecl and stdcall need
+                                     that!}
+            po_saveregisters);      {Save all registers }
         Tprocoptionset=set of Tprocoption;
 
         Tarrayoption=(ap_variant,ap_constructor,ap_arrayofconst);
@@ -219,7 +220,34 @@ type    Targconvtyp=(act_convertable,act_equal,act_exact);
             function gettypename:string;virtual;
         end;
 
+        Pvmtentry=^Tvmtentry;
+        Pglobalvmtentry=^Tglobalvmtentry;
+        Plocalvmtentry=^Tlocalvmtentry;
         Pobjectdef=^Tobjectdef;
+        Pabstractprocdef=^Pabstractprocdef;
+        Pprocvardef=^Tprocvardef;
+        Pprocdef = ^Tprocdef;
+
+        Tvmtentry=object(Tobject)
+            owner:Pobjectdef;
+            constructor init(Aowner:Pobjectdef);
+            function mangledname:string;virtual;
+        end;
+
+        Tglobalvmtentry=object(Tvmtentry)
+            constructor init(Aowner:Pobjectdef;proc:Pprocdef);
+            function mangledname:string;virtual;
+        private
+            def:Pprocdef;
+        end;
+
+        Tlocalvmtentry=object(Tvmtentry)
+            constructor init(Aowner:Pobjectdef;proc:Pprocdef);
+            function mangledname:string;virtual;
+        private
+            name:Pstring;
+        end;
+
         Tobjectdef=object(Tdef)
             childof:Pobjectdef;
             objname:Pstring;
@@ -228,17 +256,20 @@ type    Targconvtyp=(act_convertable,act_equal,act_exact);
             publicsyms:Pobjectsymtable;
             options:Tobjoptionset;
             {To be able to have a variable vmt position
-             and no vmt field for objects without virtuals }
+             and no vmt field for objects without virtuals.}
             vmt_offset:longint;
+            {Contains Tvmtentry objects to describe the layout of the vmt.}
+            vmt_layout:Pcollection;
             constructor init(const n:string;Aowner:Pcontainingsymtable;
                              parent:Pobjectdef;isclass:boolean);
             constructor load(var s:Tstream);
             procedure check_forwards;
+            function insert(Asym:Psym):boolean;
             procedure insertvmt;
             function is_related(d:Pobjectdef):boolean;
-            function search(const s:string):Psym;
-            function speedsearch(const s:string;
-                                 speedvalue:longint):Psym;virtual;
+            function search(const s:string;search_protected:boolean):Psym;
+            function speedsearch(const s:string;speedvalue:longint;
+                                 search_protected:boolean):Psym;virtual;
             function size:longint;virtual;
             procedure store(var s:Tstream);virtual;
             function vmt_mangledname : string;
@@ -456,7 +487,6 @@ type    Targconvtyp=(act_convertable,act_equal,act_exact);
             procedure write_rtti_data;virtual;
         end;
 
-        Pabstractprocdef=^Pabstractprocdef;
         Tabstractprocdef=object(Tdef)
             {Saves a definition to the return type }
             retdef:Pdef;
@@ -479,7 +509,6 @@ type    Targconvtyp=(act_convertable,act_equal,act_exact);
 {$endif GDB}
         end;
 
-        Pprocvardef=^Tprocvardef;
         Tprocvardef=object(Tabstractprocdef)
 {$IFDEF TP}
             constructor init(Aowner:Pcontainingsymtable);
@@ -510,10 +539,7 @@ type    Targconvtyp=(act_convertable,act_equal,act_exact);
         {This object can be splitted into a Tprocdef, for normal procedures,
          a Tmethoddef for methods, and a Tinlinedprocdef and a
          Tinlinedmethoddef for inlined procedures.}
-        Pprocdef = ^Tprocdef;
         Tprocdef = object(tabstractprocdef)
-           objprop:Tobjpropset;
-           extnumber:longint;
            messageinf:Tmessageinf;
            { where is this function defined, needed here because there
              is only one symbol for all overloaded functions }
@@ -524,6 +550,7 @@ type    Targconvtyp=(act_convertable,act_equal,act_exact);
            { it's a tree, but this not easy to handle }
            { used for inlined procs                   }
            code : pointer;
+           vmt_index:longint;
            { true, if the procedure is only declared }
            { (forward procedure) }
            references:Pcollection;
@@ -562,13 +589,13 @@ type    Targconvtyp=(act_convertable,act_equal,act_exact);
 
         {Relevant options for assigning a proc or a procvar to a procvar.}
 const   po_compatibility_options=[
-          poclassmethod,
-          postaticmethod,
-          pomethodpointer,
-          pocontainsself,
-          pointerrupt,
-          poiocheck,
-          poexports
+          po_classmethod,
+          po_staticmethod,
+          po_methodpointer,
+          po_containsself,
+          po_interrupt,
+          po_iocheck,
+          po_exports
         ];
 
 var     cformaldef:Pformaldef;      {Unique formal definition.}
@@ -865,7 +892,64 @@ begin
 end;
 
 {***************************************************************************
-                              TOBJECTDEF
+                                TVMTENTRY
+***************************************************************************}
+
+constructor Tvmtentry.init(Aowner:Pobjectdef);
+
+begin
+    inherited init;
+    {$IFDEF TP}setparent(typeof(Tobject));{$ENDIF}
+    owner:=Aowner;
+end;
+
+function Tvmtentry.mangledname:string;
+
+begin
+    abstract;
+end;
+
+{***************************************************************************
+                             TGLOBALVMTENTRY
+***************************************************************************}
+
+constructor Tglobalvmtentry.init(Aowner:Pobjectdef;proc:Pprocdef);
+
+begin
+    inherited init(Aowner);
+    {$IFDEF TP}setparent(typeof(Tvmtentry));{$ENDIF TP}
+    def:=proc;
+end;
+
+function Tglobalvmtentry.mangledname:string;
+
+begin
+    mangledname:=def^.mangledname;
+end;
+
+{***************************************************************************
+                              TLOCALVMTENTRY
+***************************************************************************}
+
+constructor Tlocalvmtentry.init(Aowner:Pobjectdef;proc:Pprocdef);
+
+begin
+    inherited init(Aowner);
+    {$IFDEF TP}setparent(typeof(Tvmtentry));{$ENDIF TP}
+    if po_abstractmethod in proc^.options then
+        name:=stringdup('FPC_ABSTRACTERROR')
+    else
+        name:=stringdup(proc^.mangledname);
+end;
+
+function Tlocalvmtentry.mangledname:string;
+
+begin
+    mangledname:=name^;
+end;
+
+{***************************************************************************
+                                TOBJECTDEF
 ***************************************************************************}
 
 constructor Tobjectdef.init(const n:string;Aowner:Pcontainingsymtable;
@@ -889,7 +973,7 @@ end;
 
 procedure tobjectdef.set_parent(parent:Pobjectdef);
 
-const   inherited_options=[oo_has_virtual,oo_has_private,oo_has_protected,
+const   inherited_options=[oo_has_virtual,
                            oo_has_constructor,oo_has_destructor];
 
 begin
@@ -917,15 +1001,15 @@ begin
                             inc(protectedsyms^.datasize,
                              parent^.protectedsyms^.datasize);
                         end;
-                    if oo_has_vmt in (options*parent^.options) then
+                    if oo_has_virtual in (options*parent^.options) then
                         publicsyms^.datasize:=publicsyms^.datasize-
                          target_os.size_of_pointer;
                     {If parent has a vmt field then
                      the offset is the same for the child PM }
-                     if [oo_has_vmt,oo_is_class]*parent^.options<>[] then
+                     if [oo_has_virtual,oo_is_class]*parent^.options<>[] then
                         begin
                             vmt_offset:=parent^.vmt_offset;
-                            include(options,oo_has_vmt);
+                            include(options,oo_has_virtual);
                         end;
                 end;
             savesize:=publicsyms^.datasize;
@@ -963,18 +1047,43 @@ end;
 
 procedure Tobjectdef.insertvmt;
 
-begin
-    if oo_has_vmt in options then
-        internalerror($990803)
+var o:Pobjectdef;
+    c:Pcollection;
+    i:word;
+
+begin
+    if vmt_layout<>nil then
+        internalerror($990803);
+    {Make room for a vmtlink in the object.
+     First round up to aktpakrecords.}
+    publicsyms^.datasize:=align(publicsyms^.datasize,
+     packrecordalignment[aktpackrecords]);
+    vmt_offset:=publicsyms^.datasize;
+    publicsyms^.datasize:=publicsyms^.datasize+
+     target_os.size_of_pointer;
+    {Set up the vmt layout collection.
+     First search for a vmt in a parent object.}
+    o:=childof;
+    c:=nil;
+    while o<>nil do
+        begin
+            if o^.vmt_layout<>nil then
+                begin
+                    c:=vmt_layout;
+                    break;
+                end;
+            o:=o^.childof;
+        end;
+    if c=nil then
+        new(vmt_layout,init(8,8))
     else
         begin
-            {First round up to aktpakrecords.}
-            publicsyms^.datasize:=align(publicsyms^.datasize,
-             packrecordalignment[aktpackrecords]);
-            vmt_offset:=publicsyms^.datasize;
-            publicsyms^.datasize:=publicsyms^.datasize+
-             target_os.size_of_pointer;
-            include(options,oo_has_vmt);
+            {We should copy the vmt layout of our parent object. Our vmt
+             layout will change as soon as methods are overridden or when
+             new virtual methods are added.}
+            new(vmt_layout,init(c^.limit,8));
+            for i:=0 to c^.count-1 do
+                vmt_layout^.insert(c^.at(i));
         end;
 end;
 
@@ -1009,13 +1118,47 @@ begin
         end;
 end;
 
-function Tobjectdef.search(const s:string):Psym;
+function Tobjectdef.insert(Asym:Psym):boolean;
+
+var speedvalue:longint;
+    s:Psym;
+    op:Tobjpropset;
+
+begin
+    {First check if the symbol already exists.}
+    s:=privatesyms^.speedsearch(Asym^.name,Asym^.speedvalue);
+    if s=nil then
+        protectedsyms^.speedsearch(Asym^.name,Asym^.speedvalue);
+    if s=nil then
+        publicsyms^.speedsearch(Asym^.name,Asym^.speedvalue);
+    if s<>nil then
+        duplicatesym(sym)
+    else
+        begin
+            {Asym is a Tprocsym, Tvarsym or Tpropertysym.}
+            if Asym^.is_object(typeof(Tprocsym)) then
+                op:=Pprocsym(Asym)^.objprop
+            else if Asym^.is_object(typeof(Tvarsym)) then
+                op:=Pvarsym(Asym)^.objprop
+            else if Asym^.is_object(typeof(Tpropertysym)) then
+                op:=Ppropertysym(Asym)^.objprop;
+            if sp_private in op then
+               insert:=privatesyms^.insert(Asym)
+            else if sp_protected in op then
+               insert:=protectedsyms^.insert(Asym)
+            else if sp_public in op then
+               insert:=publicsyms^.insert(Asym);
+        end;
+end;
+
+function Tobjectdef.search(const s:string;search_protected:boolean):Psym;
 
 begin
-    search:=speedsearch(s,getspeedvalue(s));
+    search:=speedsearch(s,getspeedvalue(s),search_protected);
 end;
 
-function Tobjectdef.speedsearch(const s:string;speedvalue:longint):Psym;
+function Tobjectdef.speedsearch(const s:string;speedvalue:longint;
+                                search_protected:boolean):Psym;
 
 var r:Psym;
 
@@ -1025,7 +1168,7 @@ begin
      This way, private syms are not found by objects in other units.}
     if (r=nil) and (privatesyms<>nil) then
         r:=privatesyms^.speedsearch(s,speedvalue);
-    if (r=nil) and (protectedsyms<>nil) then
+    if (r=nil) and search_protected and (protectedsyms<>nil) then
         r:=protectedsyms^.speedsearch(s,speedvalue);
 end;
 
@@ -1055,9 +1198,9 @@ end;
 function Tobjectdef.vmt_mangledname:string;
 
 begin
-    if oo_has_vmt in options then
+    if not(oo_has_virtual in options) then
         message1(parser_object_has_no_vmt,objname^);
-        vmt_mangledname:='VMT_'+owner^.name^+'$_'+objname^;
+    vmt_mangledname:='VMT_'+owner^.name^+'$_'+objname^;
 end;
 
 function Tobjectdef.rtti_name:string;
@@ -1131,7 +1274,18 @@ end;
 
 destructor Tobjectdef.done;
 
+var i:longint;
+    ve:Pvmtentry;
+
 begin
+    {We should be carefull when disposing the vmt_layout; there are
+     vmt entries in it which are from methods of our ancestor, we
+     should not dispose these. So first set them to nil.}
+    for i:=0 to vmt_layout^.count do
+        if Pvmtentry(vmt_layout^.at(i))^.owner<>@self then
+            vmt_layout^.atput(i,nil);
+    dispose(vmt_layout,done);
+
     if publicsyms<>nil then
         dispose(publicsyms,done);
     if privatesyms<>nil then
@@ -1150,7 +1304,7 @@ procedure count_published_properties(sym:Pnamedindexobject);
                                     {$ifndef fpc}far;{$endif}
 
 begin
-    if (typeof(sym^)=typeof(Tpropertysym)) and
+    if sym^.is_object(typeof(Tpropertysym)) and
      (ppo_published in Ppropertysym(sym)^.properties) then
         inc(count);
 end;
@@ -1158,41 +1312,41 @@ end;
 
 procedure write_property_info(sym:Pnamedindexobject);{$ifndef fpc}far;{$endif}
 
-var proctypesinfo : byte;
+var proctypesinfo:byte;
 
-procedure writeproc(sym:Psym;def:Pdef;shiftvalue:byte);
+    procedure writeproc(proc:Pcollection;shiftvalue:byte);
 
-var typvalue:byte;
+    var typvalue:byte;
 
-begin
-    if not(assigned(sym)) then
-        begin
-            rttilist^.concat(new(pai_const,init_32bit(1)));
-            typvalue:=3;
-        end
-    else if typeof(sym^)=typeof(Tvarsym) then
-        begin
-            rttilist^.concat(new(pai_const,init_32bit(
-             Pvarsym(sym)^.address)));
-            typvalue:=0;
-        end
-    else
-        begin
-(*          if (pprocdef(def)^.options and povirtualmethod)=0 then
-                begin
-                    rttilist^.concat(new(pai_const_symbol,initname(pprocdef(def)^.mangledname)));
-                    typvalue:=1;
-                end
-            else
-                begin
-                    {Virtual method, write vmt offset.}
-                    rttilist^.concat(new(pai_const,
-                     init_32bit(Pprocdef(def)^.extnumber*4+12)));
-                    typvalue:=2;
-                end;*)
-        end;
-    proctypesinfo:=proctypesinfo or (typvalue shl shiftvalue);
-end;
+    begin
+        if proc=nil then
+            begin
+                rttilist^.concat(new(pai_const,init_32bit(1)));
+                typvalue:=3;
+            end
+        else if Psym(proc^.at(0))^.is_object(typeof(Tvarsym)) then
+            begin
+                rttilist^.concat(new(pai_const,init_32bit(
+                 Pvarsym(sym)^.address)));
+                typvalue:=0;
+            end
+        else
+            begin
+    (*          if (pprocdef(def)^.options and povirtualmethod)=0 then
+                    begin
+                        rttilist^.concat(new(pai_const_symbol,initname(pprocdef(def)^.mangledname)));
+                        typvalue:=1;
+                    end
+                else
+                    begin
+                        {Virtual method, write vmt offset.}
+                        rttilist^.concat(new(pai_const,
+                         init_32bit(Pprocdef(def)^.extnumber*4+12)));
+                        typvalue:=2;
+                    end;*)
+            end;
+        proctypesinfo:=proctypesinfo or (typvalue shl shiftvalue);
+    end;
 
 begin
     if (typeof(sym^)=typeof(Tpropertysym)) and
@@ -1205,8 +1359,8 @@ begin
         begin
             rttilist^.concat(new(pai_const_symbol,initname(
              Ppropertysym(sym)^.definition^.get_rtti_label)));
-            writeproc(Ppropertysym(sym)^.readaccesssym,ppropertysym(sym)^.readaccessdef,0);
-            writeproc(Ppropertysym(sym)^.writeaccesssym,ppropertysym(sym)^.writeaccessdef,2);
+            writeproc(Ppropertysym(sym)^.readaccess,0);
+            writeproc(Ppropertysym(sym)^.writeaccess,2);
             { isn't it stored ? }
             if (ppo_stored in Ppropertysym(sym)^.properties) then
                 begin
@@ -1214,7 +1368,7 @@ begin
                     proctypesinfo:=proctypesinfo or (3 shl 4);
                 end
             else
-                writeproc(ppropertysym(sym)^.storedsym,ppropertysym(sym)^.storeddef,4);
+                writeproc(ppropertysym(sym)^.storedaccess,4);
             rttilist^.concat(new(pai_const,
              init_32bit(ppropertysym(sym)^.index)));
             rttilist^.concat(new(pai_const,
@@ -2585,7 +2739,7 @@ begin
     inherited init(Aowner);
     {$IFDEF TP}setparent(typeof(Tabstractprocdef));{$ENDIF}
     fileinfo:=aktfilepos;
-    extnumber:=-1;
+    vmt_index:=-1;
     new(localst,init);
     if (cs_browser in aktmoduleswitches) and make_ref then
         begin
@@ -2736,7 +2890,7 @@ end;
 destructor Tprocdef.done;
 
 begin
-    if pomsgstr in options then
+    if po_msgstr in options then
         strdispose(messageinf.str);
     if references<>nil then
         dispose(references,done);
@@ -2862,7 +3016,7 @@ end;
 function Tprocvardef.size:longint;
 
 begin
-    if pomethodpointer in options then
+    if po_methodpointer in options then
         size:=2*target_os.size_of_pointer
     else
         size:=target_os.size_of_pointer;
@@ -2937,7 +3091,7 @@ end;
 function Tprocvardef.is_publishable:boolean;
 
 begin
-    is_publishable:=pomethodpointer in options;
+    is_publishable:=po_methodpointer in options;
 end;
 
 function Tprocvardef.gettypename:string;
@@ -2978,7 +3132,11 @@ end.
 
 {
   $Log$
-  Revision 1.5  2000-03-11 21:11:24  daniel
+  Revision 1.6  2000-03-16 12:52:47  daniel
+    *  Changed names of procedures flags
+    *  Changed VMT generation
+
+  Revision 1.5  2000/03/11 21:11:24  daniel
     * Ported hcgdata to new symtable.
     * Alignment code changed as suggested by Peter
     + Usage of my is operator replacement, is_object

+ 13 - 223
compiler/new/symtable/hcgdata.pas

@@ -105,7 +105,7 @@ implementation
         var pt:Pprocdeftree;
 
         begin
-            if pomsgstr in Pprocdef(p)^.options then
+            if po_msgstr in Pprocdef(p)^.options then
                 begin
                     new(pt);
                     pt^.p:=p;
@@ -146,7 +146,7 @@ implementation
         var pt:Pprocdeftree;
 
         begin
-            if pomsgint in Pprocdef(p)^.options then
+            if po_msgint in Pprocdef(p)^.options then
                 begin
                     new(pt);
                     pt^.p:=p;
@@ -349,7 +349,7 @@ implementation
         var l:Pasmlabel;
 
         begin
-            if (sp_published in Pprocdef(q)^.objprop) then
+            if (sp_published in Pprocsym(p)^.objprop) then
                 begin
                    getlabel(l);
 
@@ -372,7 +372,7 @@ implementation
         procedure def_do_count(p:pointer);{$ifndef FPC}far;{$endif}
 
         begin
-            if (sp_published in Pprocdef(p)^.objprop) then
+            if (sp_published in Pprocsym(p)^.objprop) then
              inc(count);
         end;
 
@@ -414,236 +414,26 @@ implementation
                                     VMT
 *****************************************************************************}
 
-var wurzel:Pcollection;
-    nextvirtnumber : longint;
-    _c : pobjectdef;
-    has_constructor,has_virtual_method : boolean;
-
-procedure eachsym(sym:Pnamedindexobject);{$ifndef FPC}far;{$endif FPC}
-
-var symcoll:Pcollection;
-    _name:string;
-    stored:boolean;
-
-    {Creates a new entry in the procsym list.}
-    procedure newentry;
-
-        procedure numbervirtual(p:pointer);{$IFDEF TP}far;{$ENDIF TP}
-
-        begin
-            { if it's a virtual method }
-            if (povirtualmethod in Pprocdef(p)^.options) then
-                begin
-                    {Then it gets a number ...}
-                    Pprocdef(p)^.extnumber:=nextvirtnumber;
-                    {And we inc the number }
-                    inc(nextvirtnumber);
-                    has_virtual_method:=true;
-                end;
-
-            if (Pprocdef(p)^.proctype=potype_constructor) then
-                has_constructor:=true;
-
-            { check, if a method should be overridden }
-            if (pooverridingmethod in Pprocdef(p)^.options) then
-                messagepos1(Pprocdef(p)^.fileinfo,parser_e_nothing_to_be_overridden,
-                 _c^.objname^+'.'+_name+Pprocdef(p)^.demangled_paras);
-        end;
-
-    begin
-        symcoll^.insert(sym);
-        Pprocsym(sym)^.foreach(@numbervirtual);
-    end;
-
-    function match(p:pointer):boolean;{$IFDEF TP}far;{$ENDIF}
-
-    begin
-        {Does the symbol already exist in the list ?}
-        match:=_name=Psym(p)^.name;
-    end;
-
-    procedure eachdef(p:pointer);{$IFDEF TP}far;{$ENDIF}
-
-        function check_override(q:pointer):boolean;{$IFDEF TP}far;{$ENDIF}
-
-        begin
-            check_override:=false;
-            {Check if the parameters are equal and if one of the methods
-             is virtual.}
-            if equal_paras(Pprocdef(p)^.parameters,
-             Pprocdef(q)^.parameters,false) and
-             ((povirtualmethod in Pprocdef(p)^.options) or
-              (povirtualmethod in Pprocdef(q)^.options)) then
-                begin
-                    {Wenn sie gleich sind
-                     und eine davon virtual deklariert ist
-                     Fehler falls nur eine VIRTUAL }
-                    if (povirtualmethod in Pprocdef(p)^.options)<>
-                     (povirtualmethod in Pprocdef(q)^.options) then
-                        begin
-                            { in classes, we hide the old method }
-                            if oo_is_class in _c^.options then
-                                begin
-                                    {Warn only if it is the first time,
-                                     we hide the method.}
-                                    if _c=Pprocsym(Pprocdef(p)^.sym)^._class then
-                                        message1(parser_w_should_use_override,_c^.objname^+'.'+_name);
-                                    newentry;
-                                    check_override:=true;
-                                    exit;
-                                end
-                            else
-                                if _c=Pprocsym(Pprocdef(p)^.sym)^._class then
-                                    begin
-                                        if (povirtualmethod in Pprocdef(q)^.options) then
-                                            message1(parser_w_overloaded_are_not_both_virtual,_c^.objname^+'.'+_name)
-                                        else
-                                            message1(parser_w_overloaded_are_not_both_non_virtual,
-                                             _c^.objname^+'.'+_name);
-                                        newentry;
-                                        check_override:=true;
-                                        exit;
-                                    end;
-                        end
-                    else
-                        {The flags have to match except abstract
-                         and override, but only if both are virtual!!}
-                        if (Pprocdef(q)^.calloptions<>Pprocdef(p)^.calloptions) or
-                         (Pprocdef(q)^.proctype<>Pprocdef(p)^.proctype) or
-                         ((Pprocdef(q)^.options-[poabstractmethod,pooverridingmethod,poassembler])<>
-                         (Pprocdef(p)^.options-[poabstractmethod,pooverridingmethod,poassembler])) then
-                            message1(parser_e_header_dont_match_forward,_c^.objname^+'.'+_name);
-
-                    {Check, if the override directive is set
-                     (povirtualmethod is set!}
-
-                    {Class ?}
-                    if (oo_is_class in _c^.options) and
-                     not(pooverridingmethod in Pprocdef(p)^.options) then
-                        begin
-                            {Warn only if it is the first time,
-                             we hide the method.}
-                            if _c=Pprocsym(Pprocdef(p)^.sym)^._class then
-                                message1(parser_w_should_use_override,_c^.objname^+'.'+_name);
-                            newentry;
-                            check_override:=true;
-                            exit;
-                        end;
-
-                    { error, if the return types aren't equal }
-                    if not(is_equal(Pprocdef(q)^.retdef,Pprocdef(p)^.retdef)) and
-                     not(Pprocdef(q)^.retdef^.is_object(typeof(Tobjectdef)) and
-                      Pprocdef(p)^.retdef^.is_object(typeof(Tobjectdef)) and
-                      (oo_is_class in Pobjectdef(Pprocdef(q)^.retdef)^.options) and
-                      (oo_is_class in Pobjectdef(Pprocdef(p)^.retdef)^.options) and
-                      (pobjectdef(Pprocdef(p)^.retdef)^.is_related(
-                       pobjectdef(Pprocdef(q)^.retdef)))) then
-                        message1(parser_e_overloaded_methodes_not_same_ret,_c^.objname^+'.'+_name);
-
-
-                    {now set the number }
-                    Pprocdef(p)^.extnumber:=Pprocdef(q)^.extnumber;
-                end;  { same parameters }
-        end;
-
-    begin
-        if Pprocsym(sym)^.firstthat(@check_override)=nil then
-            newentry;
-    end;
-
-
-begin
-    {Put only subroutines into the VMT.}
-    if sym^.is_object(typeof(Tprocsym)) then
-        begin
-            symcoll:=wurzel;
-            Pprocsym(symcoll^.firstthat(@match))^.foreach(@eachdef);
-            newentry;
-        end;
-end;
 
 procedure genvmt(list:Paasmoutput;_class:Pobjectdef);
 
-var symcoll:Pcollection;
-    i:longint;
-
-    procedure do_genvmt(p:Pobjectdef);
-
-    begin
-        {Start with the base class.}
-        if assigned(p^.childof) then
-            do_genvmt(p^.childof);
-
-        { walk through all public syms }
-        { I had to change that to solve bug0260 (PM)}
-        _c:=p;
-        { Florian, please check if you agree (PM) }
-        p^.privatesyms^.foreach({$ifndef TP}@{$endif}eachsym);
-        p^.protectedsyms^.foreach({$ifndef TP}@{$endif}eachsym);
-        p^.publicsyms^.foreach({$ifndef TP}@{$endif}eachsym);
-    end;
-
- procedure symwritevmt(p:pointer);{$IFDEF TP}far;{$ENDIF}
-
-     procedure defwritevmt(q:pointer);{$IFDEF TP}far;{$ENDIF}
-
-     begin
-         { writes the addresses to the VMT }
-         { but only this which are declared as virtual }
-         if (Pprocdef(q)^.extnumber=i) and
-          (povirtualmethod in Pprocdef(q)^.options) then
-             begin
-                 { if a method is abstract, then is also the }
-                 { class abstract and it's not allow to      }
-                 { generates an instance                     }
-                 if (poabstractmethod in Pprocdef(q)^.options) then
-                     begin
-                         include(_class^.options,oo_has_abstract);
-                         list^.concat(new(pai_const_symbol,initname('FPC_ABSTRACTERROR')));
-                     end
-                 else
-                     begin
-                         list^.concat(new(pai_const_symbol,
-                          initname(Pprocdef(q)^.mangledname)));
-                     end;
-             end;
-     end;
-
- begin
-     Pprocsym(p)^.foreach(@defwritevmt);
- end;
+var i:longint;
 
 begin
-    new(wurzel,init(64,16));
-    nextvirtnumber:=0;
-
-    has_constructor:=false;
-    has_virtual_method:=false;
-
-    { generates a tree of all used methods }
-    do_genvmt(_class);
-
-    if has_virtual_method and not(has_constructor) then
-        message1(parser_w_virtual_without_constructor,_class^.objname^);
-
-
-    { generates the VMT }
-
-    { walk trough all numbers for virtual methods and search }
-    { the method                                             }
-    for i:=0 to nextvirtnumber-1 do
-        begin
-            symcoll:=wurzel;
-            symcoll^.foreach(@symwritevmt);
-        end;
-    dispose(symcoll,done);
+    for i:=0 to _class^.vmt_layout^.count-1 do
+        list^.concat(new(pai_const_symbol,
+         initname(Pvmtentry(_class^.vmt_layout^.at(i))^.mangledname)));
 end;
 
 
 end.
 {
   $Log$
-  Revision 1.1  2000-03-11 21:11:25  daniel
+  Revision 1.2  2000-03-16 12:52:48  daniel
+    *  Changed names of procedures flags
+    *  Changed VMT generation
+
+  Revision 1.1  2000/03/11 21:11:25  daniel
     * Ported hcgdata to new symtable.
     * Alignment code changed as suggested by Peter
     + Usage of my is operator replacement, is_object

+ 109 - 9
compiler/new/symtable/symbols.pas

@@ -1,4 +1,4 @@
- {
+{
     $Id$
 
     Copyright (C) 1998-2000 by Daniel Mantione
@@ -40,8 +40,11 @@ uses    symtable,aasm,objects,cobjects,defs,cpubase,tokens;
 type    Ttypeprop=(sp_primary_typesym);
         Ttypepropset=set of Ttypeprop;
 
+        Tobjprop=(sp_public,sp_private,sp_protected,sp_published,sp_static);
+        Tobjpropset=set of Tobjprop;
+
         Tpropprop=(ppo_indexed,ppo_defaultproperty,
-                   ppo_stored,ppo_published);
+                   ppo_stored,ppo_published,ppo_hasparameters);
         Tproppropset=set of Tpropprop;
 
         Tvarprop=(vo_regable,vo_fpuregable,vo_is_C_var,vo_is_external,
@@ -86,6 +89,10 @@ type    Ttypeprop=(sp_primary_typesym);
                                      Since most procedures are not
                                      overloaded, this saves a lot of
                                      memory.}
+            objprop:Tobjpropset;    {All overloaded procedures should
+                                     have the same scope, so the object
+                                     scope information is put in the
+                                     symbol.}
             sub_of:Pprocsym;
             _class:Pobjectdef;
             constructor init(const n:string;Asub_of:Pprocsym);
@@ -93,7 +100,7 @@ type    Ttypeprop=(sp_primary_typesym);
             function count:word;
             function firstthat(action:pointer):Pprocdef;
             procedure foreach(action:pointer);
-            procedure insert(def:Pdef);
+            procedure insert(def:Pprocdef);
             function mangledname:string;virtual; {Causes internalerror.}
             {Writes all declarations.}
             procedure write_parameter_lists;
@@ -246,7 +253,7 @@ type    Ttypeprop=(sp_primary_typesym);
         Pfuncretsym=^Tfuncretsym;
         Tfuncretsym=object(tsym)
             funcretprocinfo:pointer{Pprocinfo};
-            funcretdef:Pdef;
+            definition:Pdef;
             address:longint;
             constructor init(const n:string;approcinfo:pointer{pprocinfo});
             constructor load(var s:Tstream);
@@ -260,8 +267,13 @@ type    Ttypeprop=(sp_primary_typesym);
             properties:Tproppropset;
             definition:Pdef;
             objprop:Tobjpropset;
-            readaccesssym,writeaccesssym,storedsym:Psym;
-            readaccessdef,writeaccessdef,storeddef:Pdef;
+            rangedef:Pdef;  {Type of the range for array properties.}
+            {For record property's like property x read a.b.c, the
+             collection contains a as first element, b as second element,
+             and c as the third element.}
+            readaccess,
+            writeaccess,
+            storedaccess:Pcollection;
             index,default:longint;
             constructor load(var s:Tstream);
             function getsize:longint;virtual;
@@ -298,7 +310,7 @@ var current_object_option:Tobjprop;
 
 implementation
 
-uses    callspec,verbose,globals,systems,globtype;
+uses    callspec,verbose,globals,systems,globtype,types;
 
 {****************************************************************************
                                  Tlabelsym
@@ -395,11 +407,95 @@ begin
         end;
 end;
 
-procedure Tprocsym.insert(def:Pdef);
+procedure Tprocsym.insert(def:Pprocdef);
+
+    function matchparas(item:pointer):boolean;{$IFDEF TP}far;{$ENDIF}
+
+    begin
+        matchparas:=equal_paras(Pprocdef(item)^.parameters,
+         Pprocdef(def)^.parameters,false);
+    end;
 
 var c:Pcollection;
+    ovs:Pprocsym;
+    ovd:Pprocdef;
+    ve:Pvmtentry;
+    errparam:string;
 
 begin
+    if _class<>nil then
+        begin
+            {Update object information.}
+            if po_virtualmethod in def^.options then
+                include(_class^.options,oo_has_virtual);
+            if po_abstractmethod in def^.options then
+                include(_class^.options,oo_has_abstract);
+            if def^.proctype=po_type_constructor then
+                include(_class^.options,oo_has_constructor);
+            if def^.proctype=po_type_destructor then
+                include(_class^.options,oo_has_destructor);
+            {Check if we are overriding an existing method.}
+            ovs:=Pprocsym(_class^.childof^.search(name,true));
+            ovd:=ovs^.firstthat(@matchparas);
+            if ovd<>nil then
+                begin
+                    errparam:=_class^.objname^+'.'+name;
+                    {If the old method is virtual and we are not, we
+                     refuse this for objects, and warn for classes.}
+                    if (po_virtualmethod in ovd^.options) then
+                        if  (po_virtualmethod in Pprocdef(def)^.options) then
+                            if oo_is_class in _class^.options then
+                                message1(parser_w_should_use_override,errparam)
+                            else
+                                message1(parser_w_overloaded_are_not_both_virtual,errparam)
+                        else
+                            {Both are virtual.
+                             The flags have to match except abstract,
+                             assembler and override.}
+                            if (def^.calloptions<>ovd^.calloptions) or
+                             (def^.proctype<>ovd^.proctype) or
+                             ((def^.options-[po_abstractmethod,po_overridingmethod,po_assembler])<>
+                             (ovd^.options-[po_abstractmethod,po_overridingmethod,po_assembler])) then
+                                message1(parser_e_header_dont_match_forward,errparam);
+                    {Error if the return types aren't equal.}
+                    if not(is_equal(def^.retdef,ovd^.retdef)) and
+                     not(def^.retdef^.is_object(typeof(Tobjectdef)) and
+                      Pprocdef(ovd)^.retdef^.is_object(typeof(Tobjectdef)) and
+                      (oo_is_class in Pobjectdef(def^.retdef)^.options) and
+                      (oo_is_class in Pobjectdef(ovd^.retdef)^.options) and
+                      (pobjectdef(def^.retdef)^.is_related(pobjectdef(ovd^.retdef)))) then
+                        message1(parser_e_overloaded_methodes_not_same_ret,errparam);
+                    if po_virtualmethod in def^.options then
+                        begin
+                            if not(oo_has_constructor in _class^.options) then
+                                message1(parser_w_virtual_without_constructor,_class^.objname^);
+                            {We change the the vmt layout so we are called instead
+                             of our ancestor.}
+                            if sp_private in objprop then
+                                ve:=new(Plocalvmtentry,init(_class,def))
+                            else
+                                ve:=new(Pglobalvmtentry,init(_class,def));
+                            _class^.vmt_layout^.atput(ovd^.vmt_index,ve);
+                            def^.vmt_index:=ovd^.vmt_index;
+                        end;
+                end
+            else
+                begin
+                    if not(oo_has_constructor in _class^.options) then
+                        message1(parser_w_virtual_without_constructor,_class^.objname^);
+                    {The method is not overridden; if it is virtual we should
+                     generate a vmt entry.}
+                    if po_virtualmethod in def^.options then
+                        begin
+                            if sp_private in objprop then
+                                ve:=new(Plocalvmtentry,init(_class,def))
+                            else
+                                ve:=new(Pglobalvmtentry,init(_class,def));
+                            _class^.vmt_layout^.insert(ve);
+                            def^.vmt_index:=_class^.vmt_layout^.count-1;
+                        end;
+                end;
+        end;
     if definitions=nil then
         definitions:=def
     else
@@ -1473,7 +1569,11 @@ end.
 
 {
   $Log$
-  Revision 1.5  2000-03-11 21:11:25  daniel
+  Revision 1.6  2000-03-16 12:52:48  daniel
+    *  Changed names of procedures flags
+    *  Changed VMT generation
+
+  Revision 1.5  2000/03/11 21:11:25  daniel
     * Ported hcgdata to new symtable.
     * Alignment code changed as suggested by Peter
     + Usage of my is operator replacement, is_object

+ 12 - 8
compiler/new/symtable/symstack.pas

@@ -182,20 +182,24 @@ begin
                 duplicatesym(s);
         end;
     {Check for duplicate field id in inherited classes.}
-    if (typeof(sttop^)=typeof(Tobjectsymtable)) and
+    if sttop^.is_object(typeof(Tobjectsymtable)) and
      (Pobjectsymtable(sttop)^.defowner<>nil) then
         begin
-            {Don't worry about private syms, the private symtable is disposed
-             and set to nil after the unit has been compiled.}
+            {Even though the private symtable is disposed and set to nil
+             after the unit has been compiled, we will still have to check
+             for a private sym, because of interdependend units.}
             hsym:=Pobjectdef(Pobjectsymtable(sttop)^.defowner)^.
              speedsearch(s^.name,s^.speedvalue);
-            if hsym<>nil then
-                duplicateSym(hsym);
+            if (hsym<>nil) and
+             (hsym^.is_object(typeof(Tprocsym))
+              and (sp_private in Pprocsym(hsym)^.objprop)) and
+             (hsym^.is_object(typeof(Tvarsym))
+              and (sp_private in Pvarsym(hsym)^.objprop)) then
+                duplicatesym(hsym);
         end;
     entry:=(s^.speedvalue and cachesize-1)+1;
-    if (typeof(s^)=typeof(Tenumsym)) and
-     ((typeof(sttop^)=typeof(Trecordsymtable)) or
-      (typeof(sttop^)=typeof(Tobjectsymtable))) then
+    if s^.is_object(typeof(Tenumsym)) and
+     sttop^.is_object(Tabstractrecordsymtable)) then
         begin
             if pretop^.insert(s) and addtocache then
                 begin

+ 2 - 1
compiler/new/symtable/symtablt.pas

@@ -309,7 +309,8 @@ end;
 function Tprocsymtable.insert(sym:Psym):boolean;
 
 begin
-    if (method<>nil) and (Pobjectdef(method)^.search(sym^.name)<>nil) then
+    if (method<>nil) and
+     (Pobjectdef(method)^.search(sym^.name,true)<>nil) then
         insert:=inherited insert(sym)
     else
         duplicatesym(sym);

+ 9 - 5
compiler/new/symtable/types.pas

@@ -237,7 +237,7 @@ end;
 { true if a function can be assigned to a procvar }
 function proc_to_procvar_equal(def1:pprocdef;def2:pprocvardef):boolean;
 
-const   po_comp=po_compatibility_options-[pomethodpointer];
+const   po_comp=po_compatibility_options-[po_methodpointer];
 
 var ismethod:boolean;
 
@@ -250,8 +250,8 @@ begin
     {Check for method pointer.}
     ismethod:=(def1^.owner<>nil) and
      (typeof(def1^.owner^)=typeof(Tobjectsymtable));
-    if (ismethod and not (pomethodpointer in def2^.options)) or
-     (not(ismethod) and (pomethodpointer in def2^.options)) then
+    if (ismethod and not (po_methodpointer in def2^.options)) or
+     (not(ismethod) and (po_methodpointer in def2^.options)) then
         begin
             message(type_e_no_method_and_procedure_not_compatible);
             exit;
@@ -535,7 +535,7 @@ begin
         else if typeof(def^)=typeof(Tstringdef) then
            push_addr_param:=pstringdef(def)^.string_typ in [st_shortstring,st_longstring]
         else if typeof(def^)=typeof(Tprocvardef) then
-           push_addr_param:=(pomethodpointer in pprocvardef(def)^.options)
+           push_addr_param:=(po_methodpointer in pprocvardef(def)^.options)
         else if typeof(def^)=typeof(Tsetdef) then
            push_addr_param:=(psetdef(def)^.settype<>smallset);
      end;
@@ -949,7 +949,11 @@ end;
 end.
 {
   $Log$
-  Revision 1.1  2000-02-28 17:23:58  daniel
+  Revision 1.2  2000-03-16 12:52:48  daniel
+    *  Changed names of procedures flags
+    *  Changed VMT generation
+
+  Revision 1.1  2000/02/28 17:23:58  daniel
   * Current work of symtable integration committed. The symtable can be
     activated by defining 'newst', but doesn't compile yet. Changes in type
     checking and oop are completed. What is left is to write a new