Browse Source

* tp procvar handling fix for tb0448

peter 22 years ago
parent
commit
23861a4e45
1 changed files with 81 additions and 70 deletions
  1. 81 70
      compiler/pexpr.pas

+ 81 - 70
compiler/pexpr.pas

@@ -643,6 +643,23 @@ implementation
       begin
       begin
          prevafterassn:=afterassignment;
          prevafterassn:=afterassignment;
          afterassignment:=false;
          afterassignment:=false;
+         aprocdef:=nil;
+
+         { When we are expecting a procvar we also need
+           to get the address in some cases }
+         if assigned(getprocvardef) then
+          begin
+            if (block_type=bt_const) then
+             getaddr:=true
+            else
+             if (m_tp_procvar in aktmodeswitches) then
+              begin
+                aprocdef:=Tprocsym(sym).search_procdef_byprocvardef(getprocvardef);
+                if assigned(aprocdef) then
+                 getaddr:=true;
+              end;
+          end;
+
          { want we only determine the address of }
          { want we only determine the address of }
          { a subroutine ?                       }
          { a subroutine ?                       }
          if not(getaddr) then
          if not(getaddr) then
@@ -681,33 +698,35 @@ implementation
                  end;
                  end;
               end;
               end;
              p1:=ccallnode.create(para,tprocsym(sym),st,p1);
              p1:=ccallnode.create(para,tprocsym(sym),st,p1);
-             include(p1.flags,nf_auto_inherited);
            end
            end
         else
         else
            begin
            begin
               { address operator @: }
               { address operator @: }
               if not assigned(p1) then
               if not assigned(p1) then
                begin
                begin
