Studying note of GCC-3.4.6 source (111)

来源:互联网 发布:js中国地图插件 编辑:程序博客网 时间:2024/06/08 12:46

5.12.3.2.1.2.1.3.    Finishfunction handling

Then finish_function will finish filling-up ofnode of FUNCTION_DECL for the function. We will go back to this function lateragain for other example.

 

10815 tree

10816 finish_function (int flags)                                                                               in decl.c

10817 {

10818   tree fndecl = current_function_decl;

10819   tree fntype, ctype =NULL_TREE;

10820   int inclass_inline = (flags& 2) != 0;

10821   int nested;

10822

10823   /*When we get some parse errors, we can end up without a

10824    current_function_decl, so cope. */

10825   if (fndecl == NULL_TREE)

10826     returnerror_mark_node;

10827

10828   if(DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)

10829      && DECL_VIRTUAL_P(fndecl)

10830      && ! processing_template_decl)

10831   {

10832     tree fnclass =DECL_CONTEXT (fndecl);

10833     if (fndecl ==CLASSTYPE_KEY_METHOD (fnclass))

10834        keyed_classes =tree_cons (NULL_TREE, fnclass, keyed_classes);

10835   }

10836

10837   nested = function_depth> 1;

10838   fntype = TREE_TYPE (fndecl);

10839

10840   /*TREE_READONLY (fndecl) = 1;

10841     Thiscaused &foo to be of type ptr-to-const-function

10842     whichthen got a warning when stored in a ptr-to-function variable.  */

10843

10844   my_friendly_assert(building_stmt_tree (), 20000911);

10845  

10846   /*For a cloned function, we've already got all the code we need;

10847    there's no need to add any extra bits. */

10848   if (!DECL_CLONED_FUNCTION_P(fndecl))

10849   {

10850     if (DECL_MAIN_P (current_function_decl))

10851     {

10852       /*Make it so that `main' always returns 0 by default.  */

10853 #if VMS_TARGET

10854       finish_return_stmt(integer_one_node);

10855 #else

10856       finish_return_stmt(integer_zero_node);

10857 #endif

10858     }

10859

10860     /*Finish dealing with exception specifiers. */

10861     if (flag_exceptions && ! processing_template_decl

10862        && flag_enforce_eh_specs

10863        &&TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))

10864       finish_eh_spec_block(TYPE_RAISES_EXCEPTIONS

10865                        (TREE_TYPE (current_function_decl)),

10866                        current_eh_spec_block);

10867   }

10868

10869   finish_fname_decls();

10870

10871   /*If we're saving up tree structure, tie off the function now.  */

10872   finish_stmt_tree(&DECL_SAVED_TREE (fndecl));

 

If assignment statements are generated for “__FUNCTION__” and like,field TREE_VALUE of the associated item in saved_function_name_decls will record thestatements. As there may be more than one assignments kept in saved_function_name_decls(correspond to “__FUNCTION__”, “__func__”, “__PRETTY_FUNCTION__”), so below atline 1019, FOR loop integrates these statements.

 

1012   void

1013   finish_fname_decls (void)                                                                 in c-common.c

1014   {

1015     unsigned ix;

1016     tree body = NULL_TREE;

1017     tree stack =saved_function_name_decls;

1018  

1019     for(; stack && TREE_VALUE (stack); stack = TREE_CHAIN (stack))

1020       body = chainon (TREE_VALUE(stack), body);

1021  

1022     if (body)

1023     {

1024       /*They were called into existence, so add to statement tree. Add

1025         theDECL_STMTs inside the outermost scope. */

1026       tree *p =&DECL_SAVED_TREE (current_function_decl);

1027       /*Skip the dummy EXPR_STMT and any EH_SPEC_BLOCK. */

1028       while(TREE_CODE (*p) != COMPOUND_STMT)

1029       {

1030         if (TREE_CODE (*p) ==EXPR_STMT)

1031           p = &TREE_CHAIN(*p);

1032         else

1033           p =&TREE_OPERAND(*p, 0);

1034       }

1035  

1036       p = &COMPOUND_BODY(*p);

1037       if (TREE_CODE (*p) ==SCOPE_STMT)

1038         p = &TREE_CHAIN(*p);

1039  

1040       body = chainon (body, *p);

1041       *p = body;

1042     }

1043  

1044     for(ix = 0; fname_vars[ix].decl;ix++)

1045       *fname_vars[ix].decl = NULL_TREE;

1046  

1047     if (stack)

1048     {

1049       /*We had saved values, restore them.  */

1050       tree saved;

1051  

1052       for(saved = TREE_PURPOSE (stack); saved; saved = TREE_CHAIN (saved))

1053       {

1054         tree decl = TREE_PURPOSE(saved);

1055         unsigned ix =TREE_INT_CST_LOW (TREE_VALUE (saved));

1056  

1057         *fname_vars[ix].decl = decl;

1058       }

1059       stack = TREE_CHAIN(stack);

1060     }

1061     saved_function_name_decls =stack;

1062   }

 

