Ver Fonte

Merged revision(s) 47683, 47749 from trunk:
* The code generator of the exit statement must set the fc_gotolabel flag in flowcontrol for inlined routines/code blocks. It fixes the incorrect assumption that such exit statements terminate the main routine.
........
* Renamed fc_block_with_exit to fc_no_direct_exit to expand its usage.
* Set fc_no_direct_exit in case when a routine has an additional implicit exit code, such as calling FreeInstance in the destructor.
........

git-svn-id: branches/fixes_3_2@47800 -

yury há 4 anos atrás
pai
commit
b9fe6b9612
4 ficheiros alterados com 13 adições e 2 exclusões
  1. 2 1
      compiler/ncgbas.pas
  2. 2 0
      compiler/ncgflw.pas
  3. 4 1
      compiler/pass_2.pas
  4. 5 0
      compiler/psub.pas

+ 2 - 1
compiler/ncgbas.pas

@@ -428,6 +428,7 @@ interface
             oldflowcontrol:=flowcontrol;
             oldflowcontrol:=flowcontrol;
             { the nested block will not span an exit statement of the parent }
             { the nested block will not span an exit statement of the parent }
             exclude(flowcontrol,fc_exit);
             exclude(flowcontrol,fc_exit);
+            include(flowcontrol,fc_no_direct_exit);
           end;
           end;
 
 
         { do second pass on left node }
         { do second pass on left node }
@@ -453,7 +454,7 @@ interface
             current_procinfo.CurrExitLabel:=oldexitlabel;
             current_procinfo.CurrExitLabel:=oldexitlabel;
             { the exit statements inside this block are not exit statements }
             { the exit statements inside this block are not exit statements }
             { out of the parent                                             }
             { out of the parent                                             }
-            flowcontrol:=oldflowcontrol+(flowcontrol - [fc_exit]);
+            flowcontrol:=oldflowcontrol+(flowcontrol - [fc_exit,fc_no_direct_exit]);
           end;
           end;
       end;
       end;
 
 

+ 2 - 0
compiler/ncgflw.pas

@@ -413,6 +413,8 @@ implementation
       begin
       begin
          location_reset(location,LOC_VOID,OS_NO);
          location_reset(location,LOC_VOID,OS_NO);
 
 
+         if fc_no_direct_exit in flowcontrol then
+           include(flowcontrol,fc_gotolabel);
          include(flowcontrol,fc_exit);
          include(flowcontrol,fc_exit);
          if assigned(left) then
          if assigned(left) then
            secondpass(left);
            secondpass(left);

+ 4 - 1
compiler/pass_2.pas

@@ -43,7 +43,10 @@ uses
          fc_unwind_loop,
          fc_unwind_loop,
          { the left side of an expression is already handled, so we are
          { the left side of an expression is already handled, so we are
            not allowed to do ssl }
            not allowed to do ssl }
-         fc_lefthandled);
+         fc_lefthandled,
+         { in block where the exit statement jumps to an extra code instead of
+           immediately finishing execution of the current routine. }
+         fc_no_direct_exit);
 
 
        tflowcontrol = set of tenumflowcontrol;
        tflowcontrol = set of tenumflowcontrol;
 
 

+ 5 - 0
compiler/psub.pas

@@ -883,6 +883,11 @@ implementation
         final_asmnode:=casmnode.create_get_position;
         final_asmnode:=casmnode.create_get_position;
         final_used:=false;
         final_used:=false;
         bodyexitcode:=generate_bodyexit_block;
         bodyexitcode:=generate_bodyexit_block;
+        { Check if bodyexitcode is not empty }
+        with tstatementnode(tblocknode(bodyexitcode).statements) do
+          if (statement.nodetype<>nothingn) or assigned(next) then
+            { Indicate that the extra code is executed after the exit statement }
+            include(flowcontrol,fc_no_direct_exit);
 
 
         { Generate procedure by combining init+body+final,
         { Generate procedure by combining init+body+final,
           depending on the implicit finally we need to add
           depending on the implicit finally we need to add