Преглед изворни кода

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

peter пре 20 година
родитељ
комит
720815e13b
2 измењених фајлова са 122 додато и 53 уклоњено
  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
           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
+            if not is_class(tclassrefdef(methodpointer.resulttype.def).pointertype.def) then
+              internalerror(200501041);
+
             { 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
                 vmttree:=methodpointer.getcopy;
                 { Only a typenode can be passed when it is called with <class of xx>.create }
@@ -1251,33 +1232,102 @@ type
                   vmttree:=cloadvmtaddrnode.create(vmttree);
               end
             else
-              vmttree:=cpointerconstnode.create(0,voidpointertype);
+              begin
+                { Call afterconstruction }
+                vmttree:=cpointerconstnode.create(1,voidpointertype);
+              end;
           end
         else
-        { class }
+        { Class style objects }
          if is_class(methodpointer.resulttype.def) then
           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
-             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
         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;
       end;
 
@@ -2445,7 +2495,12 @@ begin
 end.
 {
   $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
      convert the calln to loadn
 

+ 20 - 6
compiler/psub.pas

@@ -272,11 +272,13 @@ implementation
                     if assigned(srsym) and
                        (srsym.typ=procsym) then
                       begin
-                        { if vmt<>0 then newinstance }
+                        { if vmt>1 then newinstance }
                         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(
                                 ctypeconvnode.create_internal(
                                     load_self_pointer_node,
@@ -1393,7 +1395,14 @@ implementation
                 begin
                   case idtoken of
                     _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:
                       begin
                         if (m_fpc in aktmodeswitches) then
@@ -1459,7 +1468,12 @@ implementation
 end.
 {
   $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
       so the used registers can't be reused when parameters are loaded
       into register variables