Bladeren bron

* 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 -

Jonas Maebe 11 jaren geleden
bovenliggende
commit
8634aa8ad2

+ 2 - 0
.gitattributes

@@ -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

+ 22 - 38
compiler/jvm/symcpu.pas

@@ -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
 ****************************************************************************}
 ****************************************************************************}

+ 6 - 2
compiler/pdecvar.pas

@@ -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);

+ 9 - 1
compiler/symsym.pas

@@ -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 }

+ 4 - 0
tests/test/jvm/testall.bat

@@ -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

+ 4 - 0
tests/test/jvm/testall.sh

@@ -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 - 0
tests/test/jvm/tprop6.pp

@@ -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 - 0
tests/test/jvm/tprop6a.pp

@@ -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.