5.12.3.2.1.1.1.3. 为类创建TEMPLATE_DECL
因为这是个类模板,它必须要有自己的TEMPLATE_DECL节点来描述其模板特性。现在就要创建这个节点。
pushtag (continue)
4656 d = maybe_process_template_type_declaration (type,
4657 globalize, b);
当前,processing_template_decl为非0值,因为我们正在处理类模板。不过因为模板参数已经被处理,processing_template_parmlist是0。注意,参数type指向类的RECORD_TYPE节点。
4525 static tree
4526 maybe_process_template_type_declaration (tree type, int globalize, in name-lookup.c
4527 cxx_scope *b)
4528 {
4529 tree decl = TYPE_NAME (type);
4530
4531 if (processing_template_parmlist)
4532 /* You can't declare a new template type in a template parameter
4533 list. But, you can declare a non-template type:
4534
4535 template <class A*> struct S;
4536
4537 is a forward-declaration of `A'. */
4538 ;
4539 else
4540 {
4541 my_friendly_assert (IS_AGGR_TYPE (type)
4542 || TREE_CODE (type) == ENUMERAL_TYPE, 0);
4543
4544 if (processing_template_decl)
4545 {
4546 /* This may change after the call to
4547 push_template_decl_real, but we want the original value. */
4548 tree name = DECL_NAME (decl);
4549
4550 decl = push_template_decl_real (decl, globalize);
4551 /* If the current binding level is the binding level for the
4552 template parameters (see the comment in
4553 begin_template_parm_list) and the enclosing level is a class
4554 scope, and we're not looking at a friend, push the
4555 declaration of the member class into the class scope. In the
4556 friend case, push_template_decl will already have put the
4557 friend into global scope, if appropriate. */
4558 if (TREE_CODE (type) != ENUMERAL_TYPE
4559 && !globalize && b->kind == sk_template_parms
4560 && b->level_chain->kind == sk_class)
4561 {
…
4577 }
4578 }
4579 }
4580
4581 return decl;
4582 }
除了我们在中间树里已经看到的节点,模板声明需要额外的节点。模板引入了具现(instantion),特化(specializaiton),偏特化(partial specialization)这些概念,需要的新的节点来记录这些概念间的关系。
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 ();
如同其他的声明,在处理之前,需要确定其所在的作用域。这里CP_DECL_CONTEXT实际上调用DECL_CONTEXT。对于这个例子,DECL_CONTEXT是名字空间“Loki”,它之前在pushtag的4652行设置好了。那么ctx在2800行被设置为NULL。
1512 bool
1513 template_parm_scope_p (void) in name-lookup.c
1514 {
1515 return innermost_scope_kind () == sk_template_parms;
1516 }
注意到现在current_binding_level指向sk_template_parms。
1504 scope_kind
1505 innermost_scope_kind (void) in name-lookup.c
1506 {
1507 return current_binding_level->kind;
1508 }
非偏特化及特化的模板声明称为主声明(primary declaration)。上面的例程template_parm_scope_p通过检查最接近的封装作用域(the closest enclosing scope)来区分这些声明。对于我们的例子,这个作用域是sk_template_parms,primary将是非0值。
push_template_decl_real (continue)
2811 if (primary)
2812 {
2813 if (current_lang_name == lang_name_c)
2814 error ("template with C linkage");
2815 else if (TREE_CODE (decl) == TYPE_DECL
2816 && ANON_AGGRNAME_P (DECL_NAME (decl)))
2817 error ("template class without a name");
2818 else if (TREE_CODE (decl) == FUNCTION_DECL)
2819 {
…
2843 }
2844 else if (DECL_IMPLICIT_TYPEDEF_P (decl)
2845 && CLASS_TYPE_P (TREE_TYPE (decl)))
2846 /* OK */;
2847 else
2848 {
2849 error ("template declaration of `%#D'", decl);
2850 return error_mark_node;
2851 }
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 ();
上面,check_default_tmpl_args不作任何事,因为我们仍然在模板的声明里(实际是定义)。正如在解析模板类型参数一节所看到的,current_template_parms为该模板声明保存了适用的模板参数。而对于嵌套的模板声明,最里层的参数出现在由该变量指向的链表的开头。
2297 tree
2298 current_template_args (void) in pt.c
2299 {
2300 tree header;
2301 tree args = NULL_TREE;
2302 int length = TMPL_PARMS_DEPTH (current_template_parms);
2303 int l = length;
2304
2305 /* If there is only one level of template parameters, we do not
2306 create a TREE_VEC of TREE_VECs. Instead, we return a single
2307 TREE_VEC containing the arguments. */
2308 if (length > 1)
2309 args = make_tree_vec (length);
2310
2311 for (header = current_template_parms; header; header = TREE_CHAIN (header))
2312 {
2313 tree a = copy_node (TREE_VALUE (header));
2314 int i;
2315
2316 TREE_TYPE (a) = NULL_TREE;
2317 for (i = TREE_VEC_LENGTH (a) - 1; i >= 0; --i)
2318 {
2319 tree t = TREE_VEC_ELT (a, i);
2320
2321 /* T will be a list if we are called from within a
2322 begin/end_template_parm_list pair, but a vector directly
2323 if within a begin/end_member_template_processing pair. */
2324 if (TREE_CODE (t) == TREE_LIST)
2325 {
2326 t = TREE_VALUE (t);
2327
2328 if (TREE_CODE (t) == TYPE_DECL
2329 || TREE_CODE (t) == TEMPLATE_DECL)
2330 t = TREE_TYPE (t);
2331 else
2332 t = DECL_INITIAL (t);
2333 TREE_VEC_ELT (a, i) = t;
2334 }
2335 }
2336
2337 if (length > 1)
2338 TREE_VEC_ELT (args, --l) = a;
2339 else
2340 args = a;
2341 }
2342
2343 return args;
2344 }
以图嵌套模板参数的布局为例,在2302行的TMPL_PARMS_DEPTH返回保存在purpose域的值,而current_template_args将返回如下图的args。看到参数被封装成更紧凑的形式,并且调转节点的次序,以最外层的参数在开头。变量current_template_parms保证了其正确性。
图53:由current_template_args返回的参数
继续这个函数,这里的ctx,正如我们在上面看到的,是NULL(它在上面的2800行被设置为NULL),因此2864行的条件被满足。
push_template_decl_real (continue)
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 {
2897 /* A specialization of a member template of a template
2898 class. */
2899 SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
2900 DECL_TEMPLATE_INFO (tmpl) = DECL_TEMPLATE_INFO (decl);
2901 DECL_TEMPLATE_INFO (decl) = NULL_TREE;
2902 }
2903 }
2904 }
作为正在被定义的模板,其RECORD_TYPE节点的域TYPE_TEMPLATE_INFO及TYPE_TI_TEMPLATE都是NULL。现在要为模板声明创建树节点了。
2349 static tree
2350 build_template_decl (tree decl, tree parms) in pt.c
2351 {
2352 tree tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE);
2353 DECL_TEMPLATE_PARMS (tmpl) = parms;
2354 DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
2355 if (DECL_LANG_SPECIFIC (decl))
2356 {
2357 DECL_STATIC_FUNCTION_P (tmpl) = DECL_STATIC_FUNCTION_P (decl);
2358 DECL_CONSTRUCTOR_P (tmpl) = DECL_CONSTRUCTOR_P (decl);
2359 DECL_DESTRUCTOR_P (tmpl) = DECL_DESTRUCTOR_P (decl);
2360 DECL_NONCONVERTING_P (tmpl) = DECL_NONCONVERTING_P (decl);
2361 DECL_ASSIGNMENT_OPERATOR_P (tmpl) = DECL_ASSIGNMENT_OPERATOR_P (decl);
2362 if (DECL_OVERLOADED_OPERATOR_P (decl))
2363 SET_OVERLOADED_OPERATOR_CODE (tmpl,
2364 DECL_OVERLOADED_OPERATOR_P (decl));
2365 }
2366
2367 return tmpl;
2368 }
这里参数decl由build_decl创建,其域lang_specific是NULL。因此被2355行IF块所包含的代码被跳过。而在push_template_decl_real中2894行的IF块亦被跳过。
在前端中,定义了许多访问模板相关节点中的域的宏。这些宏在GCC源代码中到处都在1。为了方便阅读,下图显示了指定宏访问的域及其访问的路径。
图54:访问模板定义的宏
看到对于TYPE_DECL(注意,并非此处的decl,这个节点必须由build_lang_decl来创建)及RECORD_TYPE,都有名为lang_specific的域。虽然它们都指向不同类型的对象,这些对象都有域template_info。这些对象的差别在于,对于RECORD_TYPE,其template_info指向主模板(primary template)的对象,而对于TYPE_DECL,其template_info则指向模板的特化及偏特化的对象。显然,这些template_info不是指向同一个对象的。
push_template_decl_real (continue)
2997 DECL_TEMPLATE_RESULT (tmpl) = decl;
2998 TREE_TYPE (tmpl) = TREE_TYPE (decl);
2999
3000 /* Push template declarations for global functions and types. Note
3001 that we do not try to push a global template friend declared in a
3002 template class; such a thing may well depend on the template
3003 parameters of the class. */
3004 if (new_template_p && !ctx
3005 && !(is_friend && template_class_depth (current_class_type) > 0))
3006 tmpl = pushdecl_namespace_level (tmpl);
这里new_template_p是true,而对于当前类模板定义,template_class_depth返回0(因为DECL_TEMPLATE_INFO返回NULL),因此将把这个TEMPLATE_DECL加入名字空间“Loki”。
3229 tree
3230 pushdecl_namespace_level (tree x) in name-lookup.c
3231 {
3232 struct cp_binding_level *b = current_binding_level;
3233 tree t;
3234
3235 timevar_push (TV_NAME_LOOKUP);
3236 t = pushdecl_with_scope (x, NAMESPACE_LEVEL (current_namespace));
3237
3238 /* Now, the type_shadowed stack may screw us. Munge it so it does
3239 what we want. */
3240 if (TREE_CODE (x) == TYPE_DECL)
3241 {
…
3268 }
3269 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
3270 }
这里current_binding_level返回绑定域sk_template_parms,不过当前情形下它没有用处。我们想要加入TEMPALTE_DECL的是名字空间“Loki”,它由current_namespace获得。
1941 tree
1942 pushdecl_with_scope (tree x, cxx_scope *level) in name-lookup.c
1943 {
1944 struct cp_binding_level *b;
1945 tree function_decl = current_function_decl;
1946
1947 timevar_push (TV_NAME_LOOKUP);
1948 current_function_decl = NULL_TREE;
1949 if (level->kind == sk_class)
1950 {
1951 b = class_binding_level;
1952 class_binding_level = level;
1953 pushdecl_class_level (x);
1954 class_binding_level = b;
1955 }
1956 else
1957 {
1958 b = current_binding_level;
1959 current_binding_level = level;
1960 x = pushdecl (x);
1961 current_binding_level = b;
1962 }
1963 current_function_decl = function_decl;
1964 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
1965 }
注意到,在上面,首先current_binding_level被缓存,然后设置为名字空间“Loki”,因而现在pushdecl可以如我们期望那样去执行。下面的DECL_NAMESPACE_SCOPE_P检查x的上下文的类型是否为名字空间,而且现在current_binding_level暂时返回名字空间“Loki”的作用域,而不是作用域sk_template_parms。因此满足617行的条件。
566 tree
567 pushdecl (tree x) in name-lookup.c
568 {
569 tree t;
570 tree name;
571 int need_new_binding;
572
573 timevar_push (TV_NAME_LOOKUP);
574
575 need_new_binding = 1;
…
604 name = DECL_NAME (x);
605 if (name)
606 {
607 int different_binding_level = 0;
…
617 if (DECL_NAMESPACE_SCOPE_P (x) && namespace_binding_p ())
618 t = namespace_binding (name, DECL_CONTEXT (x));
619 else
620 t = lookup_name_current_level (name);
显然在名字空间“Loki”中尚没有名字“SingleThreaded”,因此在618行,t指向NULL。
pushdecl (continue)
828 /* This name is new in its binding level.
829 Install the new declaration and return it. */
830 if (namespace_bindings_p ())
831 {
832 /* Install a global value. */
833
834 /* If the first global decl has external linkage,
835 warn if we later see static one. */
836 if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && TREE_PUBLIC (x))
837 TREE_PUBLIC (name) = 1;
838
839 /* Bind the name for the entity. */
840 if (!(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
841 && t != NULL_TREE)
842 && (TREE_CODE (x) == TYPE_DECL
843 || TREE_CODE (x) == VAR_DECL
844 || TREE_CODE (x) == ALIAS_DECL
845 || TREE_CODE (x) == NAMESPACE_DECL
846 || TREE_CODE (x) == CONST_DECL
847 || TREE_CODE (x) == TEMPLATE_DECL))
848 SET_IDENTIFIER_NAMESPACE_VALUE (name, x);
…
872 }
…
1003 }
1004
1005 if (TREE_CODE (x) == VAR_DECL)
1006 maybe_register_incomplete_var (x);
1007 }
1008
1009 if (need_new_binding)
1010 add_decl_to_level (x,
1011 DECL_NAMESPACE_SCOPE_P (x)
1012 ? NAMESPACE_LEVEL (CP_DECL_CONTEXT (x))
1013 : current_binding_level);
1014
1015 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
1016 }
SET_IDENTIFIER_NAMESPACE_VALUE仅是在其中调用set_namespace_binding。参数scope是current_namespace,而val是要加入的TEMPLATE_DECL。
2958 void
2959 set_namespace_binding (tree name, tree scope, tree val) in name-lookup.c
2960 {
2961 cxx_binding *b;
2962
2963 timevar_push (TV_NAME_LOOKUP);
2964 if (scope == NULL_TREE)
2965 scope = global_namespace;
2966 b = binding_for_name (NAMESPACE_LEVEL (scope), name);
2967 if (!b->value || TREE_CODE (val) == OVERLOAD || val == error_mark_node)
2968 b->value = val;
2969 else
2970 supplement_binding (b, val);
2971 timevar_pop (TV_NAME_LOOKUP);
2972 }
在名字空间中加入这个TEMPLATE_DECL后,中间树现在看起来如下图:
(点此打开)
图55:加入类SingleThreaded的标签 – 第二步
下面,DECL_CONV_FN_P如果非0,表示一个转换操作符;而对于这个TEMPLATE_DECL节点,其域DECL_TEMPLATE_INFO是NULL。又,因为当前的模板声明是主声明,3010行的DECL_PRIMRAY_TEMPLATE把最里层参数的type设为该模板声明(TEMPALTE_DECL),以显示这是个主模板。
push_template_decl_real (continue)
3008 if (primary)
3009 {
3010 DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
3011 if (DECL_CONV_FN_P (tmpl))
3012 {
3013 int depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl));
3014
3015 /* It is a conversion operator. See if the type converted to
3016 depends on innermost template operands. */
3017
3018 if (uses_template_parms_level (TREE_TYPE (TREE_TYPE (tmpl)),
3019 depth))
3020 DECL_TEMPLATE_CONV_FN_P (tmpl) = 1;
3021 }
3022 }
3023
3024 /* The DECL_TI_ARGS of DECL contains full set of arguments refering
3025 back to its most general template. If TMPL is a specialization,
3026 ARGS may only have the innermost set of arguments. Add the missing
3027 argument levels if necessary. */
3028 if (DECL_TEMPLATE_INFO (tmpl))
3029 args = add_outermost_template_args (DECL_TI_ARGS (tmpl), args);
3030
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 }
注意到在上面的代码中,DECL_IMPLICIT_TYPEDEF_P返回true,因为decl是由pushtag创建的隐式typedef声明。另外,DECL_TEMPLATE_INFO起初是NULL。但随后它被为SET_TYPE_TEMPLATE_INFO在3034行所更新。在处理模板特化时,这个安排是有好处的,因为DECL_TEMPLATE_INFO指向了参数的拷贝(该拷贝被更新为特化的实际参数)。
(点此打开)
图56:加入类SingleThreaded的标签 – 第三步
接下来,前端为这个模板类生成修饰名(mangled name)。
4002 static tree
4003 classtype_mangled_name (tree t) in pt.c
4004 {
4005 if (CLASSTYPE_TEMPLATE_INFO (t)
4006 /* Specializations have already had their names set up in
4007 lookup_template_class. */
4008 && !CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
4009 {
4010 tree tmpl = most_general_template (CLASSTYPE_TI_TEMPLATE (t));
4011
4012 /* For non-primary templates, the template parameters are
4013 implicit from their surrounding context. */
4014 if (PRIMARY_TEMPLATE_P (tmpl))
4015 {
4016 tree name = DECL_NAME (tmpl);
4017 char *mangled_name = mangle_class_name_for_template
4018 (IDENTIFIER_POINTER (name),
4019 DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
4020 CLASSTYPE_TI_ARGS (t));
4021 tree id = get_identifier (mangled_name);
4022 IDENTIFIER_TEMPLATE (id) = name;
4023 return id;
4024 }
4025 }
4026
4027 return TYPE_IDENTIFIER (t);
4028 }
例程most_general_template,如其名所表示,返回最普适的模板(即主模板)。