* fixed and cleanup of overriding non-visible methods

This commit is contained in:
peter 2004-09-13 20:31:07 +00:00
parent c1d4e0c3d3
commit 29207e007a

View File

@ -33,7 +33,7 @@ interface
{$endif} {$endif}
cutils,cclasses, cutils,cclasses,
globtype, globtype,
symdef, symdef,symsym,
aasmbase,aasmtai, aasmbase,aasmtai,
cpuinfo cpuinfo
; ;
@ -50,15 +50,16 @@ interface
tprocdefcoll = record tprocdefcoll = record
data : tprocdef; data : tprocdef;
hidden : boolean; hidden : boolean;
visible : boolean;
next : pprocdefcoll; next : pprocdefcoll;
end; end;
psymcoll = ^tsymcoll; pvmtentry = ^tvmtentry;
tsymcoll = record tvmtentry = record
speedvalue : cardinal; speedvalue : cardinal;
name : pstring; name : pstring;
data : pprocdefcoll; firstprocdef : pprocdefcoll;
next : psymcoll; next : pvmtentry;
end; end;
tclassheader=class tclassheader=class
@ -89,10 +90,12 @@ interface
procedure genpubmethodtableentry(p : tnamedindexitem;arg:pointer); procedure genpubmethodtableentry(p : tnamedindexitem;arg:pointer);
private private
{ vmt } { vmt }
wurzel : psymcoll; firstvmtentry : pvmtentry;
nextvirtnumber : integer; nextvirtnumber : integer;
has_constructor, has_constructor,
has_virtual_method : boolean; has_virtual_method : boolean;
procedure newdefentry(vmtentry:pvmtentry;pd:tprocdef;is_visible:boolean);
procedure newvmtentry(sym:tprocsym;is_visible:boolean);
procedure eachsym(sym : tnamedindexitem;arg:pointer); procedure eachsym(sym : tnamedindexitem;arg:pointer);
procedure disposevmttree; procedure disposevmttree;
procedure writevirtualmethods(List:TAAsmoutput); procedure writevirtualmethods(List:TAAsmoutput);
@ -148,7 +151,7 @@ implementation
strings, strings,
{$endif} {$endif}
globals,verbose,systems, globals,verbose,systems,
symtable,symconst,symtype,symsym,defcmp,paramgr, symtable,symconst,symtype,defcmp,paramgr,
{$ifdef GDB} {$ifdef GDB}
gdb, gdb,
{$endif GDB} {$endif GDB}
@ -520,60 +523,52 @@ implementation
VMT VMT
**************************************} **************************************}
procedure tclassheader.eachsym(sym : tnamedindexitem;arg:pointer);
procedure tclassheader.newdefentry(vmtentry:pvmtentry;pd:tprocdef;is_visible:boolean);
var var
procdefcoll : pprocdefcoll; procdefcoll : pprocdefcoll;
symcoll : psymcoll;
_name : string;
_speed : cardinal;
procedure newdefentry(pd:tprocdef);
begin begin
{ generate new entry }
new(procdefcoll); new(procdefcoll);
procdefcoll^.data:=pd; procdefcoll^.data:=pd;
procdefcoll^.hidden:=false; procdefcoll^.hidden:=false;
procdefcoll^.next:=symcoll^.data; procdefcoll^.visible:=is_visible;
symcoll^.data:=procdefcoll; procdefcoll^.next:=vmtentry^.firstprocdef;
vmtentry^.firstprocdef:=procdefcoll;
{ if it's a virtual method } { give virtual method a number }
if (po_virtualmethod in pd.procoptions) then if (po_virtualmethod in pd.procoptions) then
begin begin
{ then it gets a number ... }
pd.extnumber:=nextvirtnumber; pd.extnumber:=nextvirtnumber;
{ and we inc the number }
inc(nextvirtnumber); inc(nextvirtnumber);
has_virtual_method:=true; has_virtual_method:=true;
end; end;
if (pd.proctypeoption=potype_constructor) then if (pd.proctypeoption=potype_constructor) then
has_constructor:=true; has_constructor:=true;
{ check, if a method should be overridden }
if (pd._class=_class) and
(po_overridingmethod in pd.procoptions) then
MessagePos1(pd.fileinfo,parser_e_nothing_to_be_overridden,pd.fullprocname(false));
end; end;
{ creates a new entry in the procsym list }
procedure newentry;
var i:cardinal;
procedure tclassheader.newvmtentry(sym:tprocsym;is_visible:boolean);
var
i : cardinal;
vmtentry : pvmtentry;
begin begin
{ if not, generate a new symbol item } { generate new vmtentry }
new(symcoll); new(vmtentry);
symcoll^.speedvalue:=sym.speedvalue; vmtentry^.speedvalue:=sym.speedvalue;
symcoll^.name:=stringdup(sym.name); vmtentry^.name:=stringdup(sym.name);
symcoll^.next:=wurzel; vmtentry^.next:=firstvmtentry;
symcoll^.data:=nil; vmtentry^.firstprocdef:=nil;
wurzel:=symcoll; firstvmtentry:=vmtentry;
{ inserts all definitions } { inserts all definitions }
for i:=1 to Tprocsym(sym).procdef_count do for i:=1 to sym.procdef_count do
newdefentry(Tprocsym(sym).procdef[i]); newdefentry(vmtentry,sym.procdef[i],is_visible);
end; end;
procedure tclassheader.eachsym(sym : tnamedindexitem;arg:pointer);
label label
handlenextdef; handlenextdef;
var var
@ -582,12 +577,14 @@ implementation
is_visible, is_visible,
hasoverloads, hasoverloads,
pdoverload : boolean; pdoverload : boolean;
procdefcoll : pprocdefcoll;
vmtentry : pvmtentry;
_name : string;
_speed : cardinal;
begin begin
{ put only sub routines into the VMT, and routines if (tsym(sym).typ<>procsym) then
that are visible to the current class. Skip private exit;
methods in other classes }
if (tsym(sym).typ=procsym) then
begin
{ is this symbol visible from the class that we are { is this symbol visible from the class that we are
generating. This will be used to hide the other procdefs. generating. This will be used to hide the other procdefs.
When the symbol is not visible we don't hide the other When the symbol is not visible we don't hide the other
@ -598,14 +595,14 @@ implementation
{ check the current list of symbols } { check the current list of symbols }
_name:=sym.name; _name:=sym.name;
_speed:=sym.speedvalue; _speed:=sym.speedvalue;
symcoll:=wurzel; vmtentry:=firstvmtentry;
while assigned(symcoll) do while assigned(vmtentry) do
begin begin
{ does the symbol already exist in the list? First { does the symbol already exist in the list? First
compare speedvalue before doing the string compare to compare speedvalue before doing the string compare to
speed it up a little } speed it up a little }
if (_speed=symcoll^.speedvalue) and if (_speed=vmtentry^.speedvalue) and
(_name=symcoll^.name^) then (_name=vmtentry^.name^) then
begin begin
hasoverloads:=(Tprocsym(sym).procdef_count>1); hasoverloads:=(Tprocsym(sym).procdef_count>1);
{ walk through all defs of the symbol } { walk through all defs of the symbol }
@ -617,7 +614,7 @@ implementation
pdoverload:=(po_overload in pd.procoptions); pdoverload:=(po_overload in pd.procoptions);
{ compare with all stored definitions } { compare with all stored definitions }
procdefcoll:=symcoll^.data; procdefcoll:=vmtentry^.firstprocdef;
while assigned(procdefcoll) do while assigned(procdefcoll) do
begin begin
{ compare only if the definition is not hidden } { compare only if the definition is not hidden }
@ -644,7 +641,7 @@ implementation
when it has no overload directive and no overloads } when it has no overload directive and no overloads }
if not(po_virtualmethod in pd.procoptions) then if not(po_virtualmethod in pd.procoptions) then
begin begin
if tstoredsym(procdefcoll^.data.procsym).is_visible_for_object(pd._class) and if procdefcoll^.visible and
(not(pdoverload or hasoverloads) or (not(pdoverload or hasoverloads) or
(compare_paras(procdefcoll^.data.para,pd.para,cp_all,[])>=te_equal)) then (compare_paras(procdefcoll^.data.para,pd.para,cp_all,[])>=te_equal)) then
begin begin
@ -665,7 +662,7 @@ implementation
{ we start a new virtual tree, hide the old } { we start a new virtual tree, hide the old }
if (not(pdoverload or hasoverloads) or if (not(pdoverload or hasoverloads) or
(compare_paras(procdefcoll^.data.para,pd.para,cp_all,[])>=te_equal)) and (compare_paras(procdefcoll^.data.para,pd.para,cp_all,[])>=te_equal)) and
(tstoredsym(procdefcoll^.data.procsym).is_visible_for_object(pd._class)) then (procdefcoll^.visible) then
begin begin
if is_visible then if is_visible then
procdefcoll^.hidden:=true; procdefcoll^.hidden:=true;
@ -673,16 +670,6 @@ implementation
MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false)); MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false));
end; end;
end end
{ check if the method to override is visible, check is only needed
for the current parsed class. Parent classes are already validated and
need to include all virtual methods including the ones not visible in the
current class }
else if (_class=pd._class) and
(po_overridingmethod in pd.procoptions) and
(not tstoredsym(procdefcoll^.data.procsym).is_visible_for_object(pd._class)) then
begin
{ do nothing, the error will follow when adding the entry }
end
{ same parameters } { same parameters }
else if (compare_paras(procdefcoll^.data.para,pd.para,cp_all,[])>=te_equal) then else if (compare_paras(procdefcoll^.data.para,pd.para,cp_all,[])>=te_equal) then
begin begin
@ -722,10 +709,21 @@ implementation
Message2(parser_e_overridden_methods_not_same_ret,pd.fullprocname(false), Message2(parser_e_overridden_methods_not_same_ret,pd.fullprocname(false),
procdefcoll^.data.fullprocname(false)); procdefcoll^.data.fullprocname(false));
{ now set the number } { check if the method to override is visible, check is only needed
for the current parsed class. Parent classes are already validated and
need to include all virtual methods including the ones not visible in the
current class }
if (_class=pd._class) and
(po_overridingmethod in pd.procoptions) and
(not procdefcoll^.visible) then
MessagePos1(pd.fileinfo,parser_e_nothing_to_be_overridden,pd.fullprocname(false));
{ override old virtual method in VMT }
pd.extnumber:=procdefcoll^.data.extnumber; pd.extnumber:=procdefcoll^.data.extnumber;
{ and exchange }
procdefcoll^.data:=pd; procdefcoll^.data:=pd;
if is_visible then
procdefcoll^.visible:=true;
goto handlenextdef; goto handlenextdef;
end end
{ different parameters } { different parameters }
@ -767,41 +765,44 @@ implementation
procdefcoll:=procdefcoll^.next; procdefcoll:=procdefcoll^.next;
end; end;
{ new entry is needed, override was not possible }
if (_class=pd._class) and
(po_overridingmethod in pd.procoptions) then
MessagePos1(pd.fileinfo,parser_e_nothing_to_be_overridden,pd.fullprocname(false));
{ if it isn't saved in the list we create a new entry } { if it isn't saved in the list we create a new entry }
newdefentry(pd); newdefentry(vmtentry,pd,is_visible);
end; end;
handlenextdef: handlenextdef:
end; end;
exit; exit;
end; end;
symcoll:=symcoll^.next; vmtentry:=vmtentry^.next;
end;
newentry;
end; end;
newvmtentry(tprocsym(sym),is_visible);
end; end;
procedure tclassheader.disposevmttree; procedure tclassheader.disposevmttree;
var var
symcoll : psymcoll; vmtentry : pvmtentry;
procdefcoll : pprocdefcoll; procdefcoll : pprocdefcoll;
begin begin
{ disposes the above generated tree } { disposes the above generated tree }
symcoll:=wurzel; vmtentry:=firstvmtentry;
while assigned(symcoll) do while assigned(vmtentry) do
begin begin
wurzel:=symcoll^.next; firstvmtentry:=vmtentry^.next;
stringdispose(symcoll^.name); stringdispose(vmtentry^.name);
procdefcoll:=symcoll^.data; procdefcoll:=vmtentry^.firstprocdef;
while assigned(procdefcoll) do while assigned(procdefcoll) do
begin begin
symcoll^.data:=procdefcoll^.next; vmtentry^.firstprocdef:=procdefcoll^.next;
dispose(procdefcoll); dispose(procdefcoll);
procdefcoll:=symcoll^.data; procdefcoll:=vmtentry^.firstprocdef;
end; end;
dispose(symcoll); dispose(vmtentry);
symcoll:=wurzel; vmtentry:=firstvmtentry;
end; end;
end; end;
@ -820,7 +821,7 @@ implementation
end; end;
begin begin
wurzel:=nil; firstvmtentry:=nil;
nextvirtnumber:=0; nextvirtnumber:=0;
has_constructor:=false; has_constructor:=false;
@ -1180,7 +1181,7 @@ implementation
procedure tclassheader.writevirtualmethods(List:TAAsmoutput); procedure tclassheader.writevirtualmethods(List:TAAsmoutput);
var var
symcoll : psymcoll; vmtentry : pvmtentry;
procdefcoll : pprocdefcoll; procdefcoll : pprocdefcoll;
i : longint; i : longint;
begin begin
@ -1188,14 +1189,12 @@ implementation
{ the method } { the method }
for i:=0 to nextvirtnumber-1 do for i:=0 to nextvirtnumber-1 do
begin begin
symcoll:=wurzel;
{ walk trough all symbols } { walk trough all symbols }
while assigned(symcoll) do vmtentry:=firstvmtentry;
while assigned(vmtentry) do
begin begin
{ walk trough all methods } { walk trough all methods }
procdefcoll:=symcoll^.data; procdefcoll:=vmtentry^.firstprocdef;
while assigned(procdefcoll) do while assigned(procdefcoll) do
begin begin
{ writes the addresses to the VMT } { writes the addresses to the VMT }
@ -1215,7 +1214,7 @@ implementation
end; end;
procdefcoll:=procdefcoll^.next; procdefcoll:=procdefcoll^.next;
end; end;
symcoll:=symcoll^.next; vmtentry:=vmtentry^.next;
end; end;
end; end;
end; end;
@ -1382,7 +1381,10 @@ initialization
end. end.
{ {
$Log$ $Log$
Revision 1.74 2004-07-09 22:17:32 peter Revision 1.75 2004-09-13 20:31:07 peter
* fixed and cleanup of overriding non-visible methods
Revision 1.74 2004/07/09 22:17:32 peter
* revert has_localst patch * revert has_localst patch
* replace aktstaticsymtable/aktglobalsymtable with current_module * replace aktstaticsymtable/aktglobalsymtable with current_module