GCC-3.4.6源代码学习笔记(126)
2010-11-05 09:54
323 查看
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 bind
the arguments.
*/
4354
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
error_mark_node);
4355
4356
/* In the scope
of a template class, explicit references to the
4357
template class refer to the type of the
template, not any
4358
instantiation of it. For example, in:
4359
4360
template <class T> class C { void
f(C<T>); }
4361
4362
the `C<T>' is just the same as `C'.
Outside of the
4363
class, however, such a reference is an
instantiation.
*/
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 involve
template parameters. Note that we set
4409
IS_PARTIAL_INSTANTIATION for
partial specializations as
4410
well.
*/
4411
is_partial_instantiation = uses_template_parms
(arglist);
4412
4413
/* If the deduced
arguments 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 the
type.
*/
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 local
class. 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 called
start_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 the
template information. We have to figure out which
4485
template is the immediate
parent if this is a full
4486
instantiation.
*/
4487
if (parm_depth == 1 ||
is_partial_instantiation
4488
|| !PRIMARY_TEMPLATE_P (template))
4489
/* This case is
easy; 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 the
type has been registered on the instantiations
4554
list, we set up the
enumerators. Because the enumeration
4555
constants may involve the
enumeration type itself, we make
4556
sure to register the type
first, and then create the
4557
constants. That way, doing
tsubst_expr for the enumeration
4558
constants won't result in
recursive calls here; we'll find
4559
the instantiation and exit
above.
*/
4560
tsubst_enum (template_type, t, arglist);
4561
4562
/* Reset the name
of 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 generates
debugging 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 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
来获取),其中主模板的名字是一个标识符(作为比较,一个偏特化的模板的名字是一个
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 representation
of 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 are
declaring a constructor, say A<T>::A<T>, we will get
4168
an implicit
typename 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 something
like `template <class T> class X class X { ... };'
4193
we could end up with D1 having
nothing but an IDENTIFIER_VALUE.
4194
We don't want to do that, but
we have to deal with the situation,
4195
so let's give them some syntax
errors to chew on instead of a
4196
crash. Alternatively D1 might
not be a template type at all.
*/
4197
if (! template)
4198
{
4199
if (complain & tf_error)
4200
error ("`%T' is not a
template", d1);
4201
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
error_mark_node);
4202
}
4203
4204
if (TREE_CODE (template) != TEMPLATE_DECL
4205
/* Make sure
it'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 as
a template", d1);
4213
if (in_decl)
4214
cp_error_at ("for template
declaration `%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 an
example where a template template parameter declared as
4232
4233
template <class T, class
U = std::allocator<T> > class TT
4234
4235
The template parameter level
of T and U are one level larger than
4236
of TT. To proper process the
default 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 appearing
as default template argument, can be
4240
obtained from
`current_template_args ()'.
4241
4242
Suppose that TT is later
substituted 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} and
the 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, tree
extra_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
return
new_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 template
arguments (%d, should be %d)",
3829
nargs, nparms);
3830
3831
if (in_decl)
3832
cp_error_at ("provided for
`%D'", in_decl);
3833
}
3834
3835
return
error_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 are
more levels of EXTRA_ARGS than there are ARGS,
544
something very
fishy is going on.
*/
545
my_friendly_assert
(TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (extra_args),
546
0);
547
548
/* If *all* the new
arguments will be the EXTRA_ARGS, just return
549
them.
*/
550
if (TMPL_ARGS_DEPTH (args) == TMPL_ARGS_DEPTH
(extra_args))
551
return
extra_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 restore
ARGS to its full dimensions.
*/
559
TREE_VEC_LENGTH (args) += TMPL_ARGS_DEPTH
(extra_args);
560
561
return
new_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 Ith
template 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 must
be 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 is
invalid", i + 1);
3861
else
3862
arg = convert_template_argument
(TREE_VALUE (parm),
3863
arg, new_args,
complain, i,
3864
i
n_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
return
error_mark_node;
3873
3874
return
new_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_t
complain,
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 have
to 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
。相关代码参照章节
完成类名查找
。
生成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 bind
the arguments.
*/
4354
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
error_mark_node);
4355
4356
/* In the scope
of a template class, explicit references to the
4357
template class refer to the type of the
template, not any
4358
instantiation of it. For example, in:
4359
4360
template <class T> class C { void
f(C<T>); }
4361
4362
the `C<T>' is just the same as `C'.
Outside of the
4363
class, however, such a reference is an
instantiation.
*/
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 involve
template parameters. Note that we set
4409
IS_PARTIAL_INSTANTIATION for
partial specializations as
4410
well.
*/
4411
is_partial_instantiation = uses_template_parms
(arglist);
4412
4413
/* If the deduced
arguments 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 the
type.
*/
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 local
class. 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 called
start_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 the
template information. We have to figure out which
4485
template is the immediate
parent if this is a full
4486
instantiation.
*/
4487
if (parm_depth == 1 ||
is_partial_instantiation
4488
|| !PRIMARY_TEMPLATE_P (template))
4489
/* This case is
easy; 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 the
type has been registered on the instantiations
4554
list, we set up the
enumerators. Because the enumeration
4555
constants may involve the
enumeration type itself, we make
4556
sure to register the type
first, and then create the
4557
constants. That way, doing
tsubst_expr for the enumeration
4558
constants won't result in
recursive calls here; we'll find
4559
the instantiation and exit
above.
*/
4560
tsubst_enum (template_type, t, arglist);
4561
4562
/* Reset the name
of 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 generates
debugging 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 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
来获取),其中主模板的名字是一个标识符(作为比较,一个偏特化的模板的名字是一个
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 representation
of 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 are
declaring a constructor, say A<T>::A<T>, we will get
4168
an implicit
typename 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 something
like `template <class T> class X class X { ... };'
4193
we could end up with D1 having
nothing but an IDENTIFIER_VALUE.
4194
We don't want to do that, but
we have to deal with the situation,
4195
so let's give them some syntax
errors to chew on instead of a
4196
crash. Alternatively D1 might
not be a template type at all.
*/
4197
if (! template)
4198
{
4199
if (complain & tf_error)
4200
error ("`%T' is not a
template", d1);
4201
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
error_mark_node);
4202
}
4203
4204
if (TREE_CODE (template) != TEMPLATE_DECL
4205
/* Make sure
it'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 as
a template", d1);
4213
if (in_decl)
4214
cp_error_at ("for template
declaration `%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 an
example where a template template parameter declared as
4232
4233
template <class T, class
U = std::allocator<T> > class TT
4234
4235
The template parameter level
of T and U are one level larger than
4236
of TT. To proper process the
default 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 appearing
as default template argument, can be
4240
obtained from
`current_template_args ()'.
4241
4242
Suppose that TT is later
substituted 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} and
the 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, tree
extra_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
return
new_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 template
arguments (%d, should be %d)",
3829
nargs, nparms);
3830
3831
if (in_decl)
3832
cp_error_at ("provided for
`%D'", in_decl);
3833
}
3834
3835
return
error_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 are
more levels of EXTRA_ARGS than there are ARGS,
544
something very
fishy is going on.
*/
545
my_friendly_assert
(TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (extra_args),
546
0);
547
548
/* If *all* the new
arguments will be the EXTRA_ARGS, just return
549
them.
*/
550
if (TMPL_ARGS_DEPTH (args) == TMPL_ARGS_DEPTH
(extra_args))
551
return
extra_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 restore
ARGS to its full dimensions.
*/
559
TREE_VEC_LENGTH (args) += TMPL_ARGS_DEPTH
(extra_args);
560
561
return
new_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 Ith
template 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 must
be 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 is
invalid", i + 1);
3861
else
3862
arg = convert_template_argument
(TREE_VALUE (parm),
3863
arg, new_args,
complain, i,
3864
i
n_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
return
error_mark_node;
3873
3874
return
new_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_t
complain,
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 have
to 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源代码学习笔记(163)
- GCC-3.4.6源代码学习笔记(110)
- GCC-3.4.6源代码学习笔记(62)
- GCC-3.4.6源代码学习笔记(47)
- GCC-3.4.6源代码学习笔记(143)
- GCC-3.4.6源代码学习笔记(64)
- GCC-3.4.6源代码学习笔记(147-续2)
- GCC-3.4.6源代码学习笔记(20)
- GCC-3.4.6源代码学习笔记(131)
- GCC-3.4.6源代码学习笔记(136)
- GCC-3.4.6源代码学习笔记(88)
- GCC-3.4.6源代码学习笔记(9)
- GCC-3.4.6源代码学习笔记(26续1)
- GCC-3.4.6源代码学习笔记(139-续1)
- GCC-3.4.6源代码学习笔记(140)
- GCC-3.4.6源代码学习笔记(60)
- GCC-3.4.6源代码学习笔记(12)
- GCC-3.4.6源代码学习笔记(116)
- GCC-3.4.6源代码学习笔记(33)
- GCC-3.4.6源代码学习笔记(129 续)