GCC-3.4.6源代码学习笔记(111)

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

5.12.3.2.1.2.1.3.    完成函数处理

那么finish_function将为该函数完成填充其对应的FUNCTION_DECL节点。我们还将在其它例子中,回来看这个函数。

 

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));

 

如果使用了“__FUNCTION__”或相类的对象时,为其产生的赋值语句存在saved_function_name_decls对应节点的TREE_VALUE域中。因为saved_function_name_decls中可能存有多个赋值语句(对应对象“__FUNCTION__”,“__PRETTY_FUNCTION__”,“__func__”),1019行的FOR循环将它们整合一起。

 

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   }

 

1012行的IF块就是把这部分语句加入到函数体的开头。因为这些语句一直保存在fname_vars[ix].decl中,它们已得到处理,而且退出这个函数之后,它们不再有效,1044行的FOR循环将其清除。而1052行的FOR循环实际上恢复fname_vars[ix].decl的初始值。

 

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    }

 

begin_stmt_tree中,创建一个伪语句void_zero_node,因为在上面看到要用它的地址来插入语句。现在加入所有语句都已经链入,这个伪语句节点可以被移除了。

 

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);

 

根据语法,不声明抛出任何异常的函数可以抛出任意异常;要声明一个不抛出异常的函数应该在函数声明的末尾使用nothrow关键字。这个信息对于优化是有用的,需要在FUNCTION_DECL节点中记录之。在10915行开始的IF块是用于命名返回值优化(named return value optimization)的目的,后面我们将回到这个议题。

 

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 }

 

如果这是一个类模板的方法,该方法不是一个真正的函数声明。需要记住相关的language_function实例,并且释放cfun因为我们现在要退出函数的作用域。这由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 }

 

作为类的一个方法,它要么在类体外定义,要么是一个类体中的内联定义,不管哪一种10996行的ctype为该类节点,它构成该方法的上下文。当完成该方法的处理时,同时也退出该类的作用域(记住对于内联定义,它的处理被推迟到类体的解析完成的时候),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   }

 

原创粉丝点击