IF block At line 1012 puts these statements at head of thefunction-body. As these statements are saved by fname_vars[ix].decl before, nowthey got handled, and at exitting the function, they no longer valid; FOR loopat line 1044 cleans fname_vars[ix]. And FOR loop at line 1052 in factrestores fname_vars[ix].decl’sinitial value.

 

165    void

166    finish_stmt_tree (tree *t)                                                                   in c-semantics.c

167    {

168      tree stmt;

169   

170      /*Remove the fake extra statement added in begin_stmt_tree.  */

171      stmt = TREE_CHAIN (*t);

172      *t = stmt;

173      last_tree = NULL_TREE;

174   

175      if (cfun && stmt)

176      {

177        /*The line-number recorded in the outermost statement in a function

178          is the line number of the end of thefunction.  */

179        STMT_LINENO (stmt) =input_line;

180        STMT_LINENO_FOR_FN_P(stmt) = 1;

181      }

182    }

 

In begin_stmt_tree,a fake statement of void_zero_node is created because seeing in aboveaddress of it is needed for inserting the statements. Now as statements are alllinked in, this fake node can be removed.

 

finish_function (continue)

 

10874   /*If this function can't throw any exceptions, remember that.  */

10875   if (!processing_template_decl

10876       &&!cp_function_chain->can_throw

10877       && !flag_non_call_exceptions)

10878     TREE_NOTHROW (fndecl) = 1;

10879

10880   /*This must come after expand_function_end because cleanups might

10881     havedeclarations (from inline functions) that need to go into

10882     thisfunction's blocks.  */

10883  

10884   /*If the current binding level isn't the outermost binding level

10885     forthis function, either there is a bug, or we have experienced

10886     syntaxerrors and the statement tree is malformed. */

10887   if (current_binding_level->kind != sk_function_parms)

10888   {

         

10904   }

10905   poplevel(1, 0, 1);

10906

10907  /*Statements should always be full-expressions at the outermost set

10908     ofcurly braces for a function.  */

10909   my_friendly_assert (stmts_are_full_exprs_p (), 19990831);

10910

10911   /*Set up the named return value optimization, if we can. Here, we

10912    eliminate the copy from the nrv into the RESULT_DECL and any cleanup

10913     forthe nrv. genrtl_start_function and declare_return_variable

10914     handlemaking the nrv and RESULT_DECL share space. */

10915   if (current_function_return_value)

10916   {

         

10941   }

10942

10943   /*Remember that we were in class scope.  */

10944   if (current_class_name)

10945     ctype = current_class_type;

10946

10947   /*Must mark the RESULT_DECL as being in this function.  */

10948   DECL_CONTEXT (DECL_RESULT(fndecl)) = fndecl;

10949

10950   /*Set the BLOCK_SUPERCONTEXT of the outermost function scope to point

10951     to theFUNCTION_DECL node itself.  */

10952   BLOCK_SUPERCONTEXT (DECL_INITIAL(fndecl)) = fndecl;

10953

10954  /*Save away current state, if appropriate. */

10955   if (!processing_template_decl)

10956     save_function_data (fndecl);

 

By the language grammar, function without declaring throws anyexception can throw exception of any kind; to declare a function throw noexception, you should use nothrow at the end of the declaration. Thisinformation is useful for optimization, needs record it within theFUNCTION_DECL node. And IF blockbeginning at line 10915 is for named return value optimization purpose, we willcome to this topic later.

 

10614 static void

10615 save_function_data (tree decl)                                                                         in decl.c

