5.12.5. 第三个例子
现在我们已经有了“ SmallObject ”的定义,那么我们使用下面的“ main ”函数来使用这个类,从中看一下将会产生怎样的中间树。
using namespace Loki;
int main ()
{
SmallObject<> object_;
return 1;
}
5.12.5.1. using 指示
假定这个“ main ”函数在另一个源文件中,它也构成一个编译单元,因此解析器由以下调用开始, cp_parser_translation_unit à cp_parser_declaration_seq_opt ,其中的 WHILE 循环将依次处理语句。
对于第一个是 using 指示的语句,调用栈进一步延伸,从 cp_parser_declaration à cp_parser_block_declaration à cp_parser_using_directive à parse_using_directive à do_using_directive 。
3350 void
3351 do_using_directive (tree namespace) in name-lookup.c
3352 {
3353 if (namespace == error_mark_node)
3354 return ;
3355
3356 my_friendly_assert (TREE_CODE (namespace) == NAMESPACE_DECL, 20050830);
3357
3358 if (building_stmt_tree ())
3359 add_stmt (build_stmt (USING_STMT, namespace));
3360 namespace = ORIGINAL_NAMESPACE (namespace);
3361
3362 if (!toplevel_bindings_p ())
3363 push_using_directive (namespace);
3364 else
3365 /* direct usage */
3366 add_using_namespace ( current_namespace , namespace, 0);
3367 }
如果 building_stmt_tree 是非 0 值,表示正在为函数、块等结构产生语句,那么 using 指示将有 USING_STMT 为之生成。这里的实参 namespace 是相应的 NAMESPACE_DECL 。在 3362 行,如果最里层的有效非类作用域是一个名字空间( using 指示不允许在类域中使用,但可以用在其方法作用域中), toplevel_bindings_p 返回非 0 值。例如:
namespace A {
int i;
}
class B {
int func() {
using namespace A;
return i;
}
};
对于用在名字空间域的那些 using 指示,在对应于该名字空间作用域的 NAMESPACE_DECL 节点中,域 DECL_NAMESPACE_USING 将是一个 tree_list ,通过 add_using_namespace 用来把这些 using 指示串接起来。
3275 static void
3276 add_using_namespace (tree user, tree used, bool indirect) in name-lookup.c
3277 {
3278 tree t;
3279 timevar_push (TV_NAME_LOOKUP);
3280 /* Using oneself is a no-op. */
3281 if (user == used)
3282 {
3283 timevar_pop (TV_NAME_LOOKUP);
3284 return ;
3285 }
3286 my_friendly_assert (TREE_CODE (user) == NAMESPACE_DECL, 380);
3287 my_friendly_assert (TREE_CODE (used) == NAMESPACE_DECL, 380);
3288 /* Check if we already have this. */
3290 t = purpose_member (used, DECL_NAMESPACE_USING (user));
3291 if (t != NULL_TREE)
3292 {
3293 if (!indirect)
3294 /* Promote to direct usage. */
3295 TREE_INDIRECT_USING (t) = 0;
3296 timevar_pop (TV_NAME_LOOKUP);
3297 return ;
3298 }
3299
3300 /* Add used to the user's using list. */
3301 DECL_NAMESPACE_USING (user)
3302 = tree_cons (used, namespace_ancestor (user, used),
3303 DECL_NAMESPACE_USING (user));
3304
3305 TREE_INDIRECT_USING (DECL_NAMESPACE_USING (user)) = indirect;
3306
3307 /* Add user to the used's users list. */
3308 DECL_NAMESPACE_USERS (used)
3309 = tree_cons (user, 0, DECL_NAMESPACE_USERS (used));
3310
3311 /* Recursively add all namespaces used. */
3312 for (t = DECL_NAMESPACE_USING (used); t; t = TREE_CHAIN (t))
3313 /* indirect usage */
3314 add_using_namespace (user, TREE_PURPOSE (t), 1);
3315
3316 /* Tell everyone using us about the new used namespaces. */
3317 for (t = DECL_NAMESPACE_USERS (user); t; t = TREE_CHAIN (t))
3318 add_using_namespace (TREE_PURPOSE (t), used, 1);
3319 timevar_pop (TV_NAME_LOOKUP);
3320 }
在 5.12.4.1.1.2.1.3.2. 其他名字 一节中,我们看到 using 指示的使用必须不能混淆名字空间的层次,在名字查找时,前端将严格按照其层次进行搜寻。 add_using_namespace 需要记录必要的层次信息。这里 namespace_ancestor 找出 ns1 及 ns2 最接近的公共祖先。看到所有的名字空间都有相同的公共祖先——全局名字空间。(关于 add_using_namespace 生成的这个列表的使用,参考 lookup_using_namespace )。
3194 static tree
3195 namespace_ancestor (tree ns1, tree ns2) in name-lookup.c
3196 {
3197 timevar_push (TV_NAME_LOOKUP);
3198 if (is_ancestor (ns1, ns2))
3199 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ns1);
3200 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
3201 namespace_ancestor (CP_DECL_CONTEXT (ns1), ns2));
3202 }
这里参数 root 是当前名字空间,而 child 是由 using 指示指定的名字空间。那么 is_ancestor 持续地从 child 开始获取上下文,直到找到 root 或离开这棵树。对于前一种情形, root 是 child 的祖先,并且函数返回非 0 值;反之,函数返回 0 。
2502 bool
2503 is_ancestor (tree root, tree child) in name-lookup.c
2504 {
2505 my_friendly_assert ((TREE_CODE (root) == NAMESPACE_DECL
2506 || TREE_CODE (root) == FUNCTION_DECL
2507 || CLASS_TYPE_P (root)), 20030307);
2508 my_friendly_assert ((TREE_CODE (child) == NAMESPACE_DECL
2509 || CLASS_TYPE_P (child)),
2510 20030307);
2511
2512 /* The global namespace encloses everything. */
2513 if (root == global_namespace )
2514 return true;
2515
2516 while (true)
2517 {
2518 /* If we've run out of scopes, stop. */
2519 if (!child)
2520 return false;
2521 /* If we've reached the ROOT, it encloses CHILD. */
2522 if (root == child)
2523 return true;
2524 /* Go out one level. */
2525 if (TYPE_P (child))
2526 child = TYPE_NAME (child);
2527 child = DECL_CONTEXT (child);
2528 }
2529 }
那么对于我们的例子,全局名字空间在其 DECL_NAMESPACE_USERS 域串接了“ Loki ”。
5.12.5.2. Main() 的定义
5.12.5.2.1. 函数定义 – 声明符部分
对于 main 函数, cp_parser_declaration 又一次调用 cp_parser_block_declaration à cp_parser_simple_declaration 。在我们的上下文中,参数 function_definition_allowed_p 是 true ,这表示我们同时把一个函数定义( function-definition )识别作简单声明( simple-declaration )。
block-declaration 的语法如下:
block-declaration:
simple-declaration | asm-definition | namespace-alias-definition | using-declaration |
using-directive
GNU Extension:
block-declaration: __extension__ block-declaration | label-declaration
6370 static void
6371 cp_parser_block_declaration (cp_parser *parser, in parser.c
6372 bool statement_p)
6373 {
6374 cp_token *token1;
6375 int saved_pedantic;
6376
6377 /* Check for the `__extension__' keyword. */
6378 if (cp_parser_extension_opt (parser, &saved_pedantic))
6379 {
…
6386 }
6387
6388 /* Peek at the next token to figure out which kind of declaration is
6389 present. */
6390 token1 = cp_lexer_peek_token (parser->lexer);
6391
6392 /* If the next keyword is `asm', we have an asm-definition. */
6393 if (token1->keyword == RID_ASM)
6394 {
…
6398 }
6399 /* If the next keyword is `namespace', we have a
6400 namespace-alias-definition. */
6401 else if (token1->keyword == RID_NAMESPACE)
6402 cp_parser_namespace_alias_definition (parser);
6403 /* If the next keyword is `using', we have either a
6404 using-declaration or a using-directive. */
6405 else if (token1->keyword == RID_USING)
6406 {
…
6419 }
6420 /* If the next keyword is `__label__' we have a label declaration. */
6421 else if (token1->keyword == RID_LABEL)
6422 {
…
6426 }
6427 /* Anything else must be a simple-declaration. */
6428 else
6429 cp_parser_simple_declaration (parser, !statement_p);
6430 }
simple-declaration 的语法是:
simple-declaration:
decl-specifier-seq [opt] init-declarator-list [opt] ;
init-declarator-list:
init-declarator | init-declarator-list , init-declarator
看到 simple-declaration 可能被包含在一个 block-declaraition 中,而该 block-declaraition 则可能在一个函数域或类方法域中,其中要求访问控制,因此期望一个新的延迟访问实例。而在 6475 行的 stop_deferring_access_checks 防止加入更多由 perform_or_defer_access_check 检查的延迟访问控制,不过对于 decl-specifier-seq 及 init-declarator-list 访问检查都是需要的,因此稍后将通过 resume_deferring_access_checks 重新开始检查。
6444 static void
6445 cp_parser_simple_declaration (cp_parser* parser, in parser.c
6446 bool function_definition_allowed_p)
6447 {
6448 tree decl_specifiers;
6449 tree attributes;
6450 int declares_class_or_enum;
6451 bool saw_declarator;
6452
6453 /* Defer access checks until we know what is being declared; the
6454 checks for names appearing in the decl-specifier-seq should be
6455 done as if we were in the scope of the thing being declared. */
6456 push_deferring_access_checks (dk_deferred);
6457
6458 /* Parse the decl-specifier-seq. We have to keep track of whether
6459 or not the decl-specifier-seq declares a named class or
6460 enumeration type, since that is the only case in which the
6461 init-declarator-list is allowed to be empty.
6462
6463 [dcl.dcl]
6464
6465 I n a simple-declaration, the optional init-declarator-list can be
6466 omitted only when declaring a class or enumeration, that is when
6467 the decl-specifier-seq contains either a class-specifier, an
6468 elaborated-type-specifier, or an enum-specifier. */
6469 decl_specifiers
6470 = cp_parser_decl_specifier_seq (parser,
6471 CP_PARSER_FLAGS_OPTIONAL,
6472 &attributes,
6473 &declares_class_or_enum);
6474 /* We no longer need to defer access checks. */
6475 stop_deferring_access_checks ();
6476
6477 /* In a block scope, a valid declaration must always have a
6478 decl-specifier-seq. By not trying to parse declarators, we can
6479 resolve the declaration/expression ambiguity more quickly. */
6480 if (!function_definition_allowed_p && !decl_specifiers)
6481 {
6482 cp_parser_error (parser, "expected declaration");
6483 goto done;
6484 }
6485
6486 /* If the next two tokens are both identifiers, the code is
6487 erroneous. The usual cause of this situation is code like:
6488
6489 T t;
6490
6491 where "T" should name a type -- but does not. */
6492 if (cp_parser_diagnose_invalid_type_name (parser))
6493 {
6494 /* If parsing tentatively, we should commit; we really are
6495 looking at a declaration. */
6496 cp_parser_commit_to_tentative_parse (parser);
6497 /* Give up. */
6498 goto done;
6499 }
我们前面已经看到, cp_parser_decl_specifier_seq 将解析函数的返回类型;那么在这里 decl_specifiers 是一个 tree_list ,其中的 TREE_VALUE 域指向 integer_type_node 节点。注意一个函数定义可能没有返回类型(它默认为 int )。
1950 static bool
1951 cp_parser_diagnose_invalid_type_name (cp_parser *parser) in parser.c
1952 {
1953 /* If the next two tokens are both identifiers, the code is
1954 erroneous. The usual cause of this situation is code like:
1955
1956 T t;
1957
1958 where "T" should name a type -- but does not. */
1959 if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
1960 && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME)
1961 {
1962 tree name;
1963
1964 /* If parsing tentatively, we should commit; we really are
1965 looking at a declaration. */
1966 /* Consume the first identifier. */
1967 name = cp_lexer_consume_token (parser->lexer)->value;
1968 /* Issue an error message. */
1969 error ("`%s' does not name a type", IDENTIFIER_POINTER (name));
1970 /* If we're in a template class, it's possible that the user was
1971 referring to a type from a base class. For example:
1972
1973 template <typename T> struct A { typedef T X; };
1974 template <typename T> struct B : public A<T> { X x; };
1975
1976 The user should have said "typename A<T>::X". */
1977 if (processing_template_decl && current_class_type )
1978 {
1979 tree b;
1980
1981 for (b = TREE_CHAIN (TYPE_BINFO (current_class_type ));
1982 b;
1983 b = TREE_CHAIN (b))
1984 {
1985 tree base_type = BINFO_TYPE (b);
1986 if (CLASS_TYPE_P (base_type)
1987 && dependent_type_p (base_type))
1988 {
1989 tree field;
1990 /* Go from a particular instantiation of the
1991 template (which will have an empty TYPE_FIELDs),
1992 to the main version. */
1993 base_type = CLASSTYPE_PRIMARY_TEMPLATE_TYPE (base_type);
1994 for (field = TYPE_FIELDS (base_type);
1995 field;
1996 field = TREE_CHAIN (field))
1997 if (TREE_CODE (field) == TYPE_DECL
1998 && DECL_NAME (field) == name)
1999 {
2000 error ("(perhaps `typename %T::%s' was intended)",
2001 BINFO_TYPE (b), IDENTIFIER_POINTER (name));
2002 break ;
2003 }
2004 if (field)
2005 break ;
2006 }
2007 }
2008 }
2009 /* Skip to the end of the declaration; there's no point in
2010 trying to process it. */
2011 cp_parser_skip_to_end_of_statement (parser);
2012
2013 return true;
2014 }
2015
2016 return false;
2017 }
作为正确的形式, decl-specifier-seq 的核心部分应该命名一个类型。通过名字查找规则找到的该类型将被返回给 decl-specifiers ;而如果没有找到适合的类型,这个符号保持为标识符,那么 cp_parser_diagnose_invalid_type_name 诊断这个错误情况,并给出诊断消息。
cp_parser_simple_declaration (continue)
6501 /* If we have seen at least one decl-specifier, and the next token
6502 is not a parenthesis, then we must be looking at a declaration.
6503 (After "int (" we might be looking at a functional cast.) */
6504 if (decl_specifiers
6505 && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))
6506 cp_parser_commit_to_tentative_parse (parser);
6507
6508 /* Keep going until we hit the `;' at the end of the simple
6509 declaration. */
6510 saw_declarator = false;
6511 while (cp_lexer_next_token_is_not (parser->lexer,
6512 CPP_SEMICOLON))
6513 {
6514 cp_token *token;
6515 bool function_definition_p;
6516 tree decl;
6517
6518 saw_declarator = true;
6519 /* Parse the init-declarator. */
6520 decl = cp_parser_init_declarator (parser, decl_specifiers, attributes,
6521 function_definition_allowed_p,
6522 /*member_p=*/ false,
6523 declares_class_or_enum,
6524 &function_definition_p);
6525 /* If an error occurred while parsing tentatively, exit quickly.
6526 (That usually happens when in the body of a function; each
6527 statement is treated as a declaration-statement until proven
6528 otherwise.) */
6529 if (cp_parser_error_occurred (parser))
6530 goto done;
6531 /* Handle function definitions specially. */
6532 if (function_definition_p)
6533 {
6534 /* If the next token is a `,', then we are probably
6535 processing something like:
6536
6537 void f() {}, *p;
6538
6539 which is erroneous. */
6540 if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
6541 error ("mixing declarations and function-definitions is forbidden");
6542 /* Otherwise, we're done with the list of declarators. */
6543 else
6544 {
6545 pop_deferring_access_checks ();
6546 return ;
6547 }
6548 }
…
6580 }
…
6593 /* Consume the `;'. */
6594 cp_parser_require (parser, CPP_SEMICOLON, "`;'");
6595
6596 done:
6597 pop_deferring_access_checks ();
6598 }
注意到参数 declares_class_or_enum 是 0 ,因为该 type-specifier 不是 class-specifier , enum-specifier ,也不是 elaborated-type-specifier 。 init-declarator 的内容包括:
init-declarator:
declarator initializer [opt]
function-definition:
decl-specifier-seq [opt] declarator ctor-initializer [opt] function-body
decl-specifier-seq [opt] declarator function-try-block
GNU Extension:
init-declarator:
declarator asm-specification [opt] attributes [opt] initializer [opt]
function-definition:
__extension__ function-definition
注意 ctor-initializer 仅用于构造函数中。
9933 static tree
9934 cp_parser_init_declarator (cp_parser* parser, in parser.c
9935 tree decl_specifiers,
9936 tree prefix_attributes,
9937 bool function_definition_allowed_p,
9938 bool member_p,
9939 int declares_class_or_enum,
9940 bool* function_definition_p)
9941 {
9942 cp_token *token;
9943 tree declarator;
9944 tree attributes;
9945 tree asm_specification;
9946 tree initializer;
9947 tree decl = NULL_TREE;
9948 tree scope;
9949 bool is_initialized;
9950 bool is_parenthesized_init;
9951 bool is_non_constant_init;
9952 int ctor_dtor_or_conv_p;
9953 bool friend_p;
9954 bool pop_p = false;
9955
9956 /* Assume that this is not the declarator for a function
9957 definition. */
9958 if (function_definition_p)
9959 *function_definition_p = false;
9960
9961 /* Defer access checks while parsing the declarator; we cannot know
9962 what names are accessible until we know what is being
9963 declared. */
9964 resume_deferring_access_checks ();
9965
9966 /* Parse the declarator. */
9967 declarator
9968 = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
9969 &ctor_dtor_or_conv_p,
9970 /*parenthesized_p=*/ NULL,
9971 /*member_p=*/ false);
9972 /* Gather up the deferred checks. */
9973 stop_deferring_access_checks ();
“ main () ”部分是声明符,其中包括作为 declarator-id 的“ main ”,而“ () ”是参数列表。那么在 cp_parser_declarator 中, cp_parser_direct_declarator 迭代其主 WHILE 循环 2 次。在第一次中调用: cp_parser_declarator_id à cp_parser_id_expression à cp_parser_identifier 返回“ main ”的 IDENTIFIER_NODE 。第二次中调用: cp_parser_parameter_declaration_clause 返回空参数列表对应的 void_list_node 。然后 make_call_declarator 把这个 declarator-id 及 parameter-list 组合成一个如下图的 CALL_EXPR (它极像我们之前看到的类方法的解析)。