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 }