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

5.12.3.2.1.1.2.          开始类定义

跟在class-head后,应该是符号“{”,那么在下面的11890行的函数cp_parser_check_type_definition 检查定义新的类型在当前上下文是否允许(通过检查parsertype_definition_forbidden_message是否为non-null)。

 

cp_parser_class_specifier (continue)

 

11882  /* Look for the `{'.  */

11883   if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"))

11884   {

11885     pop_deferring_access_checks ();

11886     return error_mark_node;

11887   }

11888

11889   /* Issue an error message if type-definitions are forbidden here.  */

11890   cp_parser_check_type_definition (parser);

11891   /* Remember that we are defining one more class.  */

11892   ++parser->num_classes_being_defined;

11893  /* Inside the class, surrounding template-parameter-lists do not

11894     apply.  */

11895   saved_num_template_parameter_lists

11896        = parser->num_template_parameter_lists;

11897   parser->num_template_parameter_lists = 0;

11898

11899   /* Start the class.  */

11900   if (nested_name_specifier_p)

11901   {

11902     scope = CP_DECL_CONTEXT (TYPE_MAIN_DECL (type));

11903     pop_p = push_scope (scope);

11904   }

11905   type = begin_class_definition (type);

 

一旦看到“{”符号,就需要为类准备上下文,并使其成为当前的上下文环境。

 

2011 tree

2012 begin_class_definition (tree t)                                                              in semantics.c

2013 {

2014   if (t == error_mark_node)

2015     return error_mark_node;

2016

2017   if (processing_template_parmlist)

2018   {

2019     error ("definition of `%#T' inside template parameter list", t);

2020     return error_mark_node;

2021   }

2022   /* A non-implicit typename comes from code like:

2023

2024       template <typename T> struct A {

2025       template <typename U> struct A<T>::B ...

2026

2027     This is erroneous.  */

2028   else if (TREE_CODE (t) == TYPENAME_TYPE)

2029   {

2030     error ("invalid definition of qualified type `%T'", t);

2031     t = error_mark_node;

2032   }

2033

2034   if (t == error_mark_node || ! IS_AGGR_TYPE (t))

2035   {

2036     t = make_aggr_type (RECORD_TYPE);

2037     pushtag (make_anon_name (), t, 0);

2038   }

2039

2040  /* If this type was already complete, and we see another definition,

2041     that's an error.  */

2042   if (COMPLETE_TYPE_P (t))

2043   {

2044     error ("redefinition of `%#T'", t);

2045     cp_error_at ("previous definition of `%#T'", t);

2046     return error_mark_node;

2047   }

2048

2049   /* Update the location of the decl.  */

2050   DECL_SOURCE_LOCATION (TYPE_NAME (t)) = input_location;

2051  

2052   if (TYPE_BEING_DEFINED (t))

2053   {

2054     t = make_aggr_type (TREE_CODE (t));

2055     pushtag (TYPE_IDENTIFIER (t), t, 0);

2056   }

2057   maybe_process_partial_specialization (t);

2058   pushclass (t);

 

上面,TYPE_BEING_DEFINED如果非0,表示我们正在定义一个类型,对于我们的例子,这个标记将在不久后被设置,但现在这个域是0

进一步的,如果声明的不是目标的偏特化,例程maybe_process_partial_specialization不做任何事情。那么对于我们在该函数内第一件有意义的事情,是调用pushclass来建立该类的上下文。

C++中的类是可以嵌套定义的,每个类都构成了一个自己的作用域。显而易见,这些打开的类构成了一个栈。在前端中,current_class_stack就是这样的栈。它由class_stack_node_t节点构成。

 

50    typedef struct class_stack_node {                                                                 in class.c

51      /* The name of the class.  */

52      tree name;

53   

54      /* The _TYPE node for the class.  */

55      tree type;

56   

57      /* The access specifier pending for new declarations in the scope of

58        this class.  */

59      tree access;

60   

61      /* If were defining TYPE, the names used in this class.  */

62      splay_tree names_used;

63    }* class_stack_node_t;

 

那么当进入pushclass时,首先把封闭类(enclosing class)压入栈中(虽然该类现为current_class_name所指向,它实际上已经是前一个类了,当前类是正在处理的这个),而变量currnet_class_depth则记录了栈的深度。

 

5452 void

5453 pushclass (tree type)                                                                                   in class.c

5454 {

5455   type = TYPE_MAIN_VARIANT (type);

5456

5457  /* Make sure there is enough room for the new entry on the stack.  */

5458  if (current_class_depth + 1 >= current_class_stack_size)

5459   {

5460     current_class_stack_size *= 2;

5461     current_class_stack

5462           = xrealloc (current_class_stack,

5463                    current_class_stack_size

5464                    * sizeof (struct class_stack_node));

5465   }

5466

5467   /* Insert a new entry on the class stack.  */

5468   current_class_stack[current_class_depth].name = current_class_name;

5469   current_class_stack[current_class_depth].type = current_class_type;

5470   current_class_stack[current_class_depth].access = current_access_specifier;

5471   current_class_stack[current_class_depth].names_used = 0;

5472   current_class_depth++;

5473

5474   /* Now set up the new type.  */

5475   current_class_name = TYPE_NAME (type);

5476   if (TREE_CODE (current_class_name) == TYPE_DECL)

5477     current_class_name = DECL_NAME (current_class_name);

5478   current_class_type = type;

5479

5480   /* By default, things in classes are private, while things in

5481     structures or unions are public.  */

5482   current_access_specifier = (CLASSTYPE_DECLARED_CLASS (type)

5483                          ? access_private_node

5484                            : access_public_node);

5485

5486   if (previous_class_type != NULL_TREE

5487       && (type != previous_class_type

5488            || !COMPLETE_TYPE_P (previous_class_type))

5489       && current_class_depth == 1)

5490   {

5491     /* Forcibly remove any old class remnants.  */

5492     invalidate_class_lookup_cache ();

5493   }

5494

5495   /* If we're about to enter a nested class, clear

5496     IDENTIFIER_CLASS_VALUE for the enclosing classes.  */

5497   if (current_class_depth > 1)

5498     clear_identifier_class_values ();

 

当前类的信息则保存在全局变量scope_chain里,部分相关宏的定义如下。

 

240  #define class_binding_level scope_chain->class_bindings                               in cp-tree.h

727  #define current_class_name scope_chain->class_name      

738  #define current_access_specifier scope_chain->access_specifier

756  #define previous_class_type scope_chain->x_previous_class_type

 

如果current_class_depth1,这表示我们进入类栈顶。previous_class_type,如果我们之前访问过类栈,则指向前一个位于栈顶的这个类,这在popclass中设置。同时previous_class_value保存了previous_class_type类中的项。如果当前类与previous_class_type相同,这些缓存的数据能大大加快类上下文环境建立的速度。而如果当前类与previous_class_type不相同,就没有必要保留这些数据了。

 

5548 void

5549 invalidate_class_lookup_cache (void)                                                          in class.c

5550 {

5551   tree t;

5552  

5553   /* The IDENTIFIER_CLASS_VALUEs are no longer valid.  */

5554   for (t = previous_class_values; t; t = TREE_CHAIN (t))

5555     IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE;

5556

5557   previous_class_values = NULL_TREE;

5558   previous_class_type = NULL_TREE;

5559 }

 

如果current_class_depth大于1,意味着我们正深入类栈,对于这个情形,class_binding_level指向封闭类(enclosing class)。域class_shadowed用作绑定在该类域中标识符的缓存,这些标识符的IDENTIFIER_CLASS_VALUE域被设置为绑定时的值。因为我们马上就要更新class_binding_level,这些IDENTIFIER_CLASS_VALUE首先要被清零。

 

2713 void

2714 clear_identifier_class_values (void)                                                      in name-lookup.c

2715 {

2716   tree t;

2717

2718   if (!class_binding_level)

2719     return;

2720

2721   for (t = class_binding_level->class_shadowed;

2722        t;

2723        t = TREE_CHAIN (t))

2724     IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE;

2725 }

 

随后通过pushlevel_class,我们使得当前正在定义的类的作用域成为当前作用域(即被current_binding_levelclass_binding_level所指向。

 

pushclass (continue)

 

5500   pushlevel_class ();

 

在前端中,class_binding_level指向当前打开的最里层的类域,或者最近打开的类域(如果我们当前不在类域中)。因而我们将得到类似下图的中间树的布局,看到绑定域被创建,已准备好接收成员定义了。

 

2570 void

2571 pushlevel_class (void)                                                                         in name-lookup.c

2572 {

2573   if (ENABLE_SCOPE_CHECKING)

2574     is_class_level = 1;

2575

2576   class_binding_level = begin_scope (sk_class, current_class_type);

2577 }

 

点此打开

59SingleThreaded作为当前作用域

因为对于我们的例子,previous_class_typenull5502行的条件满足。块中的代码加入类的域,不过当前,该类还没有任何域,因此这些代码不作任何事(对于派生类,这些代码将加入代表基类的域)。

 

pushclass (continue)

 

5502     if (type != previous_class_type || current_class_depth > 1)

5503     {

5504       push_class_decls (type);

5505       if (CLASSTYPE_TEMPLATE_INFO (type) && !CLASSTYPE_USE_TEMPLATE (type))

5506       {

5507         /* If we are entering the scope of a template declaration (not a

5508           specialization), we need to push all the using decls with

5509           dependent scope too.  */

5510         tree fields;

5511  

5512         for (fields = TYPE_FIELDS (type);

5513             fields; fields = TREE_CHAIN (fields))

5514           if (TREE_CODE (fields) == USING_DECL && !TREE_TYPE (fields))

5515            pushdecl_class_level (fields);

5516       }

5517     }

      

5540     cxx_remember_type_decls (CLASSTYPE_NESTED_UTDS (type));

5541   }

 

在上面的5540行,在CLASSTYPE_NESTED_UTDS中的NESTED_UTDS表示嵌套的用户定义类型的意思。这个宏访问一个保存该类中所有嵌套的用户定义类型的绑定表。注意下面的current_binding_level返回的是cp_binding_level(也即是cxx_scope)对象,代表当前作用域。其type_decl项表示在该作用域中所声明的类型。当一个类成为当前作用域时,代表类的节点与代表作用域的节点要同步。

 

1542 void

1543 cxx_remember_type_decls (binding_table table)                                    in name-lookup.c

1544 {

1545   current_binding_level->type_decls = table;

1546 }

 

然后,回到begin_class_definition,注意到2059行的TYPE_BEING_DEFINED,它表示类的定义尚未完整。

 

begin_class_definition (continue)

 

2059   TYPE_BEING_DEFINED (t) = 1;

2060   if (flag_pack_struct)

2061   {

2062     tree v;

2063     TYPE_PACKED (t) = 1;

2064     /* Even though the type is being defined for the first time

2065       here, there might have been a forward declaration, so there

2066       might be cv-qualified variants of T.  */

2067     for (v = TYPE_NEXT_VARIANT (t); v; v = TYPE_NEXT_VARIANT (v))

2068       TYPE_PACKED (v) = 1;

2069   }

2070   /* Reset the interface data, at the earliest possible

2071     moment, as it might have been set via a class foo;

2072     before.  */

2073   if (! TYPE_ANONYMOUS_P (t))

2074   {

2075     CLASSTYPE_INTERFACE_ONLY (t) = interface_only;

2076     SET_CLASSTYPE_INTERFACE_UNKNOWN_X

2077                                               (t, interface_unknown);

2078   }

2079   reset_specialization();

2080  

2081   /* Make a declaration for this class in its own scope.  */

2082   build_self_reference ();

2083

2084   return t;

2085 }

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值