5.12.3.2.1.2.2. 闭合类定义
自 expand_or_defer_fn à cp_parser_late_parsing_for_member à cp_parser_late_parsing_for_member à cp_parser_class_specifier à cp_parser_type_specifier à cp_parser_decl_specifier_seq 返回至 cp_parser_single_declaration ,将执行下面的代码。
cp_parser_single_declaration (continue)
14549 /* Check for the declaration of a template class. */
14550 if (declares_class_or_enum)
14551 {
14552 if (cp_parser_declares_only_class_p (parser))
14553 {
14554 decl = shadow_tag (decl_specifiers);
14555 if (decl)
14556 decl = TYPE_NAME (decl);
14557 else
14558 decl = error_mark_node;
14559 }
14560 }
14561 /* If it's not a template class, try for a template function. If
14562 the next token is a `;', then this declaration does not declare
14563 anything. But, if there were errors in the decl-specifiers, then
14564 the error might well have come from an attempted class-specifier.
14565 In that case, there's no need to warn about a missing declarator. */
14566 if (!decl
14567 && (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)
14568 || !value_member (error_mark_node, decl_specifiers)))
14569 decl = cp_parser_init_declarator (parser,
14570 decl_specifiers,
14571 attributes,
14572 /*function_definition_allowed_p=*/ true,
14573 member_p,
14574 declares_class_or_enum,
14575 &function_definition_p);
14576
14577 pop_deferring_access_checks ();
14578
14579 /* Clear any current qualification; whatever comes next is the start
14580 of something new. */
14581 parser->scope = NULL_TREE;
14582 parser->qualifying_scope = NULL_TREE;
14583 parser->object_scope = NULL_TREE;
14584 /* Look for a trailing `;' after the declaration. */
14585 if (!function_definition_p
14586 && (decl == error_mark_node
14587 || !cp_parser_require (parser, CPP_SEMICOLON, "`;'")))
14588 cp_parser_skip_to_end_of_block_or_statement (parser);
14589
14590 return decl;
14591 }
我们已经看过, declares_class_or_enum 可被设置为以下标记的按位与的结果:
1: 该 decl-specifiers 之一是一个 elaborated-type-specifier (即一个类型声明)
2: 该 decl-specifiers 之一是一个 enum-specifier 或 class-specifier (即一个类型定义)
因此如果 declares_class_or_enum 不是 0 ,需要进一步看这是否为类定义。如果是,将执行一些安全检查,这些检查与前面章节中对嵌套类所执行的检查相仿。
因为现在只是完成了“ decl-specifier-seq[opt] init-declarator [opt]; ”中 decl-specifier-seq 部分,函数 cp_parser_declares_only_class_p 用于确认是否出现声明符。
15029 static bool
15030 cp_parser_declares_only_class_p (cp_parser *parser) in parser.c
15031 {
15032 /* If the next token is a `;' or a `,' then there is no
15033 declarator. */
15034 return (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
15035 || cp_lexer_next_token_is (parser->lexer, CPP_COMMA));
15036 }
如果没有声明符,这只能是类型声明。这需要确认。
3608 tree
3609 shadow_tag (tree declspecs) in decl.c
3610 {
3611 tree t = check_tag_decl (declspecs);
3612
3613 if (!t)
3614 return NULL_TREE;
3615
3616 maybe_process_partial_specialization (t);
3617
3618 /* This is where the variables in an anonymous union are
3619 declared. An anonymous union declaration looks like:
3620 union { ... } ;
3621 because there is no declarator after the union, the parser
3622 sends that declaration here. */
3623 if (ANON_AGGR_TYPE_P (t))
3624 {
3625 fixup_anonymous_aggr (t);
3626
3627 if (TYPE_FIELDS (t))
3628 {
3629 tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
3630 NULL);
3631 finish_anon_union (decl);
3632 }
3633 }
3634
3635 return t;
3636 }
上面的 check_tag_decl 返回了所声明的类型( *_TYPE 类型的节点),或者 NULL 如果不是声明类型的话。这个值进而又被 shadow_tag 返回。那么在 cp_parser_single_declaration 的 14556 行, decl 所指向的就是对应的 TYPE_DECL 节点。而在 14566 行,若 decl 是 NULL ,表明这不是类型声明,因为 cp_parser_single_declaration 只被 cp_parser_explicit_specialization 及 cp_parser_template_declaration_after_export 所调用(这里是后者),那么剩下的可能就是模板函数,由 14569 行的 cp_parser_init_declarator 来解析之。
从 cp_parser_single_declaration 回到 cp_parser_template_declaration_after_export 。
cp_parser_template_declaration_after_export (continue)
14461 else
14462 {
14463 decl = cp_parser_single_declaration (parser,
14464 member_p,
14465 &friend_p);
14466
14467 /* If this is a member template declaration, let the front
14468 end know. */
14469 if (member_p && !friend_p && decl)
14470 {
14471 if (TREE_CODE (decl) == TYPE_DECL)
14472 cp_parser_check_access_in_redeclaration (decl);
14473
14474 decl = finish_member_template_decl (decl);
14475 }
14476 else if (friend_p && decl && TREE_CODE (decl) == TYPE_DECL)
14477 make_friend_class (current_class_type , TREE_TYPE (decl),
14478 /*complain=*/ true);
14479 }
14480 /* We are done with the current parameter list. */
14481 --parser->num_template_parameter_lists;
14482
14483 /* Finish up. */
14484 finish_template_decl (parameter_list);
14485
14486 /* Register member declarations. */
14487 if (member_p && !friend_p && decl && !DECL_CLASS_TEMPLATE_P (decl))
14488 finish_member_declaration (decl);
14489
14490 /* If DECL is a function template, we must return to parse it later.
14491 (Even though there is no definition, there might be default
14492 arguments that need handling.) */
14493 if (member_p && decl
14494 && (TREE_CODE (decl) == FUNCTION_DECL
14495 || DECL_FUNCTION_TEMPLATE_P (decl)))
14496 TREE_VALUE (parser->unparsed_functions_queues)
14497 = tree_cons (NULL_TREE, decl,
14498 TREE_VALUE (parser->unparsed_functions_queues));
14499 }
上面,对于我们作为例子的模板声明,它不是一个类成员,因此参数 member_p 是 false 。那么对于这个例子,仅有的操作由 finish_template_decl 完成。
2208 void
2209 finish_template_decl (tree parms) in semantics.c
2210 {
2211 if (parms)
2212 end_template_decl ();
2213 else
2214 end_specialization ();
2215 }
参数 parms 提取自“ <…> ”,因此如果它是 NULL ,它一定是一个特化。
2279 void
2280 end_template_decl (void) in pt.c
2281 {
2282 reset_specialization ();
2283
2284 if (! processing_template_decl)
2285 return ;
2286
2287 /* This matches the pushlevel in begin_template_parm_list. */
2288 finish_scope ();
2289
2290 --processing_template_decl ;
2291 current_template_parms = TREE_CHAIN (current_template_parms);
2292 }
在完成目标声明解析时,意味着我们到达了其作用域的边界。这个作用域也是由 finish_scope 来关闭。并且要记住把正在处理模板声明的数目减一。参考图: 嵌套模板参数的布局 ,上面在 2291 行, current_template_parms 的域 TREE_CHAIN 指向封闭模板( containing template )的目标参数,如果存在的话。
354 void
355 finish_scope (void) in decl.c
356 {
357 poplevel (0, 0, 0);
358 }
为了方便起见,在下面我们重新显示 poplevel 的代码。因为我们正要退出类的作用域,因此参数 functionbody 是 0 ;而 keep 是 0 ,则使得没有 BLOCK 节点为该域中的声明而构建。
423 tree
424 poplevel (int keep, int reverse, int functionbody) in decl.c
425 {
426 tree link;
427 /* The chain of decls was accumulated in reverse order.
428 Put it into forward order, just for cleanliness. */
429 tree decls;
430 int tmp = functionbody;
431 int real_functionbody;
432 tree subblocks;
433 tree block = NULL_TREE;
434 tree decl;
435 int leaving_for_scope;
436 scope_kind kind;
…
454 if (current_binding_level ->keep)
455 keep = 1;
…
493 /* Get the decls in the order they were written.
494 Usually current_binding_level->names is in reverse order.
495 But parameter decls were previously put in forward order. */
496
497 if (reverse)
498 current_binding_level->names
499 = decls = nreverse (current_binding_level->names);
500 else
501 decls = current_binding_level->names;
502
503 /* Output any nested inline functions within this block
504 if they weren't already output. */
505 for (decl = decls; decl; decl = TREE_CHAIN (decl))
506 if (TREE_CODE (decl) == FUNCTION_DECL
507 && ! TREE_ASM_WRITTEN (decl)
508 && DECL_INITIAL (decl) != NULL_TREE
509 && TREE_ADDRESSABLE (decl)
510 && decl_function_context (decl) == current_function_decl )
511 {
…
523 }
524
525 /* When not in function-at-a-time mode, expand_end_bindings will
526 warn about unused variables. But, in function-at-a-time mode
527 expand_end_bindings is not passed the list of variables in the
528 current scope, and therefore no warning is emitted. So, we
529 explicitly warn here. */
530 if (!processing_template_decl )
531 warn_about_unused_variables (getdecls ());
532
533 /* If there were any declarations or structure tags in that level,
534 or if this level is a function body,
535 create a BLOCK to record them for the life of this function. */
536 block = NULL_TREE;
…
550 /* We still support the old for-scope rules, whereby the variables
551 in a for-init statement were in scope after the for-statement
552 ended. We only use the new rules if flag_new_for_scope is
553 nonzero. */
554 leaving_for_scope
555 = current_binding_level->kind == sk_for && flag_new_for_scope == 1;
556
557 /* Remove declarations for all the DECLs in this level. */
558 for (link = decls; link; link = TREE_CHAIN (link))
559 {
560 if (leaving_for_scope && TREE_CODE (link) == VAR_DECL
561 && DECL_NAME (link))
562 {
…
619 }
620 else
621 {
622 /* Remove the binding. */
623 decl = link;
624 if (TREE_CODE (decl) == TREE_LIST)
625 decl = TREE_VALUE (decl);
626 if (DECL_P (decl))
627 pop_binding (DECL_NAME (decl), decl);
628 else if (TREE_CODE (decl) == OVERLOAD)
629 pop_binding (DECL_NAME (OVL_FUNCTION (decl)), decl);
630 else
631 abort ();
632 }
633 }
634
635 /* Remove declarations for any `for' variables from inner scopes
636 that we kept around. */
637 for (link = current_binding_level->dead_vars_from_for;
638 link; link = TREE_CHAIN (link))
639 pop_binding (DECL_NAME (TREE_VALUE (link)), TREE_VALUE (link));
640
641 /* Restore the IDENTIFIER_TYPE_VALUEs. */
642 for (link = current_binding_level->type_shadowed;
643 link; link = TREE_CHAIN (link))
644 SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
645
646 /* Restore the IDENTIFIER_LABEL_VALUEs for local labels. */
647 for (link = current_binding_level->shadowed_labels;
648 link;
649 link = TREE_CHAIN (link))
650 pop_label (TREE_VALUE (link), TREE_PURPOSE (link));
…
682 kind = current_binding_level->kind;
683
684 leave_scope ();
…
722 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, block);
723 }
因为对应于作用域的 cxx_scope 对象的 names 域记录了在其中的所有声明,并且对应的 IDENTIFIER_NODE 的 bindings 域绑定了该名字与该作用域中的声明。在退出该作用域时,毫无疑问需要移除这些绑定。这样才可以安全地撤到上一级作用域。