* fixes for the support for overriding properties on the JVM target:

o only create an accessor wrapping the inherited accessor at a
     potentially lower visibility level if the overriding property
     itself does not specify a different accessor to use
   o simplified code
   o tests

git-svn-id: trunk@27954 -
This commit is contained in:
Jonas Maebe 2014-06-14 10:35:35 +00:00
parent a8ed74d4d2
commit 8634aa8ad2
8 changed files with 103 additions and 41 deletions

2
.gitattributes vendored
View File

@ -10908,6 +10908,8 @@ tests/test/jvm/tprop3.pp svneol=native#text/plain
tests/test/jvm/tprop4.pp svneol=native#text/plain tests/test/jvm/tprop4.pp svneol=native#text/plain
tests/test/jvm/tprop5.pp svneol=native#text/plain tests/test/jvm/tprop5.pp svneol=native#text/plain
tests/test/jvm/tprop5a.pp svneol=native#text/plain tests/test/jvm/tprop5a.pp svneol=native#text/plain
tests/test/jvm/tprop6.pp svneol=native#text/plain
tests/test/jvm/tprop6a.pp svneol=native#text/plain
tests/test/jvm/tptrdynarr.pp svneol=native#text/plain tests/test/jvm/tptrdynarr.pp svneol=native#text/plain
tests/test/jvm/tpvar.pp svneol=native#text/plain tests/test/jvm/tpvar.pp svneol=native#text/plain
tests/test/jvm/tpvardelphi.pp svneol=native#text/plain tests/test/jvm/tpvardelphi.pp svneol=native#text/plain

View File

