GCC-3.4.6源代码学习笔记(129)
来源:互联网 发布:淘宝达人个人简介模版 编辑:程序博客网 时间:2024/06/11 01:00
5.12.5.2.2. 函数定义–函数体部分
5.12.5.2.2.1. 准备函数体解析
现在我们在decl_specifiers中得到了return-type-specifier,declarator指向CALL_EXPR,而declares_class_or_enum为0。记得如果我们正在定义新类型,declares_class_or_enum是2,这在function-definition中不被允许。
cp_parser_init_declarator (continue)
9975 /* If theDECLARATOR was erroneous, there's no need to go
9976 further. */
9977 if (declarator == error_mark_node)
9978 returnerror_mark_node;
9979
9980 if (declares_class_or_enum & 2)
9981 cp_parser_check_for_definition_in_return_type
9982 (declarator, TREE_VALUE(decl_specifiers));
9983
9984 /* Figure out whatscope the entity declared by the DECLARATOR is
9985 located in. `grokdeclarator'sometimes changes the scope, so
9986 we compute it now. */
9987 scope = get_scope_of_declarator (declarator);
9988
9989 /* If we'reallowing GNU extensions, look for an asm-specification
9990 and attributes. */
9991 if (cp_parser_allow_gnu_extensions_p(parser))
9992 {
9993 /* Look for anasm-specification. */
9994 asm_specification =cp_parser_asm_specification_opt (parser);
9995 /* And attributes. */
9996 attributes = cp_parser_attributes_opt (parser);
9997 }
9998 else
9999 {
10000 asm_specification = NULL_TREE;
10001 attributes = NULL_TREE;
10002 }
10003
10004 /* Peek at the nexttoken. */
10005 token = cp_lexer_peek_token(parser->lexer);
10006 /* Check to see ifthe token indicates the start of a
10007 function-definition. */
10008 if (cp_parser_token_starts_function_definition_p(token))
10009 {
10010 if (!function_definition_allowed_p)
10011 {
10012 /* If afunction-definition should not appear here, issue an
10013 error message. */
10014 cp_parser_error (parser,
10015 "a function-definitionis not allowed here");
10016 return error_mark_node;
10017 }
10018 else
10019 {
10020 /* Neitherattributes nor an asm-specification are allowed
10021 on a function-definition. */
10022 if (asm_specification)
10023 error ("an asm-specification isnot allowed on a function-definition");
10024 if (attributes)
10025 error ("attributes are not allowedon a function-definition");
10026 /* This is afunction-definition. */
10027 *function_definition_p = true;
10028
10029 /* Parse thefunction definition. */
10030 if (member_p)
10031 decl =cp_parser_save_member_function_body (parser,
10032 decl_specifiers,
10033 declarator,
10034 prefix_attributes);
10035 else
10036 decl
10037 = (cp_parser_function_definition_from_specifiers_and_declarator
10038 (parser, decl_specifiers,prefix_attributes, declarator));
10039
10040 returndecl;
10041 }
10042 }
…
10197 return decl;
10198 }
如果我们在声明符后找到“{”,这表示function-definition。我们在10037行继续。
14314 static tree
14315 cp_parser_function_definition_from_specifiers_and_declarator in parser.c
14316 (cp_parser* parser,
14317 tree decl_specifiers,
14318 tree attributes,
14319 tree declarator)
14320 {
14321 tree fn;
14322 bool success_p;
14323
14324 /* Begin thefunction-definition. */
14325 success_p = begin_function_definition(decl_specifiers,
14326 attributes,
14327 declarator);
首先,我们需要设立用于函数定义的框架,并把它合并入中间树。这个框架对于所有非类绑定的函数定义都是通用的。而每个定义都以自己的方式填充该框架。
1897 int
1898 begin_function_definition (treedecl_specs, tree attributes, tree declarator) in parser.c
1899 {
1900 if (!start_function (decl_specs, declarator,attributes, SF_DEFAULT))
1901 return 0;
1902
1903 /* The things we'reabout to see are not directly qualified by any
1904 template headers we've seenthus far. */
1905 reset_specialization ();
1906
1907 return 1;
1908 }
这里的参数flags具有值SF_DEFAULT,这表示一个普通的未解析的函数。下面的have_extern_spec仅在看到“extern”时为true。
10181 int
10182 start_function(tree declspecs, tree declarator, tree attrs, int flags) in decl.c
10183 {
10184 tree decl1;
10185 tree ctype = NULL_TREE;
10186 tree fntype;
10187 tree restype;
10188 int doing_friend = 0;
10189 struct cp_binding_level *bl;
10190 tree current_function_parms;
10191
10192 /* Sanitycheck. */
10193 my_friendly_assert(TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE, 160);
10194 my_friendly_assert (TREE_CHAIN(void_list_node) == NULL_TREE, 161);
10195
10196 /* This should onlybe done once on the top most decl. */
10197 if (have_extern_spec)
10198 {
10199 declspecs = tree_cons (NULL_TREE,get_identifier ("extern"), declspecs);
10200 have_extern_spec = false;
10201 }
10202
10203 if (flags & SF_PRE_PARSED)
10204 {
...
10225 }
10226 else
10227 {
10228 decl1 = grokdeclarator (declarator,declspecs, FUNCDEF, 1, &attrs);
因为这是未解析的函数,FUNCTION_TYPE及FUNCTION_DECL节点应该被构建,作为容器来保存以中间形式产生的定义。
6462 tree
6463 grokdeclarator(tree declarator, in decl.c
6464 tree declspecs,
6465 enumdecl_context decl_context,
6466 int initialized,
6467 tree* attrlist)
6468 {
6469 RID_BIT_TYPE specbits;
6470 int nclasses = 0;
6471 tree spec;
6472 tree type = NULL_TREE;
6473 int longlong = 0;
6474 int type_quals;
6475 int virtualp, explicitp, friendp, inlinep,staticp;
6476 intexplicit_int = 0;
6477 int explicit_char = 0;
6478 int defaulted_int = 0;
6479 int extern_langp = 0;
6480 tree dependant_name = NULL_TREE;
6481
6482 tree typedef_decl = NULL_TREE;
6483 const char*name;
6484 tree typedef_type = NULL_TREE;
6485 int funcdef_flag = 0;
6486 enumtree_code innermost_code = ERROR_MARK;
6487 int bitfield = 0;
6488 #if 0
6489 /* See the codebelow that used this. */
6490 tree decl_attr = NULL_TREE;
6491 #endif
6492
6493 /* Keep track ofwhat sort of function is being processed
6494 so that we can warn aboutdefault return values, or explicit
6495 return values which do notmatch prescribed defaults. */
6496 special_function_kind sfk = sfk_none;
6497
6498 tree dname = NULL_TREE;
6499 tree ctype = current_class_type;
6500 tree ctor_return_type = NULL_TREE;
6501 enum overload_flags flags = NO_SPECIAL;
6502 tree quals = NULL_TREE;
6503 tree raises = NULL_TREE;
6504 int template_count = 0;
6505 tree in_namespace = NULL_TREE;
6506 tree returned_attrs = NULL_TREE;
6507 tree scope = NULL_TREE;
6508 tree parms = NULL_TREE;
6509
6510 RIDBIT_RESET_ALL (specbits);
6511 if (decl_context == FUNCDEF)
6512 funcdef_flag = 1, decl_context = NORMAL;
6513 else if (decl_context == MEMFUNCDEF)
6514 funcdef_flag = -1, decl_context = FIELD;
6515 else if (decl_context == BITFIELD)
6516 bitfield = 1, decl_context = FIELD;
6517
6518 /* Look inside adeclarator for the name being declared
6519 and get it as a string, for anerror message. */
6520 {
6521 tree *next = &declarator;
6522 tree decl;
6523 name = NULL;
6524
6525 while (next&& *next)
6526 {
6527 decl = *next;
6528 switch (TREE_CODE (decl))
6529 {
...
6591 caseCALL_EXPR:
6592 innermost_code = TREE_CODE (decl);
...
6601 next = &TREE_OPERAND (decl, 0);
6602 decl = *next;
...
6610 ctype = NULL_TREE;
6611 break;
...
6629 caseIDENTIFIER_NODE:
6630 if (TREE_CODE (decl) ==IDENTIFIER_NODE)
6631 dname = decl;
6632
6633 next = 0;
6634
6635 if (C_IS_RESERVED_WORD (dname))
6636 {
...
6640 }
6641 else if (!IDENTIFIER_TYPENAME_P(dname))
6642 name = IDENTIFIER_POINTER (dname);
6643 else
6644 {
...
6653 }
6654 break;
...
6784 }
6785 }
6786 }
...
6844 for (spec =declspecs; spec; spec = TREE_CHAIN (spec))
6845 {
6846 int i;
6847 tree id;
6848
6849 /* Certain parse errors slip through. Forexample,
6850 `int class;' is not caughtby the parser. Try
6851 weakly to recover here. */
6852 if (TREE_CODE (spec) != TREE_LIST)
6853 return 0;
6854
6855 id = TREE_VALUE (spec);
...
6947 if (type)
6948 error ("two or more data types indeclaration of `%s'", name);
6949 else if (TREE_CODE (id) == IDENTIFIER_NODE)
6950 {
...
6960 }
6961 else if (id != error_mark_node)
6962 /* Can't changeCLASS nodes into RECORD nodes here! */
6963 type = id;
6964
6965 found: ;
6966 }
6967
6968 #if 0
6969 /* See the codebelow that used this. */
6970 if (typedef_decl)
6971 decl_attr = DECL_ATTRIBUTES (typedef_decl);
6972 #endif
6973 typedef_type = type;
...
7179 staticp = 0;
7180 inlinep = !! RIDBIT_SETP (RID_INLINE,specbits);
7181 virtualp = RIDBIT_SETP (RID_VIRTUAL,specbits);
7182 RIDBIT_RESET (RID_VIRTUAL, specbits);
7183 explicitp = RIDBIT_SETP (RID_EXPLICIT,specbits) != 0;
7184 RIDBIT_RESET (RID_EXPLICIT, specbits);
仅就执行到的代码而言,我们可以看到这第一部分的处理相当简单,在6963行,type指向integer_type_node,其类型是INTEGER_TYPE。
grokdeclarator (continue)
7343 while(declarator && TREE_CODE (declarator) != IDENTIFIER_NODE
7344 && TREE_CODE (declarator) !=TEMPLATE_ID_EXPR)
7345 {
...
7392 switch(TREE_CODE (declarator))
7393 {
...
7432 caseCALL_EXPR:
7433 {
7434 tree arg_types;
7435 int funcdecl_p;
7436 tree inner_parms =CALL_DECLARATOR_PARMS (declarator);
7437 tree inner_decl = TREE_OPERAND(declarator, 0);
7438
7439 /* Declaringa function type.
7440 Make sure we have avalid type for the function to return. */
7441
7442 /* We nowknow that the TYPE_QUALS don't apply to the
7443 decl, but to its returntype. */
7444 type_quals = TYPE_UNQUALIFIED;
...
7471 /* Say it's adefinition only for the CALL_EXPR
7472 closest to theidentifier. */
7473 funcdecl_p
7474 = inner_decl
7475 && (TREE_CODE(inner_decl) == IDENTIFIER_NODE
7476 || TREE_CODE (inner_decl) ==TEMPLATE_ID_EXPR
7477 || TREE_CODE (inner_decl) ==BIT_NOT_EXPR);
...
7576 /* Constructthe function type and go to the next
7577 inner layer ofdeclarator. */
7578
7579 declarator = TREE_OPERAND (declarator,0);
7580
7581 arg_types = grokparms (inner_parms,&parms);
7582
7583 if (declarator && flags == DTOR_FLAG)
7584 {
...
7597 }
7598
7599 /* ANSI saysthat `const int foo ();'
7600 does not make thefunction foo const. */
7601 type = build_function_type (type, arg_types);
7602 }
7603 break;
...
7839 }
7840 }
因为声明符已经被验证,可以为之构建树节点了。CALL_DECLARATOR_PARMS提取函数的参数列表。在7581行,因为inner_parms是void_list_node,grokparms所返回的值是NULL。然后在7601行,如下的一个FUNCTION_TYPE被构建。
grokdeclarator (continue)
8163 {
8164 tree decl;
8165
8166 if (decl_context == PARM)
8167 {
...
8172 }
8173 else if (decl_context == FIELD)
8174 {
...
8427 }
8428 else if (TREE_CODE (type) == FUNCTION_TYPE
8429 || TREE_CODE (type) == METHOD_TYPE)
8430 {
8431 tree original_name;
8432 int publicp = 0;
8433
8434 if (! declarator)
8435 returnNULL_TREE;
8436
8437 if (TREE_CODE (declarator) ==TEMPLATE_ID_EXPR)
8438 original_name = dname;
8439 else
8440 original_name = declarator;
8441
8442 /* Recordpresence of `static'. */
8443 publicp = (ctype != NULL_TREE
8444 || RIDBIT_SETP (RID_EXTERN,specbits)
8445 || !RIDBIT_SETP (RID_STATIC,specbits));
8446
8447 decl = grokfndecl (ctype, type,original_name, parms, declarator,
8448 virtualp, flags, quals,raises,
8449 1, friendp,
8450 publicp, inlinep,funcdef_flag,
8451 template_count,in_namespace);
8452 if (decl == NULL_TREE)
8453 returnNULL_TREE;
8454
8455 if (staticp == 1)
8456 {
...
8461 }
8462 }
8463 else
8464 {
...
8470 }
在这里,下面函数的参数declarator来自original_name,它在8440行获得其内容;而同一行的declarator则在7579行被更新为“main”的IDENTIFIER_NODE。另外,参数parms在grokparms的7581行得到值NULL。
5582 static tree
5583 grokfndecl (treectype, in decl.c
5584 tree type,
5585 tree declarator,
5586 tree parms,
5587 tree orig_declarator,
5588 int virtualp,
5589 enum overload_flags flags,
5590 tree quals,
5591 tree raises,
5592 int check,
5593 int friendp,
5594 int publicp,
5595 int inlinep,
5596 int funcdef_flag,
5597 int template_count,
5598 tree in_namespace)
5599 {
5600 tree decl;
5601 int staticp = ctype && TREE_CODE(type) == FUNCTION_TYPE;
5602 int has_default_arg = 0;
5603 tree t;
5604
5605 if (raises)
5606 type = build_exception_variant (type,raises);
5607
5608 decl = build_lang_decl(FUNCTION_DECL, declarator, type);
5609 DECL_ARGUMENTS (decl) = parms;
5610 /* Propagatevolatile out from type to decl. */
5611 if (TYPE_VOLATILE (type))
5612 TREE_THIS_VOLATILE (decl) = 1;
5613
5614 /* If this decl hasnamespace scope, set that up. */
5615 if (in_namespace)
5616 set_decl_namespace (decl, in_namespace,friendp);
5617 else if (!ctype)
5618 DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
5619
5620 /* `main' andbuiltins have implicit 'C' linkage. */
5621 if ((MAIN_NAME_P (declarator)
5622 || (IDENTIFIER_LENGTH (declarator) > 10
5623 && IDENTIFIER_POINTER(declarator)[0] == '_'
5624 && IDENTIFIER_POINTER(declarator)[1] == '_'
5625 && strncmp (IDENTIFIER_POINTER(declarator)+2, "builtin_", 8) == 0))
5626 && current_lang_name == lang_name_cplusplus
5627 && ctype == NULL_TREE
5628 /* NULL_TREEmeans global namespace. */
5629 && DECL_CONTEXT (decl) ==NULL_TREE)
5630 SET_DECL_LANGUAGE(decl, lang_c);
首先,下面的FUNCTION_DECL被构建。记得null在context域中表示我们正在全局名字空间中。
- GCC-3.4.6源代码学习笔记(129)
- GCC-3.4.6源代码学习笔记(129 续)
- 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)
- SQL Server删除所有表的小脚本
- Linux/Unix环境下的make和makefile详解(非常详细)
- C语言程序设计综合作业报告——作业管理系统
- Copy txt file
- 效率最高的Excel数据导入---(c#调用SSIS Package将数据库数据导入到Excel文件中)
- GCC-3.4.6源代码学习笔记(129)
- Flex array数组到java Object[] 的转换方法
- 效率最高的Excel数据导入续---SSIS Package包制作图解全过程
- beta技术沙龙:大型网站的Lucene应用
- 0.0
- LC.exe已退出,代码为-1
- GCC-3.4.6源代码学习笔记(129 续)
- NSOperation与performSelectorOnMainThread
- H.263:视频编码和解码(Video Coding and Decoding - CODEC rk)