Ver Fonte

* ensure that a finalization section is parsed before the generation of specializations as otherwise specializations in such sections would result in unresolved forward declarations

git-svn-id: trunk@34582 -
svenbarth há 8 anos atrás
pai
commit
246de84ef3
3 ficheiros alterados com 68 adições e 21 exclusões
  1. 1 0
      .gitattributes
  2. 49 21
      compiler/pmodules.pas
  3. 18 0
      tests/test/tgeneric103.pp

+ 1 - 0
.gitattributes

@@ -12382,6 +12382,7 @@ tests/test/tgeneric10.pp svneol=native#text/plain
 tests/test/tgeneric100.pp svneol=native#text/pascal
 tests/test/tgeneric100.pp svneol=native#text/pascal
 tests/test/tgeneric101.pp svneol=native#text/pascal
 tests/test/tgeneric101.pp svneol=native#text/pascal
 tests/test/tgeneric102.pp svneol=native#text/pascal
 tests/test/tgeneric102.pp svneol=native#text/pascal
+tests/test/tgeneric103.pp svneol=native#text/pascal
 tests/test/tgeneric11.pp svneol=native#text/plain
 tests/test/tgeneric11.pp svneol=native#text/plain
 tests/test/tgeneric12.pp svneol=native#text/plain
 tests/test/tgeneric12.pp svneol=native#text/plain
 tests/test/tgeneric13.pp svneol=native#text/plain
 tests/test/tgeneric13.pp svneol=native#text/plain

+ 49 - 21
compiler/pmodules.pas

@@ -783,6 +783,7 @@ implementation
 type
 type
     tfinishstate=record
     tfinishstate=record
       init_procinfo:tcgprocinfo;
       init_procinfo:tcgprocinfo;
+      finalize_procinfo:tcgprocinfo;
     end;
     end;
     pfinishstate=^tfinishstate;
     pfinishstate=^tfinishstate;
 
 
@@ -792,6 +793,7 @@ type
       var
       var
          main_file: tinputfile;
          main_file: tinputfile;
          s1,s2  : ^string; {Saves stack space}
          s1,s2  : ^string; {Saves stack space}
+         finalize_procinfo,
          init_procinfo : tcgprocinfo;
          init_procinfo : tcgprocinfo;
          unitname : ansistring;
          unitname : ansistring;
          unitname8 : string[8];
          unitname8 : string[8];
@@ -803,6 +805,7 @@ type
          result:=true;
          result:=true;
 
 
          init_procinfo:=nil;
          init_procinfo:=nil;
+         finalize_procinfo:=nil;
 
 
          if m_mac in current_settings.modeswitches then
          if m_mac in current_settings.modeswitches then
            current_module.mode_switch_allowed:= false;
            current_module.mode_switch_allowed:= false;
@@ -1023,6 +1026,15 @@ type
              init_procinfo.parse_body;
              init_procinfo.parse_body;
              { save file pos for debuginfo }
              { save file pos for debuginfo }
              current_module.mainfilepos:=init_procinfo.entrypos;
              current_module.mainfilepos:=init_procinfo.entrypos;