-                 if (st.symtabletype=withsymtable) and
-                    (st.defowner.deftype=objectdef) then
-                   begin
-                     p1:=tnode(twithsymtable(st).withrefnode).getcopy;
-                   end
-                 else
-                   begin
-                      { we must provide a method pointer, if it isn't given, }
-                      { it is self                                           }
-                      if (st.symtabletype=objectsymtable) then
+                 case st.symtabletype of
+                   withsymtable :
+                     begin
+                       if (st.defowner.deftype=objectdef) then
+                         p1:=tnode(twithsymtable(st).withrefnode).getcopy;
+                     end;
+                   objectsymtable :
+                     begin
+                       { we must provide a method pointer, if it isn't given, }
+                       { it is self                                           }
                        p1:=cselfnode.create(tobjectdef(st.defowner));
                        p1:=cselfnode.create(tobjectdef(st.defowner));
-                   end;
+                     end;
+                 end;
                end;
                end;
 
 
+               { Retrieve info which procvar to call. For tp_procvar the
+                 aprocdef is already loaded above so we can reuse it }
+              if not assigned(aprocdef) and
+                 assigned(getprocvardef) then
+                aprocdef:=Tprocsym(sym).search_procdef_byprocvardef(getprocvardef);
+
               { generate a methodcallnode or proccallnode }
               { generate a methodcallnode or proccallnode }
               { we shouldn't convert things like @tcollection.load }
               { we shouldn't convert things like @tcollection.load }
-              if assigned(getprocvardef) then
-                aprocdef:=Tprocsym(sym).search_procdef_byprocvardef(getprocvardef)
-              else
-                aprocdef:=nil;
               p2:=cloadnode.create_procvar(sym,aprocdef,st);
               p2:=cloadnode.create_procvar(sym,aprocdef,st);
               if assigned(p1) and
               if assigned(p1) and
                  (p1.nodetype<>typen) then
                  (p1.nodetype<>typen) then
@@ -720,38 +739,42 @@ implementation
          afterassignment:=prevafterassn;
          afterassignment:=prevafterassn;
       end;
       end;
 
 
-    procedure handle_procvar(pv : tprocvardef;var p2 : tnode; getaddr: boolean);
-
-        procedure doconv(procvar : tprocvardef;var t : tnode);
-        var
-          hp : tnode;
-          currprocdef : tprocdef;
-        begin
-          hp:=nil;
-          currprocdef:=tcallnode(t).symtableprocentry.search_procdef_byprocvardef(procvar);
-          if assigned(currprocdef) then
-           begin
-             hp:=cloadnode.create_procvar(tprocsym(tcallnode(t).symtableprocentry),currprocdef,tcallnode(t).symtableproc);
-             if (po_methodpointer in procvar.procoptions) then
-               tloadnode(hp).set_mp(tnode(tcallnode(t).methodpointer).getcopy);
-             t.destroy;
-             t:=hp;
-           end;
-        end;
 
 
+    procedure handle_procvar(pv : tprocvardef;var p2 : tnode);
+      var
+        hp,hp2 : tnode;
+        hpp    : ^tnode;
+        currprocdef : tprocdef;
       begin
       begin
-        if ((m_tp_procvar in aktmodeswitches) or
-            not getaddr) then
-          if (p2.nodetype=calln) and
-             { a procvar can't have parameters! }
-             not assigned(tcallnode(p2).left) then
-           doconv(pv,p2)
-          else
-           if (p2.nodetype=typeconvn) and
-              (ttypeconvnode(p2).left.nodetype=calln) and
+        if not assigned(pv) then
+         internalerror(200301121);
+        if (m_tp_procvar in aktmodeswitches) then
+         begin
+           hp:=p2;
+           hpp:=@p2;
+           while assigned(hp) and
+                 (hp.nodetype=typeconvn) do
+            begin
+              hp:=ttypeconvnode(hp).left;
+              { save orignal address of the old tree so we can replace the node }
+              hpp:=@hp;
+            end;
+           if (hp.nodetype=calln) and
               { a procvar can't have parameters! }
               { a procvar can't have parameters! }
-              not assigned(tcallnode(ttypeconvnode(p2).left).left) then
-            doconv(pv,ttypeconvnode(p2).left);
+              not assigned(tcallnode(hp).left) then
+            begin
+              currprocdef:=tcallnode(hp).symtableprocentry.search_procdef_byprocvardef(pv);
+              if assigned(currprocdef) then
+               begin
+                 hp2:=cloadnode.create_procvar(tprocsym(tcallnode(hp).symtableprocentry),currprocdef,tcallnode(hp).symtableproc);
+                 if (po_methodpointer in pv.procoptions) then
+                   tloadnode(hp2).set_mp(tnode(tcallnode(hp).methodpointer).getcopy);
+                 hp.destroy;
+                 { replace the old callnode with the new loadnode }
+                 hpp^:=hp2;
+               end;
+            end;
+         end;
       end;
       end;
 
 
 
 
@@ -831,7 +854,7 @@ implementation
                            getprocvardef:=tprocvardef(tpropertysym(sym).proptype.def);
                            getprocvardef:=tprocvardef(tpropertysym(sym).proptype.def);
                          p2:=comp_expr(true);
                          p2:=comp_expr(true);
                          if assigned(getprocvardef) then
                          if assigned(getprocvardef) then
-                           handle_procvar(getprocvardef,p2,getaddr);
+                           handle_procvar(getprocvardef,p2);
                          tcallnode(p1).left:=ccallparanode.create(p2,tcallnode(p1).left);
                          tcallnode(p1).left:=ccallparanode.create(p2,tcallnode(p1).left);
                          include(tcallnode(p1).flags,nf_isproperty);
                          include(tcallnode(p1).flags,nf_isproperty);
                          getprocvardef:=nil;
                          getprocvardef:=nil;
@@ -932,17 +955,8 @@ implementation
                  procsym:
                  procsym:
                    begin
                    begin
                       do_proc_call(sym,sym.owner,
                       do_proc_call(sym,sym.owner,
-                                   (getaddr and not(token in [_CARET,_POINT])) or
-                                   (assigned(getprocvardef) and
-                                    ((block_type=bt_const) or
-                                     ((m_tp_procvar in aktmodeswitches) and
-                                      (proc_to_procvar_equal(tprocsym(sym).first_procdef,getprocvardef)>te_incompatible)
-                                     )
-                                    )
-                                   ),again,p1);
-                      if (block_type=bt_const) and
-                         assigned(getprocvardef) then
-                        handle_procvar(getprocvardef,p1,getaddr);
+                                   (getaddr and not(token in [_CARET,_POINT])),
+                                   again,p1);
                       { we need to know which procedure is called }
                       { we need to know which procedure is called }
                       do_resulttypepass(p1);
                       do_resulttypepass(p1);
                       { now we know the real method e.g. we can check for a class method }
                       { now we know the real method e.g. we can check for a class method }
@@ -1275,17 +1289,8 @@ implementation
                                     assigned(aktprocsym) and
                                     assigned(aktprocsym) and
                                     (po_classmethod in aktprocdef.procoptions);
                                     (po_classmethod in aktprocdef.procoptions);
                     do_proc_call(srsym,srsymtable,
                     do_proc_call(srsym,srsymtable,
-                                 (getaddr and not(token in [_CARET,_POINT])) or
-                                 (assigned(getprocvardef) and
-                                  ((block_type=bt_const) or
-                                   ((m_tp_procvar in aktmodeswitches) and
-                                    (proc_to_procvar_equal(tprocsym(srsym).first_procdef,getprocvardef)>te_incompatible)
-                                   )
-                                  )
-                                 ),again,p1);
-                    if (block_type=bt_const) and
-                       assigned(getprocvardef) then
-                     handle_procvar(getprocvardef,p1,getaddr);
+                                 (getaddr and not(token in [_CARET,_POINT])),
+                                 again,p1);
                     { we need to know which procedure is called }
                     { we need to know which procedure is called }
                     if possible_error then
                     if possible_error then
                      begin
                      begin
@@ -1793,6 +1798,9 @@ implementation
                         p1:=ctypenode.create(htype);
                         p1:=ctypenode.create(htype);
                       end;
                       end;
                      do_member_read(false,sym,p1,again);
                      do_member_read(false,sym,p1,again);
+                     { Add flag to indicate that inherited is used }
+                     if p1.nodetype=calln then
+                       include(p1.flags,nf_auto_inherited);
                    end
                    end
                   else
                   else
                    begin
                    begin
@@ -2220,7 +2228,7 @@ implementation
                   getprocvardef:=tprocvardef(p1.resulttype.def);
                   getprocvardef:=tprocvardef(p1.resulttype.def);
                 p2:=sub_expr(opcompare,true);
                 p2:=sub_expr(opcompare,true);
                 if assigned(getprocvardef) then
                 if assigned(getprocvardef) then
-                  handle_procvar(getprocvardef,p2,true);
+                  handle_procvar(getprocvardef,p2);
                 getprocvardef:=nil;
                 getprocvardef:=nil;
                 p1:=cassignmentnode.create(p1,p2);
                 p1:=cassignmentnode.create(p1,p2);
              end;
              end;
@@ -2304,7 +2312,10 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.97  2003-01-05 22:44:14  peter
+  Revision 1.98  2003-01-12 17:51:42  peter
+    * tp procvar handling fix for tb0448
+
+  Revision 1.97  2003/01/05 22:44:14  peter
     * remove a lot of code to support typen in loadn-procsym
     * remove a lot of code to support typen in loadn-procsym
 
 
   Revision 1.96  2002/12/11 22:40:36  peter
   Revision 1.96  2002/12/11 22:40:36  peter