Преглед на файлове

* also set aktcallnode during tcallnode.pass_1, so that the callparanode
pass_1 code can make use of it

git-svn-id: trunk@29818 -

Jonas Maebe преди 10 години
родител
ревизия
aae879d28a
променени са 1 файла, в които са добавени 115 реда и са изтрити 107 реда
  1. 115 107
      compiler/ncal.pas

+ 115 - 107
compiler/ncal.pas

@@ -3600,123 +3600,131 @@ implementation
 
       var
         para: tcallparanode;
+        oldcallnode: tcallnode;
       begin
          result:=nil;
 
-         { as pass_1 is never called on the methodpointer node, we must check
-           here that it's not a helper type }
-         if assigned(methodpointer) and
-             (methodpointer.nodetype=typen) and
-             is_objectpascal_helper(ttypenode(methodpointer).typedef) and
-             not ttypenode(methodpointer).helperallowed then
-           Message(parser_e_no_category_as_types);
-
-         { can we get rid of the call? }
-         if (cs_opt_remove_emtpy_proc in current_settings.optimizerswitches) and
-            not(cnf_return_value_used in callnodeflags) and
-           (procdefinition.typ=procdef) and
-           tprocdef(procdefinition).isempty and
-           { allow only certain proc options }
-           ((tprocdef(procdefinition).procoptions-[po_none,po_classmethod,po_staticmethod,
-             po_interrupt,po_iocheck,po_assembler,po_msgstr,po_msgint,po_exports,po_external,po_overload,
-             po_nostackframe,po_has_mangledname,po_has_public_name,po_forward,po_global,
-             po_inline,po_compilerproc,po_has_importdll,po_has_importname,po_kylixlocal,po_dispid,po_delphi_nested_cc,
-             po_rtlproc,po_ignore_for_overload_resolution,po_auto_raised_visibility])=[]) then
-           begin
-             { check parameters for side effects }
-             para:=tcallparanode(left);
-             while assigned(para) do
-               begin
-                 if (para.parasym.typ = paravarsym) and
-                    ((para.parasym.refs>0) or
-                    { array of consts are converted later on so we need to skip them here
-                      else no error detection is done }
-                     is_array_of_const(para.parasym.vardef) or
-                     not(cs_opt_dead_values in current_settings.optimizerswitches) or
-                     might_have_sideeffects(para.left)) then
-                     break;
-                  para:=tcallparanode(para.right);
-               end;
-             { finally, remove it if no parameter with side effect has been found }
-             if para=nil then
-               begin
-                 result:=cnothingnode.create;
-                 exit;
-               end;
-           end;
-
-         { convert Objective-C calls into a message call }
-         if (procdefinition.typ=procdef) and
-            (po_objc in tprocdef(procdefinition).procoptions) then
-           begin
-             if not(cnf_objc_processed in callnodeflags) then
-               objc_convert_to_message_send;
-           end
-         else
-           begin
-             { The following don't apply to obj-c: obj-c methods can never be
-               inlined because they're always virtual and the destination can
-               change at run, and for the same reason we also can't perform
-               WPO on them (+ they have no constructors) }
+         oldcallnode:=aktcallnode;
+         aktcallnode:=self;
 
-             { Check if the call can be inlined, sets the cnf_do_inline flag }
-             check_inlining;
+         try
+           { as pass_1 is never called on the methodpointer node, we must check
+             here that it's not a helper type }
+           if assigned(methodpointer) and
+               (methodpointer.nodetype=typen) and
+               is_objectpascal_helper(ttypenode(methodpointer).typedef) and
+               not ttypenode(methodpointer).helperallowed then
+             Message(parser_e_no_category_as_types);
+
+           { can we get rid of the call? }
+           if (cs_opt_remove_emtpy_proc in current_settings.optimizerswitches) and
+              not(cnf_return_value_used in callnodeflags) and
+             (procdefinition.typ=procdef) and
+             tprocdef(procdefinition).isempty and
+             { allow only certain proc options }
+             ((tprocdef(procdefinition).procoptions-[po_none,po_classmethod,po_staticmethod,
+               po_interrupt,po_iocheck,po_assembler,po_msgstr,po_msgint,po_exports,po_external,po_overload,
+               po_nostackframe,po_has_mangledname,po_has_public_name,po_forward,po_global,
+               po_inline,po_compilerproc,po_has_importdll,po_has_importname,po_kylixlocal,po_dispid,po_delphi_nested_cc,
+               po_rtlproc,po_ignore_for_overload_resolution,po_auto_raised_visibility])=[]) then
+             begin
+               { check parameters for side effects }
+               para:=tcallparanode(left);
+               while assigned(para) do
+                 begin
+                   if (para.parasym.typ = paravarsym) and
+                      ((para.parasym.refs>0) or
+                      { array of consts are converted later on so we need to skip them here
+                        else no error detection is done }
+                       is_array_of_const(para.parasym.vardef) or
+                       not(cs_opt_dead_values in current_settings.optimizerswitches) or
+                       might_have_sideeffects(para.left)) then
+                       break;
+                    para:=tcallparanode(para.right);
+                 end;
+               { finally, remove it if no parameter with side effect has been found }
+               if para=nil then
+                 begin
+                   result:=cnothingnode.create;
+                   exit;
+                 end;
+             end;
 
-             { must be called before maybe_load_in_temp(methodpointer), because
-               it converts the methodpointer into a temp in case it's a call
-               (and we want to know the original call)
-             }
-             register_created_object_types;
-           end;
+           { convert Objective-C calls into a message call }
+           if (procdefinition.typ=procdef) and
+              (po_objc in tprocdef(procdefinition).procoptions) then
+             begin
+               if not(cnf_objc_processed in callnodeflags) then
+                 objc_convert_to_message_send;
+             end
+           else
+             begin
+               { The following don't apply to obj-c: obj-c methods can never be
+                 inlined because they're always virtual and the destination can
+                 change at run, and for the same reason we also can't perform
+                 WPO on them (+ they have no constructors) }
+
+               { Check if the call can be inlined, sets the cnf_do_inline flag }
+               check_inlining;
+
+               { must be called before maybe_load_in_temp(methodpointer), because
+                 it converts the methodpointer into a temp in case it's a call
+                 (and we want to know the original call)
+               }
+               register_created_object_types;
+             end;
 
-         { Maybe optimize the loading of the methodpointer using a temp. When the methodpointer
-           is a calln this is even required to not execute the calln twice.
-           This needs to be done after the resulttype pass, because in the resulttype we can still convert the
-           calln to a loadn (PFV) }
-         if assigned(methodpointer) then
-           maybe_load_in_temp(methodpointer);
+           { Maybe optimize the loading of the methodpointer using a temp. When the methodpointer
+             is a calln this is even required to not execute the calln twice.
+             This needs to be done after the resulttype pass, because in the resulttype we can still convert the
+             calln to a loadn (PFV) }
+           if assigned(methodpointer) then
+             maybe_load_in_temp(methodpointer);
 
-         { Create destination (temp or assignment-variable reuse) for function result if it not yet set }
-         maybe_create_funcret_node;
+           { Create destination (temp or assignment-variable reuse) for function result if it not yet set }
+           maybe_create_funcret_node;
 
-         { Insert the self,vmt,function result in the parameters }
-         gen_hidden_parameters;
+           { Insert the self,vmt,function result in the parameters }
+           gen_hidden_parameters;
 
-         { Remove useless nodes from init/final blocks }
-         { (simplify depends on typecheck info)        }
-         if assigned(callinitblock) then
-           begin
-             typecheckpass(tnode(callinitblock));
-             doinlinesimplify(tnode(callinitblock));
-           end;
-         if assigned(callcleanupblock) then
-           begin
-             typecheckpass(tnode(callcleanupblock));
-             doinlinesimplify(tnode(callcleanupblock));
-           end;
+           { Remove useless nodes from init/final blocks }
+           { (simplify depends on typecheck info)        }
+           if assigned(callinitblock) then
+             begin
+               typecheckpass(tnode(callinitblock));
+               doinlinesimplify(tnode(callinitblock));
+             end;
+           if assigned(callcleanupblock) then
+             begin
+               typecheckpass(tnode(callcleanupblock));
+               doinlinesimplify(tnode(callcleanupblock));
+             end;
 
-         { If a constructor calls another constructor of the same or of an
-           inherited class, some targets (jvm) have to generate different
-           entry code for the constructor. }
-         if (current_procinfo.procdef.proctypeoption=potype_constructor) and
-            (procdefinition.typ=procdef) and
-            (tprocdef(procdefinition).proctypeoption=potype_constructor) and
-            ([cnf_member_call,cnf_inherited] * callnodeflags <> []) then
-           current_procinfo.ConstructorCallingConstructor:=true;
-
-         { object check helper will load VMT -> needs GOT }
-         if (cs_check_object in current_settings.localswitches) and
-            (cs_create_pic in current_settings.moduleswitches) then
-           include(current_procinfo.flags,pi_needs_got);
-
-         { Continue with checking a normal call or generate the inlined code }
-         if cnf_do_inline in callnodeflags then
-           result:=pass1_inline
-         else
-           begin
-             mark_unregable_parameters;
-             result:=pass1_normal;
-           end;
+           { If a constructor calls another constructor of the same or of an
+             inherited class, some targets (jvm) have to generate different
+             entry code for the constructor. }
+           if (current_procinfo.procdef.proctypeoption=potype_constructor) and
+              (procdefinition.typ=procdef) and
+              (tprocdef(procdefinition).proctypeoption=potype_constructor) and
+              ([cnf_member_call,cnf_inherited] * callnodeflags <> []) then
+             current_procinfo.ConstructorCallingConstructor:=true;
+
+           { object check helper will load VMT -> needs GOT }
+           if (cs_check_object in current_settings.localswitches) and
+              (cs_create_pic in current_settings.moduleswitches) then
+             include(current_procinfo.flags,pi_needs_got);
+
+           { Continue with checking a normal call or generate the inlined code }
+           if cnf_do_inline in callnodeflags then
+             result:=pass1_inline
+           else
+             begin
+               mark_unregable_parameters;
+               result:=pass1_normal;
+             end;
+         finally
+           aktcallnode:=oldcallnode;
+         end;
       end;