* 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 if codegenerror then
exit; 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 if (right.resultdef.typ=classrefdef) then
begin begin
{ left must be a class } { left must be a class }
@ -3399,6 +3404,10 @@ implementation
procname: string; procname: string;
begin begin
result:=nil; 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 if not assigned(call) then
begin begin
if is_class(left.resultdef) and if is_class(left.resultdef) and

View File

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

View File

@ -255,7 +255,16 @@ interface
nf_get_asm_position, nf_get_asm_position,
{ tblocknode } { 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; exit;
end; 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 { if it's for a vmtentry of an objdef and the objdef is
not instantiated, then we can fill the vmt with pointers not instantiated, then we can fill the vmt with pointers
to FPC_ABSTRACTERROR, except for published methods to FPC_ABSTRACTERROR, except for published methods
@ -1073,7 +1061,34 @@ unit optvirt;
to the original method) to the original method)
} }
if forvmtentry and 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; exit;
if forvmtentry and if forvmtentry and
(objdef.typ=objectdef) and (objdef.typ=objectdef) and
@ -1081,7 +1096,9 @@ unit optvirt;
{ virtual class methods can be called even if the class is not instantiated } { virtual class methods can be called even if the class is not instantiated }
not(po_classmethod in tprocdef(procdef).procoptions) then not(po_classmethod in tprocdef(procdef).procoptions) then
begin begin
staticname:='FPC_ABSTRACTERROR'; { already set above
staticname:='FPC_ABSTRACTERROR';
}
result:=true; result:=true;
end end
else else