Studying note of GCC-3.4.6 source (92)
来源:互联网 发布:js删除对象中的元素 编辑:程序博客网 时间:2024/04/28 01:24
5.12.1.2. Parse decl-specifier-seq part of template declaration
During parsing, we may encounter error statement, to continue parsing as possible, it is prefer to advance to the nearest “>” (of course, if the statement is correct, the next token should be “>”). Next for parsing member template like:
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) {}
At line 14458 checks for the part “template<class T2>” of the method and processes it in recursion at line 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 }
In the statement of our run-through example, the unparsed part is: “class SingleThreaded {…”; according to the syntax rule, it should be decl-specifier-seq. Structure decl-specifier-seq contains sequence of decl-specifier, which is a complex structure shown in below.
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 (); In below function, if declares_class_or_enum is non-null, *declares_class_or_enum is set to the bitwise or of the following flags: 1: one of the decl-specifiers is an elaborated-type-specifier (i.e., a type declaration) 2: one of the decl-specifiers is an enum-specifier or a class-specifier (i.e., a type definition) 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 } We skip GCC entension attribution above and go on for the handling of decl-specifier excluding type-specifier. See that among these items, friend, function-specifier, typedef, storage-class-specifier must be followed by type-specifier (see the break statement). Local variable decl_spec records the information about these items. cp_parser_decl_specifier_seq (continue) 6676 /* If the next token is an appropriate keyword, we can simply 6677 add it to the list. */ 6678 switch (token->keyword) 6679 { 6680 case RID_FRIEND: 6681 /* decl-specifier: 6682 friend */ 6683 if (friend_p) 6684 error ("duplicate `friend'"); 6685 else 6686 friend_p = true; 6687 /* The representation of the specifier is simply the 6688 appropriate TREE_IDENTIFIER node. */ 6689 decl_spec = token->value; 6690 /* Consume the token. */ 6691 cp_lexer_consume_token (parser->lexer); 6692 break; 6693 6694 /* function-specifier: 6695 inline 6696 virtual 6697 explicit */ 6698 case RID_INLINE: 6699 case RID_VIRTUAL: 6700 case RID_EXPLICIT: 6701 decl_spec = cp_parser_function_specifier_opt (parser); 6702 break; 6703 6704 /* decl-specifier: 6705 typedef */ 6706 case RID_TYPEDEF: 6707 /* The representation of the specifier is simply the 6708 appropriate TREE_IDENTIFIER node. */ 6709 decl_spec = token->value; 6710 /* Consume the token. */ 6711 cp_lexer_consume_token (parser->lexer); 6712 /* A constructor declarator cannot appear in a typedef. */ 6713 constructor_possible_p = false; 6714 /* The "typedef" keyword can only occur in a declaration; we 6715 may as well commit at this point. */ 6716 cp_parser_commit_to_tentative_parse (parser); 6717 break; 6718 6719 /* storage-class-specifier: 6720 auto 6721 register 6722 static 6723 extern 6724 mutable 6725 6726 GNU Extension: 6727 thread */ 6728 case RID_AUTO: 6729 case RID_REGISTER: 6730 case RID_STATIC: 6731 case RID_EXTERN: 6732 case RID_MUTABLE: 6733 case RID_THREAD: 6734 decl_spec = cp_parser_storage_class_specifier_opt (parser); 6735 break; 6736 6737 default: 6738 break; 6739 } Routine cp_parser_function_specifier_opt and cp_parser_storage_class_specifier_opt just double check expected token fetched. In the language, decl-specifier-seq specify how names are to be interpreted, while a declarator delcares a single object, function, or type, within a declaration. Considering constructor, for example: class A { public: A(); }; In A(); A should not be parsed as decl-specifier, it is not declaration, instead it is declarator. Notice that A() aligns with the format of simple-declaration, it hasn’t decl-specifier part. As it is a such special case, it needs be handled specially. Of course, it will not be a problem during parsing declarator, note that at line 6713, constructor_possible_p is the reverse of in_declarator_p slot in parser which is true during parsing declarator. cp_parser_decl_specifier_seq (continue) 6741 /* Constructors are a special case. The `S' in `S()' is not a 6742 decl-specifier; it is the beginning of the declarator. */ 6743 constructor_p = (!decl_spec 6744 && constructor_possible_p 6745 && cp_parser_constructor_declarator_p (parser, 6746 friend_p)); Also notice that parsing of constructor here never consumes tokens no matter it successes or not as it is not decl-specifier but declarator. And finding it just means error. To avoid deviating to far away from our focus, we just skip the parsing of constructor here temperarily. If above cases can’t be found, now we can try type-specifier as below. Type-specifier is the key part of decl-specifier-seq, which is the major part of the declaration. cp_parser_decl_specifier_seq (continue) 6748 /* If we don't have a DECL_SPEC yet, then we must be looking at 6749 a type-specifier. */ 6750 if (!decl_spec && !constructor_p) 6751 { 6752 int decl_spec_declares_class_or_enum; 6753 bool is_cv_qualifier; 6754 6755 decl_spec 6756 = cp_parser_type_specifier (parser, flags, 6757 friend_p, 6758 /*is_declaration=*/true, 6759 &decl_spec_declares_class_or_enum, 6760 &is_cv_qualifier); 6761 6762 *declares_class_or_enum |= decl_spec_declares_class_or_enum; 6763 6764 /* If this type-specifier referenced a user-defined type 6765 (a typedef, class-name, etc.), then we can't allow any 6766 more such type-specifiers henceforth. 6767 6768 [dcl.spec] 6769 6770 The longest sequence of decl-specifiers that could 6771 possibly be a type name is taken as the 6772 decl-specifier-seq of a declaration. The sequence shall 6773 be self-consistent as described below. 6774 6775 [dcl.type] 6776 6777 As a general rule, at most one type-specifier is allowed 6778 in the complete decl-specifier-seq of a declaration. The 6779 only exceptions are the following: 6780 6781 -- const or volatile can be combined with any other 6782 type-specifier. 6783 6784 -- signed or unsigned can be combined with char, long, 6785 short, or int. 6786 6787 -- .. 6788 6789 Example: 6790 6791 typedef char* Pc; 6792 void g (const int Pc); 6793 6794 Here, Pc is *not* part of the decl-specifier seq; it's 6795 the declarator. Therefore, once we see a type-specifier 6796 (other than a cv-qualifier), we forbid any additional 6797 user-defined types. We *do* still allow things like `int 6798 int' to be considered a decl-specifier-seq, and issue the 6799 error message later. */ 6800 if (decl_spec && !is_cv_qualifier) 6801 flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES; 6802 /* A constructor declarator cannot follow a type-specifier. */ 6803 if (decl_spec) 6804 constructor_possible_p = false; 6805 } The abbreviate syntax tree of type-specifier is shown in below. type-specifier ├ simple-type-specifier ├ class-specifier ├ enum-specifier ├ elaborated-type-specifier ├ cv-qualifier GUN ext Ⅼ __complex__ In below function, parameter declares_class_or_enum if non-null, and the type-specifier is a class-specifier, enum-specifier, or elaborated-type-specifier, then *declares_class_or_enum is set to a nonzero value. The value is 1 if a type is declared, 2 if it is defined; otherwise, it is set to zero. And if is_cv_qualifier is non-null, and the type-specifier is a cv-qualifier, then *is_cv_qualifier is set to true; otherwise, it is set to false. 8713 static tree 8714 cp_parser_type_specifier (cp_parser* parser, in parser.c 8715 cp_parser_flags flags, 8716 bool is_friend, 8717 bool is_declaration, 8718 int* declares_class_or_enum, 8719 bool* is_cv_qualifier) 8720 { 8721 tree type_spec = NULL_TREE; 8722 cp_token *token; 8723 enum rid keyword; 8724 8725 /* Assume this type-specifier does not declare a new type. */ 8726 if (declares_class_or_enum) 8727 *declares_class_or_enum = 0; 8728 /* And that it does not specify a cv-qualifier. */ 8729 if (is_cv_qualifier) 8730 *is_cv_qualifier = false; 8731 /* Peek at the next token. */ 8732 token = cp_lexer_peek_token (parser->lexer); 8733 8734 /* If we're looking at a keyword, we can use that to guide the 8735 production we choose. */ 8736 keyword = token->keyword; 8737 switch (keyword) 8738 { 8739 case RID_ENUM: ... 8763 /* Any of these indicate either a class-specifier, or an 8764 elaborated-type-specifier. */ 8765 case RID_CLASS: 8766 case RID_STRUCT: 8767 case RID_UNION: 8768 /* Parse tentatively so that we can back up if we don't find a 8769 class-specifier or enum-specifier. */ 8770 cp_parser_parse_tentatively (parser); 8771 /* Look for the class-specifier. */ 8772 type_spec = cp_parser_class_specifier (parser); 8773 /* If that worked, we're done. */ 8774 if (cp_parser_parse_definitely (parser)) 8775 { 8776 if (declares_class_or_enum) 8777 *declares_class_or_enum = 2; 8778 return type_spec; 8779 } The coming tokens of the second statement of our example form the class-specifier. They are further handled by cp_parser_class_specifier. 5.12.3.2.1. Parse type-specifier
- Studying note of GCC-3.4.6 source (92)
- Studying note of GCC-3.4.6 source (6)
- Studying note of GCC-3.4.6 source (1)
- Studying note of GCC-3.4.6 source (2)
- Studying note of GCC-3.4.6 source (3)
- Studying note of GCC-3.4.6 source (4)
- Studying note of GCC-3.4.6 source (5)
- Studying note of GCC-3.4.6 source (7)
- Studying note of GCC-3.4.6 source (8)
- Studying note of GCC-3.4.6 source (9)
- Studying note of GCC-3.4.6 source (10)
- Studying note of GCC-3.4.6 source (10 cont1)
- Studying note of GCC-3.4.6 source (10 cont2)
- Studying note of GCC-3.4.6 source (10 cont3)
- Studying note of GCC-3.4.6 source (10 cont4)
- Studying note of GCC-3.4.6 source (11)
- Studying note of GCC-3.4.6 source (12)
- Studying note of GCC-3.4.6 source (13)
- Ravens rise to 8th most valuable NFL franchise
- ASP读取ACCESS数据库随机记录的方法
- Section 2.2 Runaround Numbers
- 详解javascript类继承机制的原理
- 用API OleLoadPicture通过IStream来加载JPG、GIF格式的图片
- Studying note of GCC-3.4.6 source (92)
- 竞争优势-2009年写的第八篇日记
- 图形视图框架(The QGraphics View Framework)
- 读取 显示 jpeg stream 视频流
- 利用ASP控制WEB打印代码方法集合
- .NET ArrayList 的排序的使用
- 朦胧的您-2009年写的第九篇日记
- 学生选课系统pb课程设计
- 浅谈如何增强ASP程序性能