Browse Source

* an exception in a construcor calls now the destructor (this applies only
to classes)

florian 25 years ago
parent
commit
a0cc4f970b
5 changed files with 135 additions and 39 deletions
  1. 33 10
      compiler/cg386cal.pas
  2. 34 22
      compiler/cgai386.pas
  3. 7 3
      compiler/psub.pas
  4. 52 1
      compiler/symdef.inc
  5. 9 3
      compiler/symdefh.inc

+ 33 - 10
compiler/cg386cal.pas

@@ -551,7 +551,7 @@ implementation
                                       emit_reg(A_PUSH,S_L,R_ESI);
                                       emit_reg(A_PUSH,S_L,R_ESI);
                                     { if an inherited con- or destructor should be  }
                                     { if an inherited con- or destructor should be  }
                                     { called in a con- or destructor then a warning }
                                     { called in a con- or destructor then a warning }
-                                    { will be made                                }
+                                    { will be made                                  }
                                     { con- and destructors need a pointer to the vmt }
                                     { con- and destructors need a pointer to the vmt }
                                     if is_con_or_destructor and
                                     if is_con_or_destructor and
                                     not(pobjectdef(p^.methodpointer^.resulttype)^.is_class) and
                                     not(pobjectdef(p^.methodpointer^.resulttype)^.is_class) and
@@ -561,12 +561,18 @@ implementation
                                                 [potype_constructor,potype_destructor]) then
                                                 [potype_constructor,potype_destructor]) then
                                           CGMessage(cg_w_member_cd_call_from_method);
                                           CGMessage(cg_w_member_cd_call_from_method);
                                       end;
                                       end;
-                                    { class destructors get there flag below }
+                                    { class destructors get there flag above }
+                                    { constructor flags ?                    }
                                     if is_con_or_destructor and
                                     if is_con_or_destructor and
                                         not(pobjectdef(p^.methodpointer^.resulttype)^.is_class and
                                         not(pobjectdef(p^.methodpointer^.resulttype)^.is_class and
                                         assigned(aktprocsym) and
                                         assigned(aktprocsym) and
                                         (aktprocsym^.definition^.proctypeoption=potype_destructor)) then
                                         (aktprocsym^.definition^.proctypeoption=potype_destructor)) then
-                                       push_int(0);
+                                      begin
+                                         { a constructor needs also a flag }
+                                         if pobjectdef(p^.methodpointer^.resulttype)^.is_class then
+                                           push_int(0);
+                                         push_int(0);
+                                      end;
                                  end;
                                  end;
                                hnewn:
                                hnewn:
                                  begin
                                  begin
@@ -643,7 +649,7 @@ implementation
                                              emit_ref_reg(A_MOV,S_L,r,R_ESI);
                                              emit_ref_reg(A_MOV,S_L,r,R_ESI);
                                           end;
                                           end;
 
 
