mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-23 05:29:26 +02:00
* fixed and cleanup of overriding non-visible methods
This commit is contained in:
parent
c1d4e0c3d3
commit
29207e007a
@ -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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user