mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-08 06:08:16 +02:00
* 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:
parent
4074bf412b
commit
ee75bfaaf4
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user