diff --git a/compiler/ncal.pas b/compiler/ncal.pas index 0723691e8c..edc709ebdb 100644 --- a/compiler/ncal.pas +++ b/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 .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 diff --git a/compiler/psub.pas b/compiler/psub.pas index d1f8c0638c..021cb471d1 100644 --- a/compiler/psub.pas +++ b/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