Browse Source

* correctly handle t*def.getreusable*() in case the original def was in
an exception symtable (then the new def cannot be safely made reusable,
as the exception symtable may be freed before the module is completely
compiled)

git-svn-id: trunk@32340 -

Jonas Maebe 9 years ago
parent
commit
46dfa1af30
2 changed files with 40 additions and 12 deletions
  1. 38 10
      compiler/symdef.pas
  2. 2 2
      compiler/symtype.pas

+ 38 - 10
compiler/symdef.pas

@@ -70,6 +70,14 @@ interface
           typesymderef  : tderef;
           procedure ppuwrite_platform(ppufile:tcompilerppufile);virtual;
           procedure ppuload_platform(ppufile:tcompilerppufile);virtual;
+          { a (possibly) reusable def is always created on the basis of another
+            def, and contains a reference to this other def. If this other
+            def is in a non-persistent symboltable, the new def cannot actually
+            be safely reused everywhere in the current module. This routine
+            abtracts that checking, and also restores the symtable stack
+            (which had to be reset before creating the new def, so that the new
+             def did not automatically get added to its top) }
+          class procedure setup_reusable_def(origdef, newdef: tdef; res: PHashSetItem; oldsymtablestack: tsymtablestack);
        public
 {$ifdef EXTDEBUG}
           fileinfo   : tfileposinfo;
@@ -1676,6 +1684,23 @@ implementation
       end;
 
 
+    class procedure tstoreddef.setup_reusable_def(origdef, newdef: tdef; res: PHashSetItem; oldsymtablestack: tsymtablestack);
+      var
+        reusablesymtab: tsymtable;
+      begin
+        { must not yet belong to a symtable }
+        if assigned(newdef.owner) then
+          internalerror(2015111503);
+        reusablesymtab:=origdef.getreusablesymtab;
+        { exception symtable are freed while compiling the current module
+          -> don't reuse }
+        if reusablesymtab.symtabletype<>stt_excepTSymtable then
+          res^.Data:=newdef;
+        reusablesymtab.insertdef(newdef);
+        symtablestack:=oldsymtablestack;
+      end;
+
+
     constructor tstoreddef.create(dt:tdeftyp;doregister:boolean);
       begin
          inherited create(dt);
@@ -3232,9 +3257,10 @@ implementation
             { do not simply push/pop current_module.localsymtable, because
               that can have side-effects (e.g., it removes helpers) }
             symtablestack:=nil;
-            res^.Data:=cpointerdef.create(def);
-            def.getreusablesymtab.insertdef(tdef(res^.Data));
-            symtablestack:=oldsymtablestack;
+            result:=cpointerdef.create(def);
+            setup_reusable_def(def,result,res,oldsymtablestack);
+            { res^.Data may still be nil -> don't overwrite result }
+            exit;
           end;
         result:=tpointerdef(res^.Data);
       end;
@@ -3556,10 +3582,11 @@ implementation
             { do not simply push/pop current_module.localsymtable, because
               that can have side-effects (e.g., it removes helpers) }
             symtablestack:=nil;
-            res^.Data:=carraydef.create(0,elems-1,ptrsinttype);
-            tarraydef(res^.Data).elementdef:=def;
-            def.getreusablesymtab.insertdef(tdef(res^.Data));
-            symtablestack:=oldsymtablestack;
+            result:=carraydef.create(0,elems-1,ptrsinttype);
+            result.elementdef:=def;
+            setup_reusable_def(def,result,res,oldsymtablestack);
+            { res^.Data may still be nil -> don't overwrite result }
+            exit;
           end;
         result:=tarraydef(res^.Data);
       end;
@@ -6109,9 +6136,10 @@ implementation
             { do not simply push/pop current_module.localsymtable, because
               that can have side-effects (e.g., it removes helpers) }
             symtablestack:=nil;
-            res^.Data:=def.getcopyas(procvardef,pc_address_only);
-            def.getreusablesymtab.insertdef(tdef(res^.Data));
-            symtablestack:=oldsymtablestack;
+            result:=tprocvardef(def.getcopyas(procvardef,pc_address_only));
+            setup_reusable_def(def,result,res,oldsymtablestack);
+            { res^.Data may still be nil -> don't overwrite result }
+            exit;
           end;
         result:=tprocvardef(res^.Data);
       end;

+ 2 - 2
compiler/symtype.pas

@@ -400,9 +400,9 @@ implementation
           won't be saved to the ppu and as a result we can get unreachable
           defs when reloading the derived ones from the ppu }
         origowner:=owner;
-        while not(origowner.symtabletype in [localsymtable,staticsymtable,globalsymtable]) do
+        while not(origowner.symtabletype in [localsymtable,staticsymtable,globalsymtable,stt_excepTSymtable]) do
           origowner:=origowner.defowner.owner;
-        if origowner.symtabletype=localsymtable then
+        if origowner.symtabletype in [stt_excepTSymtable,localsymtable] then
           result:=origowner
         else if assigned(current_module.localsymtable) then
           result:=current_module.localsymtable