* don't mark classes used in "is"- or "as"-expressions as potentially

instantiated (for wpo)
  * also replace vmt-entries for classes for which we don't have any
    information at all with FPC_ABSTRACTERROR (since that means they
    certainly are not instantiated), except for their published and
    virtual class methods
  * fixed check for published methods in wpo

git-svn-id: trunk@13219 -
This commit is contained in:
Jonas Maebe 2009-05-31 13:52:40 +00:00
parent 380e957a79
commit 66c14c8a88
4 changed files with 54 additions and 18 deletions

View File

@ -3202,6 +3202,11 @@ implementation
if codegenerror then
exit;
{ Passing a class type to an "is" expression cannot result in a class
of that type to be constructed.
}
include(right.flags,nf_ignore_for_wpo);
if (right.resultdef.typ=classrefdef) then
begin
{ left must be a class }
@ -3399,6 +3404,10 @@ implementation
procname: string;
begin
result:=nil;
{ Passing a class type to an "as" expression cannot result in a class
of that type to be constructed.
}
include(right.flags,nf_ignore_for_wpo);
if not assigned(call) then
begin
if is_class(left.resultdef) and

View File

@ -172,9 +172,10 @@ implementation
expectloc:=LOC_REGISTER;
if left.nodetype<>typen then
firstpass(left)
else if not assigned(current_procinfo) or
(po_inline in current_procinfo.procdef.procoptions) or
wpoinfomanager.symbol_live(current_procinfo.procdef.mangledname) then
else if not(nf_ignore_for_wpo in flags) and
(not assigned(current_procinfo) or
(po_inline in current_procinfo.procdef.procoptions) or
wpoinfomanager.symbol_live(current_procinfo.procdef.mangledname)) then
begin
{ keep track of which classes might be instantiated via a classrefdef }
if (left.resultdef.typ=classrefdef) then

View File

@ -255,7 +255,16 @@ interface
nf_get_asm_position,
{ tblocknode }
nf_block_with_exit
nf_block_with_exit,
{ tloadvmtaddrnode }
nf_ignore_for_wpo { we know that this loadvmtaddrnode cannot be used to construct a class instance }
{ WARNING: there are now 32 elements in this type, and a set of this
type is written to the PPU. So before adding any more elements,
either move some flags to specific nodes, or stream a normalset
to the ppu
}
);

View File

@ -1054,18 +1054,6 @@ unit optvirt;
exit;
end;
{ get the component names for the class/procdef combo }
defsdecompose(realobjdef,tprocdef(procdef),unitid,classid,vmtentry);
{ do we have any info for this unit? }
unitdevirtinfo:=findunit(unitid^);
result:=false;
if not assigned(unitdevirtinfo) then
exit;
{ and for this class? }
classdevirtinfo:=unitdevirtinfo.findclass(classid^);
if not assigned(classdevirtinfo) then
exit;
{ if it's for a vmtentry of an objdef and the objdef is
not instantiated, then we can fill the vmt with pointers
to FPC_ABSTRACTERROR, except for published methods
@ -1073,7 +1061,34 @@ unit optvirt;
to the original method)
}
if forvmtentry and
(tprocdef(procdef).procsym.visibility=vis_published) then
(tprocdef(procdef).visibility=vis_published) then
begin
result:=false;
exit;
end;
{ get the component names for the class/procdef combo }
defsdecompose(realobjdef,tprocdef(procdef),unitid,classid,vmtentry);
{ If we don't have information about a particular unit/class/method,
it means that such class cannot be instantiated. So if we are
looking up information for a vmt entry, we can always safely return
FPC_ABSTRACTERROR if we do not find anything, unless it's a
published method (but those are handled already above) or a
class method (can be called even if the class is not instantiated).
}
result:=
forvmtentry and
not(po_classmethod in tprocdef(procdef).procoptions);
staticname:='FPC_ABSTRACTERROR';
{ do we have any info for this unit? }
unitdevirtinfo:=findunit(unitid^);
if not assigned(unitdevirtinfo) then
exit;
{ and for this class? }
classdevirtinfo:=unitdevirtinfo.findclass(classid^);
if not assigned(classdevirtinfo) then
exit;
if forvmtentry and
(objdef.typ=objectdef) and
@ -1081,7 +1096,9 @@ unit optvirt;
{ virtual class methods can be called even if the class is not instantiated }
not(po_classmethod in tprocdef(procdef).procoptions) then
begin
staticname:='FPC_ABSTRACTERROR';
{ already set above
staticname:='FPC_ABSTRACTERROR';
}
result:=true;
end
else