mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-10-25 13:25:47 +02:00
* 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:
parent
a8ed74d4d2
commit
8634aa8ad2
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
****************************************************************************}
|
****************************************************************************}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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 }
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
40
tests/test/jvm/tprop6.pp
Normal 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
16
tests/test/jvm/tprop6a.pp
Normal 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.
|
||||||
Loading…
Reference in New Issue
Block a user