2
0
Эх сурвалжийг харах

* copy the implicit pointer rather than the contents of var/out/constref
implicit pointer types into the nestedfpstruct, so that the original
parameter is properly changed when updated from inside nested routines

git-svn-id: branches/jvmbackend@19645 -

Jonas Maebe 13 жил өмнө
parent
commit
4dee36b64b

+ 1 - 0
.gitattributes

@@ -9794,6 +9794,7 @@ tests/test/jvm/testshort.pp svneol=native#text/plain
 tests/test/jvm/tformalpara.pp svneol=native#text/plain
 tests/test/jvm/tint.pp svneol=native#text/plain
 tests/test/jvm/tintstr.pp svneol=native#text/plain
+tests/test/jvm/tnestedset.pp svneol=native#text/plain
 tests/test/jvm/tnestproc.pp svneol=native#text/plain
 tests/test/jvm/tprop.pp svneol=native#text/plain
 tests/test/jvm/tprop2.pp svneol=native#text/plain

+ 16 - 0
compiler/jvm/njvmld.pas

@@ -36,6 +36,7 @@ type
    protected
     function is_copyout_addr_param_load: boolean;
     function handle_threadvar_access: tnode; override;
+    function keep_param_address_in_nested_struct: boolean; override;
    public
     function is_addr_param_load: boolean; override;
     procedure pass_generate_code; override;
@@ -189,6 +190,21 @@ function tjvmloadnode.handle_threadvar_access: tnode;
   end;
 
 
+function tjvmloadnode.keep_param_address_in_nested_struct: boolean;
+  begin
+    { we don't need an extra load when implicit pointer types  are passed as
+      var/out/constref parameter (since they are already pointers). However,
+      when transfering them into a nestedfp struct, we do want to transfer the
+      pointer and not make a deep copy in case they are var/out/constref (since
+      changes made to the var/out parameter should propagate up) }
+    result:=
+     is_addr_param_load or
+     ((symtableentry.typ=paravarsym) and
+      jvmimplicitpointertype(tparavarsym(symtableentry).vardef) and
+      (tparavarsym(symtableentry).varspez in [vs_var,vs_constref,vs_out]));
+  end;
+
+
 function tjvmloadnode.is_addr_param_load: boolean;
   begin
     result:=

+ 8 - 1
compiler/ncgnstld.pas

@@ -40,6 +40,7 @@ interface
          nestsym: tsym;
          nestsymderef: tderef;
          procedure generate_nested_access(vs: tsym);override;
+         function  keep_param_address_in_nested_struct: boolean; virtual;
         public
          function  pass_typecheck: tnode; override;
          function  pass_1:tnode;override;
@@ -80,6 +81,12 @@ implementation
       end;
 
 
+    function tcgnestloadnode.keep_param_address_in_nested_struct: boolean;
+      begin
+        result:=is_addr_param_load;
+      end;
+
+
     function tcgnestloadnode.pass_typecheck: tnode;
       var
         nestedvars: tsym;
@@ -115,7 +122,7 @@ implementation
                       nestedvars:=tprocdef(symtable.defowner).parentfpstruct;
                     end;
                   {  store result for use in pass_1 }
-                  nestsym:=maybe_add_sym_to_parentfpstruct(tprocdef(symtableentry.owner.defowner),symtableentry,resultdef,is_addr_param_load);
+                  nestsym:=maybe_add_sym_to_parentfpstruct(tprocdef(symtableentry.owner.defowner),symtableentry,resultdef,keep_param_address_in_nested_struct);
                   { left normally holds the parentfp node. If it's not assigned,
                     this is an access to a local variable/para from the routine
                     in which it was actually declared -> redirect to its

+ 31 - 0
tests/test/jvm/tnestedset.pp

@@ -0,0 +1,31 @@
+program tnestedset;
+
+{$mode delphi}
+
+uses
+  jdk15;
+
+type
+  tnestedfpstructenum = (ea,eb,ec);
+  tnestedfpstructenumset = set of tnestedfpstructenum;
+
+procedure test(var s: tnestedfpstructenumset);
+
+ procedure sub;
+ begin
+   s:=s+[eb];
+ end;
+
+
+begin
+  sub
+end;
+
+var
+  s: tnestedfpstructenumset;
+begin
+  test(s);
+  if s<>[eb] then
+    raise jlexception.create;
+  jlsystem.fout.println(jlstring(juenumset(@s).toString));
+end.