现在我们在 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 the DECLARATOR was erroneous, there's no need to go
9976 further. */
9977 if (declarator == error_mark_node)
9978 return error_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 what scope 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're allowing GNU extensions, look for an asm-specification
9990 and attributes. */
9991 if (cp_parser_allow_gnu_extensions_p (parser))
9992 {
9993 /* Look for an asm-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 next token. */
10005 token = cp_lexer_peek_token (parser->lexer);
10006 /* Check to see if the 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 a function-definition should not appear here, issue an
10013 error message. */
10014 cp_parser_error (parser,
10015 "a function-definition is not allowed here");
10016 return error_mark_node;
10017 }
10018 else
10019 {
10020 /* Neither attributes nor an asm-specification are allowed
10021 on a function-definition. */
10022 if (asm_specification)
10023 error ("an asm-specification is not allowed on a function-definition");
10024 if (attributes)
10025 error ("attributes are not allowed on a function-definition");
10026 /* This is a function-definition. */
10027 *function_definition_p = true;
10028
10029 /* Parse the function 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 return decl;
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 the function-definition. */
14325 success_p = begin_function_definition (decl_specifiers,
14326 attributes,
14327 declarator);
首先,我们需要设立用于函数定义的框架,并把它合并入中间树。这个框架对于所有非类绑定的函数定义都是通用的。而每个定义都以自己的方式填充该框架。
1897 int
1898 begin_function_definition (tree decl_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're about to see are not directly qualified by any
1904 template headers we've seen thus 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 /* Sanity check. */
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 only be 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, i n decl.c
6464 tree declspecs,
6465 enum decl_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 int explicit_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 enum tree_code innermost_code = ERROR_MARK;
6487 int bitfield = 0;
6488 #if 0
6489 /* See the code below that used this. */
6490 tree decl_attr = NULL_TREE;
6491 #endif
6492
6493 /* Keep track of what sort of function is being processed
6494 so that we can warn about default return values, or explicit
6495 return values which do not match 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 a declarator for the name being declared
6519 and get it as a string, for an error 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 case CALL_EXPR:
6592 innermost_code = TREE_CODE (decl);
...
6601 next = &TREE_OPERAND (decl, 0);
6602 decl = *next;
...
6610 ctype = NULL_TREE;
6611 break ;
...
6629 case IDENTIFIER_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. For example,
6850 `int class;' is not caught by 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 in declaration of `%s'", name);
6949 else if (TREE_CODE (id) == IDENTIFIER_NODE)
6950 {
...
6960 }
6961 else if (id != error_mark_node)
6962 /* Can't change CLASS nodes into RECORD nodes here! */
6963 type = id;
6964
6965 found: ;
6966 }
6967
6968 #if 0
6969 /* See the code below 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 case CALL_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 /* Declaring a function type.
7440 Make sure we have a valid type for the function to return. */
7441
7442 /* We now know that the TYPE_QUALS don't apply to the
7443 decl, but to its return type. */
7444 type_quals = TYPE_UNQUALIFIED;
...
7471 /* Say it's a definition only for the CALL_EXPR
7472 closest to the identifier. */
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 /* Construct the function type and go to the next
7577 inner layer of declarator. */
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 says that `const int foo ();'
7600 does not make the function 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 return NULL_TREE;
8436
8437 if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
8438 original_name = dname;
8439 else
8440 original_name = declarator;
8441
8442 /* Record presence 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 return NULL_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 (tree ctype, 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 /* Propagate volatile out from type to decl. */
5611 if (TYPE_VOLATILE (type))
5612 TREE_THIS_VOLATILE (decl) = 1;
5613
5614 /* If this decl has namespace 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' and builtins 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_TREE means global namespace. */
5629 && DECL_CONTEXT (decl) == NULL_TREE)
5630 SET_DECL_LANGUAGE (decl, lang_c);
首先,下面的 FUNCTION_DECL 被构建。记得 null 在 context 域中表示我们正在全局名字空间中。