* change non-virtual instance methods to "virtual; final;" methods on the

JVM target, because that's the only way to guarantee their semantics on
    that platform (see comments in pdecobj)
  * allow starting new inheritance trees (which is the same as adding a new
    non-virtual method as of this revision) on the JVM target in case the
    parameters of the new routine match the old one, but the complete mangled
    name does not (because then the JVM won't consider them to be the same
    either -> Pascal semantics are matched)

git-svn-id: branches/jvmbackend@18695 -
This commit is contained in:
Jonas Maebe 2011-08-20 08:25:24 +00:00
parent 4074bf412b
commit ee75bfaaf4
4 changed files with 61 additions and 7 deletions

View File

@ -240,6 +240,10 @@ implementation
// returns true if we can stop checking, false if we have to continue
function found_entry(var vmtpd: tprocdef; var vmtentryvis: tvisibility; updatevalues: boolean): boolean;
{$ifdef jvm}
var
javanewtreeok: boolean;
{$endif jvm}
begin
result:=false;
@ -269,9 +273,16 @@ implementation
hasequalpara:=(compare_paras(vmtpd.paras,pd.paras,cp_none,[cpo_ignoreuniv,cpo_ignorehidden])>=te_equal);
{ check that we are not trying to override a final method }
{ in Java, new virtual inheritance trees can never be started ->
treat all methods as "overriding" in the context of this check
(Java does check whether the mangled names are identical, so if they
are not we can stil get away with it) }
if (po_finalmethod in vmtpd.procoptions) and
hasequalpara and (po_overridingmethod in pd.procoptions) and
(is_class(_class) or is_objectpascal_helper(_class)) then
hasequalpara and
((po_overridingmethod in pd.procoptions) or
(is_javaclass(_class) and
(pd.mangledname=vmtpd.mangledname))) and
(is_class(_class) or is_objectpascal_helper(_class) or is_javaclass(_class)) then
MessagePos1(pd.fileinfo,parser_e_final_can_no_be_overridden,pd.fullprocname(false))
else
{ old definition has virtual
@ -296,9 +307,21 @@ implementation
hasequalpara
) then
begin
if not(po_reintroduce in pd.procoptions) then
if not(is_objc_class_or_protocol(_class)) and
not(is_java_class_or_interface(_class)) then
{$ifdef jvm}
{ if the mangled names are different, the inheritance trees
are different too in Java }
javanewtreeok:=
is_java_class_or_interface(_class) and
(pd.jvmmangledbasename(false)<>vmtpd.jvmmangledbasename(false));
{$endif}
if not(po_reintroduce in pd.procoptions) and
not(po_java_nonvirtual in vmtpd.procoptions) then
if not(is_objc_class_or_protocol(_class))
{$ifdef jvm}
and (not is_java_class_or_interface(_class) or
javanewtreeok)
{$endif jvm}
then
MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false))
else
begin
@ -341,6 +364,15 @@ implementation
dec(tobjectdef(pd.owner.defowner).abstractcnt);
result:=true;
exit;
{$ifdef jvm}
end
else
if not javanewtreeok and
is_java_class_or_interface(_class) then
begin
{ mangled names are the same -> can only override }
MessagePos1(pd.fileinfo,parser_e_must_use_override,FullTypeName(tdef(vmtpd.owner.defowner),nil))
{$endif jvm}
end;
{ disable/hide old VMT entry }
if updatevalues then

View File

@ -782,6 +782,24 @@ implementation
begin
if is_java_class_or_interface(pd.struct) then
begin
{ mark all non-virtual instance methods as "virtual; final;",
because
a) that's the only way to guarantee "non-virtual" behaviour
(other than making them class methods with an explicit self
pointer, but that causes problems with interface mappings
and procvars)
b) if we don't mark them virtual, they don't get added to the
vmt and we can't check whether child classes try to override
them
}
if is_javaclass(pd.struct) and
not(po_virtualmethod in pd.procoptions) and
not(po_classmethod in pd.procoptions) then
begin
include(pd.procoptions,po_virtualmethod);
include(pd.procoptions,po_finalmethod);
include(pd.procoptions,po_java_nonvirtual);
end;
end;
end;

View File

@ -315,7 +315,10 @@ type
(when calling a regular procedure using the above convention, it will
simply not see the frame pointer parameter, and since the caller cleans
up the stack will also remain balanced) }
po_delphi_nested_cc
po_delphi_nested_cc,
{ Non-virtual method of a Java class that has been transformed into a
"virtual; final;" method for JVM-implementation reasons }
po_java_nonvirtual
);
tprocoptions=set of tprocoption;

View File

@ -1148,7 +1148,8 @@ const
(mask:po_objc; str:'ObjC'),
(mask:po_enumerator_movenext; str:'EnumeratorMoveNext'),
(mask:po_optional; str: 'Optional'),
(mask:po_delphi_nested_cc;str: 'Delphi-style nested frameptr')
(mask:po_delphi_nested_cc;str: 'Delphi-style nested frameptr'),
(mask:po_java_nonvirtual; str: 'Java non-virtual method')
);
var
proctypeoption : tproctypeoption;