Browse Source

* fix aftercosntruction calls, vmt=1 is used to indicate that
afterconstruction needs to be called
* only accept resourcestring when objpas is loaded

peter 20 years ago
parent
commit
720815e13b
2 changed files with 122 additions and 53 deletions
  1. 102 47
      compiler/ncal.pas
  2. 20 6
      compiler/psub.pas

+ 102 - 47
compiler/ncal.pas

@@ -1216,34 +1216,15 @@ type
         if not(procdefinition.proctypeoption in [potype_constructor,potype_destructor]) then
         if not(procdefinition.proctypeoption in [potype_constructor,potype_destructor]) then
           internalerror(200305051);
           internalerror(200305051);
 
 
-        { inherited call, no create/destroy }
-        if (cnf_inherited in callnodeflags) then
-          vmttree:=cpointerconstnode.create(0,voidpointertype)
-        else
-          { do not create/destroy when called from member function
-            without specifying self explicit }
-          if (cnf_member_call in callnodeflags) then
-            begin
-              if (methodpointer.resulttype.def.deftype=classrefdef) and
-                (procdefinition.proctypeoption=potype_constructor) then
-                vmttree:=methodpointer.getcopy
-              else
-                vmttree:=cpointerconstnode.create(0,voidpointertype);
-            end
-        else
-          { constructor with extended syntax called from new }
-          if (cnf_new_call in callnodeflags) then
-            vmttree:=cloadvmtaddrnode.create(ctypenode.create(methodpointer.resulttype))
-        else
-          { destructor with extended syntax called from dispose }
-          if (cnf_dispose_call in callnodeflags) then
-            vmttree:=cloadvmtaddrnode.create(methodpointer.getcopy)
-        else
-         if (methodpointer.resulttype.def.deftype=classrefdef) then
+        { Handle classes and legacy objects separate to make it
+          more maintainable }
+        if (methodpointer.resulttype.def.deftype=classrefdef) then
           begin
           begin
+            if not is_class(tclassrefdef(methodpointer.resulttype.def).pointertype.def) then
+              internalerror(200501041);
+
             { constructor call via classreference => allocate memory }
             { constructor call via classreference => allocate memory }
-            if (procdefinition.proctypeoption=potype_constructor) and
-               is_class(tclassrefdef(methodpointer.resulttype.def).pointertype.def) then
+            if (procdefinition.proctypeoption=potype_constructor) then
               begin
               begin
                 vmttree:=methodpointer.getcopy;
                 vmttree:=methodpointer.getcopy;
                 { Only a typenode can be passed when it is called with <class of xx>.create }
                 { Only a typenode can be passed when it is called with <class of xx>.create }
@@ -1251,33 +1232,102 @@ type
                   vmttree:=cloadvmtaddrnode.create(vmttree);
                   vmttree:=cloadvmtaddrnode.create(vmttree);
               end
               end
             else
             else
-              vmttree:=cpointerconstnode.create(0,voidpointertype);
+              begin
+                { Call afterconstruction }
+                vmttree:=cpointerconstnode.create(1,voidpointertype);
+              end;
           end
           end
         else
         else
-        { class }
+        { Class style objects }
          if is_class(methodpointer.resulttype.def) then
          if is_class(methodpointer.resulttype.def) then
           begin
           begin
-            { destructor: release instance, flag(vmt)=1
-              constructor: direct call, do nothing, leave vmt=0 }
-            if (procdefinition.proctypeoption=potype_destructor) then
-             vmttree:=cpointerconstnode.create(1,voidpointertype)
+            { inherited call, no create/destroy }
+            if (cnf_inherited in callnodeflags) then
+              vmttree:=cpointerconstnode.create(0,voidpointertype)
             else
             else
-             vmttree:=cpointerconstnode.create(0,voidpointertype);
+              { do not create/destroy when called from member function
+                without specifying self explicit }
+              if (cnf_member_call in callnodeflags) then
+                begin
+                  { destructor: don't release instance, vmt=0
+                    constructor:
+                      if called from a constructor in the same class then
+                        don't call afterconstruction, vmt=0
+                      else
+                        call afterconstrution, vmt=1 }
+                  if (procdefinition.proctypeoption=potype_destructor) then
+                    vmttree:=cpointerconstnode.create(0,voidpointertype)
+                  else
+                    begin
+                      if (current_procinfo.procdef.proctypeoption=potype_constructor) and
+                         (procdefinition.proctypeoption=potype_constructor) then
+                        vmttree:=cpointerconstnode.create(0,voidpointertype)
+                      else
+                        vmttree:=cpointerconstnode.create(1,voidpointertype);
+                    end;
+                end
+            else
+            { normal call to method like cl1.proc }
+              begin
+                { destructor: release instance, vmt=1
+                  constructor:
+                    if called from a constructor in the same class using self.create then
+                      don't call afterconstruction, vmt=0
+                    else
+                      call afterconstrution, vmt=1 }
+                if (procdefinition.proctypeoption=potype_destructor) then
+                  vmttree:=cpointerconstnode.create(1,voidpointertype)
+                else
+                  begin
+                    if (current_procinfo.procdef.proctypeoption=potype_constructor) and
+                       (procdefinition.proctypeoption=potype_constructor) and
+                       (nf_is_self in methodpointer.flags) then
+                      vmttree:=cpointerconstnode.create(0,voidpointertype)
+                    else
+                      vmttree:=cpointerconstnode.create(1,voidpointertype);
+                  end;
+              end;
           end
           end
         else
         else
