GCC-3.4.6源代码学习笔记(118)
2010-10-22 09:55
393 查看
5.12.4.1.1.2.
处理模板模板参数
同样地,在解析完模板模板参数后,模板模板参数的子树也需要额外的节点。这是函数
process_template_parm
的任务。注意该函数的参数
next
指向上图中的
parameter
。
2161
tree
2162
process_template_parm
(tree list, tree next)
in pt.c
2163
{
2164
tree parm;
2165
tree decl = 0;
2166
tree defval;
2167
int is_type, idx;
2168
2169
parm = next;
2170
my_friendly_assert (TREE_CODE (parm) ==
TREE_LIST, 259);
2171
defval = TREE_PURPOSE (parm);
2172
parm = TREE_VALUE (parm);
2173
is_type = TREE_PURPOSE (parm) == class_type_node;
2174
2175
if (list)
2176
{
2177
tree p = TREE_VALUE (tree_last (list));
2178
2179
if (TREE_CODE (p) == TYPE_DECL || TREE_CODE
(p) == TEMPLATE_DECL)
2180
idx = TEMPLATE_TYPE_IDX (TREE_TYPE (p));
2181
else
2182
idx = TEMPLATE_PARM_IDX (DECL_INITIAL
(p));
2183
++idx;
2184
}
2185
else
2186
idx = 0;
2187
2188
if (!is_type)
2189
{
…
2212
}
2213
else
2214
{
2215
tree t;
2216
parm = TREE_VALUE (parm);
2217
2218
if (parm && TREE_CODE (parm) ==
TEMPLATE_DECL)
2219
{
2220
t =
make_aggr_type
(TEMPLATE_TEMPLATE_PARM);
2221
/* This is for
distinguishing between real templates and template
2222
template parameters */
2223
TREE_TYPE (parm) = t;
2224
TREE_TYPE (DECL_TEMPLATE_RESULT (parm)) =
t;
2225
decl = parm;
2226
}
2227
else
2228
{
…
2232
}
2233
2234
TYPE_NAME (t) = decl;
2235
TYPE_STUB_DECL (t) = decl;
2236
parm = decl;
2237
TEMPLATE_TYPE_PARM_INDEX (t)
2238
= build_template_parm_index
(idx, processing_template_decl,
2239
processing_template_decl,
2240
decl, TREE_TYPE
(parm));
2241
}
2242
DECL_ARTIFICIAL (decl) = 1;
2243
SET_DECL_TEMPLATE_PARM_P (decl);
2244
pushdecl (decl);
2245
parm = build_tree_list (defval, parm);
2246
return
chainon (list, parm);
2247
}
注意到
idx
是
0
;而
processing_template_decl
现在是
1
,它表示这是最顶层的第一个参数。树节点
TEMPLATE_TYPE_PARM_INDEX
记录了这个信息。然后通过
pushdecl
将把这个子树插入到中间树中。
566
tree
567
pushdecl (tree
x)
in name-lookup.c
568
{
569
tree t;
570
tree name;
571
int need_new_binding;
572
573
timevar_push (TV_NAME_LOOKUP);
574
575
need_new_binding = 1;
576
577
if (DECL_TEMPLATE_PARM_P (x))
578
/* Template
parameters have no context; they are not X::T even
579
when declared
within a class or namespace.
*/
580
;
581
else
582
{
…
602
}
603
604
name = DECL_NAME (x);
605
if (name)
606
{
607
int different_binding_level = 0;
…
615
/* In case this
decl was explicitly namespace-qualified, look it
616
up in its
namespace context.
*/
617
if (DECL_NAMESPACE_SCOPE_P (x) &&
namespace_bindings_p ())
618
t = namespace_binding (name, DECL_CONTEXT
(x));
619
else
620
t = lookup_name_current_level (name);
…
743
check_template_shadow (x);
…
828
/* This name is new in its binding level.
829
Install the new
declaration and return it.
*/
830
if (namespace_bindings_p ())
831
{
…
872
}
873
else
874
{
875
/* Here to
install a non-global value.
*/
876
tree oldlocal = IDENTIFIER_VALUE (name);
877
tree oldglobal =
IDENTIFIER_NAMESPACE_VALUE (name);
878
879
if (need_new_binding)
880
{
881
push_local_binding
(name, x, 0);
882
/* Because
push_local_binding will hook X on to the
883
current_binding_level's name list, we don't want to
884
do that
again below.
*/
885
need_new_binding = 0;
886
}
…
1003
}
1004
1005
if (TREE_CODE (x) == VAR_DECL)
1006
maybe_register_incomplete_var (x);
1007
}
1008
1009
if (need_new_binding)
1010
add_decl_to_level
(x,
1011
DECL_NAMESPACE_SCOPE_P (x)
1012
? NAMESPACE_LEVEL (CP_DECL_CONTEXT
(x))
1013
: current_binding_level);
1014
1015
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
1016
}
在执行
pushdecl
后,中间树的相关部分将具有如下的结构。
(
点此打开
)
图
103
:加入模板模板参数
从
pushdecl
返回,
process_template_parm
余下的部分重新安排
parm
,并剔除无用的节点。如下图所示。
(
点此打开
)
图
104
:完成模板模板参数处理
处理模板模板参数
同样地,在解析完模板模板参数后,模板模板参数的子树也需要额外的节点。这是函数
process_template_parm
的任务。注意该函数的参数
next
指向上图中的
parameter
。
2161
tree
2162
process_template_parm
(tree list, tree next)
in pt.c
2163
{
2164
tree parm;
2165
tree decl = 0;
2166
tree defval;
2167
int is_type, idx;
2168
2169
parm = next;
2170
my_friendly_assert (TREE_CODE (parm) ==
TREE_LIST, 259);
2171
defval = TREE_PURPOSE (parm);
2172
parm = TREE_VALUE (parm);
2173
is_type = TREE_PURPOSE (parm) == class_type_node;
2174
2175
if (list)
2176
{
2177
tree p = TREE_VALUE (tree_last (list));
2178
2179
if (TREE_CODE (p) == TYPE_DECL || TREE_CODE
(p) == TEMPLATE_DECL)
2180
idx = TEMPLATE_TYPE_IDX (TREE_TYPE (p));
2181
else
2182
idx = TEMPLATE_PARM_IDX (DECL_INITIAL
(p));
2183
++idx;
2184
}
2185
else
2186
idx = 0;
2187
2188
if (!is_type)
2189
{
…
2212
}
2213
else
2214
{
2215
tree t;
2216
parm = TREE_VALUE (parm);
2217
2218
if (parm && TREE_CODE (parm) ==
TEMPLATE_DECL)
2219
{
2220
t =
make_aggr_type
(TEMPLATE_TEMPLATE_PARM);
2221
/* This is for
distinguishing between real templates and template
2222
template parameters */
2223
TREE_TYPE (parm) = t;
2224
TREE_TYPE (DECL_TEMPLATE_RESULT (parm)) =
t;
2225
decl = parm;
2226
}
2227
else
2228
{
…
2232
}
2233
2234
TYPE_NAME (t) = decl;
2235
TYPE_STUB_DECL (t) = decl;
2236
parm = decl;
2237
TEMPLATE_TYPE_PARM_INDEX (t)
2238
= build_template_parm_index
(idx, processing_template_decl,
2239
processing_template_decl,
2240
decl, TREE_TYPE
(parm));
2241
}
2242
DECL_ARTIFICIAL (decl) = 1;
2243
SET_DECL_TEMPLATE_PARM_P (decl);
2244
pushdecl (decl);
2245
parm = build_tree_list (defval, parm);
2246
return
chainon (list, parm);
2247
}
注意到
idx
是
0
;而
processing_template_decl
现在是
1
,它表示这是最顶层的第一个参数。树节点
TEMPLATE_TYPE_PARM_INDEX
记录了这个信息。然后通过
pushdecl
将把这个子树插入到中间树中。
566
tree
567
pushdecl (tree
x)
in name-lookup.c
568
{
569
tree t;
570
tree name;
571
int need_new_binding;
572
573
timevar_push (TV_NAME_LOOKUP);
574
575
need_new_binding = 1;
576
577
if (DECL_TEMPLATE_PARM_P (x))
578
/* Template
parameters have no context; they are not X::T even
579
when declared
within a class or namespace.
*/
580
;
581
else
582
{
…
602
}
603
604
name = DECL_NAME (x);
605
if (name)
606
{
607
int different_binding_level = 0;
…
615
/* In case this
decl was explicitly namespace-qualified, look it
616
up in its
namespace context.
*/
617
if (DECL_NAMESPACE_SCOPE_P (x) &&
namespace_bindings_p ())
618
t = namespace_binding (name, DECL_CONTEXT
(x));
619
else
620
t = lookup_name_current_level (name);
…
743
check_template_shadow (x);
…
828
/* This name is new in its binding level.
829
Install the new
declaration and return it.
*/
830
if (namespace_bindings_p ())
831
{
…
872
}
873
else
874
{
875
/* Here to
install a non-global value.
*/
876
tree oldlocal = IDENTIFIER_VALUE (name);
877
tree oldglobal =
IDENTIFIER_NAMESPACE_VALUE (name);
878
879
if (need_new_binding)
880
{
881
push_local_binding
(name, x, 0);
882
/* Because
push_local_binding will hook X on to the
883
current_binding_level's name list, we don't want to
884
do that
again below.
*/
885
need_new_binding = 0;
886
}
…
1003
}
1004
1005
if (TREE_CODE (x) == VAR_DECL)
1006
maybe_register_incomplete_var (x);
1007
}
1008
1009
if (need_new_binding)
1010
add_decl_to_level
(x,
1011
DECL_NAMESPACE_SCOPE_P (x)
1012
? NAMESPACE_LEVEL (CP_DECL_CONTEXT
(x))
1013
: current_binding_level);
1014
1015
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
1016
}
在执行
pushdecl
后,中间树的相关部分将具有如下的结构。
(
点此打开
)
图
103
:加入模板模板参数
从
pushdecl
返回,
process_template_parm
余下的部分重新安排
parm
,并剔除无用的节点。如下图所示。
(
点此打开
)
图
104
:完成模板模板参数处理
相关文章推荐
- GCC-3.4.6源代码学习笔记(109)
- GCC-3.4.6源代码学习笔记(139-续1)
- GCC-3.4.6源代码学习笔记(140)
- GCC-3.4.6源代码学习笔记(129 续)
- GCC-3.4.6源代码学习笔记(144)
- GCC-3.4.6源代码学习笔记(66)
- GCC-3.4.6源代码学习笔记(17)
- GCC-3.4.6源代码学习笔记(148)
- GCC-3.4.6源代码学习笔记 (101)
- GCC-3.4.6源代码学习笔记(19)
- GCC-3.4.6源代码学习笔记(74)
- GCC-3.4.6源代码学习笔记(132)
- GCC-3.4.6源代码学习笔记(133)
- GCC-3.4.6源代码学习笔记 (104)
- GCC-3.4.6源代码学习笔记(80)
- GCC-3.4.6源代码学习笔记(83)
- GCC-3.4.6源代码学习笔记(87)
- GCC-3.4.6源代码学习笔记(164)
- GCC-3.4.6源代码学习笔记(89)
- GCC-3.4.6源代码学习笔记(26续2)