您的位置:首页 > 编程语言

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

2010-09-03 11:32 471 查看
5.12.3.2.1.1.2.1. 构建对自己的引用
在2082行,根据ISO-IEC-14882-2003的要求,函数build_self_reference构建了一个对自己的伪引用,使得Derived::Base(及A::A)能够工作
“类名亦加入类作用域本身。出于访问检查的目的,加入的类名被视为公有成员名。”

6290 void
6291 build_self_reference (void) in class.c
6292 {
6293 tree name = constructor_name (current_class_type);
6294 tree value = build_lang_decl (TYPE_DECL, name, current_class_type);
6295 tree saved_cas;
6296
6297 DECL_NONLOCAL (value) = 1;
6298 DECL_CONTEXT (value) = current_class_type;
6299 DECL_ARTIFICIAL (value) = 1;
6300 SET_DECL_SELF_REFERENCE_P (value);
6301
6302 if (processing_template_decl)
6303 value = push_template_decl (value);
6304
6305 saved_cas = current_access_specifier;
6306 current_access_specifier = access_public_node;
6307 finish_member_declaration (value);
6308 current_access_specifier = saved_cas;
6309 }

constructor_name负责为类获取正确的名字。它需要考虑模板特化的命名。

1792 tree
1793 constructor_name (tree type) in name-lookup.c
1794 {
1795 tree name;
1796 name = constructor_name_full (type);
1797 if (IDENTIFIER_TEMPLATE (name))
1798 name = IDENTIFIER_TEMPLATE (name);
1799 return name;
1800 }

这里我们把名字“SingleThreaded”给予这个类,constructor_name_full把对应的标识符节点返回给我们。

1777 tree
1778 constructor_name_full (tree type) in name-lookup.c
1779 {
1780 type = TYPE_MAIN_VARIANT (type);
1781 if (CLASS_TYPE_P (type) && TYPE_WAS_ANONYMOUS (type)
1782 && TYPE_HAS_CONSTRUCTOR (type))
1783 return DECL_NAME (OVL_CURRENT (CLASSTYPE_CONSTRUCTORS (type)));
1784 else
1785 return TYPE_IDENTIFIER (type);
1786 }

看到在上面6306行,公有的访问属性被赋予了这个引用,然后它被作为类成员加入。注意到参数decl包含了build_lang_decl由分配的lang_specific节点,这使得DECL_LANG_SPECIFIC返回非空值。而它的DECL_CONTEXT域表示其声明所在的作用域。这里在6298行,这是它自己本身。
5.12.3.2.1.1.2.2. 为自己的引用构建TEMPLATE_DECL
作为一个模板类,在build_self_reference的6302行,processing_template_parms是非0值,表示模板声明尚未结束。

3048 tree
3049 push_template_decl (tree decl) in pt.c
3050 {
3051 return push_template_decl_real (decl, 0);
3052 }

这次当进入push_template_decl_real时,下面获取的ctx是类模板的RECORD_TYPE,它在build_self_reference中被设为该TYPE_DECL的上下文。 而现在current_binding_level 指向类的作用域,因而下面的primary是0。

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 {

3041 }
3042 else if (DECL_LANG_SPECIFIC (decl))
3043 DECL_TEMPLATE_INFO (decl) = info;
3044
3045 return DECL_TEMPLATE_RESULT (tmpl);
3046 }

该类的定义正在被处理,因此上面2866行的条件满足;但因为decl是新创建的,其DECL_TEMPLATE_INFO及DECL_IMPLICIT_TYPEDEF_P项还没设置,在2889行的ELSE 块被执行以创建另一个TEMPLATE_DECL。

点此打开
图60:创建对自己的引用—第一步
5.12.3.2.1.1.2.3. 作为成员加入类域
作为最后一步,这个对自己的引用被加入为类成员,成员与类之间的关系将被设立。