@ -187,10 +187,11 @@ type
visibility, then we have to create a getter and/or setter with that same visibility, then we have to create a getter and/or setter with that same
higher visibility to make sure that using the property does not result higher visibility to make sure that using the property does not result
in JVM verification errors } in JVM verification errors }
function create_getter_or_setter_for_property(orgaccesspd: tprocdef; getter: boolean): tprocdef; procedure create_getter_or_setter_for_property(orgaccesspd: tprocdef; getter: boolean);
procedure finalize_getter_or_setter_for_sym(getset: tpropaccesslisttypes; sym: tsym; fielddef: tdef; accessordef: tprocdef); override; procedure finalize_getter_or_setter_for_sym(getset: tpropaccesslisttypes; sym: tsym; fielddef: tdef; accessordef: tprocdef); override;
procedure register_override(overriddenprop: tpropertysym); override;
procedure maybe_create_overridden_getter_or_setter(getset: tpropaccesslisttypes); procedure maybe_create_overridden_getter_or_setter(getset: tpropaccesslisttypes);
public
procedure inherit_accessor(getset: tpropaccesslisttypes); override;
end; end;
tcpupropertysymclass = class of tcpupropertysym; tcpupropertysymclass = class of tcpupropertysym;
@ -224,7 +225,7 @@ implementation
tcpuproptertysym tcpuproptertysym
****************************************************************************} ****************************************************************************}
function tcpupropertysym.create_getter_or_setter_for_property(orgaccesspd: tprocdef; getter: boolean): tprocdef; procedure tcpupropertysym.create_getter_or_setter_for_property(orgaccesspd: tprocdef; getter: boolean);
var var
obj: tabstractrecorddef; obj: tabstractrecorddef;
ps: tprocsym; ps: tprocsym;
@ -311,7 +312,6 @@ implementation
parentpd.visibility:=visibility; parentpd.visibility:=visibility;
include(parentpd.procoptions,po_auto_raised_visibility); include(parentpd.procoptions,po_auto_raised_visibility);
end; end;
result:=parentpd;
{ we are done, no need to create a wrapper } { we are done, no need to create a wrapper }
exit exit
end end
@ -344,7 +344,10 @@ implementation
finish_copied_procdef(pd,parentpd.procsym.realname,obj.symtable,obj); finish_copied_procdef(pd,parentpd.procsym.realname,obj.symtable,obj);
exclude(pd.procoptions,po_external); exclude(pd.procoptions,po_external);
pd.synthetickind:=tsk_anon_inherited; pd.synthetickind:=tsk_anon_inherited;
result:=pd; { set the accessor in the property }
propaccesslist[accesstyp].clear;
propaccesslist[accesstyp].addsym(sl_call,pd.procsym);
propaccesslist[accesstyp].procdef:=pd;
exit; exit;
end; end;
end; end;
@ -400,7 +403,6 @@ implementation
pd.procoptions:=pd.procoptions+procoptions; pd.procoptions:=pd.procoptions+procoptions;
{ visibility } { visibility }
pd.visibility:=visibility; pd.visibility:=visibility;
result:=pd;
{ new procsym? } { new procsym? }
if not assigned(sym) or if not assigned(sym) or
@ -501,7 +503,7 @@ implementation
procedure tcpupropertysym.finalize_getter_or_setter_for_sym(getset: tpropaccesslisttypes; sym: tsym; fielddef: tdef; accessordef: tprocdef); procedure tcpupropertysym.finalize_getter_or_setter_for_sym(getset: tpropaccesslisttypes; sym: tsym; fielddef: tdef; accessordef: tprocdef);
var var
orgaccesspd, newaccesspd: tprocdef; orgaccesspd: tprocdef;
pprefix: pshortstring; pprefix: pshortstring;
wrongvisibility: boolean; wrongvisibility: boolean;
begin begin
@ -510,7 +512,6 @@ implementation
pprefix:=@prop_auto_getter_prefix pprefix:=@prop_auto_getter_prefix
else else
pprefix:=@prop_auto_setter_prefix; pprefix:=@prop_auto_setter_prefix;
newaccesspd:=nil;
case sym.typ of case sym.typ of
procsym: procsym:
begin begin
@ -523,7 +524,7 @@ implementation
if wrongvisibility or if wrongvisibility or
((pprefix^<>'') and ((pprefix^<>'') and
(sym.RealName<>pprefix^+RealName)) then (sym.RealName<>pprefix^+RealName)) then
newaccesspd:=create_getter_or_setter_for_property(orgaccesspd,getset=palt_read) create_getter_or_setter_for_property(orgaccesspd,getset=palt_read)
end; end;
fieldvarsym: fieldvarsym:
begin begin
@ -533,43 +534,17 @@ implementation
which the property is visibile } which the property is visibile }
if (pprefix^<>'') or if (pprefix^<>'') or
(tfieldvarsym(sym).visibility<visibility) then (tfieldvarsym(sym).visibility<visibility) then
newaccesspd:=create_getter_or_setter_for_property(nil,getset=palt_read); create_getter_or_setter_for_property(nil,getset=palt_read);
end; end;
else else
internalerror(2014061101); internalerror(2014061101);
end; end;
{ update the getter/setter used for this property (already done in case
a new method was created from scratch, but not if we overrode a
getter/setter generated for the inherited property) }
if assigned(newaccesspd) then
begin
if propaccesslist[getset].firstsym^.sym.typ<>procsym then
internalerror(2014061201);
propaccesslist[getset].procdef:=newaccesspd;
propaccesslist[getset].firstsym^.sym:=newaccesspd.procsym;
end;
end;
procedure tcpupropertysym.register_override(overriddenprop: tpropertysym);
var
sym: tsym;
begin
inherited;
{ new property has higher visibility than previous one -> maybe override
the getters/setters }
if (overriddenprop.visibility<visibility) then
begin
maybe_create_overridden_getter_or_setter(palt_read);
maybe_create_overridden_getter_or_setter(palt_write);
end;
end; end;
procedure tcpupropertysym.maybe_create_overridden_getter_or_setter(getset: tpropaccesslisttypes); procedure tcpupropertysym.maybe_create_overridden_getter_or_setter(getset: tpropaccesslisttypes);
var var
sym: tsym; sym: tsym;
fielddef: tdef;
accessordef: tprocdef; accessordef: tprocdef;
psym: tpropertysym; psym: tpropertysym;
begin begin
@ -590,14 +565,12 @@ implementation
accessordef:=tprocdef(psym.propaccesslist[getset].procdef); accessordef:=tprocdef(psym.propaccesslist[getset].procdef);
if accessordef.visibility>=visibility then if accessordef.visibility>=visibility then
exit; exit;
fielddef:=nil;
end; end;
fieldvarsym: fieldvarsym:
begin begin
if sym.visibility>=visibility then if sym.visibility>=visibility then
exit; exit;
accessordef:=nil; accessordef:=nil;
fielddef:=tfieldvarsym(sym).vardef;
end; end;
else else
internalerror(2014061102); internalerror(2014061102);
@ -607,6 +580,17 @@ implementation
end; end;
procedure tcpupropertysym.inherit_accessor(getset: tpropaccesslisttypes);
begin
inherited;
{ new property has higher visibility than previous one -> maybe override
the getters/setters }
if assigned(overriddenpropsym) and
(overriddenpropsym.visibility<visibility) then
maybe_create_overridden_getter_or_setter(getset);
end;
{**************************************************************************** {****************************************************************************
tcpuenumdef tcpuenumdef
****************************************************************************} ****************************************************************************}

View File

@ -535,7 +535,9 @@ implementation
end; end;
p.add_getter_or_setter_for_sym(palt_read,sym,def,readprocdef); p.add_getter_or_setter_for_sym(palt_read,sym,def,readprocdef);
end; end;
end; end
else
p.inherit_accessor(palt_read);
if try_to_consume(_WRITE) then if try_to_consume(_WRITE) then
begin begin
p.propaccesslist[palt_write].clear; p.propaccesslist[palt_write].clear;
@ -555,7 +557,9 @@ implementation
end; end;
p.add_getter_or_setter_for_sym(palt_write,sym,def,writeprocdef); p.add_getter_or_setter_for_sym(palt_write,sym,def,writeprocdef);
end; end;
end; end
else
p.inherit_accessor(palt_write);
end end
else else
parse_dispinterface(p,readprocdef,writeprocdef,paranr); parse_dispinterface(p,readprocdef,writeprocdef,paranr);

View File

