Studying note of GCC-3.4.6 source (134)
2010-12-25 13:47
405 查看
5.12.5.2.2.2.1.3.1.
Instantiate
base class – substituting argument for parameter
The base class
may depends on template parameter as our example here. So to instantiate the
derived class, it first needs instantiate its base classes appropriately. Here
we display the intermediate tree of “SmallObject” in below again for convience.
“SmallObject” has single base class – “ThreadingModel” which defaults to
“SingleThreaded”, and “SmallObject” is declared within namespace “Loki”.
(Click
here for open
)
figure 115
:
intermediate tree for “SmallObject”
In instantiate_class_template
,
at line 5320, pattern
is the node of RECORD_TYPE at top in the figure; and pinfo
at line 5400 is that pointed
by binfo
field of pattern
.
Then at line 5425, namespace “Loki” is made as the current binding context. So
at line 5439, the first argument for tsubst
is the node of
BOUND_TEMPLATE_TEMPLATE_PARM, and the second argument args
is the tree_vec in red in
below figure.
(Click
here for open
)
figure 116
:
intermediate tree for the VAR_DECL
6681
static
tree
6682
tsubst (tree t,
tree args, tsubst_flags_t complain, tree in_decl)
in pt.c
6683
{
6684
tree type, r;
6685
6686
if (t == NULL_TREE || t == error_mark_node
6687
|| t == integer_type_node
6688
|| t == void_type_node
6689
|| t == char_type_node
6690
|| t == unknown_type_node
6691
|| TREE_CODE (t) == NAMESPACE_DECL)
6692
return
t;
6693
6694
if
(TREE_CODE (t) == IDENTIFIER_NODE)
6695
type = IDENTIFIER_TYPE_VALUE (t);
6696
else
6697
type = TREE_TYPE (t);
6698
6699
my_friendly_assert (type !=
unknown_type_node, 20030716);
6700
6701
if (type && TREE_CODE (t) !=
FUNCTION_DECL
6702
&& TREE_CODE (t) != TYPENAME_TYPE
6703
&& TREE_CODE (t) != TEMPLATE_DECL
6704
&& TREE_CODE (t) != IDENTIFIER_NODE
6705
&& TREE_CODE (t) !=
FUNCTION_TYPE
6706
&& TREE_CODE (t) != METHOD_TYPE)
6707
type = tsubst (type, args, complain,
in_decl);
6708
if (type == error_mark_node)
6709
return
error_mark_node;
6710
6711
if (DECL_P (t))
6712
return
tsubst_decl (t, args, type, complain);
6713
6714
switch
(TREE_CODE (t))
6715
{
…
6776
case
TEMPLATE_TYPE_PARM:
6777
case
TEMPLATE_TEMPLATE_PARM:
6778
case
BOUND_TEMPLATE_TEMPLATE_PARM:
6779
case
TEMPLATE_PARM_INDEX:
6780
{
6781
int idx;
6782
int level;
6783
int levels;
6784
6785
r = NULL_TREE;
6786
6787
if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
6788
|| TREE_CODE (t) ==
TEMPLATE_TEMPLATE_PARM
6789
|| TREE_CODE (t) ==
BOUND_TEMPLATE_TEMPLATE_PARM)
6790
{
6791
idx = TEMPLATE_TYPE_IDX (t);
6792
level = TEMPLATE_TYPE_LEVEL (t);
6793
}
6794
else
6795
{
6796
idx = TEMPLATE_PARM_IDX (t);
6797
level = TEMPLATE_PARM_LEVEL (t);
6798
}
6799
6800
if (TREE_VEC_LENGTH (args) > 0)
6801
{
6802
tree arg = NULL_TREE;
6803
6804
levels = TMPL_ARGS_DEPTH (args);
6805
if (level <= levels)
6806
arg = TMPL_ARG (args, level, idx);
6807
6808
if (arg == error_mark_node)
6809
return
error_mark_node;
6810
else if (arg != NULL_TREE)
6811
{
6812
if (TREE_CODE (t) ==
TEMPLATE_TYPE_PARM)
6813
{
6814
my_friendly_assert (TYPE_P (arg),
0);
6815
return
cp_build_qualified_type_real
6816
(arg, cp_type_quals (arg) |
cp_type_quals (t),
6817
complain |
tf_ignore_bad_quals);
6818
}
6819
else if (TREE_CODE (t) ==
BOUND_TEMPLATE_TEMPLATE_PARM)
6820
{
6821
/* We are
processing a type constructed from
6822
a template
template parameter.
*/
6823
tree argvec = tsubst (TYPE_TI_ARGS
(t),
6824
args, complain, in_decl);
6825
if (argvec == error_mark_node)
6826
return
error_mark_node;
As t
refers to the node of BOUND_TEMPLATE_TEMPALTE_PARM, at line 6791 idx
is
0, and level
is 1; arg
at line 6806 then points to the node of TEMPLATE_DECL of “SingleThreaded”. Also
notice that at line 6823, the first argument of tsubst
“TYPE_TI_ARGS (t)”
for our example refers to the tree_vec containing 2 elements in the first
figure in this section [Its definition is: (TI_ARGS
(TYPE_TEMPLATE_INFO (NODE)))
].
6681
static
tree
6682
tsubst (tree t,
tree args, tsubst_flags_t complain, tree in_decl)
in pt.c
6683
{
6684
tree type, r;
...
6694
if (TREE_CODE (t) == IDENTIFIER_NODE)
6695
type = IDENTIFIER_TYPE_VALUE (t);
6696
else
6697
type = TREE_TYPE (t);
…
6714
switch
(TREE_CODE (t))
6715
{
…
6950
case
TREE_VEC:
6951
if (type != NULL_TREE)
6952
{
…
6970
}
6971
6972
/* Otherwise,
a vector of template arguments.
*/
6973
return
tsubst_template_args
(t, args, complain,
in_decl);
…
7304
}
7305
}
Here argument t
stands for the parameters of the template,
while args
represents the arguments at instantiation. As semantic check should be taken at
point of instantiation for template, tsubst_template_args
verifies if the
arguments are compatible with the parameters. Now t points to node in red as
below figure.
![](http://hi.csdn.net/attachment/201012/25/4457637_1293255193SCi8.jpg)
5744
static
tree
5745
tsubst_template_args
(tree t, tree args,
tsubst_flags_t complain, tree in_decl)
in pt.c
5746
{
5747
int len = TREE_VEC_LENGTH (t);
5748
int need_new = 0, i;
5749
tree *elts = alloca (len * sizeof
(tree));
5750
5751
for
(i = 0; i < len; i++)
5752
{
5753
tree orig_arg = TREE_VEC_ELT (t, i);
5754
tree new_arg;
5756
5757
if (TREE_CODE (orig_arg) == TREE_VEC)
5758
new_arg = tsubst_template_args (orig_arg,
args, complain, in_decl);
5759
else
5760
new_arg = tsubst_template_arg
(orig_arg, args, complain, in_decl);
5761
5762
if (new_arg == error_mark_node)
5763
return
error_mark_node;
5764
5765
elts[i] = new_arg;
5766
if (new_arg != orig_arg)
5767
need_new = 1;
5768
}
5769
5770
if (!need_new)
5771
return
t;
5772
5773
t = make_tree_vec (len);
5774
for
(i = 0; i
< len; i++)
5775
TREE_VEC_ELT (t, i) = elts[i];
5776
5777
return
t;
5778
}
See that the first element in t
is a tree_vec, which are the parameters for
outer template. This tree_vec (the first element) and the second element as the
parameter of the inner template both are processed by tsubst_template_arg
. In the
function, for all candidates, TYPE_P returns zero as they are not node of
types. See that the arguments of t
and args
in tsubst_expr
are the same as those in tsubst_template_arg
.
7822
static
tree
7823
tsubst_expr (tree
t, tree args, tsubst_flags_t complain, tree in_decl)
in pt.c
7824
{
7825
tree stmt, tmp;
7826
tsubst_flags_t stmt_expr
7827
= complain & (tf_stmt_expr_cmpd |
tf_stmt_expr_body);
7828
7829
complain ^= stmt_expr;
7830
if (t == NULL_TREE || t == error_mark_node)
7831
return
t;
7832
7833
if (!STATEMENT_CODE_P (TREE_CODE (t)))
7834
return
tsubst_copy_and_build (t, args, complain, in_decl,
7835
/*function_p=*/
false);
…
8156
}
Here all template arguments are not of statement, so tsubst_copy_and_build
is always invoked.
8179
tree
8180
tsubst_copy_and_build
(tree t,
in pt.c
8181
tree args,
8182
tsubst_flags_t complain,
8183
tree
in_decl,
8184
bool
function_p)
8185
{
8186
#define
RECUR(NODE) /
8187
tsubst_copy_and_build (NODE, args, complain,
in_decl, /*function_p=*/
false)
8188
8189
tree op1;
8190
8191
if (t == NULL_TREE || t == error_mark_node)
8192
return
t;
8193
8194
switch
(TREE_CODE (t))
8195
{
…
8693
default
:
8694
return
tsubst_copy
(t, args, complain, in_decl);
8695
}
8696
8697
#undef
RECUR
8698
}
For the outer template parameters, the first is
TEMPLATE_TEMPALTE_PARM, the second and the third both are TEMPLATE_PARM_INDEX;
and the parameter of the inner template is the TEMPLATE_TYPE_PARM. All these
nodes are processed by tsubst_copy
.
7449
static
tree
7450
tsubst_copy (tree
t, tree args, tsubst_flags_t complain, tree in_decl)
in pt.c
7451
{
7452
enum
tree_code code;
7453
tree r;
7454
7455
if (t == NULL_TREE || t == error_mark_node)
7456
return
t;
7457
7458
code = TREE_CODE (t);
7469
7460
switch
(code)
7461
{
…
7767
case
RECORD_TYPE:
7768
case
UNION_TYPE:
7769
case
ENUMERAL_TYPE:
7770
case
INTEGER_TYPE:
7771
case
TEMPLATE_TYPE_PARM:
7772
case
TEMPLATE_TEMPLATE_PARM:
7773
case
BOUND_TEMPLATE_TEMPLATE_PARM:
7774
case
TEMPLATE_PARM_INDEX:
7775
case
POINTER_TYPE:
7776
case
REFERENCE_TYPE:
7777
case
OFFSET_TYPE:
7778
case
FUNCTION_TYPE:
7779
case
METHOD_TYPE:
7780
case
ARRAY_TYPE:
7781
case
TYPENAME_TYPE:
7782
case
UNBOUND_CLASS_TEMPLATE:
7783
case
TYPEOF_TYPE:
7784
case
TYPE_DECL:
7785
return
tsubst (t, args, complain, in_decl);
…
7816
}
7817
}
Again for all nodes, tsubst
is invoked. And remember that t
refers
to the template parameters and args
holds the template arguments.
6681
static
tree
6682
tsubst (tree t,
tree args, tsubst_flags_t complain, tree in_decl)
in pt.c
6683
{
6684
tree type, r;
6685
6686
if (t
== NULL_TREE || t == error_mark_node
6687
|| t == integer_type_node
6688
|| t == void_type_node
6689
|| t == char_type_node
6690
|| t == unknown_type_node
6691
|| TREE_CODE (t) == NAMESPACE_DECL)
6692
return
t;
6693
6694
if
(TREE_CODE (t) == IDENTIFIER_NODE)
6695
type = IDENTIFIER_TYPE_VALUE (t);
6696
else
6697
type = TREE_TYPE (t);
6698
6699
my_friendly_assert (type !=
unknown_type_node, 20030716);
6700
6701
if (type && TREE_CODE (t) !=
FUNCTION_DECL
6702
&& TREE_CODE (t) != TYPENAME_TYPE
6703
&& TREE_CODE (t) != TEMPLATE_DECL
6704
&& TREE_CODE (t) != IDENTIFIER_NODE
6705
&& TREE_CODE (t) !=
FUNCTION_TYPE
6706
&& TREE_CODE (t) != METHOD_TYPE)
6707
type = tsubst (type, args, complain,
in_decl);
6708
if (type == error_mark_node)
6709
return
error_mark_node;
6710
6711
if (DECL_P (t))
6712
return
tsubst_decl (t, args, type, complain);
6713
6714
switch
(TREE_CODE (t))
6715
{
…
6776
case
TEMPLATE_TYPE_PARM:
6777
case
TEMPLATE_TEMPLATE_PARM:
6778
case
BOUND_TEMPLATE_TEMPLATE_PARM:
6779
case
TEMPLATE_PARM_INDEX:
6780
{
6781
int idx;
6782
int level;
6783
int levels;
6784
6785
r = NULL_TREE;
6786
6787
if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
6788
|| TREE_CODE (t) ==
TEMPLATE_TEMPLATE_PARM
6789
|| TREE_CODE (t) ==
BOUND_TEMPLATE_TEMPLATE_PARM)
6790
{
6791
idx = TEMPLATE_TYPE_IDX (t);
6792
level = TEMPLATE_TYPE_LEVEL (t);
6793
}
6794
else
6795
{
6796
idx = TEMPLATE_PARM_IDX (t);
6797
level = TEMPLATE_PARM_LEVEL (t);
6798
}
6799
6800
if (TREE_VEC_LENGTH (args) > 0)
6801
{
6802
tree arg = NULL_TREE;
6803
6804
levels = TMPL_ARGS_DEPTH (args);
6805
if (level <= levels)
6806
arg = TMPL_ARG (args, level, idx);
6807
6808
if (arg == error_mark_node)
6809
return
error_mark_node;
6810
else if (arg != NULL_TREE)
6811
{
6812
if (TREE_CODE (t) ==
TEMPLATE_TYPE_PARM)
6813
{
…
6818
}
6819
else if (TREE_CODE (t) ==
BOUND_TEMPLATE_TEMPLATE_PARM)
6820
{
…
6843
}
6844
else
6845
/*
TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX.
*/
6846
return
arg;
6847
}
6848
}
…
6907
}
…
7304
}
7305
}
Node of TEMPLATE_TEMPLATE_PRAM has null type
field. And idx
and level
at
line 6791 are set according to the associated TEMPLATE_PARM_INDEX node as 0 and
1 respectively. At line 6806 arg
points to the TEMPALTE_DECL of
“SingleThreaded”. When returning this node back to tsubst_template_arg
, uses_template_parms
at line 5713 returns zero for this node as it is not dependent one. And this
node is returned further.
The second
parameter of the outer template is the node of TEMPLATE_PARM_INDEX in below
figure. While arg
at line 6806 refers to the INTEGER_CST of 4096 in the rear figure; and it is returned at line
6846 also.
(Click
here for open
)
Similar is the third parameter for the outer template, which is
omitted in previous section, as it very resembles the second one. For the inner
template, the parameter is the node of TEMPLATE_TYPE_PARM in below figure.
![](http://hi.csdn.net/attachment/201012/25/4457637_1293255194zYv8.jpg)
The level
recorded by the associated
TEMPLATE_PARM_INDEX in the figure is 2 while level
indicated by args
is
1; following code will be executed in tsubst
for this node.
6681
static
tree
6682
tsubst (tree t,
tree args, tsubst_flags_t complain, tree in_decl)
in pt.c
6683
{
6684
tree type, r;
…
6694
if (TREE_CODE (t) == IDENTIFIER_NODE)
6695
type = IDENTIFIER_TYPE_VALUE (t);
6696
else
6697
type = TREE_TYPE (t);
…
6714
switch
(TREE_CODE (t))
6715
{
…
6776
case
TEMPLATE_TYPE_PARM:
6777
case
TEMPLATE_TEMPLATE_PARM:
6778
case
BOUND_TEMPLATE_TEMPLATE_PARM:
6779
case
TEMPLATE_PARM_INDEX:
6780
{
6781
int idx;
6782
int level;
6783
int levels;
6784
6785
r = NULL_TREE;
6786
6787
if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
6788
|| TREE_CODE (t) ==
TEMPLATE_TEMPLATE_PARM
6789
|| TREE_CODE (t) ==
BOUND_TEMPLATE_TEMPLATE_PARM)
6790
{
6791
idx = TEMPLATE_TYPE_IDX (t);
6792
level = TEMPLATE_TYPE_LEVEL (t);
6793
}
6794
else
6795
{
6796
idx = TEMPLATE_PARM_IDX (t);
6797
level = TEMPLATE_PARM_LEVEL (t);
6798
}
6799
6800
if (TREE_VEC_LENGTH (args) > 0)
6801
{
6802
tree arg = NULL_TREE;
6803
6804
levels = TMPL_ARGS_DEPTH (args);
6805
if (level <= levels)
6806
arg = TMPL_ARG (args, level, idx);
6807
6808
if (arg == error_mark_node)
6809
return
error_mark_node;
6810
else if (arg != NULL_TREE)
6811
{
…
6847
}
6848
}
6849
else
6850
abort ();
6851
6852
if (level == 1)
6853
/* This can
happen during the attempted tsubst'ing in
6854
unify. This means that
we don't yet have any information
6855
about the template
parameter in question.
*/
6856
return
t;
6857
6858
/* If we get
here, we must have been looking at a parm for a
6859
more deeply nested
template. Make a new version of this
6860
template parameter, but with a lower
level.
*/
6861
switch
(TREE_CODE (t))
6862
{
6863
case
TEMPLATE_TYPE_PARM:
6864
case
TEMPLATE_TEMPLATE_PARM:
6865
case
BOUND_TEMPLATE_TEMPLATE_PARM:
6866
if (cp_type_quals (t))
6867
{
…
6873
}
6874
else
6875
{
6876
r = copy_type (t);
6877
TEMPLATE_TYPE_PARM_INDEX (r)
6878
= reduce_template_parm_level
(TEMPLATE_TYPE_PARM_INDEX (t),
6879
r,
levels);
6880
TYPE_STUB_DECL (r)
= TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
6881
TYPE_MAIN_VARIANT (r) = r;
6882
TYPE_POINTER_TO (r) = NULL_TREE;
6883
TYPE_REFERENCE_TO (r) = NULL_TREE;
6884
6885
if (TREE_CODE (t) ==
BOUND_TEMPLATE_TEMPLATE_PARM)
6886
{
…
6894
}
6895
}
6896
break
;
6897
6898
case
TEMPLATE_PARM_INDEX:
6899
r = reduce_template_parm_level (t,
type, levels);
6900
break
;
6901
6902
default
:
6903
abort ();
6904
}
6905
6906
return
r;
6907
}
…
7304
}
7305
}
Above at line 6878, TEMPLATE_TYPE_PARM_INDEX fetches the node in value
field of the node of TEMPLATE_TYPE_PARM, which is the node of
TEMPLATE_PARM_INDEX.
2128
static
tree
2129
reduce_template_parm_level
(tree index,
tree type, int levels)
in pt.c
2130
{
2131
if (TEMPLATE_PARM_DESCENDANTS (index) ==
NULL_TREE
2132
|| (TEMPLATE_PARM_LEVEL
(TEMPLATE_PARM_DESCENDANTS (index))
2133
!= TEMPLATE_PARM_LEVEL (index) -
levels))
2134
{
2135
tree orig_decl = TEMPLATE_PARM_DECL (index);
2136
tree decl, t;
2137
2138
decl = build_decl
(TREE_CODE (orig_decl), DECL_NAME (orig_decl), type);
2139
TREE_CONSTANT (decl) = TREE_CONSTANT
(orig_decl);
2140
TREE_READONLY (decl) = TREE_READONLY
(orig_decl);
2141
DECL_ARTIFICIAL (decl) = 1;
2142
SET_DECL_TEMPLATE_PARM_P (decl);
2143
2144
t = build_template_parm_index
(TEMPLATE_PARM_IDX (index),
2145
TEMPLATE_PARM_LEVEL
(index) - levels,
2146
TEMPLATE_PARM_ORIG_LEVEL (index),
2147
decl, type);
2148
TEMPLATE_PARM_DESCENDANTS (index) = t;
2149
2150
/* Template
template parameters need this.
*/
2151
DECL_TEMPLATE_PARMS (decl)
2152
= DECL_TEMPLATE_PARMS (TEMPLATE_PARM_DECL
(index));
2153
}
2154
2155
return
TEMPLATE_PARM_DESCENDANTS (index);
2156
}
A new
TEMPLATE_PARM_INDEX is created with decreased level
to indicate the instantiation
of the inner template parameter. And this node is chained as the immediate
descendant of the orginial TEMPLATE_PARM_INDEX node.
![](http://hi.csdn.net/attachment/201012/25/4457637_12932551941N50.jpg)
Then at line 6823 in
tsubst
,
argvec
created by the nested tsubst
for parameters in the node of
BOUND_TEMPLATE_TEMPLATE_PARM is shown in below figure.
(Click
here for open
)
Continue in the tsubst
handling the node of BOUND_TEMPLATE_TEMPLATE_PARM; remember that arg
below refers to TEMPLATE_DECL of “SingleThreaded” in the below figure. As now
we are instantiating the outer template, it is the precondition to instantiate
the inner template first. It is done implicitly by lookup_template_class
below.
tsubst (continue)
6828
/* We can
get a TEMPLATE_TEMPLATE_PARM here when
6829
we are resolving
nested-types in the signature of
6830
a member
function templates.
6831
Otherwise ARG is a
TEMPLATE_DECL and is the real
6832
template to be
instantiated.
*/
6833
if (TREE_CODE (arg) ==
TEMPLATE_TEMPLATE_PARM)
6834
arg = TYPE_NAME (arg);
6835
6836
r = lookup_template_class (arg,
6837
argvec,
in_decl,
6838
DECL_CONTEXT
(arg),
6839
/*entering_scope=*/
0,
6840
complain);
6841
return
cp_build_qualified_type_real
6842
(r, TYPE_QUALS (t),
complain);
6843
}
6844
else
6845
/*
TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX.
*/
6846
return
arg;
6847
}
6848
}
6849
else
6850
abort ();
So at
invocation of lookup_template_class
,
argument dl
is the TEMPLATE_DECL in red in below figure, and arglist
is the argvec
in tusbst
above, and context
is the scope of “Loki”.
(Click
here for open
)
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
{
…
4162
}
4163
else if (TREE_CODE (d1) == TYPE_DECL
&& IS_AGGR_TYPE (TREE_TYPE (d1)))
4164
{
…
4177
}
4178
else if (TREE_CODE (d1) == ENUMERAL_TYPE
4179
|| (TYPE_P (d1) && IS_AGGR_TYPE
(d1)))
4180
{
…
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
}
…
4219
complain &= ~tf_user;
4220
4221
if (DECL_TEMPLATE_TEMPLATE_PARM_P (template))
4222
{
…
4259
}
4260
else
4261
{
4262
tree template_type = TREE_TYPE (template);
4263
tree gen_tmpl;
4264
tree type_decl;
4265
tree found = NULL_TREE;
4266
tree *tp;
4267
int arg_depth;
4268
int parm_depth;
4269
int is_partial_instantiation;
4270
4271
gen_tmpl = most_general_template
(template);
4272
parmlist = DECL_TEMPLATE_PARMS (gen_tmpl);
4273
parm_depth = TMPL_PARMS_DEPTH (parmlist);
4274
arg_depth = TMPL_ARGS_DEPTH (arglist);
4275
4276
if (arg_depth == 1 && parm_depth
> 1)
4277
{
…
4294
}
4295
4296
/* Now we should
have enough arguments.
*/
4297
my_friendly_assert (parm_depth == arg_depth,
0);
4298
4299
/* From here on,
we're only interested in the most general
4300
template.
*/
4301
template = gen_tmpl;
4302
4303
/* Calculate the
BOUND_ARGS. These will be the args that are
4304
actually tsubst'd into the
definition to create the
4305
instantiation.
*/
4306
if (parm_depth > 1)
4307
{
…
4344
}
4345
else
4346
arglist
4347
= coerce_template_parms
(INNERMOST_TEMPLATE_PARMS (parmlist),
4348
INNERMOST_TEMPLATE_ARGS
(arglist),
4349
template,
4350
complain, /*require_all_args=*/
1);
4351
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);
Above parmlist
is the tree_list pointed by arguments
field of the TEMPLATE_DECL of
“SingleThreaded”. So argument parms
below is the tree_vec referred by value
field of this tree_list; it is the parameters in the declaration.
INNERMOST_TEMPLATE_ARGS following accesses the second element of the argvec
above – the argument for inner template.
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);
…
3838
new_inner_args = make_tree_vec (nparms);
3839
new_args = add_outermost_template_args (args,
new_inner_args);
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
}
As both parms
and args
are tree_vec of size 1, add_outermost_template_args
at line 3839 does nothing. Further at line 3850, arg
points to the new created
TEMPLATE_TYPE_PARM node.
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);
…
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
}
Node of TEMPLATE_TYPE_PARM is regarded as type, so is_type
at line 3676 is true as TYPE_P returns true for arg
. Following at line 3761, as arg
is
not a tree_list, groktypename
just returns arg
back. Note that arg
is placed into arglist
at line 4347 in lookup_template_class
.
lookup_template_class (continue)
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
{
4367
found = template_type;
4368
4369
if (!entering_scope &&
PRIMARY_TEMPLATE_P (template))
4370
{
4371
tree ctx;
4372
4373
for
(ctx = current_class_type
;
4374
ctx && TREE_CODE (ctx) !=
NAMESPACE_DECL;
4375
ctx = (TYPE_P (ctx)
4376
? TYPE_CONTEXT (ctx)
4377
: DECL_CONTEXT (ctx)))
4378
if (TYPE_P (ctx) && same_type_p
(ctx, template_type))
4379
goto
found_ctx;
4380
4381
/* We're not
in the scope of the class, so the
4382
TEMPLATE_TYPE is not the
type we want after all.
*/
4383
found = NULL_TREE;
4384
found_ctx:;
4385
}
4386
}
4387
if (found)
4388
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
found);
…
4431
context = tsubst (DECL_CONTEXT (template),
arglist,
4432
complain, in_decl);
4433
if (!context)
4434
context = global_namespace
;
4435
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
}
Notice that template_type
is the node of RECORD_TYPE of
“SingleThreaded”, though comp_template_args
at line 4364 finds that
its argument is the same as arglist
, we are not within class context (current_class_type
is NULL), we have to abondon this found RECORD_TYPE.
Next context
is NAMESPACE_DECL of “Loki”, tsubst
at line 4431 does nothing but returns
this node. The code following is to create the RECORD_TYPE and associated nodes
for the base class instantiation. So following nodes are created. At last the
node of RECORD_TYPE is returned in instantiate_class_template
at line 5439.
(Click
here for open
)
Instantiate
base class – substituting argument for parameter
The base class
may depends on template parameter as our example here. So to instantiate the
derived class, it first needs instantiate its base classes appropriately. Here
we display the intermediate tree of “SmallObject” in below again for convience.
“SmallObject” has single base class – “ThreadingModel” which defaults to
“SingleThreaded”, and “SmallObject” is declared within namespace “Loki”.
(Click
here for open
)
figure 115
:
intermediate tree for “SmallObject”
In instantiate_class_template
,
at line 5320, pattern
is the node of RECORD_TYPE at top in the figure; and pinfo
at line 5400 is that pointed
by binfo
field of pattern
.
Then at line 5425, namespace “Loki” is made as the current binding context. So
at line 5439, the first argument for tsubst
is the node of
BOUND_TEMPLATE_TEMPLATE_PARM, and the second argument args
is the tree_vec in red in
below figure.
(Click
here for open
)
figure 116
:
intermediate tree for the VAR_DECL
6681
static
tree
6682
tsubst (tree t,
tree args, tsubst_flags_t complain, tree in_decl)
in pt.c
6683
{
6684
tree type, r;
6685
6686
if (t == NULL_TREE || t == error_mark_node
6687
|| t == integer_type_node
6688
|| t == void_type_node
6689
|| t == char_type_node
6690
|| t == unknown_type_node
6691
|| TREE_CODE (t) == NAMESPACE_DECL)
6692
return
t;
6693
6694
if
(TREE_CODE (t) == IDENTIFIER_NODE)
6695
type = IDENTIFIER_TYPE_VALUE (t);
6696
else
6697
type = TREE_TYPE (t);
6698
6699
my_friendly_assert (type !=
unknown_type_node, 20030716);
6700
6701
if (type && TREE_CODE (t) !=
FUNCTION_DECL
6702
&& TREE_CODE (t) != TYPENAME_TYPE
6703
&& TREE_CODE (t) != TEMPLATE_DECL
6704
&& TREE_CODE (t) != IDENTIFIER_NODE
6705
&& TREE_CODE (t) !=
FUNCTION_TYPE
6706
&& TREE_CODE (t) != METHOD_TYPE)
6707
type = tsubst (type, args, complain,
in_decl);
6708
if (type == error_mark_node)
6709
return
error_mark_node;
6710
6711
if (DECL_P (t))
6712
return
tsubst_decl (t, args, type, complain);
6713
6714
switch
(TREE_CODE (t))
6715
{
…
6776
case
TEMPLATE_TYPE_PARM:
6777
case
TEMPLATE_TEMPLATE_PARM:
6778
case
BOUND_TEMPLATE_TEMPLATE_PARM:
6779
case
TEMPLATE_PARM_INDEX:
6780
{
6781
int idx;
6782
int level;
6783
int levels;
6784
6785
r = NULL_TREE;
6786
6787
if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
6788
|| TREE_CODE (t) ==
TEMPLATE_TEMPLATE_PARM
6789
|| TREE_CODE (t) ==
BOUND_TEMPLATE_TEMPLATE_PARM)
6790
{
6791
idx = TEMPLATE_TYPE_IDX (t);
6792
level = TEMPLATE_TYPE_LEVEL (t);
6793
}
6794
else
6795
{
6796
idx = TEMPLATE_PARM_IDX (t);
6797
level = TEMPLATE_PARM_LEVEL (t);
6798
}
6799
6800
if (TREE_VEC_LENGTH (args) > 0)
6801
{
6802
tree arg = NULL_TREE;
6803
6804
levels = TMPL_ARGS_DEPTH (args);
6805
if (level <= levels)
6806
arg = TMPL_ARG (args, level, idx);
6807
6808
if (arg == error_mark_node)
6809
return
error_mark_node;
6810
else if (arg != NULL_TREE)
6811
{
6812
if (TREE_CODE (t) ==
TEMPLATE_TYPE_PARM)
6813
{
6814
my_friendly_assert (TYPE_P (arg),
0);
6815
return
cp_build_qualified_type_real
6816
(arg, cp_type_quals (arg) |
cp_type_quals (t),
6817
complain |
tf_ignore_bad_quals);
6818
}
6819
else if (TREE_CODE (t) ==
BOUND_TEMPLATE_TEMPLATE_PARM)
6820
{
6821
/* We are
processing a type constructed from
6822
a template
template parameter.
*/
6823
tree argvec = tsubst (TYPE_TI_ARGS
(t),
6824
args, complain, in_decl);
6825
if (argvec == error_mark_node)
6826
return
error_mark_node;
As t
refers to the node of BOUND_TEMPLATE_TEMPALTE_PARM, at line 6791 idx
is
0, and level
is 1; arg
at line 6806 then points to the node of TEMPLATE_DECL of “SingleThreaded”. Also
notice that at line 6823, the first argument of tsubst
“TYPE_TI_ARGS (t)”
for our example refers to the tree_vec containing 2 elements in the first
figure in this section [Its definition is: (TI_ARGS
(TYPE_TEMPLATE_INFO (NODE)))
].
6681
static
tree
6682
tsubst (tree t,
tree args, tsubst_flags_t complain, tree in_decl)
in pt.c
6683
{
6684
tree type, r;
...
6694
if (TREE_CODE (t) == IDENTIFIER_NODE)
6695
type = IDENTIFIER_TYPE_VALUE (t);
6696
else
6697
type = TREE_TYPE (t);
…
6714
switch
(TREE_CODE (t))
6715
{
…
6950
case
TREE_VEC:
6951
if (type != NULL_TREE)
6952
{
…
6970
}
6971
6972
/* Otherwise,
a vector of template arguments.
*/
6973
return
tsubst_template_args
(t, args, complain,
in_decl);
…
7304
}
7305
}
Here argument t
stands for the parameters of the template,
while args
represents the arguments at instantiation. As semantic check should be taken at
point of instantiation for template, tsubst_template_args
verifies if the
arguments are compatible with the parameters. Now t points to node in red as
below figure.
![](http://hi.csdn.net/attachment/201012/25/4457637_1293255193SCi8.jpg)
5744
static
tree
5745
tsubst_template_args
(tree t, tree args,
tsubst_flags_t complain, tree in_decl)
in pt.c
5746
{
5747
int len = TREE_VEC_LENGTH (t);
5748
int need_new = 0, i;
5749
tree *elts = alloca (len * sizeof
(tree));
5750
5751
for
(i = 0; i < len; i++)
5752
{
5753
tree orig_arg = TREE_VEC_ELT (t, i);
5754
tree new_arg;
5756
5757
if (TREE_CODE (orig_arg) == TREE_VEC)
5758
new_arg = tsubst_template_args (orig_arg,
args, complain, in_decl);
5759
else
5760
new_arg = tsubst_template_arg
(orig_arg, args, complain, in_decl);
5761
5762
if (new_arg == error_mark_node)
5763
return
error_mark_node;
5764
5765
elts[i] = new_arg;
5766
if (new_arg != orig_arg)
5767
need_new = 1;
5768
}
5769
5770
if (!need_new)
5771
return
t;
5772
5773
t = make_tree_vec (len);
5774
for
(i = 0; i
< len; i++)
5775
TREE_VEC_ELT (t, i) = elts[i];
5776
5777
return
t;
5778
}
See that the first element in t
is a tree_vec, which are the parameters for
outer template. This tree_vec (the first element) and the second element as the
parameter of the inner template both are processed by tsubst_template_arg
. In the
function, for all candidates, TYPE_P returns zero as they are not node of
types. See that the arguments of t
and args
in tsubst_expr
are the same as those in tsubst_template_arg
.
7822
static
tree
7823
tsubst_expr (tree
t, tree args, tsubst_flags_t complain, tree in_decl)
in pt.c
7824
{
7825
tree stmt, tmp;
7826
tsubst_flags_t stmt_expr
7827
= complain & (tf_stmt_expr_cmpd |
tf_stmt_expr_body);
7828
7829
complain ^= stmt_expr;
7830
if (t == NULL_TREE || t == error_mark_node)
7831
return
t;
7832
7833
if (!STATEMENT_CODE_P (TREE_CODE (t)))
7834
return
tsubst_copy_and_build (t, args, complain, in_decl,
7835
/*function_p=*/
false);
…
8156
}
Here all template arguments are not of statement, so tsubst_copy_and_build
is always invoked.
8179
tree
8180
tsubst_copy_and_build
(tree t,
in pt.c
8181
tree args,
8182
tsubst_flags_t complain,
8183
tree
in_decl,
8184
bool
function_p)
8185
{
8186
#define
RECUR(NODE) /
8187
tsubst_copy_and_build (NODE, args, complain,
in_decl, /*function_p=*/
false)
8188
8189
tree op1;
8190
8191
if (t == NULL_TREE || t == error_mark_node)
8192
return
t;
8193
8194
switch
(TREE_CODE (t))
8195
{
…
8693
default
:
8694
return
tsubst_copy
(t, args, complain, in_decl);
8695
}
8696
8697
#undef
RECUR
8698
}
For the outer template parameters, the first is
TEMPLATE_TEMPALTE_PARM, the second and the third both are TEMPLATE_PARM_INDEX;
and the parameter of the inner template is the TEMPLATE_TYPE_PARM. All these
nodes are processed by tsubst_copy
.
7449
static
tree
7450
tsubst_copy (tree
t, tree args, tsubst_flags_t complain, tree in_decl)
in pt.c
7451
{
7452
enum
tree_code code;
7453
tree r;
7454
7455
if (t == NULL_TREE || t == error_mark_node)
7456
return
t;
7457
7458
code = TREE_CODE (t);
7469
7460
switch
(code)
7461
{
…
7767
case
RECORD_TYPE:
7768
case
UNION_TYPE:
7769
case
ENUMERAL_TYPE:
7770
case
INTEGER_TYPE:
7771
case
TEMPLATE_TYPE_PARM:
7772
case
TEMPLATE_TEMPLATE_PARM:
7773
case
BOUND_TEMPLATE_TEMPLATE_PARM:
7774
case
TEMPLATE_PARM_INDEX:
7775
case
POINTER_TYPE:
7776
case
REFERENCE_TYPE:
7777
case
OFFSET_TYPE:
7778
case
FUNCTION_TYPE:
7779
case
METHOD_TYPE:
7780
case
ARRAY_TYPE:
7781
case
TYPENAME_TYPE:
7782
case
UNBOUND_CLASS_TEMPLATE:
7783
case
TYPEOF_TYPE:
7784
case
TYPE_DECL:
7785
return
tsubst (t, args, complain, in_decl);
…
7816
}
7817
}
Again for all nodes, tsubst
is invoked. And remember that t
refers
to the template parameters and args
holds the template arguments.
6681
static
tree
6682
tsubst (tree t,
tree args, tsubst_flags_t complain, tree in_decl)
in pt.c
6683
{
6684
tree type, r;
6685
6686
if (t
== NULL_TREE || t == error_mark_node
6687
|| t == integer_type_node
6688
|| t == void_type_node
6689
|| t == char_type_node
6690
|| t == unknown_type_node
6691
|| TREE_CODE (t) == NAMESPACE_DECL)
6692
return
t;
6693
6694
if
(TREE_CODE (t) == IDENTIFIER_NODE)
6695
type = IDENTIFIER_TYPE_VALUE (t);
6696
else
6697
type = TREE_TYPE (t);
6698
6699
my_friendly_assert (type !=
unknown_type_node, 20030716);
6700
6701
if (type && TREE_CODE (t) !=
FUNCTION_DECL
6702
&& TREE_CODE (t) != TYPENAME_TYPE
6703
&& TREE_CODE (t) != TEMPLATE_DECL
6704
&& TREE_CODE (t) != IDENTIFIER_NODE
6705
&& TREE_CODE (t) !=
FUNCTION_TYPE
6706
&& TREE_CODE (t) != METHOD_TYPE)
6707
type = tsubst (type, args, complain,
in_decl);
6708
if (type == error_mark_node)
6709
return
error_mark_node;
6710
6711
if (DECL_P (t))
6712
return
tsubst_decl (t, args, type, complain);
6713
6714
switch
(TREE_CODE (t))
6715
{
…
6776
case
TEMPLATE_TYPE_PARM:
6777
case
TEMPLATE_TEMPLATE_PARM:
6778
case
BOUND_TEMPLATE_TEMPLATE_PARM:
6779
case
TEMPLATE_PARM_INDEX:
6780
{
6781
int idx;
6782
int level;
6783
int levels;
6784
6785
r = NULL_TREE;
6786
6787
if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
6788
|| TREE_CODE (t) ==
TEMPLATE_TEMPLATE_PARM
6789
|| TREE_CODE (t) ==
BOUND_TEMPLATE_TEMPLATE_PARM)
6790
{
6791
idx = TEMPLATE_TYPE_IDX (t);
6792
level = TEMPLATE_TYPE_LEVEL (t);
6793
}
6794
else
6795
{
6796
idx = TEMPLATE_PARM_IDX (t);
6797
level = TEMPLATE_PARM_LEVEL (t);
6798
}
6799
6800
if (TREE_VEC_LENGTH (args) > 0)
6801
{
6802
tree arg = NULL_TREE;
6803
6804
levels = TMPL_ARGS_DEPTH (args);
6805
if (level <= levels)
6806
arg = TMPL_ARG (args, level, idx);
6807
6808
if (arg == error_mark_node)
6809
return
error_mark_node;
6810
else if (arg != NULL_TREE)
6811
{
6812
if (TREE_CODE (t) ==
TEMPLATE_TYPE_PARM)
6813
{
…
6818
}
6819
else if (TREE_CODE (t) ==
BOUND_TEMPLATE_TEMPLATE_PARM)
6820
{
…
6843
}
6844
else
6845
/*
TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX.
*/
6846
return
arg;
6847
}
6848
}
…
6907
}
…
7304
}
7305
}
Node of TEMPLATE_TEMPLATE_PRAM has null type
field. And idx
and level
at
line 6791 are set according to the associated TEMPLATE_PARM_INDEX node as 0 and
1 respectively. At line 6806 arg
points to the TEMPALTE_DECL of
“SingleThreaded”. When returning this node back to tsubst_template_arg
, uses_template_parms
at line 5713 returns zero for this node as it is not dependent one. And this
node is returned further.
The second
parameter of the outer template is the node of TEMPLATE_PARM_INDEX in below
figure. While arg
at line 6806 refers to the INTEGER_CST of 4096 in the rear figure; and it is returned at line
6846 also.
(Click
here for open
)
Similar is the third parameter for the outer template, which is
omitted in previous section, as it very resembles the second one. For the inner
template, the parameter is the node of TEMPLATE_TYPE_PARM in below figure.
![](http://hi.csdn.net/attachment/201012/25/4457637_1293255194zYv8.jpg)
The level
recorded by the associated
TEMPLATE_PARM_INDEX in the figure is 2 while level
indicated by args
is
1; following code will be executed in tsubst
for this node.
6681
static
tree
6682
tsubst (tree t,
tree args, tsubst_flags_t complain, tree in_decl)
in pt.c
6683
{
6684
tree type, r;
…
6694
if (TREE_CODE (t) == IDENTIFIER_NODE)
6695
type = IDENTIFIER_TYPE_VALUE (t);
6696
else
6697
type = TREE_TYPE (t);
…
6714
switch
(TREE_CODE (t))
6715
{
…
6776
case
TEMPLATE_TYPE_PARM:
6777
case
TEMPLATE_TEMPLATE_PARM:
6778
case
BOUND_TEMPLATE_TEMPLATE_PARM:
6779
case
TEMPLATE_PARM_INDEX:
6780
{
6781
int idx;
6782
int level;
6783
int levels;
6784
6785
r = NULL_TREE;
6786
6787
if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
6788
|| TREE_CODE (t) ==
TEMPLATE_TEMPLATE_PARM
6789
|| TREE_CODE (t) ==
BOUND_TEMPLATE_TEMPLATE_PARM)
6790
{
6791
idx = TEMPLATE_TYPE_IDX (t);
6792
level = TEMPLATE_TYPE_LEVEL (t);
6793
}
6794
else
6795
{
6796
idx = TEMPLATE_PARM_IDX (t);
6797
level = TEMPLATE_PARM_LEVEL (t);
6798
}
6799
6800
if (TREE_VEC_LENGTH (args) > 0)
6801
{
6802
tree arg = NULL_TREE;
6803
6804
levels = TMPL_ARGS_DEPTH (args);
6805
if (level <= levels)
6806
arg = TMPL_ARG (args, level, idx);
6807
6808
if (arg == error_mark_node)
6809
return
error_mark_node;
6810
else if (arg != NULL_TREE)
6811
{
…
6847
}
6848
}
6849
else
6850
abort ();
6851
6852
if (level == 1)
6853
/* This can
happen during the attempted tsubst'ing in
6854
unify. This means that
we don't yet have any information
6855
about the template
parameter in question.
*/
6856
return
t;
6857
6858
/* If we get
here, we must have been looking at a parm for a
6859
more deeply nested
template. Make a new version of this
6860
template parameter, but with a lower
level.
*/
6861
switch
(TREE_CODE (t))
6862
{
6863
case
TEMPLATE_TYPE_PARM:
6864
case
TEMPLATE_TEMPLATE_PARM:
6865
case
BOUND_TEMPLATE_TEMPLATE_PARM:
6866
if (cp_type_quals (t))
6867
{
…
6873
}
6874
else
6875
{
6876
r = copy_type (t);
6877
TEMPLATE_TYPE_PARM_INDEX (r)
6878
= reduce_template_parm_level
(TEMPLATE_TYPE_PARM_INDEX (t),
6879
r,
levels);
6880
TYPE_STUB_DECL (r)
= TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
6881
TYPE_MAIN_VARIANT (r) = r;
6882
TYPE_POINTER_TO (r) = NULL_TREE;
6883
TYPE_REFERENCE_TO (r) = NULL_TREE;
6884
6885
if (TREE_CODE (t) ==
BOUND_TEMPLATE_TEMPLATE_PARM)
6886
{
…
6894
}
6895
}
6896
break
;
6897
6898
case
TEMPLATE_PARM_INDEX:
6899
r = reduce_template_parm_level (t,
type, levels);
6900
break
;
6901
6902
default
:
6903
abort ();
6904
}
6905
6906
return
r;
6907
}
…
7304
}
7305
}
Above at line 6878, TEMPLATE_TYPE_PARM_INDEX fetches the node in value
field of the node of TEMPLATE_TYPE_PARM, which is the node of
TEMPLATE_PARM_INDEX.
2128
static
tree
2129
reduce_template_parm_level
(tree index,
tree type, int levels)
in pt.c
2130
{
2131
if (TEMPLATE_PARM_DESCENDANTS (index) ==
NULL_TREE
2132
|| (TEMPLATE_PARM_LEVEL
(TEMPLATE_PARM_DESCENDANTS (index))
2133
!= TEMPLATE_PARM_LEVEL (index) -
levels))
2134
{
2135
tree orig_decl = TEMPLATE_PARM_DECL (index);
2136
tree decl, t;
2137
2138
decl = build_decl
(TREE_CODE (orig_decl), DECL_NAME (orig_decl), type);
2139
TREE_CONSTANT (decl) = TREE_CONSTANT
(orig_decl);
2140
TREE_READONLY (decl) = TREE_READONLY
(orig_decl);
2141
DECL_ARTIFICIAL (decl) = 1;
2142
SET_DECL_TEMPLATE_PARM_P (decl);
2143
2144
t = build_template_parm_index
(TEMPLATE_PARM_IDX (index),
2145
TEMPLATE_PARM_LEVEL
(index) - levels,
2146
TEMPLATE_PARM_ORIG_LEVEL (index),
2147
decl, type);
2148
TEMPLATE_PARM_DESCENDANTS (index) = t;
2149
2150
/* Template
template parameters need this.
*/
2151
DECL_TEMPLATE_PARMS (decl)
2152
= DECL_TEMPLATE_PARMS (TEMPLATE_PARM_DECL
(index));
2153
}
2154
2155
return
TEMPLATE_PARM_DESCENDANTS (index);
2156
}
A new
TEMPLATE_PARM_INDEX is created with decreased level
to indicate the instantiation
of the inner template parameter. And this node is chained as the immediate
descendant of the orginial TEMPLATE_PARM_INDEX node.
![](http://hi.csdn.net/attachment/201012/25/4457637_12932551941N50.jpg)
Then at line 6823 in
tsubst
,
argvec
created by the nested tsubst
for parameters in the node of
BOUND_TEMPLATE_TEMPLATE_PARM is shown in below figure.
(Click
here for open
)
Continue in the tsubst
handling the node of BOUND_TEMPLATE_TEMPLATE_PARM; remember that arg
below refers to TEMPLATE_DECL of “SingleThreaded” in the below figure. As now
we are instantiating the outer template, it is the precondition to instantiate
the inner template first. It is done implicitly by lookup_template_class
below.
tsubst (continue)
6828
/* We can
get a TEMPLATE_TEMPLATE_PARM here when
6829
we are resolving
nested-types in the signature of
6830
a member
function templates.
6831
Otherwise ARG is a
TEMPLATE_DECL and is the real
6832
template to be
instantiated.
*/
6833
if (TREE_CODE (arg) ==
TEMPLATE_TEMPLATE_PARM)
6834
arg = TYPE_NAME (arg);
6835
6836
r = lookup_template_class (arg,
6837
argvec,
in_decl,
6838
DECL_CONTEXT
(arg),
6839
/*entering_scope=*/
0,
6840
complain);
6841
return
cp_build_qualified_type_real
6842
(r, TYPE_QUALS (t),
complain);
6843
}
6844
else
6845
/*
TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX.
*/
6846
return
arg;
6847
}
6848
}
6849
else
6850
abort ();
So at
invocation of lookup_template_class
,
argument dl
is the TEMPLATE_DECL in red in below figure, and arglist
is the argvec
in tusbst
above, and context
is the scope of “Loki”.
(Click
here for open
)
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
{
…
4162
}
4163
else if (TREE_CODE (d1) == TYPE_DECL
&& IS_AGGR_TYPE (TREE_TYPE (d1)))
4164
{
…
4177
}
4178
else if (TREE_CODE (d1) == ENUMERAL_TYPE
4179
|| (TYPE_P (d1) && IS_AGGR_TYPE
(d1)))
4180
{
…
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
}
…
4219
complain &= ~tf_user;
4220
4221
if (DECL_TEMPLATE_TEMPLATE_PARM_P (template))
4222
{
…
4259
}
4260
else
4261
{
4262
tree template_type = TREE_TYPE (template);
4263
tree gen_tmpl;
4264
tree type_decl;
4265
tree found = NULL_TREE;
4266
tree *tp;
4267
int arg_depth;
4268
int parm_depth;
4269
int is_partial_instantiation;
4270
4271
gen_tmpl = most_general_template
(template);
4272
parmlist = DECL_TEMPLATE_PARMS (gen_tmpl);
4273
parm_depth = TMPL_PARMS_DEPTH (parmlist);
4274
arg_depth = TMPL_ARGS_DEPTH (arglist);
4275
4276
if (arg_depth == 1 && parm_depth
> 1)
4277
{
…
4294
}
4295
4296
/* Now we should
have enough arguments.
*/
4297
my_friendly_assert (parm_depth == arg_depth,
0);
4298
4299
/* From here on,
we're only interested in the most general
4300
template.
*/
4301
template = gen_tmpl;
4302
4303
/* Calculate the
BOUND_ARGS. These will be the args that are
4304
actually tsubst'd into the
definition to create the
4305
instantiation.
*/
4306
if (parm_depth > 1)
4307
{
…
4344
}
4345
else
4346
arglist
4347
= coerce_template_parms
(INNERMOST_TEMPLATE_PARMS (parmlist),
4348
INNERMOST_TEMPLATE_ARGS
(arglist),
4349
template,
4350
complain, /*require_all_args=*/
1);
4351
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);
Above parmlist
is the tree_list pointed by arguments
field of the TEMPLATE_DECL of
“SingleThreaded”. So argument parms
below is the tree_vec referred by value
field of this tree_list; it is the parameters in the declaration.
INNERMOST_TEMPLATE_ARGS following accesses the second element of the argvec
above – the argument for inner template.
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);
…
3838
new_inner_args = make_tree_vec (nparms);
3839
new_args = add_outermost_template_args (args,
new_inner_args);
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
}
As both parms
and args
are tree_vec of size 1, add_outermost_template_args
at line 3839 does nothing. Further at line 3850, arg
points to the new created
TEMPLATE_TYPE_PARM node.
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);
…
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
}
Node of TEMPLATE_TYPE_PARM is regarded as type, so is_type
at line 3676 is true as TYPE_P returns true for arg
. Following at line 3761, as arg
is
not a tree_list, groktypename
just returns arg
back. Note that arg
is placed into arglist
at line 4347 in lookup_template_class
.
lookup_template_class (continue)
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
{
4367
found = template_type;
4368
4369
if (!entering_scope &&
PRIMARY_TEMPLATE_P (template))
4370
{
4371
tree ctx;
4372
4373
for
(ctx = current_class_type
;
4374
ctx && TREE_CODE (ctx) !=
NAMESPACE_DECL;
4375
ctx = (TYPE_P (ctx)
4376
? TYPE_CONTEXT (ctx)
4377
: DECL_CONTEXT (ctx)))
4378
if (TYPE_P (ctx) && same_type_p
(ctx, template_type))
4379
goto
found_ctx;
4380
4381
/* We're not
in the scope of the class, so the
4382
TEMPLATE_TYPE is not the
type we want after all.
*/
4383
found = NULL_TREE;
4384
found_ctx:;
4385
}
4386
}
4387
if (found)
4388
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
found);
…
4431
context = tsubst (DECL_CONTEXT (template),
arglist,
4432
complain, in_decl);
4433
if (!context)
4434
context = global_namespace
;
4435
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
}
Notice that template_type
is the node of RECORD_TYPE of
“SingleThreaded”, though comp_template_args
at line 4364 finds that
its argument is the same as arglist
, we are not within class context (current_class_type
is NULL), we have to abondon this found RECORD_TYPE.
Next context
is NAMESPACE_DECL of “Loki”, tsubst
at line 4431 does nothing but returns
this node. The code following is to create the RECORD_TYPE and associated nodes
for the base class instantiation. So following nodes are created. At last the
node of RECORD_TYPE is returned in instantiate_class_template
at line 5439.
(Click
here for open
)
相关文章推荐
- Studying note of GCC-3.4.6 source (132)
- Studying note of GCC-3.4.6 source (138)
- Studying note of GCC-3.4.6 source (6)
- Studying note of GCC-3.4.6 source (7)
- Studying note of GCC-3.4.6 source (9)
- Studying note of GCC-3.4.6 source (141 - cont 1)
- Studying note of GCC-3.4.6 source (148 continue)
- Studying note of GCC-3.4.6 source (31)
- Studying note of GCC-3.4.6 source (42)
- Studying note of GCC-3.4.6 source (58)
- Studying note of GCC-3.4.6 source (63)
- Studying note of GCC-3.4.6 source (73)
- Studying note of GCC-3.4.6 source (97)
- Studying note of GCC-3.4.6 source (106)
- Studying note of GCC-3.4.6 source (112)
- Studying note of GCC-3.4.6 source (116)
- Studying note of GCC-3.4.6 source (130)
- Studying note of GCC-3.4.6 source (5)
- Studying note of GCC-3.4.6 source (140 - continue)
- Studying note of GCC-3.4.6 source (13)