10616 {

10617   structlanguage_function *f;

10618

10619   /*Save the language-specific per-function data so that we can

10620     get itback when we really expand this function. */

10621   my_friendly_assert(!DECL_PENDING_INLINE_P (decl),

10622                   19990908);

10623

10624   /*Make a copy.  */

10625   f = ggc_alloc (sizeof (structlanguage_function));

10626   memcpy (f,cp_function_chain, sizeof (struct language_function));

10627   DECL_SAVED_FUNCTION_DATA(decl) = f;

10628

10629   /*Clear out the bits we don't need.  */

10630  f->base.x_stmt_tree.x_last_stmt = NULL_TREE;

10631  f->base.x_stmt_tree.x_last_expr_type = NULL_TREE;

10632   f->x_named_label_uses =NULL;

10633   f->bindings = NULL;

10634   f->x_local_names = NULL;

10635

10636   /*If we've already decided that we cannot inline this function, we

10637     mustremember that fact when we actually go to expand the

10638    function.  */

10639   if(current_function_cannot_inline)

10640   {

10641     f->cannot_inline =current_function_cannot_inline;

10642     DECL_INLINE (decl) = 0;

10643   }

10644 }

 

If it is method of class-template, the method is not the realfunction declaration. For the real function declaration, it needs remember thisassociated language_function and release cfun as we get out of the function declarationand scope now. It is done by save_function_data.

 

finish_function (continue)

 

10958   /*If this function calls `setjmp' it cannot be inlined. When

10959    `longjmp' is called it is not guaranteed to restore the value of

10960     localvariables that have been modified since the call to

10961    `setjmp'. So, if were to inline this function into some caller

10962     `c',then when we `longjmp', we might not restore all variables

10963     in`c'. (It might seem, at first blush, that there's no way for

10964     thisfunction to modify local variables in `c', but their

10965    addresses may have been stored somewhere accessible to this

10966    function.)  */

10967   if (!processing_template_decl &&calls_setjmp_p (fndecl))

10968     DECL_UNINLINABLE (fndecl)= 1;

10969

10970   /*Complain if there's just no return statement. */

10971   if (warn_return_type

10972       && TREE_CODE(TREE_TYPE (fntype)) != VOID_TYPE

10973       && !dependent_type_p (TREE_TYPE(fntype))

10974       && !current_function_returns_value&& !current_function_returns_null

10975       /* Don't complain if we abort or throw.  */

10976       && !current_function_returns_abnormally

10977       && !DECL_NAME(DECL_RESULT (fndecl))

10978       /*Normally, with -Wreturn-type, flow will complain. Unless we're an

10979         inline function, as we might never be compiledseparately.  */

10980       && (DECL_INLINE(fndecl) || processing_template_decl))

10981     warning ("no returnstatement in function returning non-void");

10982

10983   /*We're leaving the context of this function, so zap cfun. It's still in

10984    DECL_SAVED_INSNS, and we'll restore it in tree_rest_of_compilation.  */

10985   cfun = NULL;

10986   current_function_decl = NULL;

10987

10988   /*If this is an in-class inline definition, we may have to pop the

10989    bindings for the template parameters that we added in

10990    maybe_begin_member_template_processing when start_function was

10991    called.  */

10992   if (inclass_inline)

10993    maybe_end_member_template_processing ();

10994

10995   /*Leave the scope of the class.  */

10996   if (ctype)

10997     pop_nested_class();

10998

10999   --function_depth;

11000

11001   /*Clean up.  */

11002   if (! nested)

11003     /*Let the error reporting routines know that we're outside a

11004      function. For a nested function, this value is used in

11005      cxx_pop_function_context and then reset via pop_function_context.  */

11006     current_function_decl = NULL_TREE;

11007

11008   returnfndecl;

11009 }

 

Being a method of class, it is either defined outside the classbody, or defined as inclass-inline, no matter what kind, ctype at line 10996points to the class node which forms the context for the method. When finishhandling the method, it also steps out of the class (remember forinclass-inline definition, its handling is deferred to the finish of classbody). Exitting from the class scope is done by pop_nested_class.

 

5650   void

5651   pop_nested_class (void)                                                                           in class.c

5652   {

5653     tree context = DECL_CONTEXT(TYPE_MAIN_DECL (current_class_type));

5654  

5655     popclass();

5656     if (context &&CLASS_TYPE_P (context))

5657       pop_nested_class ();

5658   }

 

原创粉丝点击