-                                        { direct call to destructor: don't remove data! }
+                                        { direct call to destructor: remove data }
                                         if (p^.procdefinition^.proctypeoption=potype_destructor) and
                                         if (p^.procdefinition^.proctypeoption=potype_destructor) and
                                            (p^.methodpointer^.resulttype^.deftype=objectdef) and
                                            (p^.methodpointer^.resulttype^.deftype=objectdef) and
                                            (pobjectdef(p^.methodpointer^.resulttype)^.is_class) then
                                            (pobjectdef(p^.methodpointer^.resulttype)^.is_class) then
@@ -653,9 +659,19 @@ implementation
                                         if (p^.procdefinition^.proctypeoption=potype_constructor) and
                                         if (p^.procdefinition^.proctypeoption=potype_constructor) and
                                            (p^.methodpointer^.resulttype^.deftype=objectdef) and
                                            (p^.methodpointer^.resulttype^.deftype=objectdef) and
                                            (pobjectdef(p^.methodpointer^.resulttype)^.is_class) then
                                            (pobjectdef(p^.methodpointer^.resulttype)^.is_class) then
-                                          emit_const(A_PUSH,S_L,0)
+                                          begin
+                                             emit_const(A_PUSH,S_L,0);
+                                             emit_const(A_PUSH,S_L,0);
+                                          end
                                         else
                                         else
-                                          emit_reg(A_PUSH,S_L,R_ESI);
+                                          begin
+                                             { constructor call via classreference => allocate memory }
+                                             if (p^.procdefinition^.proctypeoption=potype_constructor) and
+                                                (p^.methodpointer^.resulttype^.deftype=classrefdef) and
+                                                (pobjectdef(pclassrefdef(p^.methodpointer^.resulttype)^.pointertype.def)^.is_class) then
+                                                emit_const(A_PUSH,S_L,1);
+                                             emit_reg(A_PUSH,S_L,R_ESI);
+                                          end;
                                       end;
                                       end;
 
 
                                     if is_con_or_destructor then
                                     if is_con_or_destructor then
@@ -671,7 +687,7 @@ implementation
                                                      pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname));
                                                      pobjectdef(p^.methodpointer^.resulttype)^.vmt_mangledname));
                                                 end
                                                 end
                                               { destructors haven't to dispose the instance, if this is }
                                               { destructors haven't to dispose the instance, if this is }
-                                              { a direct call                                      }
+                                              { a direct call                                           }
                                               else
                                               else
                                                 push_int(0);
                                                 push_int(0);
                                            end;
                                            end;
@@ -709,7 +725,10 @@ implementation
                                   emit_reg(A_PUSH,S_L,R_ESI);
                                   emit_reg(A_PUSH,S_L,R_ESI);
                                end
                                end
                              else if (p^.procdefinition^.proctypeoption=potype_constructor) then
                              else if (p^.procdefinition^.proctypeoption=potype_constructor) then
-                               emit_const(A_PUSH,S_L,0)
+                               begin
+                                  emit_const(A_PUSH,S_L,0);
+                                  emit_const(A_PUSH,S_L,0);
+                               end
                              else
                              else
                                emit_reg(A_PUSH,S_L,R_ESI);
                                emit_reg(A_PUSH,S_L,R_ESI);
                           end
                           end
@@ -1332,7 +1351,11 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.123  2000-01-26 15:03:59  peter
+  Revision 1.124  2000-02-04 20:00:21  florian
+    * an exception in a construcor calls now the destructor (this applies only
+      to classes)
+
+  Revision 1.123  2000/01/26 15:03:59  peter
     * fixed pop_size included twice with clearstack
     * fixed pop_size included twice with clearstack
 
 
   Revision 1.122  2000/01/26 12:02:29  peter
   Revision 1.122  2000/01/26 12:02:29  peter
@@ -1465,4 +1488,4 @@ end.
   Revision 1.90.2.3  1999/06/22 13:30:08  peter
   Revision 1.90.2.3  1999/06/22 13:30:08  peter
     * fixed return with packenum
     * fixed return with packenum
 
 
-}
+}

+ 34 - 22
compiler/cgai386.pas

@@ -3089,9 +3089,9 @@ procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
       { a constructor needs a help procedure }
       { a constructor needs a help procedure }
       if (aktprocsym^.definition^.proctypeoption=potype_constructor) then
       if (aktprocsym^.definition^.proctypeoption=potype_constructor) then
         begin
         begin
-          {!!!! not yet procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;}
           if procinfo^._class^.is_class then
           if procinfo^._class^.is_class then
             begin
             begin
+              procinfo^.flags:=procinfo^.flags or pi_needs_implicit_finally;
               exprasmlist^.insert(new(paicpu,op_cond_sym(A_Jcc,C_Z,S_NO,faillabel)));
               exprasmlist^.insert(new(paicpu,op_cond_sym(A_Jcc,C_Z,S_NO,faillabel)));
               emitinsertcall('FPC_NEW_CLASS');
               emitinsertcall('FPC_NEW_CLASS');
             end
             end
@@ -3404,12 +3404,11 @@ procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
        mangled_length : longint;
        mangled_length : longint;
        p : pchar;
        p : pchar;
 {$endif GDB}
 {$endif GDB}
-       nofinal,okexitlabel,noreraiselabel : pasmlabel;
+       nofinal,okexitlabel,noreraiselabel,nodestroycall : pasmlabel;
        hr : treference;
        hr : treference;
        oldexprasmlist : paasmoutput;
        oldexprasmlist : paasmoutput;
        ai : paicpu;
        ai : paicpu;
        pd : pprocdef;
        pd : pprocdef;
-       r : preference;
 
 
   begin
   begin
       oldexprasmlist:=exprasmlist;
       oldexprasmlist:=exprasmlist;