@ -349,7 +349,9 @@ interface
procedure add_index_parameter(var paranr: word; readprocdef, writeprocdef: tprocdef); procedure add_index_parameter(var paranr: word; readprocdef, writeprocdef: tprocdef);
{ set up the accessors for this property } { set up the accessors for this property }
procedure add_getter_or_setter_for_sym(getset: tpropaccesslisttypes; sym: tsym; fielddef: tdef; accessordef: tprocdef); procedure add_getter_or_setter_for_sym(getset: tpropaccesslisttypes; sym: tsym; fielddef: tdef; accessordef: tprocdef);
procedure register_override(overriddenprop: tpropertysym); virtual; procedure register_override(overriddenprop: tpropertysym);
{ inherit the read/write property }
procedure inherit_accessor(getset: tpropaccesslisttypes); virtual;
end; end;
tpropertysymclass = class of tpropertysym; tpropertysymclass = class of tpropertysym;
@ -1445,6 +1447,12 @@ implementation
end; end;
procedure tpropertysym.inherit_accessor(getset: tpropaccesslisttypes);
begin
{ nothing to do by default }
end;
procedure tpropertysym.makeduplicate(p: tpropertysym; readprocdef, writeprocdef: tprocdef; out paranr: word); procedure tpropertysym.makeduplicate(p: tpropertysym; readprocdef, writeprocdef: tprocdef; out paranr: word);
begin begin
{ inherit all type related entries } { inherit all type related entries }

View File

@ -298,3 +298,7 @@ ppcjvm -O2 -g -B -Sa tprop5a
java -Dfile.encoding=UTF-8 -cp ..\..\..\rtl\units\jvm-java;. tprop5a java -Dfile.encoding=UTF-8 -cp ..\..\..\rtl\units\jvm-java;. tprop5a
ppcjvm -O2 -g -B -Sa tprop5a -CTautosetterprefix=Set -CTautogetterprefix=Get ppcjvm -O2 -g -B -Sa tprop5a -CTautosetterprefix=Set -CTautogetterprefix=Get
java -Dfile.encoding=UTF-8 -cp ..\..\..\rtl\units\jvm-java;. tprop5a java -Dfile.encoding=UTF-8 -cp ..\..\..\rtl\units\jvm-java;. tprop5a
ppcjvm -O2 -g -B -Sa tprop6a
java -Dfile.encoding=UTF-8 -cp ..\..\..\rtl\units\jvm-java;. tprop6a
ppcjvm -O2 -g -B -Sa tprop6a -CTautosetterprefix=Set -CTautogetterprefix=Get
java -Dfile.encoding=UTF-8 -cp ..\..\..\rtl\units\jvm-java;. tprop6a

View File

@ -178,3 +178,7 @@ $PPC -O2 -g -B -Sa tprop5a
java -Dfile.encoding=UTF-8 -cp ../../../rtl/units/$RTLDIR:. tprop5a java -Dfile.encoding=UTF-8 -cp ../../../rtl/units/$RTLDIR:. tprop5a
$PPC -O2 -g -B -Sa tprop5a -CTautosetterprefix=Set -CTautogetterprefix=Get $PPC -O2 -g -B -Sa tprop5a -CTautosetterprefix=Set -CTautogetterprefix=Get
java -Dfile.encoding=UTF-8 -cp ../../../rtl/units/$RTLDIR:. tprop5a java -Dfile.encoding=UTF-8 -cp ../../../rtl/units/$RTLDIR:. tprop5a
$PPC -O2 -g -B -Sa tprop6a
java -Dfile.encoding=UTF-8 -cp ../../../rtl/units/$RTLDIR:. tprop6a
$PPC -O2 -g -B -Sa tprop6a -CTautosetterprefix=Set -CTautogetterprefix=Get
java -Dfile.encoding=UTF-8 -cp ../../../rtl/units/$RTLDIR:. tprop6a

40
tests/test/jvm/tprop6.pp Normal file
View File

@ -0,0 +1,40 @@
{$mode delphi}
{$modeswitch unicodestrings}
{$namespace org.freepascal.test}
Unit tprop6;
interface
uses
jdk15;
type
TBaseClassProp6 = class
private
FLevel : integer;
procedure SetLevel(value: integer); virtual;
public
property Level: Integer read FLevel write SetLevel;
end;
TDerivedClassProp6 = class(TBaseClassProp6)
protected
procedure SetLevel(value: integer); override;
public
property Level: Integer read FLevel write SetLevel;
end;
implementation
procedure TBaseClassProp6.SetLevel(Value: integer);
begin
FLevel := Value;
end;
procedure TDerivedClassProp6.SetLevel(Value: integer);
begin
FLevel := Value+1;
end;
end.

16
tests/test/jvm/tprop6a.pp Normal file
View File

@ -0,0 +1,16 @@
program tprop6a;
uses
tprop6;
var
c: tbaseclassprop6;
d: tderivedclassprop6;
begin
c:=tbaseclassprop6.create;
c.level:=4;
if c.level<>4 then
halt(1);
d:=tderivedclassprop6.create;
d.level:=5;
halt(d.level-6);
end.