GCC-3.4.6源代码学习笔记(98)

5.12.3.2.1.1.3.          解析类体

正常的话,跟在class-head后面的符号应该是“{”,不过要是发生了错误,就不能肯定该符号一定会出现。保险起见,“}”之前的符号都将丢弃,并触发错误。否则,就可以继续放心地解析member-specification部分。

 

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 `}'.  */

 

这个函数尝试按照下面的语法树解析符号。

{ 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 }

 

注意current_access_specifier确实记录了随后的成员的访问属性。而member-declaration部分由cp_parser_member_declaration来处理,这部分语法相当复杂。

t

至于我们的例子,第一个成员是:

public:

   struct Lock {

      Lock() {}

      Lock(const Host&) {}

};

这是一个嵌套类定义。作为宿主类的一个成员,它将由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);

 

这第一个成员依照decl-specifier-seq的规则来编译,而这正是我们当前正在解析的(即路径member-specifier à class-specifier à type-specifier à decl-specifier)。该规则递归了!同样适用于这第一个成员的规则也是class-specifier。其处理过程也相当相似,不过下面的pushtag的处理各有不同。

5.12.3.2.1.1.3.1.    加入嵌套类的标签

同样的,为该类创建了RECORD_TYPE节点。

 

xref_tag (continue)

 

9571       t = make_aggr_type (code);

9572       TYPE_CONTEXT (t) = context;

9573       pushtag (name, t, globalize);

 

注意到这里globalizefalsecurrent_binding_level返回类SingleThreaded的作用域在这里是b

 

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);

 

上面name指向标识符“Lock”,这是个新标识符,因而其type域是NULL(由IDENTIFIER_TYPE_VALUE检查)。然后我们将获得如下的中间树,其中蓝色的节点是这次调用所构建的。

点此打开

63:为嵌套类“Lock”加入标签

5.12.3.2.1.1.3.2.    为嵌套类创建TEMPLATE_DECL

maybe_process_template_type_declaration中,因为我们仍然在类模板“SingleThreaded”的定义之中,并且processing_template_parms记录了打开的模板定义(声明)的层数—现在是1。因为类“Lock”是声明在类模板之中,它自己也是泛型类型。

 

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 }

 

更进一步的,因为是类模板中的嵌套类,在函数push_template_decl_real中,primary则是0。注意到current_template_parms直到现在还未改变,根据其创建出同样的args

 

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 }

 

经过相似的过程,嵌套类“Lock”的RECORD_TYPEtemplate_info处的所被创建的子树如下图中红色节点。

点此打开

64:类“Lock”的TEMPLATE_DECL子树

当从maybe_process_template_type_declaration返回时,在pushtag4661行,PROCESSING_REAL_TEMPLATE_DECL_P返回非0,因而执行pushdecl_class_level,在封闭类中加入嵌套类,实际执行的是以下的代码片段。

 

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   }

 

下面重新列出push_class_level_binding。在一个类模板里面, check_template_shadow仍然称职地检查该嵌套类的定义是否会屏蔽模板参数。

 

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 }

 

那么其IDNETIFIER_NODEbindings域记录了其所在的非名字空间作用域,这是名字查找时,非常重要的数据结构(该数据由上面的push_class_binding构建)。另一方面, 封闭类的class_shadowed域则记录了其中所声明的类型,当push_class_binding成功,就为之构建。那么现在中间树看起来如下。

点此打开

65:为嵌套类“Lock”加入标签—完成

5.12.3.2.1.1.3.3.    开始嵌套类定义

通过同样的路径,嵌套类“Lock”调用pushclass,在这其中把类“SingleThreaded”加入current_class_stack,而后current_class_type被更新为“Lock”。而被“SingleThreaded”掩蔽的IDENTIFIER_NODE节点的class_value域都被清零,因为这个域应该总是保存该名字当前的类型,而现在不知道这个名字是否会被重新声明(clear_identifier_class_values)。接着pushlevel_class开始了“Lock”的作用域。在pushclass 5504行的push_class_decls,该函数将填充的current_class_type基类,以及其域的IDENTIFIER_NODE节点的class_values域,使其成为当前作用域中使用得的类型。在这里,这个函数也是不作任何事情。

进一步的,通过类似的对自己引用的构建过程(参考构建对自己的引用),中间树看起来就像下面。

点此打开

66:开始“Lock”的类定义—对自己的引用

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值