Studying note of GCC-3.4.6 source (98)
来源:互联网 发布:网络求医皮肤 编辑:程序博客网 时间:2024/06/15 02:52
If valid, token follows class-head should be “{“, however when error occurs, it is no sure that token can appear. Taking a conservative approach, tokens before “}” will be abandoned with error. Otherwise, it can happily continue to parse member-specification part.
cp_parser_class_specifier (continue)
11906 if (type == error_mark_node)
11907 /* If the type is erroneous, skip the entire body of the class. */
11908 cp_parser_skip_to_closing_brace (parser);
11909 else
11910 /* Parse the member-specification. */
11911 cp_parser_member_specification_opt (parser);
11912 /* Look for the trailing `}'. */
This routine attempts to parse tokens in following syntax tree.
{ member-specification [opt] }
Ⅼ access-specifier : member-specification [opt]
Ⅼ member-declaration member-specification [opt]
12392 static void
12393 cp_parser_member_specification_opt (cp_parser* parser) in parser.c
12394 {
12395 while (true)
12396 {
12397 cp_token *token;
12398 enum rid keyword;
12399
12400 /* Peek at the next token. */
12401 token = cp_lexer_peek_token (parser->lexer);
12402 /* If it's a `}', or EOF then we've seen all the members. */
12403 if (token->type == CPP_CLOSE_BRACE || token->type == CPP_EOF)
12404 break;
12405
12406 /* See if this token is a keyword. */
12407 keyword = token->keyword;
12408 switch (keyword)
12409 {
12410 case RID_PUBLIC:
12411 case RID_PROTECTED:
12412 case RID_PRIVATE:
12413 /* Consume the access-specifier. */
12414 cp_lexer_consume_token (parser->lexer);
12415 /* Remember which access-specifier is active. */
12416 current_access_specifier = token->value;
12417 /* Look for the `:'. */
12418 cp_parser_require (parser, CPP_COLON, "`:'");
12419 break;
12420
12421 default:
12422 /* Otherwise, the next construction must be a
12423 member-declaration. */
12424 cp_parser_member_declaration (parser);
12425 }
12426 }
12427 }
See current_access_specifier indeed records the accessibility of the members following. And the member-declaration part is handled by cp_parser_member_declaration, which forms a quite complex tree.
For our example, the first coming member is: public: struct Lock { Lock() {} Lock(const Host&) {} }; It is a nested class definition. And being a member of host class, it will be handled by cp_parser_member_declaration. 12457 static void 12458 cp_parser_member_declaration (cp_parser* parser) in parser.c 12459 { 12460 tree decl_specifiers; 12461 tree prefix_attributes; 12462 tree decl; 12463 int declares_class_or_enum; 12464 bool friend_p; 12465 cp_token *token; 12466 int saved_pedantic; … 12502 /* Parse the decl-specifier-seq. */ 12503 decl_specifiers 12504 = cp_parser_decl_specifier_seq (parser, 12505 CP_PARSER_FLAGS_OPTIONAL, 12506 &prefix_attributes, 12507 &declares_class_or_enum); This first member complies with rule of decl-specifier-seq, which we are now parsing within (i.e, member-specifier à class-specifier à type-specifier à decl-specifier). The rule recurs! Also the rule applicable to the first member is also class-specifier. The handling procedure is quite similar, but each going his own way in pushtag as following. 5.12.3.2.1.1.3.1. Push tag for nested class Again the node of RECORD_TYPE is created for the class. xref_tag (continue) 9571 t = make_aggr_type (code); 9572 TYPE_CONTEXT (t) = context; 9573 pushtag (name, t, globalize); Notice that globalize here is false, and current_binding_level returns the scope of class “SingleThreaded” which is b used here. 4589 void 4590 pushtag (tree name, tree type, int globalize) in name-lookup.c 4591 { 4592 struct cp_binding_level *b; 4593 4594 timevar_push (TV_NAME_LOOKUP); 4595 b = current_binding_level; 4596 while (/* Cleanup scopes are not scopes from the point of view of 4597 the language. */ 4598 b->kind == sk_cleanup 4599 /* Neither are the scopes used to hold template parameters 4600 for an explicit specialization. For an ordinary template 4601 declaration, these scopes are not scopes from the point of 4602 view of the language -- but we need a place to stash 4603 things that will go in the containing namespace when the 4604 template is instantiated. */ 4605 || (b->kind == sk_template_parms && b->explicit_spec_p) 4606 || (b->kind == sk_class 4607 && (globalize 4608 /* We may be defining a new type in the initializer 4609 of a static member variable. We allow this when 4610 not pedantic, and it is particularly useful for 4611 type punning via an anonymous union. */ 4612 || COMPLETE_TYPE_P (b->this_entity)))) 4613 b = b->level_chain; 4614 4615 if (b->type_decls == NULL) 4616 b->type_decls = binding_table_new (SCOPE_DEFAULT_HT_SIZE); 4617 binding_table_insert (b->type_decls, name, type); 4618 4619 if (name) 4620 { 4621 /* Do C++ gratuitous typedefing. */ 4622 if (IDENTIFIER_TYPE_VALUE (name) != type) 4623 { 4624 tree d = NULL_TREE; 4625 int in_class = 0; 4626 tree context = TYPE_CONTEXT (type); … 4643 if (b->kind == sk_class 4644 || (b->kind == sk_template_parms 4645 && b->level_chain->kind == sk_class)) 4646 in_class = 1; 4647 4648 if (current_lang_name == lang_name_java) 4649 TYPE_FOR_JAVA (type) = 1; 4650 4651 d = create_implicit_typedef (name, type); 4652 DECL_CONTEXT (d) = FROB_CONTEXT (context); 4653 if (! in_class) 4654 set_identifier_type_value_with_scope (name, d, b); Above name refers to identifier of “Lock”, it is a new comer, so its type slot is NULL (checked by IDENTIFIER_TYPE_VALUE). Then we can get following intermediate tree with nodes in blue fresh created for this invocation. (Click here for open) Figure 63: Push tag for nested class “Lock” 5.12.3.2.1.1.3.2. Create TEMPLATE_DECL for nested class Within maybe_process_template_type_declaration, as we are still within the definition of the class template “SingleThreaded”, and processing_template_parms records the level of opened template definition (declaration) which is 1 now. It is not surprising, becaue class “Lock” is declared within the class template, it self is generic too. push_tag (continue) 4656 d = maybe_process_template_type_declaration (type, 4657 globalize, b); 4658 4659 if (b->kind == sk_class) 4660 { 4661 if (!PROCESSING_REAL_TEMPLATE_DECL_P ()) 4662 /* Put this TYPE_DECL on the TYPE_FIELDS list for the 4663 class. But if it's a member template class, we 4664 want the TEMPLATE_DECL, not the TYPE_DECL, so this 4665 is done later. */ 4666 finish_member_declaration (d); 4667 else 4668 pushdecl_class_level (d); 4669 } 4670 else 4671 d = pushdecl_with_scope (d, b); 4672 4673 /* FIXME what if it gets a name from typedef? */ 4674 if (ANON_AGGRNAME_P (name)) 4675 DECL_IGNORED_P (d) = 1; 4676 4677 TYPE_CONTEXT (type) = DECL_CONTEXT (d); 4678 4679 /* If this is a local class, keep track of it. We need this 4680 information for name-mangling, and so that it is possible to find 4681 all function definitions in a translation unit in a convenient 4682 way. (It's otherwise tricky to find a member function definition 4683 it's only pointed to from within a local class.) */ 4684 if (TYPE_CONTEXT (type) 4685 && TREE_CODE (TYPE_CONTEXT (type)) == FUNCTION_DECL 4686 && !processing_template_decl) 4687 VARRAY_PUSH_TREE (local_classes, type); 4688 } 4689 if (b->kind == sk_class 4690 && !COMPLETE_TYPE_P (current_class_type)) 4691 { 4692 maybe_add_class_template_decl_list (current_class_type, 4693 type, /*friend_p=*/0); 4694 CLASSTYPE_NESTED_UTDS (current_class_type) = b->type_decls; 4695 } 4696 } 4697 4698 if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL) 4699 /* Use the canonical TYPE_DECL for this node. */ 4700 TYPE_STUB_DECL (type) = TYPE_NAME (type); 4701 else 4702 { … 4713 } 4714 timevar_pop (TV_NAME_LOOKUP); 4715 } What’s more, it is the nested class of the class template, in routine push_template_decl_real, primary found is zero. Also seeing that current_template_parms is unchanged till now, and same args are created from. 2770 tree 2771 push_template_decl_real (tree decl, int is_friend) in pt.c 2772 { 2773 tree tmpl; 2774 tree args; 2775 tree info; 2776 tree ctx; 2777 int primary; 2778 int is_partial; 2779 int new_template_p = 0; 2780 2781 /* See if this is a partial specialization. */ 2782 is_partial = (DECL_IMPLICIT_TYPEDEF_P (decl) 2783 && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE 2784 && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl))); 2785 2786 is_friend |= (TREE_CODE (decl) == FUNCTION_DECL && DECL_FRIEND_P (decl)); 2787 2788 if (is_friend) 2789 /* For a friend, we want the context of the friend function, not 2790 the type of which it is a friend. */ 2791 ctx = DECL_CONTEXT (decl); 2792 else if (CP_DECL_CONTEXT (decl) 2793 && TREE_CODE (CP_DECL_CONTEXT (decl)) != NAMESPACE_DECL) 2794 /* In the case of a virtual function, we want the class in which 2795 it is defined. */ 2796 ctx = CP_DECL_CONTEXT (decl); 2797 else 2798 /* Otherwise, if we're currently defining some class, the DECL 2799 is assumed to be a member of the class. */ 2800 ctx = current_scope (); 2801 2802 if (ctx && TREE_CODE (ctx) == NAMESPACE_DECL) 2803 ctx = NULL_TREE; 2804 2805 if (!DECL_CONTEXT (decl)) 2806 DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace); 2807 2808 /* See if this is a primary template. */ 2809 primary = template_parm_scope_p (); 2810 2811 if (primary) 2812 { … 2852 } 2853 2854 /* Check to see that the rules regarding the use of default 2855 arguments are not being violated. */ 2856 check_default_tmpl_args (decl, current_template_parms, 2857 primary, is_partial); 2858 2859 if (is_partial) 2860 return process_partial_specialization (decl); 2861 2862 args = current_template_args (); 2863 2864 if (!ctx 2865 || TREE_CODE (ctx) == FUNCTION_DECL 2866 || (CLASS_TYPE_P (ctx) && TYPE_BEING_DEFINED (ctx)) 2867 || (is_friend && !DECL_TEMPLATE_INFO (decl))) 2868 { 2869 if (DECL_LANG_SPECIFIC (decl) 2870 && DECL_TEMPLATE_INFO (decl) 2871 && DECL_TI_TEMPLATE (decl)) 2872 tmpl = DECL_TI_TEMPLATE (decl); 2873 /* If DECL is a TYPE_DECL for a class-template, then there won't 2874 be DECL_LANG_SPECIFIC. The information equivalent to 2875 DECL_TEMPLATE_INFO is found in TYPE_TEMPLATE_INFO instead. */ 2876 else if (DECL_IMPLICIT_TYPEDEF_P (decl) 2877 && TYPE_TEMPLATE_INFO (TREE_TYPE (decl)) 2878 && TYPE_TI_TEMPLATE (TREE_TYPE (decl))) 2879 { … 2888 } 2889 else 2890 { 2891 tmpl = build_template_decl (decl, current_template_parms); 2892 new_template_p = 1; 2893 2894 if (DECL_LANG_SPECIFIC (decl) 2895 && DECL_TEMPLATE_SPECIALIZATION (decl)) 2896 { … 2902 } 2903 } 2904 } … 2997 DECL_TEMPLATE_RESULT (tmpl) = decl; 2998 TREE_TYPE (tmpl) = TREE_TYPE (decl); … 3031 info = tree_cons (tmpl, args, NULL_TREE); 3032 3033 if (DECL_IMPLICIT_TYPEDEF_P (decl)) 3034 { 3035 SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info); 3036 if ((!ctx || TREE_CODE (ctx) != FUNCTION_DECL) 3037 && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE 3038 /* Don't change the name if we've already set it up. */ 3039 && !IDENTIFIER_TEMPLATE (DECL_NAME (decl))) 3040 DECL_NAME (decl) = classtype_mangled_name (TREE_TYPE (decl)); 3041 } 3042 else if (DECL_LANG_SPECIFIC (decl)) 3043 DECL_TEMPLATE_INFO (decl) = info; 3044 3045 return DECL_TEMPLATE_RESULT (tmpl); 3046 } With similar procedure, sub-tree for template_info of the RECORD_TYPE of the nested class “Lock” is created as below figure. (Click here for open) Figure 64: sub-tree for TEMPLATE_DECL of class “Lock” When returning from maybe_process_template_type_declaration, in pushtag at line 4661, PROCESSING_REAL_TEMPLATE_DECL_P returns nonzero; and as result it executes pushdecl_class_level to push the nested class within the enclosing scope, which in fact runs following code snippet. pushdecl_class_level 2740 name = DECL_NAME (x); 2741 2742 if (name) 2743 { 2744 is_valid = push_class_level_binding (name, x); 2745 if (TREE_CODE (x) == TYPE_DECL) 2746 set_identifier_type_value (name, x); 2747 } It is worth seeing push_class_level_binding again in below. See that as within a class template, check_template_shadow faithfully checks for us if the declaration of this nested class shadows the template parameter. 2772 bool 2773 push_class_level_binding (tree name, tree x) in namespace-lookup.c 2774 { … 2783 /* Make sure that this new member does not have the same name 2784 as a template parameter. */ 2785 if (TYPE_BEING_DEFINED (current_class_type)) 2786 check_template_shadow (x); … 2824 /* If this declaration shadows a declaration from an enclosing 2825 class, then we will need to restore IDENTIFIER_CLASS_VALUE when 2826 we leave this class. Record the shadowed declaration here. */ 2827 binding = IDENTIFIER_BINDING (name); … 2880 /* If we didn't replace an existing binding, put the binding on the 2881 stack of bindings for the identifier, and update the shadowed list. */ 2882 if (push_class_binding (name, x)) 2883 { 2884 class_binding_level->class_shadowed 2885 = tree_cons (name, NULL, 2886 class_binding_level->class_shadowed); 2887 /* Record the value we are binding NAME to so that we can know 2888 what to pop later. */ 2889 TREE_TYPE (class_binding_level->class_shadowed) = x; 2890 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true); 2891 } 2892 2893 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, false); 2894 } Thus bindings field of the IDNETIFIER_NODE records the non-namespace enclosing scope(s), it is an important data for name look-up (this data is built by push_class_binding above). On the other hand, class_shadowed field of the enclosing class keeps track of types declared within, which is built up when push_class_binding successes. Then the intermediate tree becomes following shape. (Click here for open) Figure 65: Push tag for nested class “Lock” - finish 5.12.3.2.1.1.3.3. Begin nested class defintion In exactly the same path, the nested class “Lock” invokes pushclass which push class “SingleThreaded” into current_class_stack, and then current_class_type is updated as “Lock”. And class_value field of IDENTIFIER_NODEs shadowed by “SingleThreaded” are cleaned as this field should always caches currently effective type of the name, and now it doesn’t know whether the name will be redeclared (clear_identifier_class_values). Next pushlevel_class begins the scope of “Lock”, push_class_decls at line 5504 in pushclass, the function will fill class_values of IDENTIFIER_NODEs for fields of the bases of current_class_type and the bases themselves to make them the version in the scope. Here, again this function does nothing. Now intermediate tree is shown in below. Further by similar self reference creation proccess (refers to Build self reference), the self reference member is created as following figure. (Click here for open) Figure 66: Begin class definition of “Lock” – self reference
- Studying note of GCC-3.4.6 source (98)
- 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)
- CListCtrl控件的详细用法
- CListCtrl控件的详细用法
- PHP中的串行化变量和序列化对象
- 最好的开发语言和编译器
- SQL中distinct的用法
- Studying note of GCC-3.4.6 source (98)
- 包和dll
- 关于 alert弹出消息的问题
- 生成验证码图片
- Using log4Net
- Delphi中关于DES加密解密的方法
- Sql Server2005中Sql Server身份验证无法登录问题
- java调用php的webService
- 模拟电子技术37 56-------- 常见复合管 NPN+NPN