2089 void
2090 finish_member_declaration (tree decl) in semantics.c
2091 {

2103 /* Set up access control for DECL. */
2104 TREE_PRIVATE (decl)
2105 = (current_access_specifier == access_private_node);
2106 TREE_PROTECTED (decl)
2107 = (current_access_specifier == access_protected_node);
2108 if (TREE_CODE (decl) == TEMPLATE_DECL)
2109 {
2110 TREE_PRIVATE (DECL_TEMPLATE_RESULT (decl)) = TREE_PRIVATE (decl);
2111 TREE_PROTECTED (DECL_TEMPLATE_RESULT (decl)) = TREE_PROTECTED (decl);
2112 }
2113
2114 /* Mark the DECL as a member of the current class. */
2115 DECL_CONTEXT (decl) = current_class_type;
2116
2117 /* [dcl.link]
2118
2119 A C language linkage is ignored for the names of class members
2120 and the member function type of class member functions. */
2121 if (DECL_LANG_SPECIFIC (decl) && DECL_LANGUAGE (decl) == lang_c)
2122 SET_DECL_LANGUAGE (decl, lang_cplusplus);
2123
2124 /* Put functions on the TYPE_METHODS list and everything else on the
2125 TYPE_FIELDS list. Note that these are built up in reverse order.
2126 We reverse them (to obtain declaration order) in finish_struct. */
2127 if (TREE_CODE (decl) == FUNCTION_DECL
2128 || DECL_FUNCTION_TEMPLATE_P (decl))
2129 {

2139 }
2140 /* Enter the DECL into the scope of the class. */
2141 else if ((TREE_CODE (decl) == USING_DECL && TREE_TYPE (decl))
2142 || pushdecl_class_level (decl))
2143 {
2144 /* All TYPE_DECLs go at the end of TYPE_FIELDS. Ordinary fields
2145 go at the beginning. The reason is that lookup_field_1
2146 searches the list in order, and we want a field name to
2147 override a type name so that the "struct stat hack" will
2148 work. In particular:
2149
2150 struct S { enum E { }; int E } s;
2151 s.E = 3;
2152
2153 is valid. In addition, the FIELD_DECLs must be maintained in
2154 declaration order so that class layout works as expected.
2155 However, we don't need that order until class layout, so we
2156 save a little time by putting FIELD_DECLs on in reverse order
2157 here, and then reversing them in finish_struct_1. (We could
2158 also keep a pointer to the correct insertion points in the
2159 list.) */
2160
2161 if (TREE_CODE (decl) == TYPE_DECL)
2162 TYPE_FIELDS (current_class_type)
2163 = chainon (TYPE_FIELDS (current_class_type), decl);
2164 else
2165 {
2166 TREE_CHAIN (decl) = TYPE_FIELDS (current_class_type);
2167 TYPE_FIELDS (current_class_type) = decl;
2168 }
2169
2170 maybe_add_class_template_decl_list (current_class_type, decl,
2171 /*friend_p=*/0);
2172 }
2173 }

对自己的引用不是一个方法的声明,也不是using声明,因此它需要由在2142行的pushdecl_class_level加入为成员。在2748到2763之间的代码处理匿名union,根据ISO-IEC-14882-2003,应该遵从以下规则:

一个union具有形式

union { member-specification } ;
它定义了一个匿名类型的匿名对象。一个匿名union的member-specification只能定义非静态数据成员(嵌套类型及函数不能被声明在一个匿名union里)。一个匿名union里的成员的名字,必须区别于该匿名union声明所在作用域中的,其他项的名字。出于名字查找的目的,在匿名union的定义后,该匿名union的成员被视为定义在该匿名union声明所在作用域中。例如:
void f()
{
union { int a; char* p; };
a = 1;
// ...
p = "Jennifer";
// ...
}
在这里a及p就像普通(非成员)变量那样使用,不过因为它们是union的成员,它们拥有相同的地址。
声明在一个具名名字空间或全局名字空间的匿名union,应该被声明为静态。声明在一个块作用域(block scope)的匿名union应该被声明具有,作为一个块局部变量所允许的,储存类别(storage class),或不指定储存类别。在一个类域中声明的匿名union不允许使用存储类别。一个匿名union不能具有private或protected成员(条款11)。一个匿名union也不能具有函数成员。

