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 }
- GCC-3.4.6源代码学习笔记(111)
- GCC-3.4.6源代码学习笔记 (100)
- GCC-3.4.6源代码学习笔记 (101)
- GCC-3.4.6源代码学习笔记 (102)
- GCC-3.4.6源代码学习笔记 (103)
- GCC-3.4.6源代码学习笔记 (104)
- GCC-3.4.6源代码学习笔记 (105)
- GCC-3.4.6源代码学习笔记 (106)
- GCC-3.4.6源代码学习笔记(166)
- GCC-3.4.6源代码学习笔记
- GCC-3.4.6源代码学习笔记(6)
- GCC-3.4.6源代码学习笔记(1)
- GCC-3.4.6源代码学习笔记(2)
- GCC-3.4.6源代码学习笔记(3)
- GCC-3.4.6源代码学习笔记(4)
- GCC-3.4.6源代码学习笔记(5)
- GCC-3.4.6源代码学习笔记(7)
- GCC-3.4.6源代码学习笔记(8)
- Studying note of GCC-3.4.6 source (110)
- mysql热备份和恢复
- 取消UpdatePanel更新,防止多次提交
- The Presentation Secrets of Steve Jobs
- C++中extern “C”含义深层探索
- GCC-3.4.6源代码学习笔记(111)
- FZU 网赛最后K题 Three kingdoms(有点卡常数的)
- Android JNI
- 转一个支付宝接口的ASP代码 支付宝接口(应用实例)2008-08-22 16:33支付宝接口的ASP代码
- Studying note of GCC-3.4.6 source (111)
- 支付宝接口(asp-支持UTF8、GB2312)
- GCC-3.4.6源代码学习笔记(112)
- KNN分类算法
- C# where用法