@@ -3477,30 +3476,39 @@ procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
            emitjmp(C_E,noreraiselabel);
            emitjmp(C_E,noreraiselabel);
            if (aktprocsym^.definition^.proctypeoption=potype_constructor) then
            if (aktprocsym^.definition^.proctypeoption=potype_constructor) then
              begin
              begin
-                {
                 if assigned(procinfo^._class) then
                 if assigned(procinfo^._class) then
                   begin
                   begin
                      pd:=procinfo^._class^.searchdestructor;
                      pd:=procinfo^._class^.searchdestructor;
-                     if procinfo^._class^.is_class then
-                       begin
-                          emit_const(A_PUSH,S_L,1);
-                          emit_reg(A_PUSH,S_L,R_ESI);
-                       end
-                     else
-                       begin
-                          emit_reg(A_PUSH,S_L,R_ESI);
-                          emit_sym(A_PUSH,S_L,newasmsymbol(procinfo._class^.vmt_mangledname);
-                       end;
-                     if (po_virtualmethod in pd^.procoptions) then
-                       begin
-                          emit_ref_reg(A_MOV,S_L,ref,R_EDI)
-                          emit_ref(A_CALL,S_NO,ref);
-                       end
-                     else
+                     if assigned(pd) then
                        begin
                        begin
+                          getlabel(nodestroycall);
+                          emit_const_ref(A_CMP,S_L,0,new_reference(procinfo^.framepointer,
+                            procinfo^.selfpointer_offset));
+                          emitjmp(C_E,nodestroycall);
+                          if procinfo^._class^.is_class then
+                            begin
+                               emit_const(A_PUSH,S_L,1);
+                               emit_reg(A_PUSH,S_L,R_ESI);
+                            end
+                          else
+                            begin
+                               emit_reg(A_PUSH,S_L,R_ESI);
+                               emit_sym(A_PUSH,S_L,newasmsymbol(procinfo^._class^.vmt_mangledname));
+                            end;
+                          if (po_virtualmethod in pd^.procoptions) then
+                            begin
+                               emit_ref_reg(A_MOV,S_L,new_reference(R_ESI,0),R_EDI);
+                               emit_ref(A_CALL,S_NO,new_reference(R_EDI,procinfo^._class^.vmtmethodoffset(pd^.extnumber)));
+                            end
+                          else
+                            emitcall(pd^.mangledname);
+                          { not necessary because the result is never assigned in the
+                            case of an exception (FK) }
+                          emit_const_reg(A_MOV,S_L,0,R_ESI);
+                          emit_const_ref(A_MOV,S_L,0,new_reference(procinfo^.framepointer,8));
+                          emitlab(nodestroycall);
                        end;
                        end;
                   end
                   end
-                }
              end
              end
            else
            else
            { must be the return value finalized before reraising the exception? }
            { must be the return value finalized before reraising the exception? }
@@ -3724,7 +3732,11 @@ procedure mov_reg_to_dest(p : ptree; s : topsize; reg : tregister);
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.76  2000-02-04 14:29:57  pierre
+  Revision 1.77  2000-02-04 20:00:21  florian
+    * an exception in a construcor calls now the destructor (this applies only
+      to classes)
+
+  Revision 1.76  2000/02/04 14:29:57  pierre
    + add pseudo local var parent_ebp for local procs
    + add pseudo local var parent_ebp for local procs
 
 
   Revision 1.75  2000/01/25 08:46:03  pierre
   Revision 1.75  2000/01/25 08:46:03  pierre

+ 7 - 3
compiler/psub.pas

@@ -310,10 +310,10 @@ begin
         inc(paramoffset,target_os.size_of_pointer);
         inc(paramoffset,target_os.size_of_pointer);
     end;
     end;
 
 
-  { destructor flag ? }
+  { con/-destructor flag ? }
   if assigned (procinfo^._Class) and
   if assigned (procinfo^._Class) and
      procinfo^._class^.is_class and
      procinfo^._class^.is_class and
-     (pd^.proctypeoption=potype_destructor) then
+     (pd^.proctypeoption in [potype_destructor,potype_constructor]) then
     inc(paramoffset,target_os.size_of_pointer);
     inc(paramoffset,target_os.size_of_pointer);
 
 
   procinfo^.para_offset:=paramoffset;
   procinfo^.para_offset:=paramoffset;
@@ -1969,7 +1969,11 @@ end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.45  2000-02-04 14:54:17  jonas
+  Revision 1.46  2000-02-04 20:00:22  florian
+    * an exception in a construcor calls now the destructor (this applies only
+      to classes)
+
+  Revision 1.45  2000/02/04 14:54:17  jonas
     * moved call to resetusableregs to compile_proc_body (put it right before the
     * moved call to resetusableregs to compile_proc_body (put it right before the
       reset of the temp generator) so the optimizer can know which registers are
       reset of the temp generator) so the optimizer can know which registers are
       regvars
       regvars

+ 52 - 1
compiler/symdef.inc

@@ -3342,6 +3342,53 @@ Const local_symtable_index : longint = $8001;
         is_related:=false;
         is_related:=false;
      end;
      end;
 
 
+   var
+      sd : pprocdef;
+
+   procedure _searchdestructor(sym : pnamedindexobject);{$ifndef fpc}far;{$endif}
+
+     var
+        p : pprocdef;
+
+     begin
+        { if we found already a destructor, then we exit }
+        if assigned(sd) then
+          exit;
+        if psym(sym)^.typ=procsym then
+          begin
+             p:=pprocsym(sym)^.definition;
+             while assigned(p) do
+               begin
+                  if p^.proctypeoption=potype_destructor then
+                    begin
+                       sd:=p;
+                       exit;
+                    end;
+                  p:=p^.nextoverloaded;
+               end;
+          end;
+     end;
+
+   function tobjectdef.searchdestructor : pprocdef;
+
+     var
+        o : pobjectdef;
+
+     begin
+        searchdestructor:=nil;
+        o:=@self;
+        sd:=nil;
+        while assigned(o) do
+          begin
+             symtable^.foreach({$ifndef TP}@{$endif}_searchdestructor);
+             if assigned(sd) then
+               begin
+                  searchdestructor:=sd;
+                  exit;
+               end;
+             o:=o^.childof;
+          end;
+     end;
 
 
     function tobjectdef.size : longint;
     function tobjectdef.size : longint;
       begin
       begin
@@ -3868,7 +3915,11 @@ Const local_symtable_index : longint = $8001;
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.191  2000-01-30 23:29:06  peter
+  Revision 1.192  2000-02-04 20:00:22  florian
+    * an exception in a construcor calls now the destructor (this applies only
+      to classes)
+
+  Revision 1.191  2000/01/30 23:29:06  peter
     * fixed dup rtti writing for classes
     * fixed dup rtti writing for classes
 
 
   Revision 1.190  2000/01/28 23:17:53  florian
   Revision 1.190  2000/01/28 23:17:53  florian

+ 9 - 3
compiler/symdefh.inc

@@ -174,6 +174,8 @@
 {$endif GDB}
 {$endif GDB}
        end;
        end;
 
 
+       pprocdef = ^tprocdef;
+
        pobjectdef = ^tobjectdef;
        pobjectdef = ^tobjectdef;
        tobjectdef = object(tdef)
        tobjectdef = object(tdef)
           childof  : pobjectdef;
           childof  : pobjectdef;
@@ -200,6 +202,7 @@
           function  next_free_name_index : longint;
           function  next_free_name_index : longint;
           procedure insertvmt;
           procedure insertvmt;
           procedure set_parent(c : pobjectdef);
           procedure set_parent(c : pobjectdef);
+          function searchdestructor : pprocdef;
           { debug }
           { debug }
 {$ifdef GDB}
 {$ifdef GDB}
           function stabstring : pchar;virtual;
           function stabstring : pchar;virtual;
@@ -381,7 +384,6 @@
            1 : (i : longint);
            1 : (i : longint);
        end;
        end;
 
 
-       pprocdef = ^tprocdef;
        tprocdef = object(tabstractprocdef)
        tprocdef = object(tabstractprocdef)
        private
        private
           _mangledname : pchar;
           _mangledname : pchar;
@@ -528,7 +530,11 @@
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.51  2000-01-26 12:02:30  peter
+  Revision 1.52  2000-02-04 20:00:22  florian
+    * an exception in a construcor calls now the destructor (this applies only
+      to classes)
+
+  Revision 1.51  2000/01/26 12:02:30  peter
     * abstractprocdef.para_size needs alignment parameter
     * abstractprocdef.para_size needs alignment parameter
     * secondcallparan gets para_alignment size instead of dword_align
     * secondcallparan gets para_alignment size instead of dword_align
 
 
@@ -646,4 +652,4 @@
       position info
       position info
     * Removed comp warnings
     * Removed comp warnings
 
 
-}
+}