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

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     return error_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     This caused &foo to be of type ptr-to-const-function

10842     which then 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         the DECL_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 the function.  */

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     have declarations (from inline functions) that need to go into

10882     this function's blocks.  */

10883  

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

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

10886     syntax errors 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     of curly 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     for the nrv. genrtl_start_function and declare_return_variable

10914     handle making 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 the FUNCTION_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   struct language_function *f;

10618

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

10620     get it back 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 (struct language_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     must remember 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     local variables 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     this function 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 compiled separately.  */

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

10981     warning ("no return statement 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   return fndecl;

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   }

 

你可能感兴趣的:(GCC-3.4.6源代码学习笔记(111))