5.12.3.2. 解析模板声明的decl-specifier-seq部分
在解析过程中,我们可能会遇到错误的语句,为了尽可能的继续解析,最好前进到最近的“>”(显然,如果语句是正确的,下一个符号应该是“>”)。接下来为了解析如下类模板的成员模板函数:
template<class T> class string {
public:
template<class T2> int compare(const T2&);
template<class T2> string(const string<T2>& s) { /* ... */ }
// ...
};
template<class T> template<class T2> int string<T>::compare(const T2& s) {}
14458行检查方法的“template<class T2>”部分,并在14460处的递归对其进行处理。
cp_parser_template_declaration_after_export (continue)
14452 /* Look for the `>'. */
14453 cp_parser_skip_until_found (parser, CPP_GREATER, "`>'");
14454 /* We just processed one more parameter list. */
14455 ++parser->num_template_parameter_lists;
14456 /* If the next token is `template', there are more template
14457 parameters. */
14458 if (cp_lexer_next_token_is_keyword (parser->lexer,
14459 RID_TEMPLATE))
14460 cp_parser_template_declaration_after_export (parser, member_p);
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 }
在我们这个贯穿整章的例子的语句中,现在未解析的部分是“class SingleThreaded {…”,根据语法规则,它应该是decl-specifier-seq。decl-specifier-seq结构包含了decl-specifier序列,decl-specifier是如下的一个复杂结构。
14508 static tree
14509 cp_parser_single_declaration (cp_parser* parser, in parser.c
14510 bool member_p,
14511 bool* friend_p)
14512 {
14513 int declares_class_or_enum;
14514 tree decl = NULL_TREE;
14515 tree decl_specifiers;
14516 tree attributes;
14517 bool function_definition_p = false;
14518
14519 /* This function is only used when processing a template
14520 declaration. */
14521 if (innermost_scope_kind () != sk_template_parms
14522 && innermost_scope_kind () != sk_template_spec)
14523 abort ();
14524
14525 /* Defer access checks until we know what is being declared. */
14526 push_deferring_access_checks (dk_deferred);
14527
14528 /* Try the `decl-specifier-seq [opt] init-declarator [opt]'
14529 alternative. */
14530 decl_specifiers
14531 = cp_parser_decl_specifier_seq (parser,
14532 CP_PARSER_FLAGS_OPTIONAL,
14533 &attributes,
14534 &declares_class_or_enum);
14535 if (friend_p)
14536 *friend_p = cp_parser_friend_p (decl_specifiers);
14537
14538 /* There are no template typedefs. */
14539 if (cp_parser_typedef_p (decl_specifiers))
14540 {
14541 error ("template declaration of `typedef'");
14542 decl = error_mark_node;
14543 }
14544
14545 /* Gather up the access checks that occurred the
14546 decl-specifier-seq. */
14547 stop_deferring_access_checks ();
在下面的函数中,如果declares_class_or_enum非空,*declares_class_or_enum被按位设置为以下标记:
1:其中一个decl-specifiers是elaborated-type-specifier(即一个类型声明)。
2:其中一个decl-specifiers是enum-specifier或class-specifier(一个类型定义)。
6642 static tree
6643 cp_parser_decl_specifier_seq (cp_parser* parser, in parser.c
6644 cp_parser_flags flags,
6645 tree* attributes,
6646 int* declares_class_or_enum)
6647 {
6648 tree decl_specs = NULL_TREE;
6649 bool friend_p = false;
6650 bool constructor_possible_p = !parser->in_declarator_p;
6651
6652 /* Assume no class or enumeration type is declared. */
6653 *declares_class_or_enum = 0;
6654
6655 /* Assume there are no attributes. */
6656 *attributes = NULL_TREE;
6657
6658 /* Keep reading specifiers until there are no more to read. */
6659 while (true)
6660 {
6661 tree decl_spec = NULL_TREE;
6662 bool constructor_p;
6663 cp_token *token;
6664
6665 /* Peek at the next token. */
6666 token = cp_lexer_peek_token (parser->lexer);
6667 /* Handle attributes. */
6668 if (token->keyword == RID_ATTRIBUTE)
6669 {
6670 /* Parse the attributes. */
6671 decl_spec = cp_parser_attributes_opt (parser);
6672 /* Add them to the list. */
6673 *attributes = chainon (*attributes, decl_spec);
6674 continue;
6675 }
我们跳过上面的GCC扩展的属性。继续除type-specifier以外的decl-specifier的解析。 看到在这些项中,friend,function-specifier,typedef,storage-class-specifier都必须在后面跟有type-specifier(注意break语句)。局部变量decl_spec<