+
+             { parse finalization section }
+             if token=_FINALIZATION then
+               begin
+                 { Compile the finalize }
+                 finalize_procinfo:=create_main_proc(make_mangledname('',current_module.localsymtable,'finalize'),potype_unitfinalize,current_module.localsymtable);
+                 finalize_procinfo.procdef.aliasnames.insert(make_mangledname('FINALIZE$',current_module.localsymtable,''));
+                 finalize_procinfo.parse_body;
+               end
            end;
            end;
 
 
          { remove all units that we are waiting for that are already waiting for
          { remove all units that we are waiting for that are already waiting for
@@ -1041,6 +1053,7 @@ type
          { save all information that is needed for finishing the unit }
          { save all information that is needed for finishing the unit }
          New(finishstate);
          New(finishstate);
          finishstate^.init_procinfo:=init_procinfo;
          finishstate^.init_procinfo:=init_procinfo;
+         finishstate^.finalize_procinfo:=finalize_procinfo;
          current_module.finishstate:=finishstate;
          current_module.finishstate:=finishstate;
 
 
          if result then
          if result then
@@ -1115,8 +1128,7 @@ type
            internalerror(2012091801);
            internalerror(2012091801);
          finishstate:=pfinishstate(current_module.finishstate)^;
          finishstate:=pfinishstate(current_module.finishstate)^;
 
 
-         finalize_procinfo:=nil;
-
+         finalize_procinfo:=finishstate.finalize_procinfo;
          init_procinfo:=finishstate.init_procinfo;
          init_procinfo:=finishstate.init_procinfo;
 
 
          { Generate specializations of objectdefs methods }
          { Generate specializations of objectdefs methods }
@@ -1158,16 +1170,20 @@ type
                end;
                end;
              init_procinfo:=gen_implicit_initfinal(uf_init,current_module.localsymtable);
              init_procinfo:=gen_implicit_initfinal(uf_init,current_module.localsymtable);
            end;
            end;
-         { finalize? }
-         if not current_module.interface_only and (token=_FINALIZATION) then
+         if (force_init_final or cnodeutils.force_final) and
+            (
+              not assigned(finalize_procinfo) or
+              has_no_code(finalize_procinfo.code)
+            ) then
            begin
            begin
-              { Compile the finalize }
-              finalize_procinfo:=create_main_proc(make_mangledname('',current_module.localsymtable,'finalize'),potype_unitfinalize,current_module.localsymtable);
-              finalize_procinfo.procdef.aliasnames.insert(make_mangledname('FINALIZE$',current_module.localsymtable,''));
-              finalize_procinfo.parse_body;
-           end
-         else if force_init_final or cnodeutils.force_final then
-           finalize_procinfo:=gen_implicit_initfinal(uf_finalize,current_module.localsymtable);
+             { first release the not used finalize procinfo }
+             if assigned(finalize_procinfo) then
+               begin
+                 release_proc_symbol(finalize_procinfo.procdef);
+                 release_main_proc(finalize_procinfo);
+               end;
+             finalize_procinfo:=gen_implicit_initfinal(uf_finalize,current_module.localsymtable);
+           end;
 
 
          { Now both init and finalize bodies are read and it is known
          { Now both init and finalize bodies are read and it is known
            which variables are used in both init and finalize we can now
            which variables are used in both init and finalize we can now
@@ -2079,6 +2095,16 @@ type
          { save file pos for debuginfo }
          { save file pos for debuginfo }
          current_module.mainfilepos:=main_procinfo.entrypos;
          current_module.mainfilepos:=main_procinfo.entrypos;
 
 
+         { finalize? }
+         if token=_FINALIZATION then
+           begin
+              { Parse the finalize }
+              finalize_procinfo:=create_main_proc(make_mangledname('',current_module.localsymtable,'finalize'),potype_unitfinalize,current_module.localsymtable);
+              finalize_procinfo.procdef.aliasnames.insert(make_mangledname('FINALIZE$',current_module.localsymtable,''));
+              finalize_procinfo.procdef.aliasnames.insert('PASCALFINALIZE');
+              finalize_procinfo.parse_body;
+           end;
+
          { Generate specializations of objectdefs methods }
          { Generate specializations of objectdefs methods }
          generate_specialization_procs;
          generate_specialization_procs;
 
 
@@ -2102,18 +2128,20 @@ type
             ((current_module.flags and uf_has_exports)<>0) then
             ((current_module.flags and uf_has_exports)<>0) then
            current_asmdata.asmlists[al_procedures].concat(tai_const.createname(make_mangledname('EDATA',current_module.localsymtable,''),0));
            current_asmdata.asmlists[al_procedures].concat(tai_const.createname(make_mangledname('EDATA',current_module.localsymtable,''),0));
 
 
-         { finalize? }
-         if token=_FINALIZATION then
+         if (force_init_final or cnodeutils.force_final) and
+            (
+              not assigned(finalize_procinfo)
+              or has_no_code(finalize_procinfo.code)
+            ) then
            begin
            begin
-              { Parse the finalize }
-              finalize_procinfo:=create_main_proc(make_mangledname('',current_module.localsymtable,'finalize'),potype_unitfinalize,current_module.localsymtable);
-              finalize_procinfo.procdef.aliasnames.insert(make_mangledname('FINALIZE$',current_module.localsymtable,''));
-              finalize_procinfo.procdef.aliasnames.insert('PASCALFINALIZE');
-              finalize_procinfo.parse_body;
-           end
-         else
-           if force_init_final or cnodeutils.force_final then
+             { first release the not used finalize procinfo }
+             if assigned(finalize_procinfo) then
+               begin
+                 release_proc_symbol(finalize_procinfo.procdef);
+                 release_main_proc(finalize_procinfo);
+               end;
              finalize_procinfo:=gen_implicit_initfinal(uf_finalize,current_module.localsymtable);
              finalize_procinfo:=gen_implicit_initfinal(uf_finalize,current_module.localsymtable);
+           end;
 
 
           { the finalization routine of libraries is generic (and all libraries need to }
           { the finalization routine of libraries is generic (and all libraries need to }
           { be finalized, so they can finalize any units they use                       }
           { be finalized, so they can finalize any units they use                       }

+ 18 - 0
tests/test/tgeneric103.pp

@@ -0,0 +1,18 @@
+unit tgeneric103;
+
+{$mode objfpc}{$H+}
+
+interface
+
+implementation
+
+generic procedure Test<T>(aArg: T);
+begin
+
+end;
+
+initialization
+finalization
+  specialize Test<LongInt>(42);
+end.
+