浏览代码

* 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 8 年之前
父节点
当前提交
246de84ef3
共有 3 个文件被更改,包括 68 次插入21 次删除
  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/tgeneric101.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/tgeneric12.pp svneol=native#text/plain
 tests/test/tgeneric13.pp svneol=native#text/plain

+ 49 - 21
compiler/pmodules.pas

@@ -783,6 +783,7 @@ implementation
 type
     tfinishstate=record
       init_procinfo:tcgprocinfo;
+      finalize_procinfo:tcgprocinfo;
     end;
     pfinishstate=^tfinishstate;
 
@@ -792,6 +793,7 @@ type
       var
          main_file: tinputfile;
          s1,s2  : ^string; {Saves stack space}
+         finalize_procinfo,
          init_procinfo : tcgprocinfo;
          unitname : ansistring;
          unitname8 : string[8];
@@ -803,6 +805,7 @@ type
          result:=true;
 
          init_procinfo:=nil;
+         finalize_procinfo:=nil;
 
          if m_mac in current_settings.modeswitches then
            current_module.mode_switch_allowed:= false;
@@ -1023,6 +1026,15 @@ type
              init_procinfo.parse_body;
              { save file pos for debuginfo }
              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;
 
          { 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 }
          New(finishstate);
          finishstate^.init_procinfo:=init_procinfo;
+         finishstate^.finalize_procinfo:=finalize_procinfo;
          current_module.finishstate:=finishstate;
 
          if result then
@@ -1115,8 +1128,7 @@ type
            internalerror(2012091801);
          finishstate:=pfinishstate(current_module.finishstate)^;
 
-         finalize_procinfo:=nil;
-
+         finalize_procinfo:=finishstate.finalize_procinfo;
          init_procinfo:=finishstate.init_procinfo;
 
          { Generate specializations of objectdefs methods }
@@ -1158,16 +1170,20 @@ type
                end;
              init_procinfo:=gen_implicit_initfinal(uf_init,current_module.localsymtable);
            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
-              { 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
            which variables are used in both init and finalize we can now
@@ -2079,6 +2095,16 @@ type
          { save file pos for debuginfo }
          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_specialization_procs;
 
@@ -2102,18 +2128,20 @@ type
             ((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));
 
-         { 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
-              { 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);
+           end;
 
           { the finalization routine of libraries is generic (and all libraries need to }
           { 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.
+