Studying note of GCC-3.4.6 source (98)

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.

t

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

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值