2729 bool
2730 pushdecl_class_level (tree x) in name-lookup.c
2731 {
2732 tree name;
2733 bool is_valid = true;
2734
2735 timevar_push (TV_NAME_LOOKUP);
2736 /* Get the name of X. */
2737 if (TREE_CODE (x) == OVERLOAD)
2738 name = DECL_NAME (get_first_fn (x));
2739 else
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 }
2748 else if (ANON_AGGR_TYPE_P (TREE_TYPE (x)))
2749 {

2763 }
2764 timevar_pop (TV_NAME_LOOKUP);
2765
2766 return is_valid;
2767 }

使用下面的函数,我们尝试把具有名字name的声明x加入当前类域中。这里x及name都来自对自己的引用所生成的TYPE_DECL节点。

2772 bool
2773 push_class_level_binding (tree name, tree x) in name-lookup.c
2774 {
2775 cxx_binding *binding;
2776
2777 timevar_push (TV_NAME_LOOKUP);
2778 /* The class_binding_level will be NULL if x is a template
2779 parameter name in a member template. */
2780 if (!class_binding_level)
2781 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
2782
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);
2787
2788 /* [class.mem]
2789
2790 If T is the name of a class, then each of the following shall
2791 have a name different from T:
2792
2793 -- every static data member of class T;
2794
2795 -- every member of class T that is itself a type;
2796
2797 -- every enumerator of every member of class T that is an
2798 enumerated type;
2799
2800 -- every member of every anonymous union that is a member of
2801 class T.
2802
2803 (Non-static data members were also forbidden to have the same
2804 name as T until TC1.) */
2805 if ((TREE_CODE (x) == VAR_DECL
2806 || TREE_CODE (x) == CONST_DECL
2807 || (TREE_CODE (x) == TYPE_DECL
2808 && !DECL_SELF_REFERENCE_P (x))
2809 || DECL_CLASS_TEMPLATE_P (x)
2810 /* A data member of an anonymous union. */
2811 || (TREE_CODE (x) == FIELD_DECL
2812 && DECL_CONTEXT (x) != current_class_type))
2813 && DECL_NAME (x) == constructor_name (current_class_type))
2814 {

2822 }

作为一个模板类,其类定义绑定在作用域sk_template_parms中(在图SingleThreaded作为当前作用域,我们可以看到类域的对象的level_chain指向sk_template_parms,不过sk_template_parms的names域并不像通常的作用域,它没有包括该类的定义,这体现了模板参数与类定义间的特殊关系)。在sk_template_parms作用域内,是模板参数;显然,如果在类中我们声明一个同名的成员,它将屏蔽相应的模板参数。
语法规定,模板参数不能在其作用域内被重新声明(包括嵌套作用域中)。函数check_template_shadow检查是否有这个错误。

2063 void
2064 check_template_shadow (tree decl) in pt.c
2065 {
2066 tree olddecl;
2067
2068 /* If we're not in a template, we can't possibly shadow a template
2069 parameter. */
2070 if (!current_template_parms)
2071 return;
2072
2073 /* Figure out what we're shadowing. */
2074 if (TREE_CODE (decl) == OVERLOAD)
2075 decl = OVL_CURRENT (decl);
2076 olddecl = IDENTIFIER_VALUE (DECL_NAME (decl));
2077
2078 /* If there's no previous binding for this name, we're not shadowing
2079 anything, let alone a template parameter. */
2080 if (!olddecl)
2081 return;
2082
2083 /* If we're not shadowing a template parameter, we're done. Note
2084 that OLDDECL might be an OVERLOAD (or perhaps even an
2085 ERROR_MARK), so we can't just blithely assume it to be a _DECL
2086 node. */
2087 if (!DECL_P (olddecl) || !DECL_TEMPLATE_PARM_P (olddecl))
2088 return;
2089
2090 /* We check for decl != olddecl to avoid bogus errors for using a
2091 name inside a class. We check TPFI to avoid duplicate errors for
2092 inline member templates. */
2093 if (decl == olddecl
2094 || TEMPLATE_PARMS_FOR_INLINE (current_template_parms))
2095 return;
2096
2097 cp_error_at ("declaration of `%#D'", decl);
2098 cp_error_at (" shadows template parm `%#D'", olddecl);
2099 }

