GCC-3.4.6源代码学习笔记(126)
来源:互联网 发布:sql中文查询设计器 编辑:程序博客网 时间:2024/06/03 17:15
5.12.4.2.3.1.1.3. 生成template-id
那么作为结果,对于这个非类型实参,“chunkSize”的IDENTIFIER_NODE被返回。类似的还有下一个实参“maxSmallObjectSize”。因此在lookup_template_class的4346行退出coerce_template_parms时,arglist为下图中标记为红色的节点。
(点此打开)
图111:构建的arglist
lookup_template_class (continue)
4352 if (arglist == error_mark_node)
4353 /* We were unable to bindthe arguments. */
4354 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,error_mark_node);
4355
4356 /* In the scopeof a template class, explicit references to the
4357 template class refer to the type of thetemplate, not any
4358 instantiation of it. For example, in:
4359
4360 template <class T> class C { voidf(C<T>); }
4361
4362 the `C<T>' is just the same as `C'.Outside of the
4363 class, however, such a reference is aninstantiation. */
4364 if (comp_template_args (TYPE_TI_ARGS(template_type),
4365 arglist))
4366 {
…
4386 }
4387 if (found)
4388 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,found);
4389
4390 for (tp =&DECL_TEMPLATE_INSTANTIATIONS (template);
4391 *tp;
4392 tp = &TREE_CHAIN (*tp))
4393 if (comp_template_args (TREE_PURPOSE(*tp), arglist))
4394 {
…
4405 }
4406
4407 /* This type is a"partial instantiation" if any of the template
4408 arguments still involvetemplate parameters. Note that we set
4409 IS_PARTIAL_INSTANTIATION forpartial specializations as
4410 well. */
4411 is_partial_instantiation = uses_template_parms (arglist);
4412
4413 /* If the deducedarguments are invalid, then the binding
4414 failed. */
4415 if (!is_partial_instantiation
4416 && check_instantiated_args(template,
4417 INNERMOST_TEMPLATE_ARGS(arglist),
4418 complain))
4419 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,error_mark_node);
4420
4421 if (!is_partial_instantiation
4422 && !PRIMARY_TEMPLATE_P(template)
4423 && TREE_CODE (CP_DECL_CONTEXT(template)) == NAMESPACE_DECL)
4424 {
4425 found = xref_tag_from_type (TREE_TYPE(template),
4426 DECL_NAME(template),
4427 /*globalize=*/1);
4428 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,found);
4429 }
4430
4431 context = tsubst (DECL_CONTEXT (template),arglist,
4432 complain, in_decl);
4433 if (!context)
4434 context = global_namespace;
在4411行对于标记为红色的TREE_VEC,uses_template_parms将依次遍历其成员,任一成员为类型依赖或值依赖都将导致该函数返回非0值,使得is_partial_instantiation成为1。同样在4431行,变量template指向“SmallObject”的TEMPLATE_DECL,因此其上下文是Loki的NAMESPACE_DECL,它由tsubst返回不作任何处理。
lookup_template_class (continue)
4436 /* Create thetype. */
4437 if (TREE_CODE (template_type) ==ENUMERAL_TYPE)
4438 {
…
4450 }
4451 else
4452 {
4453 t = make_aggr_type(TREE_CODE (template_type));
4454 CLASSTYPE_DECLARED_CLASS (t)
4455 = CLASSTYPE_DECLARED_CLASS(template_type);
4456 SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t);
4457 TYPE_FOR_JAVA (t) = TYPE_FOR_JAVA(template_type);
4458
4459 /* A localclass. Make sure the decl gets registered properly. */
4460 if (context == current_function_decl)
4461 pushtag (DECL_NAME (template), t, 0);
4462 }
4463
4464 /* If we calledstart_enum or pushtag above, this information
4465 will already be set up. */
4466 if (!TYPE_NAME (t))
4467 {
4468 TYPE_CONTEXT (t) = FROB_CONTEXT (context);
4469
4470 type_decl = create_implicit_typedef (DECL_NAME(template), t);
4471 DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
4472 TYPE_STUB_DECL (t) = type_decl;
4473 DECL_SOURCE_LOCATION (type_decl)
4474 = DECL_SOURCE_LOCATION (TYPE_STUB_DECL(template_type));
4475 }
4476 else
4477 type_decl = TYPE_NAME (t);
4478
4479 TREE_PRIVATE (type_decl)
4480 = TREE_PRIVATE (TYPE_STUB_DECL(template_type));
4481 TREE_PROTECTED (type_decl)
4482 = TREE_PROTECTED (TYPE_STUB_DECL(template_type));
4483
4484 /* Set up thetemplate information. We have to figure out which
4485 template is the immediateparent if this is a full
4486 instantiation. */
4487 if (parm_depth == 1 ||is_partial_instantiation
4488 || !PRIMARY_TEMPLATE_P (template))
4489 /* This case iseasy; there are no member templates involved. */
4490 found = template;
4491 else
4492 {
…
4544 }
4545
4546 SET_TYPE_TEMPLATE_INFO (t, tree_cons (found, arglist, NULL_TREE));
4547 DECL_TEMPLATE_INSTANTIATIONS (template)
4548 = tree_cons(arglist, t,
4549 DECL_TEMPLATE_INSTANTIATIONS(template));
4550
4551 if (TREE_CODE (t) == ENUMERAL_TYPE
4552 && !is_partial_instantiation)
4553 /* Now that thetype has been registered on the instantiations
4554 list, we set up theenumerators. Because the enumeration
4555 constants may involve theenumeration type itself, we make
4556 sure to register the typefirst, and then create the
4557 constants. That way, doingtsubst_expr for the enumeration
4558 constants won't result inrecursive calls here; we'll find
4559 the instantiation and exitabove. */
4560 tsubst_enum (template_type, t, arglist);
4561
4562 /* Reset the nameof the type, now that CLASSTYPE_TEMPLATE_INFO
4563 is set up. */
4564 if (TREE_CODE (t) != ENUMERAL_TYPE)
4565 DECL_NAME (type_decl) = classtype_mangled_name (t);
4566 if (is_partial_instantiation)
4567 /* If the type makes use of template parameters, the
4568 code that generatesdebugging information will crash. */
4569 DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1;
4570
4571 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
4572 }
4573 timevar_pop (TV_NAME_LOOKUP);
4574 }
变量template_type是“SmallObject”的RECORD_TYPE节点。首先在4551行之前,下面红色的节点被构建了。
(点此打开)
作为具现的实例,要求一个修饰名而不是之前看到的朴素名(plain 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 theirnames 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 /* Fornon-primary templates, the template parameters are
4013 implicit from theirsurrounding 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 returnid;
4024 }
4025 }
4026
4027 returnTYPE_IDENTIFIER (t);
4028 }
修饰名根据主模板来构建(它通常就是最泛化的模板,通过most_general_template来获取),其中主模板的名字是一个标识符(作为比较,一个偏特化的模板的名字是一个template-id)。以下的宏用于检查指定的模板是否为主模板。
2783 #define DECL_PRIMARY_TEMPLATE(NODE)/ in cp-tree.h
2784 (TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS(NODE)))
2785
2786 /* Returns nonzero if NODE is a primary template. */
27873 #define PRIMARY_TEMPLATE_P(NODE) (DECL_PRIMARY_TEMPLATE (NODE) == (NODE))
2661 #define DECL_INNERMOST_TEMPLATE_PARMS(NODE)/
2662 INNERMOST_TEMPLATE_PARMS(DECL_TEMPLATE_PARMS (NODE))
INNERMOST_TEMPLATE_P ARMS只是返回节点value域中的内容;而DECL_TEMPLATE_PARMS返回TEMPLATE_DECL的arguments域的指针。
那么具现实例的TYPE_DECL被更新为如下的修饰名。
(点此打开)
图112:内层的template-id
作为结果,lookup_template_class返回具现实例所对应的RECORD_TYPE节点。接下来,通过其chain域(在finish_template_type中的TYPE_STUB_DECL)把TYPE_DECL(粗红线节点)作为template-id返回。
5.12.4.2.3.1.2. 外层template-id
对于外层的template-id,内层template-id——“SmallObject<ThreadingModel,chunkSize, maxSmallObjectSize>”是其一个实参;而且下面的arguments是一个具有单个成员为该template-id的tree_vec。然后我们又以下面的代码进行解析。
cp_parser_template_id
7991 /* Build a representationof the specialization. */
7992 if (TREE_CODE (template) == IDENTIFIER_NODE)
7993 template_id = build_min_nt(TEMPLATE_ID_EXPR, template, arguments);
7994 else if (DECL_CLASS_TEMPLATE_P (template)
7995 ||DECL_TEMPLATE_TEMPLATE_PARM_P (template))
7996 template_id
7997 = finish_template_type(template, arguments,
7998 cp_lexer_next_token_is(parser->lexer,
7999 CPP_SCOPE));
不过在lookup_template_class中的处理有一些不同,因为“ThreadingModel”是模板参数。
4133 tree
4134 lookup_template_class(tree d1, in pt.c
4135 tree arglist,
4136 tree in_decl,
4137 tree context,
4138 int entering_scope,
4139 tsubst_flags_t complain)
4140 {
4141 tree template = NULL_TREE, parmlist;
4142 tree t;
4143
4144 timevar_push (TV_NAME_LOOKUP);
4145
4146 if (TREE_CODE (d1) == IDENTIFIER_NODE)
4147 {
4148 if (IDENTIFIER_VALUE (d1)
4149 && DECL_TEMPLATE_TEMPLATE_PARM_P (IDENTIFIER_VALUE (d1)))
4150 template = IDENTIFIER_VALUE (d1);
4151 else
4152 {
4153 if (context)
4154 push_decl_namespace (context);
4155 template= lookup_name (d1, /*prefer_type=*/0);
4156 template = maybe_get_template_decl_from_type_decl(template);
4157 if (context)
4158 pop_decl_namespace();
4159 }
4160 if (template)
4161 context = DECL_CONTEXT (template);
4162 }
4163 else if (TREE_CODE (d1) == TYPE_DECL&& IS_AGGR_TYPE (TREE_TYPE (d1)))
4164 {
4165 tree type = TREE_TYPE (d1);
4166
4167 /* If we aredeclaring a constructor, say A<T>::A<T>, we will get
4168 an implicittypename for the second A. Deal with it. */
4169 if (TREE_CODE (type) == TYPENAME_TYPE&& TREE_TYPE (type))
4170 type = TREE_TYPE (type);
4171
4172 if (CLASSTYPE_TEMPLATE_INFO (type))
4173 {
4174 template = CLASSTYPE_TI_TEMPLATE (type);
4175 d1= DECL_NAME (template);
4176 }
4177 }
4178 else if (TREE_CODE (d1) == ENUMERAL_TYPE
4179 || (TYPE_P (d1) && IS_AGGR_TYPE(d1)))
4180 {
4181 template = TYPE_TI_TEMPLATE (d1);
4182 d1 = DECL_NAME (template);
4183 }
4184 else if (TREE_CODE (d1) == TEMPLATE_DECL
4185 && TREE_CODE(DECL_TEMPLATE_RESULT (d1)) == TYPE_DECL)
4186 {
4187 template = d1;
4188 d1 = DECL_NAME (template);
4189 context = DECL_CONTEXT (template);
4190 }
4191
4192 /* With somethinglike `template <class T> class X class X { ... };'
4193 we could end up with D1 havingnothing but an IDENTIFIER_VALUE.
4194 We don't want to do that, butwe have to deal with the situation,
4195 so let's give them some syntaxerrors to chew on instead of a
4196 crash. Alternatively D1 mightnot be a template type at all. */
4197 if (! template)
4198 {
4199 if (complain & tf_error)
4200 error ("`%T' is not atemplate", d1);
4201 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,error_mark_node);
4202 }
4203
4204 if (TREE_CODE (template) != TEMPLATE_DECL
4205 /* Make sureit's a user visible template, if it was named by
4206 the user. */
4207 || ((complain & tf_user) &&!DECL_TEMPLATE_PARM_P (template)
4208 && !PRIMARY_TEMPLATE_P(template)))
4209 {
4210 if (complain & tf_error)
4211 {
4212 error ("non-template type `%T' used asa template", d1);
4213 if (in_decl)
4214 cp_error_at ("for templatedeclaration `%D'", in_decl);
4215 }
4216 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,error_mark_node);
4217 }
4218
4219 complain &= ~tf_user;
4220
4221 if (DECL_TEMPLATE_TEMPLATE_PARM_P (template))
4222 {
4223 /*Create a new TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM node to store
4224 template arguments */
4225
4226 tree parm;
4227 tree arglist2;
4228
4229 parmlist = DECL_INNERMOST_TEMPLATE_PARMS(template);
4230
4231 /* Consider anexample where a template template parameter declared as
4232
4233 template <class T, classU = std::allocator<T> > class TT
4234
4235 The template parameter levelof T and U are one level larger than
4236 of TT. To proper process thedefault argument of U, say when an
4237 instantiation`TT<int>' is seen, we need to build the full
4238 arguments containing {int}as the innermost level. Outer levels,
4239 available when not appearingas default template argument, can be
4240 obtained from`current_template_args ()'.
4241
4242 Suppose that TT is latersubstituted with std::vector. The above
4243 instantiation is `TT<int,std::allocator<T> >' with TT at
4244 level 1, and T at level 2,while the template arguments at level 1
4245 becomes {std::vector} andthe inner level 2 is {int}. */
4246
4247 if (current_template_parms)
4248 arglist = add_to_template_args(current_template_args (), arglist);
4249
4250 arglist2 = coerce_template_parms (parmlist,arglist, template,
4251 complain, /*require_all_args=*/1);
4252 if (arglist2 == error_mark_node
4253 || (!uses_template_parms (arglist2)
4254 && check_instantiated_args(template, arglist2, complain)))
4255 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,error_mark_node);
4256
4257 parm = bind_template_template_parm (TREE_TYPE(template), arglist2);
4258 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,parm);
4259 }
…
4574 }
上面的d1指向下图的TEMPLATE_DECL。而arglist指向代表内层template-id的子树。
(点此打开)
还有注意current_template_parms指向的节点,它是“SmallObject”的实参。它还应该是“ThreadingModel”的实参,因为“ThreadingModel”被包括在“SmallObject”的参数列表中。因此在4248行,函数current_template_args拷贝出这个向量,不过拷贝节点的type域是空的。
511 static tree
512 add_to_template_args (tree args, treeextra_args) in pt.c
513 {
514 tree new_args;
515 int extra_depth;
516 int i;
517 int j;
518
519 extra_depth = TMPL_ARGS_DEPTH (extra_args);
520 new_args = make_tree_vec (TMPL_ARGS_DEPTH(args) + extra_depth);
521
522 for (i = 1; i <= TMPL_ARGS_DEPTH (args); ++i)
523 SET_TMPL_ARGS_LEVEL (new_args, i,TMPL_ARGS_LEVEL (args, i));
524
525 for (j = 1; j<= extra_depth; ++j, ++i)
526 SET_TMPL_ARGS_LEVEL (new_args, i, TMPL_ARGS_LEVEL(extra_args, j));
527
528 returnnew_args;
529 }
接着在4248行,构建了TREE_VEC类型的arglists,其第一个成员指向上图中红色的TREE_VEC,而第二个成员指向内层template-id(在下面传递给args)的TREE_VEC。那么在4250行的parmlist(在下面传递给parms)指向图112中的其他TREE_VEC,这个节点代表“ThreadingModel”的实参。
3805 static tree
3806 coerce_template_parms(tree parms, in pt.c
3807 tree args,
3808 tree in_decl,
3809 tsubst_flags_t complain,
3810 int require_all_arguments)
3811 {
3812 int nparms, nargs, i, lost = 0;
3813 tree inner_args;
3814 tree new_args;
3815 tree new_inner_args;
3816
3817 inner_args = INNERMOST_TEMPLATE_ARGS (args);
3818 nargs = inner_args ? NUM_TMPL_ARGS(inner_args) : 0;
3819 nparms = TREE_VEC_LENGTH (parms);
3820
3821 if (nargs > nparms
3822 || (nargs < nparms
3823 && require_all_arguments
3824 && TREE_PURPOSE (TREE_VEC_ELT(parms, nargs)) == NULL_TREE))
3825 {
3826 if (complain & tf_error)
3827 {
3828 error ("wrong number of templatearguments (%d, should be %d)",
3829 nargs, nparms);
3830
3831 if (in_decl)
3832 cp_error_at ("provided for`%D'", in_decl);
3833 }
3834
3835 returnerror_mark_node;
3836 }
3837
3838 new_inner_args = make_tree_vec (nparms);
3839 new_args = add_outermost_template_args (args,new_inner_args);
在3817行,INNERMOST_TEMPLATE_ARGS返回先前所构建的arglists的最后一个成员,这是代表内层template-id的节点。作为结果,我们得到nparms(1),nargs(1)。
538 static tree
539 add_outermost_template_args(tree args, tree extra_args) in pt.c
540 {
541 tree new_args;
542
543 /* If there aremore levels of EXTRA_ARGS than there are ARGS,
544 something veryfishy is going on. */
545 my_friendly_assert(TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (extra_args),
546 0);
547
548 /* If *all* the newarguments will be the EXTRA_ARGS, just return
549 them. */
550 if (TMPL_ARGS_DEPTH (args) == TMPL_ARGS_DEPTH(extra_args))
551 returnextra_args;
552
553 /* For the moment,we make ARGS look like it contains fewer levels. */
554 TREE_VEC_LENGTH (args) -= TMPL_ARGS_DEPTH(extra_args);
555
556 new_args = add_to_template_args(args, extra_args);
557
558 /* Now, we restoreARGS to its full dimensions. */
559 TREE_VEC_LENGTH (args) += TMPL_ARGS_DEPTH(extra_args);
560
561 returnnew_args;
562 }
因为args是包含TREE_VEC的TREE_VEC,TMPL_ARGS_DEPTH返回的外层向量的长度(它是2),extra_args是长度是1的TREE_VEC,因为不是包含TREE_VEC的TREE_VEC,TMPL_ARGS_DEPTH对其总是返回1。因此add_outermost_template_args的总体效果是使用extra_args来替代args的最后的成员。
coerce_template_parms (continue)
3840 for (i = 0; i < nparms; i++)
3841 {
3842 tree arg;
3843 tree parm;
3844
3845 /* Get the Ithtemplate parameter. */
3846 parm = TREE_VEC_ELT (parms, i);
3847
3848 /*Calculate the Ith argument. */
3849 if (i < nargs)
3850 arg = TREE_VEC_ELT (inner_args, i);
3851 else if (require_all_arguments)
3852 /* There mustbe a default arg in this case. */
3853 arg = tsubst_template_arg (TREE_PURPOSE(parm), new_args,
3854 complain, in_decl);
3855 else
3856 break;
3857
3858 my_friendly_assert (arg, 20030727);
3859 if (arg == error_mark_node)
3860 error ("template argument %d isinvalid", i + 1);
3861 else
3862 arg = convert_template_argument(TREE_VALUE (parm),
3863 arg, new_args,complain, i,
3864 in_decl);
3865
3866 if (arg == error_mark_node)
3867 lost++;
3868 TREE_VEC_ELT (new_inner_args, i) = arg;
3869 }
3870
3871 if (lost)
3872 returnerror_mark_node;
3873
3874 returnnew_inner_args;
3875 }
在这个函数的调用中,参数parm是上图(不是图112)中的TYPE_DECL;arg是内层template-id(它是TYPE_DECL节点);args是由add_outermost_template_args构建的包含TREE_VEC的TREE_VEC。
3636 static tree
3637 convert_template_argument(tree parm, in pt.c
3638 tree arg,
3639 tree args,
3640 tsubst_flags_tcomplain,
3641 int i,
3642 tree in_decl)
3643 {
3644 tree val;
3645 tree inner_args;
3646 int is_type, requires_type, is_tmpl_type,requires_tmpl_type;
3647
3648 inner_args = INNERMOST_TEMPLATE_ARGS (args);
3649
3650 if (TREE_CODE (arg) == TREE_LIST
3651 && TREE_CODE (TREE_VALUE (arg))== OFFSET_REF)
3652 {
…
3660 }
3661
3662 requires_tmpl_type = TREE_CODE (parm) ==TEMPLATE_DECL;
3663 requires_type = (TREE_CODE (parm) ==TYPE_DECL
3664 || requires_tmpl_type);
3665
3666 is_tmpl_type = ((TREE_CODE (arg) ==TEMPLATE_DECL
3667 &&TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
3668 || TREE_CODE (arg) ==TEMPLATE_TEMPLATE_PARM
3669 || TREE_CODE (arg) ==UNBOUND_CLASS_TEMPLATE);
3670
3671 if (is_tmpl_type
3672 && (TREE_CODE (arg) ==TEMPLATE_TEMPLATE_PARM
3673 || TREE_CODE (arg) ==UNBOUND_CLASS_TEMPLATE))
3674 arg= TYPE_STUB_DECL (arg);
3675
3676 is_type = TYPE_P (arg) || is_tmpl_type;
…
3722 if (is_type)
3723 {
3724 if (requires_tmpl_type)
3725 {
…
3759 }
3760 else
3761 val = groktypename (arg);
3762 }
3763 else
3764 {
…
3790 }
3791
3792 return val;
3793 }
因为arg是一个TYPE_DECL节点,在3761行,groktypename不对它做任何事,只是返回它。然后在3868行,在coerce_template_parms中该节点被填入new_inner_args。记得当构建new_inner_args时,这个节点被刻意忽略了,但现在我们开始照顾到它了。因此从4250行返回到lookup_template_class时,arglist2与arglist相同。
记住在4257行的template指向代表“ThreadingModel”的TEMPLATE_DECL。接下来,将构建BOUND_TEMPLATE_TEMPLATE_PARM节点,正如其名字所暗示,它代表模板模板参数的一个绑定。
995 tree
996 bind_template_template_parm (tree t,tree newargs) in tree.c
997 {
998 tree decl = TYPE_NAME (t);
999 tree t2;
1000
1001 t2 = make_aggr_type(BOUND_TEMPLATE_TEMPLATE_PARM);
1002 decl = build_decl(TYPE_DECL, DECL_NAME (decl), NULL_TREE);
1003
1004 /* These nodes haveto be created to reflect new TYPE_DECL and template
1005 arguments. */
1006 TEMPLATE_TYPE_PARM_INDEX (t2) = copy_node(TEMPLATE_TYPE_PARM_INDEX (t));
1007 TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (t2)) = decl;
1008 TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t2)
1009 = tree_cons (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t),
1010 newargs, NULL_TREE);
1011
1012 TREE_TYPE (decl) = t2;
1013 TYPE_NAME (t2) = decl;
1014 TYPE_STUB_DECL (t2) = decl;
1015 TYPE_SIZE (t2) = 0;
1016
1017 return t2;
1018 }
最终,所构建的BOUND_TEMPLATE_TEMPLATE_PARM节点如下图所示。并且它被lookup_template_class返回。
(点此打开)
图113:BOUND_TEMPLATE_TEMPLATE_PARM节点
那么在finish_template_type及cp_parser_template_id中,通过该节点的chain域得到的TYPE_DECL被返回作为该template-id的代表。
接着该节点为cp_parser_class_name返回给cp_parser_base_specifier。相关代码参照章节完成类名查找。
- GCC-3.4.6源代码学习笔记(126)
- GCC-3.4.6源代码学习笔记 (100)
- GCC-3.4.6源代码学习笔记 (101)
- GCC-3.4.6源代码学习笔记 (102)
- GCC-3.4.6源代码学习笔记 (103)
- GCC-3.4.6源代码学习笔记 (104)
- GCC-3.4.6源代码学习笔记 (105)
- GCC-3.4.6源代码学习笔记 (106)
- GCC-3.4.6源代码学习笔记(166)
- GCC-3.4.6源代码学习笔记
- GCC-3.4.6源代码学习笔记(6)
- GCC-3.4.6源代码学习笔记(1)
- GCC-3.4.6源代码学习笔记(2)
- GCC-3.4.6源代码学习笔记(3)
- GCC-3.4.6源代码学习笔记(4)
- GCC-3.4.6源代码学习笔记(5)
- GCC-3.4.6源代码学习笔记(7)
- GCC-3.4.6源代码学习笔记(8)
- Ubuntu cron定时执行任务
- jsp中文乱码处理问题
- javascript中的cookie使用(javascript权威指南)
- 中国经济的真相(转)
- 采用WAVECOM模块组装-串口的终端GSM MODEM,性能稳定.短信发送量最快可达600条/小时,比用手机发送短信更稳定、快捷。该设备广泛应用于企业短信广告、短信通知、短信查询、短信监控等领域。
- GCC-3.4.6源代码学习笔记(126)
- ADO.NET学习摘记5
- hdu 1452 Happy 2004
- GetProcAddress函数
- 中国互联网“第一次世界大战”
- Studying note of GCC-3.4.6 source (126)
- POJ 1006 Biorhthms
- Shell实现Unix进程间信息交换的几种方法(转)
- 在MDK平台下调试mini2440