Browse Source

* when assigning a value to a temp marked as ti_const, do not immediately
release the source location in case it was also a temp. Reason: we
don't increase reference counts when assigning to a ti_const (they are
like const parameters), so the original value must stay alive until
the ti_const temp is freed
o free the original data in the ttempdelete node for the ti_const temp
o don't increase reference counts when assigning composite types to
ti_const temps either

git-svn-id: trunk@34287 -

Jonas Maebe 9 years ago
parent
commit
18580d3069
4 changed files with 23 additions and 2 deletions
  1. 6 1
      compiler/nbas.pas
  2. 13 0
      compiler/ncgbas.pas
  3. 3 1
      compiler/ncgld.pas
  4. 1 0
      compiler/nld.pas

+ 6 - 1
compiler/nbas.pas

@@ -153,7 +153,12 @@ interface
          }
          }
          ti_nofini,
          ti_nofini,
          { the value described by this temp. node is const/immutable, this is important for
          { the value described by this temp. node is const/immutable, this is important for
-           managed types like ansistrings where temp. refs are pointers to the actual value }
+           managed types like ansistrings where temp. refs are pointers to the actual value
+           -- in this case, assignments to the temp do not increase the
+             reference count, and if the assigned value was a temp itself then
+             that temp is not deallocated until this temp is deleted (since
+             otherwise the assigned value may be freed before the last use of
+             the temp) }
          ti_const
          ti_const
          );
          );
        ttempinfoflags = set of ttempinfoflag;
        ttempinfoflags = set of ttempinfoflag;

+ 13 - 0
compiler/ncgbas.pas

@@ -540,6 +540,19 @@ interface
 
 
         location_reset(location,LOC_VOID,OS_NO);
         location_reset(location,LOC_VOID,OS_NO);
 
 
+        { see comments at ti_const declaration: if we initialised this temp with
+          the value of another temp, that other temp was not freed because the
+          ti_const flag was set }
+        if (ti_const in tempinfo^.flags) and
+           assigned(tempinfo^.tempinitcode) then
+          begin
+            if tempinfo^.tempinitcode.nodetype<>assignn then
+              internalerror(2016081201);
+            if tbinarynode(tempinfo^.tempinitcode).right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
+              tg.ungetiftemp(current_asmdata.CurrAsmList,tbinarynode(tempinfo^.tempinitcode).right.location.reference);
+          end;
+
+
         case tempinfo^.location.loc of
         case tempinfo^.location.loc of
           LOC_REFERENCE:
           LOC_REFERENCE:
             begin
             begin

+ 3 - 1
compiler/ncgld.pas

@@ -703,7 +703,9 @@ implementation
              exit;
              exit;
          end;
          end;
 
 
-        releaseright:=true;
+        releaseright:=
+          (left.nodetype<>temprefn) or
+          not(ti_const in ttemprefnode(left).tempinfo^.flags);
 
 
         { shortstring assignments are handled separately }
         { shortstring assignments are handled separately }
         if is_shortstring(left.resultdef) then
         if is_shortstring(left.resultdef) then

+ 1 - 0
compiler/nld.pas

@@ -809,6 +809,7 @@ implementation
             (left.resultdef.typ in [arraydef,objectdef,recorddef]) and
             (left.resultdef.typ in [arraydef,objectdef,recorddef]) and
             not is_interfacecom_or_dispinterface(left.resultdef) and
             not is_interfacecom_or_dispinterface(left.resultdef) and
             not is_dynamic_array(left.resultdef) and
             not is_dynamic_array(left.resultdef) and
+            not is_const(left) and
             not(target_info.system in systems_garbage_collected_managed_types) then
             not(target_info.system in systems_garbage_collected_managed_types) then
          begin
          begin
            hp:=ccallparanode.create(caddrnode.create_internal(
            hp:=ccallparanode.create(caddrnode.create_internal(