这里类的标识符节点还没有设定其bindings域,因此在2076行的IDENTIFIER_VALUE返回NULL。

push_class_level_binding (continue)

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);
2828 if (binding && binding->value)
2829 {

2878 }
2879
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 }

因为IDENTIFIER_VALUE在这里返回NULL,在上面就跳到2882行执行push_class_binding。

2657 int
2658 push_class_binding (tree id, tree decl) in name-lookup.c
2659 {
2660 int result = 1;
2661 cxx_binding *binding = IDENTIFIER_BINDING (id);
2662 tree context;
2663
2664 timevar_push (TV_NAME_LOOKUP);
2665 /* Note that we declared this value so that we can issue an error if
2666 this is an invalid redeclaration of a name already used for some
2667 other purpose. */
2668 note_name_declared_in_class (id, decl);
2669
2670 if (binding && binding->scope == class_binding_level)
2671 /* Supplement the existing binding. */
2672 result = supplement_binding (IDENTIFIER_BINDING (id), decl);
2673 else
2674 /* Create a new binding. */
2675 push_binding (id, decl, class_binding_level);

对于每个缓存的项,都需要检查是否是有效的声明。而对于每个类,都有一个伴随的splay树来记录在该类中使用过的名字。

6415 void
6416 note_name_declared_in_class (tree name, tree decl) in class.c
6417 {
6418 splay_tree names_used;
6419 splay_tree_node n;
6420
6421 /* Look to see if we ever used this name. */
6422 names_used
6423 = current_class_stack[current_class_depth - 1].names_used;
6424 if (!names_used)
6425 return;
6426
6427 n = splay_tree_lookup (names_used, (splay_tree_key) name);
6428 if (n)
6429 {
6430 /* [basic.scope.class]
6431
6432 A name N used in a class S shall refer to the same declaration
6433 in its context and when re-evaluated in the completed scope of
6434 S. */
6435 error ("declaration of `%#D'", decl);
6436 cp_error_at ("changes meaning of `%D' from `%+#D'",
6437 DECL_NAME (OVL_CURRENT (decl)),
6438 (tree) n->value);
6439 }
6440 }

上面current_class_stack的names_used域是splay树的根节点,用于记录每个类的域声明。在插入新域之前,要通过上面的这个函数来确认相同的名字之前没有被使用过。【3】给出了例子:
typedef int c;
enum { i = 1 };
class X {
char v[i]; // error: i refers to ::i but when reevaluated is X::i
int f() { return sizeof(c); } // OK: X::c
char c;
enum { i = 2 };
};
上面的声明char v[i]将被note_name_declared_in_class作为错误捕捉。这是因为,类数据成员的解析处理是顺序进行的,假若调换声明char v[i]及enum { i=2 },char v[i]的含义就不同了。【3】把这种情况定义为病态程序。而对类内联方法的分析,是在解析完类声明结尾的“};”后,才进行。因此上面的“f()”方法的不受影响。
而上面2670行的条件则是检查重复声明的情况。对于新的定义,一个cxx_binding记录了这个绑定信息。

