Bladeren bron

* ensure that dispose(managed_ptr) does not result in multiple evaluations of
the managed_ptr expression

git-svn-id: trunk@45673 -

Jonas Maebe 5 jaren geleden
bovenliggende
commit
3cb341eabc
3 gewijzigde bestanden met toevoegingen van 36 en 3 verwijderingen
  1. 1 0
      .gitattributes
  2. 17 3
      compiler/pinline.pas
  3. 18 0
      tests/webtbs/tw37228.pp

+ 1 - 0
.gitattributes

@@ -18333,6 +18333,7 @@ tests/webtbs/tw37154.pp svneol=native#text/pascal
 tests/webtbs/tw3719.pp svneol=native#text/plain
 tests/webtbs/tw3721.pp svneol=native#text/plain
 tests/webtbs/tw37218.pp svneol=native#text/pascal
+tests/webtbs/tw37228.pp svneol=native#text/plain
 tests/webtbs/tw3742.pp svneol=native#text/plain
 tests/webtbs/tw3751.pp svneol=native#text/plain
 tests/webtbs/tw3758.pp svneol=native#text/plain

+ 17 - 3
compiler/pinline.pas

@@ -53,7 +53,7 @@ implementation
        symbase,symconst,symdef,symsym,symtable,defutil,
        { pass 1 }
        pass_1,htypechk,
-       ncal,nmem,ncnv,ninl,ncon,nld,nbas,ngenutil,
+       ncal,nmem,ncnv,ninl,ncon,nld,nbas,ngenutil,nutils,
        { parser }
        scanner,
        pbase,pexpr;
@@ -404,15 +404,29 @@ implementation
                    end
                   else
                    begin
+                     temp:=nil;
                      { create call to fpc_finalize }
                      if is_managed_type(tpointerdef(p.resultdef).pointeddef) then
-                       addstatement(newstatement,cnodeutils.finalize_data_node(cderefnode.create(p.getcopy)));
+                       if might_have_sideeffects(p) then
+                         begin
+                           { ensure that p gets evaluated only once, in case it is e.g. a call }
+                           temp:=ctempcreatenode.create_value(p.resultdef,p.resultdef.size,tt_persistent,true,p);
+                           addstatement(newstatement,temp);
+                           addstatement(newstatement,cnodeutils.finalize_data_node(cderefnode.create(ctemprefnode.create(temp))));
+                         end
+                       else
+                         addstatement(newstatement,cnodeutils.finalize_data_node(cderefnode.create(p.getcopy)));
 
                      ReadVariantRecordConstants;
 
                      { create call to fpc_freemem }
-                     para := ccallparanode.create(p,nil);
+                     if not assigned(temp) then
+                       para := ccallparanode.create(p,nil)
+                     else
+                       para := ccallparanode.create(ctemprefnode.create(temp),nil);
                      addstatement(newstatement,ccallnode.createintern('fpc_freemem',para));
+                     if assigned(temp) then
+                       addstatement(newstatement,ctempdeletenode.create(temp));
                    end;
                end;
           end;

+ 18 - 0
tests/webtbs/tw37228.pp

@@ -0,0 +1,18 @@
+{$mode objfpc} {$h+}
+var
+  i: longint;
+
+function CreateString: pString;
+begin
+    if i<>0 then
+      halt(1);
+    inc(i);
+    writeln('Creating a string');
+    new(result);
+end;
+
+begin
+    dispose(CreateString); // prints “Creating a string” twice
+    if i<>1 then
+      halt(2);
+end.