-        { object }
-         begin
-           { destructor: direct call, no dispose, vmt=0
-             constructor: initialize object, load vmt }
-           if (procdefinition.proctypeoption=potype_constructor) then
-             { old styled inherited call? }
-             if (methodpointer.nodetype=typen) then
-               vmttree:=cpointerconstnode.create(0,voidpointertype)
-             else
-               vmttree:=cloadvmtaddrnode.create(ctypenode.create(methodpointer.resulttype))
-           else
-             vmttree:=cpointerconstnode.create(0,voidpointertype);
-         end;
+        { Old style object }
+          begin
+            { constructor with extended syntax called from new }
+            if (cnf_new_call in callnodeflags) then
+                vmttree:=cloadvmtaddrnode.create(ctypenode.create(methodpointer.resulttype))
+            else
+              { destructor with extended syntax called from dispose }
+              if (cnf_dispose_call in callnodeflags) then
+                vmttree:=cloadvmtaddrnode.create(methodpointer.getcopy)
+            else
+              { inherited call, no create/destroy }
+              if (cnf_inherited in callnodeflags) then
+                vmttree:=cpointerconstnode.create(0,voidpointertype)
+            else
+              { do not create/destroy when called from member function
+                without specifying self explicit }
+              if (cnf_member_call in callnodeflags) then
+                begin
+                  { destructor: don't release instance, vmt=0
+                    constructor: don't initialize instance, vmt=0 }
+                  vmttree:=cpointerconstnode.create(0,voidpointertype)
+                end
+            else
+            { normal object call like obj.proc }
+             begin
+               { destructor: direct call, no dispose, vmt=0
+                 constructor: initialize object, load vmt }
+               if (procdefinition.proctypeoption=potype_constructor) then
+                 begin
+                   { old styled inherited call? }
+                   if (methodpointer.nodetype=typen) then
+                     vmttree:=cpointerconstnode.create(0,voidpointertype)
+                   else
+                     vmttree:=cloadvmtaddrnode.create(ctypenode.create(methodpointer.resulttype))
+                 end
+               else
+                 vmttree:=cpointerconstnode.create(0,voidpointertype);
+             end;
+          end;
         result:=vmttree;
         result:=vmttree;
       end;
       end;
 
 
@@ -2445,7 +2495,12 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.274  2005-01-02 16:58:48  peter
+  Revision 1.275  2005-01-04 16:36:31  peter
+    * fix aftercosntruction calls, vmt=1 is used to indicate that
+      afterconstruction needs to be called
+    * only accept resourcestring when objpas is loaded
+
+  Revision 1.274  2005/01/02 16:58:48  peter
     * Don't release methodpointer. It is maybe still needed when we need to
     * Don't release methodpointer. It is maybe still needed when we need to
      convert the calln to loadn
      convert the calln to loadn
 
 

+ 20 - 6
compiler/psub.pas

@@ -272,11 +272,13 @@ implementation
                     if assigned(srsym) and
                     if assigned(srsym) and
                        (srsym.typ=procsym) then
                        (srsym.typ=procsym) then
                       begin
                       begin
-                        { if vmt<>0 then newinstance }
+                        { if vmt>1 then newinstance }
                         addstatement(newstatement,cifnode.create(
                         addstatement(newstatement,cifnode.create(
-                            caddnode.create(unequaln,
-                                load_vmt_pointer_node,
-                                cnilnode.create),
+                            caddnode.create(gtn,
+                                ctypeconvnode.create_internal(
+                                    load_vmt_pointer_node,
+                                    voidpointertype),
+                                cpointerconstnode.create(1,voidpointertype)),
                             cassignmentnode.create(
                             cassignmentnode.create(
                                 ctypeconvnode.create_internal(
                                 ctypeconvnode.create_internal(
                                     load_self_pointer_node,
                                     load_self_pointer_node,
@@ -1393,7 +1395,14 @@ implementation
                 begin
                 begin
                   case idtoken of
                   case idtoken of
                     _RESOURCESTRING :
                     _RESOURCESTRING :
-                      resourcestring_dec;
+                      begin
+                        { m_class is needed, because the resourcestring
+                          loading is in the ObjPas unit }
+                        if (m_class in aktmodeswitches) then
+                          resourcestring_dec
+                        else
+                          break;
+                      end;
                     _PROPERTY:
                     _PROPERTY:
                       begin
                       begin
                         if (m_fpc in aktmodeswitches) then
                         if (m_fpc in aktmodeswitches) then
@@ -1459,7 +1468,12 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.228  2005-01-03 22:27:56  peter
+  Revision 1.229  2005-01-04 16:36:31  peter
+    * fix aftercosntruction calls, vmt=1 is used to indicate that
+      afterconstruction needs to be called
+    * only accept resourcestring when objpas is loaded
+
+  Revision 1.228  2005/01/03 22:27:56  peter
     * insert stack_check helper call before doing register allocation
     * insert stack_check helper call before doing register allocation
       so the used registers can't be reused when parameters are loaded
       so the used registers can't be reused when parameters are loaded
       into register variables
       into register variables