358 static void
359 push_binding (tree id, tree decl, cxx_scope* level) in name-lookup.c
360 {
361 cxx_binding *binding = cxx_binding_make (decl, NULL);
362
363 /* Now, fill in the binding information. */
364 binding->previous = IDENTIFIER_BINDING (id);
365 binding->scope = level;
366 INHERITED_VALUE_BINDING_P (binding) = 0;
367 LOCAL_BINDING_P (binding) = (level != class_binding_level);
368
369 /* And put it on the front of the list of bindings for ID. */
370 IDENTIFIER_BINDING (id) = binding;
371 }

如果非空,域IDENTIFIER_CLASS_VALUE是一个tree_list,它记录了类中所声明的所有成员。不过在push_binding中所构建的cxx_binding的value域是空的(因为它不是重载方法),因此下面的代码不作任何事,返回result 1。

push_class_binding (continue)

2677 /* Update the IDENTIFIER_CLASS_VALUE for this ID to be the
2678 class-level declaration. Note that we do not use DECL here
2679 because of the possibility of the `struct stat' hack; if DECL is
2680 a class-name or enum-name we might prefer a field-name, or some
2681 such. */
2682 IDENTIFIER_CLASS_VALUE (id) = IDENTIFIER_BINDING (id)->value;
2683
2684 /* If this is a binding from a base class, mark it as such. */
2685 binding = IDENTIFIER_BINDING (id);
2686 if (binding->value == decl && TREE_CODE (decl) != TREE_LIST)
2687 {
2688 if (TREE_CODE (decl) == OVERLOAD)
2689 context = CP_DECL_CONTEXT (OVL_CURRENT (decl));
2690 else
2691 {
2692 my_friendly_assert (DECL_P (decl), 0);
2693 context = context_for_name_lookup (decl);
2694 }
2695
2696 if (is_properly_derived_from (current_class_type, context))
2697 INHERITED_VALUE_BINDING_P (binding) = 1;
2698 else
2699 INHERITED_VALUE_BINDING_P (binding) = 0;
2700 }
2701 else if (binding->value == decl)
2702 /* We only encounter a TREE_LIST when push_class_decls detects an
2703 ambiguity. Such an ambiguity can be overridden by a definition
2704 in this class. */
2705 INHERITED_VALUE_BINDING_P (binding) = 1;
2706
2707 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result);
2708 }

因为push_class_binding在的2882行返回1,该成员被串入class_shadowed链表,该链表保存该类所声明的成员。最后push_class_level_binding返回true。
返回pushdecl_class_level的2744行,变量x是一个TYPE_DECL(参考build_lang_decl),进一步的绑定结构由set_identifier_type_value构建。在这一步,标识符节点的type域被更新为指向类的RECORD_TYPE节点,同时type域的原始值(global_type_node)被保存在相应的cxx_binding节点的type_shadowed域里。

点此打开
图61:创建对自己的引用—第二步
注意IDENTIFIER_NODE和“SingleThreaded”的cxx_scope对象的变化是相配合的。在pushdecl_class_level向finish_member_declaration返回1后,这个对自己的引用被串接入类的域声明链表(即RECORD_TYPE的values域)的末尾。
接着maybe_add_class_template_decl_list被执行。对于类模板,CLASSTYPE_DECL_LIST是一个依声明次序用于所有数据成员,函数及友元的tree_list。其中的每个节点的TREE_PURPOSE,对于友元是NULL_TREE,而对于类模板则是其RECORD_TYPE。

2583 void
2584 maybe_add_class_template_decl_list (tree type, tree t, int friend_p) in class.c
2585 {
2586 /* Save some memory by not creating TREE_LIST if TYPE is not template. */
2587 if (CLASSTYPE_TEMPLATE_INFO (type))
2588 CLASSTYPE_DECL_LIST (type)
2589 = tree_cons (friend_p ? NULL_TREE : type,
2590 t, CLASSTYPE_DECL_LIST (type));
2591 }

点此打开
图62:创建对自己的引用—第三步
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: