GCC-3.4.6源代码学习笔记(64)
2010-07-28 09:58
531 查看
4.3.1.7.8.
完成初始化
下面的
abort_fndecl
代表函数
abort
,而函数
build_library_fn_ptr
与
build_library_fn
相仿,不过它接受字符串作为名字,而不是标识符节点。
cxx_init_decl_processing
(continue)
3115
abort_fndecl
3116
= build_library_fn_ptr ("__cxa_pure_virtual", void_ftype);
3117
3118
/* Perform other language dependent
initializations.
*/
3119
init_class_processing
();
3120
init_search_processing
();
3121
init_rtti_processing
();
3122
3123
if (flag_exceptions
)
3124
init_exception_processing
();
3125
3126
if (! supports_one_only
())
3127
flag_weak
= 0;
3128
3129
make_fname_decl
= cp_make_fname_decl;
3130
start_fname_decls
();
3131
3132
/* Show we use EH for cleanups.
*/
3133
using_eh_for_cleanups ();
3134
3135
/* Maintain consistency. Perhaps we should
just complain if they
3136
say
-fwritable-strings?
*/
3137
if (flag_writable_strings
)
3138
flag_const_strings
= 0;
3139
}
4.3.1.7.8.1.
初始化类处理参数
在处理类声明时,
GCC
使用以下的全局变量来控制其处理过程。其中
current_class_depth
表示当前类的嵌套深度,这些嵌套的类毫无疑问构成了一个栈,这就是
current_class_stack
,而
current_class_stack_size
就是栈的当前大小。
GNU C++
有一个扩展,允许在函数体中定义类,当然这个类只能在该函数体内可见,为了与其他类区别,它们被保存在
local_classes
中。
5424
void
5425
init_class_processing
(void)
in class.c
5426
{
5427
current_class_depth
= 0;
5428
current_class_stack_size
= 10;
5429
current_class_stack
5430
= xmalloc (current_class_stack_size
* sizeof
(struct
class_stack_node));
5431
VARRAY_TREE_INIT (local_classes
, 8, "local_classes");
5432
5433
ridpointers
[(int)
RID_PUBLIC] = access_public_node;
5434
ridpointers
[(int)
RID_PRIVATE] = access_private_node;
5435
ridpointers
[(int)
RID_PROTECTED] = access_protected_node;
5436
}
而下面所初始化的
search_obstack
在当前版本中已没有用处,在
V4
版本中已被去除。
2346
void
2347
init_search_processing
(void)
in search.c
2348
{
2349
gcc_obstack_init
(&search_obstack
);
2350
}
4.3.1.7.8.2.
运行时类型识别
RTTI
4.3.1.7.8.2.1.
构建
TYPE_DECL
节点
运行时类型识别(
runtime type identification
,
RTTI
)允许操纵基类的指针或引用对象,来获取该指针或引用对象的实际派生类型。为了支持
RTTI
,
GCC
提供了
2
个操作符:
typeid
和
dynamic_cast
。
typeid
的返回类型是
type_info
,而
type_info
的定义是依赖于实现的。在这里对
RTTI
的初始化中,不像
std::bad_alloc
,必须创建完整的定义,因为这个类是运行时环境所需要使用的。
115
void
116
init_rtti_processing
(void)
in rtti.c
117
{
118
tree const_type_info_type;
119
120
push_namespace
(std_identifier);
121
type_info_type_node
122
= xref_tag
(class_type, get_identifier
("type_info"),
123
true, false);
124
pop_namespace
();
125
const_type_info_type = build_qualified_type
(type_info_type_node,
126
TYPE_QUAL_CONST);
127
type_info_ptr_type = build_pointer_type
(const_type_info_type);
128
type_info_ref_type = build_reference_type
(const_type_info_type);
129
130
VARRAY_TREE_INIT (unemitted_tinfo_decls
, 10, "RTTI
decls");
131
132
create_tinfo_types
();
133
}
这儿
xref_tag
尝试获取具有
name
名字的
struct
,
enum
或
union
(
tag_code
告知是哪个)。如果该类型还没定义,把标签(
tag
)定义为前向引用。
如果参数
globalize
是
false
,表示标识符
name
是一个定义。在
C++
中,首先,它允许在不同绑定域(即作用域)中定义同名的类型;其次,在同一绑定域中,同名的不同类型是一个语法错误,除非它们的定义是相同的。在
9476
行,
lookup_tag
尝试,在由
b
提交的绑定域中,找出由
code
和
name
指定的类型定义。我们在后面来看这个函数的定义。
而如果
globalize
是
true
,则
name
只是一个类型声明。在
C++
中,我们可以仅声明一个用户定义类型,然后使用其指针(只要不解引用)。例如,
class A;
A* pa = NULL;
在
GCC
内部,当它发现找不到任何东西时,它将创建一个伪类型(记得
std::bad_alloc
?),然后为它声明一个隐式的
typedef
,并且将由这个隐式
typedef
所构建的
TYPE_DECL
节点加入指定的绑定域。那么前向声明实际上就是引用这个
TYPE_DECL
,随后当遇到真正的定义时,对应的类型节点(类型
RECORD_TYPE
,或
UNION_TYPE
,或
ENUMERAL_TYPE
)进行相应地更新。而当
GCC
找到存在的类型声明(不是伪类型),而且该声明与泛型编程相关,则需要特殊的处理,我们不久将看到这一点。
9443
tree
9444
xref_tag
(enum
tag_types tag_code, tree name,
in decl.c
9445
bool globalize, bool template_header_p)
9446
{
9447
enum
tree_code code;
9448
tree t;
9449
struct
cp_binding_level *b =
current_binding_level;
9450
tree context = NULL_TREE;
9451
9452
timevar_push (TV_NAME_LOOKUP);
9453
9454
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 0);
9455
9456
switch
(tag_code)
9457
{
9458
case
record_type:
9459
case
class_type:
9460
code = RECORD_TYPE;
9461
break
;
9462
case
union_type:
9463
code = UNION_TYPE;
9464
break
;
9465
case
enum_type:
9466
code = ENUMERAL_TYPE;
9467
break
;
9468
default
:
9469
abort ();
9470
}
9471
9472
if (! globalize)
9473
{
9474
/* If we know we are defining this tag, only
look it up in
9475
this scope and don't try to find it as a
type.
*/
9476
t = lookup_tag (code, name, b, 1);
9477
}
9478
else
9479
{
9480
tree decl = lookup_name (name, 2);
这里
globalize
是
true
,使用
lookup_name
来类型声明,因为其第二个参数表示抛弃非类型声明。
lookup_name
是一个复杂的函数,为了不使这里的过程太漫长,我们暂时跳过它。对于我们这里的情形,
lookup_name
应该返回
NULL
,因为这必须是第一次声明这个类型。
xref_tag
(continue)
9558
if (! t)
9559
{
9560
/* If no such tag is yet defined, create a
forward-reference node
9561
and record it as the
"definition".
9562
When a real declaration of this type is
found,
9563
the forward-reference will be altered
into a real type.
*/
9564
if (code == ENUMERAL_TYPE)
9565
{
9566
error ("use of enum `%#D'
without previous declaration", name);
9567
POP_TIMEVAR_AND_RETURN
(TV_NAME_LOOKUP, error_mark_node);
9568
}
9569
else
9570
{
9571
t = make_aggr_type
(code);
9572
TYPE_CONTEXT (t) = context;
9573
pushtag
(name,
t, globalize);
9574
}
9575
}
9576
else
9577
{
...
9587
}
9588
9589
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
9590
}
因为在
9480
行,没有标签(
tag
)被
lookup_name
所找出,那么将为之创建一个节点。并且由于参数
tag_code
是
class_type
,这个节点应该是
RECORD_TYPE
,而且它的上下文首先被设置为空(参见
9450
行的
NULL_TREE
)。
4589
void
4590
pushtag
(tree name, tree type, int
globalize)
in name-lookup.c
4591
{
4592
struct
cp_binding_level *b;
4593
4594
timevar_push (TV_NAME_LOOKUP);
4595
b = current_binding_level
;
4596
while
(/*
Cleanup scopes are not scopes from the point of view of
4597
the language.
*/
4598
b->kind == sk_cleanup
4599
/*
Neither are the scopes used to hold template parameters
4600
for an explicit specialization. For an
ordinary template
4601
declaration, these scopes are not scopes
from the point of
4602
view of the language -- but we need a
place to stash
4603
things that will go in the containing
namespace when the
4604
template is instantiated.
*/
4605
|| (b->kind ==
sk_template_parms && b->explicit_spec_p)
4606
|| (b->kind == sk_class
4607
&& (globalize
4608
/* We may be defining a new type in the initializer
4609
of a static member variable. We allow
this when
4610
not pedantic, and it is particularly
useful for
4611
type punning via an anonymous
union.
*/
4612
|| COMPLETE_TYPE_P (b->this_entity))))
4613
b = b->level_chain;
4614
4615
if (b->type_decls == NULL)
4616
b->type_decls = binding_table_new
(SCOPE_DEFAULT_HT_SIZE);
4617
binding_table_insert
(b->type_decls, name, type);
pushtag
首先把类型定义加入当前名字空间。我们已经看到,在一个绑定域中的用户定义类型,被保存在相应的
cp_binding_level
结构的
type_decls
域中。下面的
binding_table_insert
提供了这个处理。
190
static
void
191
binding_table_insert
(binding_table table, tree name,
tree type)
in name-lookup.c
192
{
193
const unsigned int hash = IDENTIFIER_HASH_VALUE (name);
194
const size_t i = ENTRY_INDEX (hash, table->chain_count);
195
binding_entry entry = binding_entry_make
(name, type);
196
197
entry->chain = table->chain[i];
198
table->chain[i] = entry;
199
++table->entry_count;
200
201
if (3 * table->chain_count < 5 * table->entry_count)
202
binding_table_expand (table);
203
}
注意到
type_decls
实际上是一个哈希表,所有具有同一哈希值的类型定义被链接在一起。为了控制链表的长度,如果链表的数目(域
chain_count
)与表项数(
entry_count
)具有如下关系时:
3*table->chain_count <
5*table->entry_count
,
binding_table_expand
将链表数目加倍,并重新哈希及链接已记录的类型。
67
static
inline
binding_entry
68
binding_entry_make
(tree name, tree type)
in name-lookup.c
69
{
70
binding_entry entry;
71
72
if (free_binding_entry
)
73
{
74
entry = free_binding_entry
;
75
free_binding_entry
= entry->chain;
76
}
77
else
78
entry = ggc_alloc (sizeof
(struct
binding_entry_s));
79
80
entry->name = name;
81
entry->type = type;
82
entry->chain = NULL;
83
84
return
entry;
85
}
在上面是
binding_entry_make
中,虽然标识符与类型定义通过
binding_entry
实例关联起来了,但标识符节点还没有与
TYPE_DECL
节点绑定。因此在下面,
IDENTIFIER_TYPE_VALUE
返回
NULL
。
1700
tree
1701
identifier_type_value
(tree id)
in name-lookup.c
1702
{
1703
timevar_push (TV_NAME_LOOKUP);
1704
/* There is no type with that name,
anywhere.
*/
1705
if (REAL_IDENTIFIER_TYPE_VALUE (id) == NULL_TREE)
1706
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
1707
/* This is not the type marker, but the real
thing.
*/
1708
if (REAL_IDENTIFIER_TYPE_VALUE (id) != global_type_node
)
1709
POP_TIMEVAR_AND_RETURN(TV_NAME_LOOKUP, REAL_IDENTIFIER_TYPE_VALUE (id));
1710
/* Have to search for it. It must be on the
global level, now.
1711
Ask lookup_name not to return
non-types.
*/
1712
id = lookup_name_real (id, 2, 1, 0, LOOKUP_COMPLAIN);
1713
if (id)
1714
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_TYPE (id));
1715
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
1716
}
IDENTIFIER_TYPE_VALUE
只是
identifier_type_value
的一个直接的封装。在这里,在我们的情形下,
REAL_IDENTIFIER_TYPE_VALUE
应该返回
NULL_TREE
,而下面
4622
行的
type
则是刚创建的
RECORD_TYPE
节点。
pushtag
(continue)
4619
if (name)
4620
{
4621
/* Do C++ gratuitous typedefing.
*/
4622
if (IDENTIFIER_TYPE_VALUE
(name) != type)
4623
{
4624
tree d = NULL_TREE;
4625
int in_class = 0;
4626
tree context = TYPE_CONTEXT
(type);
4627
4628
if (! context)
4629
{
4630
tree cs =
current_scope
();
4631
4632
if (! globalize)
4633
context = cs;
4634
else if (cs != NULL_TREE
&& TYPE_P (cs))
4635
/* When
declaring a friend class of a local class, we want
4636
to inject the newly named class
into the scope
4637
containing the local class, not the
namespace scope.
*/
4638
context = decl_function_context
(get_type_decl (cs));
4639
}
4640
if (!context)
4641
context = current_namespace
;
4642
4643
if (b->kind == sk_class
4644
|| (b->kind ==
sk_template_parms
4645
&& b->level_chain->kind ==
sk_class))
4646
in_class = 1;
4647
4648
if (current_lang_name ==
lang_name_java)
4649
TYPE_FOR_JAVA (type) = 1;
4650
4651
d = create_implicit_typedef
(name, type);
4652
DECL_CONTEXT (d) = FROB_CONTEXT
(context);
4653
if (! in_class)
4654
set_identifier_type_value_with_scope
(name, d, b);
回忆这个类型的上下文是
NULL
,因而在
4630
行,
current_scope
被调用。这是一个宏,视情况在
current_function_decl
和
current_class_type
中选择,对于名字空间作用域,它永远返回
NULL
。那么因为我们在
std
名字空间中,在
4641
行,类型上下文被设为当前名字空间作用域。
接着在
4651
行,由
create_implicit_typedef
为类型构建了一个
TYPE_DECL
节点。然后在
set_identifier_type_value_with_scope
里,这个
TYPE_DECL
节点(注意不是类型定义)将被记录入标识符节点的
namespace_bindings
域中。
1731
static
void
1732
set_identifier_type_value_with_scope
(tree id, tree decl, cxx_scope *b)
in name-lookup.c
1733
{
1734
tree type;
1735
1736
if (b->kind != sk_namespace)
1737
{
1738
/* Shadow the marker, not the real thing, so
that the marker
1739
gets
restored later.
*/
1740
tree old_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
1741
b->type_shadowed
1742
= tree_cons (id,
old_type_value, b->type_shadowed);
1743
type = decl ? TREE_TYPE (decl) : NULL_TREE;
1744
}
1745
else
1746
{
1747
cxx_binding *binding =
1748
binding_for_name
(NAMESPACE_LEVEL (current_namespace), id);
1749
if (decl)
1750
{
1751
if (binding->value)
1752
supplement_binding (binding, decl);
1753
else
1754
binding->value = decl;
1755
}
1756
else
1757
abort ();
1758
/* Store marker instead of real type.
*/
1759
type = global_type_node
;
1760
}
1761
SET_IDENTIFIER_TYPE_VALUE (id, type);
1762
}
在上面
1754
行的赋值操作设置了该标识符目前对应的声明(这是个类型声明)。自此,在当前作用域,该标识符就表示该类型。
pushtag
(continue)
4656
d =
maybe_process_template_type_declaration (type,
4657
globalize, b);
4658
4659
if (b->kind == sk_class)
4660
{
4661
if
(!PROCESSING_REAL_TEMPLATE_DECL_P ())
4662
/* Put this
TYPE_DECL on the TYPE_FIELDS list for the
4663
class. But if it's a member
template class, we
4664
want the TEMPLATE_DECL, not the
TYPE_DECL, so this
4665
is done later.
*/
4666
finish_member_declaration (d);
4667
else
4668
pushdecl_class_level (d);
4669
}
4670
else
4671
d = pushdecl_with_scope
(d, b);
4672
4673
/*
FIXME what if it gets a name from typedef?
*/
4674
if (ANON_AGGRNAME_P (name))
4675
DECL_IGNORED_P (d) = 1;
4676
4677
TYPE_CONTEXT (type) =
DECL_CONTEXT (d);
4678
4679
/* If
this is a local class, keep track of it. We need this
4680
information for name-mangling, and so
that it is possible to find
4681
all function definitions in a
translation unit in a convenient
4682
way. (It's otherwise tricky to find a
member function definition
4683
it's only pointed to from within a
local class.)
*/
4684
if (TYPE_CONTEXT (type)
4685
&& TREE_CODE
(TYPE_CONTEXT (type)) == FUNCTION_DECL
4686
&&
!processing_template_decl)
4687
VARRAY_PUSH_TREE (local_classes
,
type);
4688
}
4689
if (b->kind == sk_class
4690
&& !COMPLETE_TYPE_P (current_class_type
))
4691
{
4692
maybe_add_class_template_decl_list (current_class_type
,
4693
type, /*friend_p=*/
0);
4694
CLASSTYPE_NESTED_UTDS (current_class_type
)
= b->type_decls;
4695
}
4696
}
4697
4698
if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
4699
/* Use the canonical TYPE_DECL for this
node.
*/
4700
TYPE_STUB_DECL (type) = TYPE_NAME (type);
4701
else
4702
{
4703
/* Create a fake NULL-named TYPE_DECL node
whose TREE_TYPE
4704
will be the tagged type we just added to
the current
4705
binding level. This fake NULL-named
TYPE_DECL node helps
4706
dwarfout.c to know when it needs to
output a
4707
representation of a tagged type, and it
also gives us a
4708
convenient place to record the
"scope start" address for
4709
the tagged type.
*/
4710
4711
tree d = build_decl (TYPE_DECL, NULL_TREE, type);
4712
TYPE_STUB_DECL (type) = pushdecl_with_scope (d, b);
4713
}
4714
timevar_pop (TV_NAME_LOOKUP);
4715
}
现在我们已经把类型定义(
RECORD_TYPE
节点)加入到了绑定域中,还把对应的
TYPE_DECL
节点加入到标识符节点的绑定链里。下面的
1960
行,
pushdecl
只是调用
add_decl_to_level
把
TYPE_DECL
节点加入对应
cxx_scope
的
names
域。
1941
tree
1942
pushdecl_with_scope
(tree x, cxx_scope *level)
in name-lookup.c
1943
{
1944
struct
cp_binding_level *b;
1945
tree function_decl = current_function_decl
;
1946
1947
timevar_push (TV_NAME_LOOKUP);
1948
current_function_decl
= NULL_TREE;
1949
if (level->kind == sk_class)
1950
{
1951
b = class_binding_level;
1952
class_binding_level = level;
1953
pushdecl_class_level (x);
1954
class_binding_level = b;
1955
}
1956
else
1957
{
1958
b = current_binding_level
;
1959
current_binding_level
= level;
1960
x = pushdecl (x);
1961
current_binding_level
= b;
1962
}
1963
current_function_decl
=
function_decl;
1964
POP_TIMEVAR_AND_RETURN
(TV_NAME_LOOKUP, x);
1965
}
type_info
实际上是一个类型系列,编译器根据类的结构选择其一,结构相同的类所选用的
type_info
是一样的,但是不同的实例。因此,编译器在遇到使用
type_info
的地方,并不急着构建实例,而是在前端最后完成这个编译单元时,集中地构建。这些
type_info
所需要的缓存就是在
init_rtti_processing
的
130
行的
unemitted_tinfo_decls
。
完成初始化
下面的
abort_fndecl
代表函数
abort
,而函数
build_library_fn_ptr
与
build_library_fn
相仿,不过它接受字符串作为名字,而不是标识符节点。
cxx_init_decl_processing
(continue)
3115
abort_fndecl
3116
= build_library_fn_ptr ("__cxa_pure_virtual", void_ftype);
3117
3118
/* Perform other language dependent
initializations.
*/
3119
init_class_processing
();
3120
init_search_processing
();
3121
init_rtti_processing
();
3122
3123
if (flag_exceptions
)
3124
init_exception_processing
();
3125
3126
if (! supports_one_only
())
3127
flag_weak
= 0;
3128
3129
make_fname_decl
= cp_make_fname_decl;
3130
start_fname_decls
();
3131
3132
/* Show we use EH for cleanups.
*/
3133
using_eh_for_cleanups ();
3134
3135
/* Maintain consistency. Perhaps we should
just complain if they
3136
say
-fwritable-strings?
*/
3137
if (flag_writable_strings
)
3138
flag_const_strings
= 0;
3139
}
4.3.1.7.8.1.
初始化类处理参数
在处理类声明时,
GCC
使用以下的全局变量来控制其处理过程。其中
current_class_depth
表示当前类的嵌套深度,这些嵌套的类毫无疑问构成了一个栈,这就是
current_class_stack
,而
current_class_stack_size
就是栈的当前大小。
GNU C++
有一个扩展,允许在函数体中定义类,当然这个类只能在该函数体内可见,为了与其他类区别,它们被保存在
local_classes
中。
5424
void
5425
init_class_processing
(void)
in class.c
5426
{
5427
current_class_depth
= 0;
5428
current_class_stack_size
= 10;
5429
current_class_stack
5430
= xmalloc (current_class_stack_size
* sizeof
(struct
class_stack_node));
5431
VARRAY_TREE_INIT (local_classes
, 8, "local_classes");
5432
5433
ridpointers
[(int)
RID_PUBLIC] = access_public_node;
5434
ridpointers
[(int)
RID_PRIVATE] = access_private_node;
5435
ridpointers
[(int)
RID_PROTECTED] = access_protected_node;
5436
}
而下面所初始化的
search_obstack
在当前版本中已没有用处,在
V4
版本中已被去除。
2346
void
2347
init_search_processing
(void)
in search.c
2348
{
2349
gcc_obstack_init
(&search_obstack
);
2350
}
4.3.1.7.8.2.
运行时类型识别
RTTI
4.3.1.7.8.2.1.
构建
TYPE_DECL
节点
运行时类型识别(
runtime type identification
,
RTTI
)允许操纵基类的指针或引用对象,来获取该指针或引用对象的实际派生类型。为了支持
RTTI
,
GCC
提供了
2
个操作符:
typeid
和
dynamic_cast
。
typeid
的返回类型是
type_info
,而
type_info
的定义是依赖于实现的。在这里对
RTTI
的初始化中,不像
std::bad_alloc
,必须创建完整的定义,因为这个类是运行时环境所需要使用的。
115
void
116
init_rtti_processing
(void)
in rtti.c
117
{
118
tree const_type_info_type;
119
120
push_namespace
(std_identifier);
121
type_info_type_node
122
= xref_tag
(class_type, get_identifier
("type_info"),
123
true, false);
124
pop_namespace
();
125
const_type_info_type = build_qualified_type
(type_info_type_node,
126
TYPE_QUAL_CONST);
127
type_info_ptr_type = build_pointer_type
(const_type_info_type);
128
type_info_ref_type = build_reference_type
(const_type_info_type);
129
130
VARRAY_TREE_INIT (unemitted_tinfo_decls
, 10, "RTTI
decls");
131
132
create_tinfo_types
();
133
}
这儿
xref_tag
尝试获取具有
name
名字的
struct
,
enum
或
union
(
tag_code
告知是哪个)。如果该类型还没定义,把标签(
tag
)定义为前向引用。
如果参数
globalize
是
false
,表示标识符
name
是一个定义。在
C++
中,首先,它允许在不同绑定域(即作用域)中定义同名的类型;其次,在同一绑定域中,同名的不同类型是一个语法错误,除非它们的定义是相同的。在
9476
行,
lookup_tag
尝试,在由
b
提交的绑定域中,找出由
code
和
name
指定的类型定义。我们在后面来看这个函数的定义。
而如果
globalize
是
true
,则
name
只是一个类型声明。在
C++
中,我们可以仅声明一个用户定义类型,然后使用其指针(只要不解引用)。例如,
class A;
A* pa = NULL;
在
GCC
内部,当它发现找不到任何东西时,它将创建一个伪类型(记得
std::bad_alloc
?),然后为它声明一个隐式的
typedef
,并且将由这个隐式
typedef
所构建的
TYPE_DECL
节点加入指定的绑定域。那么前向声明实际上就是引用这个
TYPE_DECL
,随后当遇到真正的定义时,对应的类型节点(类型
RECORD_TYPE
,或
UNION_TYPE
,或
ENUMERAL_TYPE
)进行相应地更新。而当
GCC
找到存在的类型声明(不是伪类型),而且该声明与泛型编程相关,则需要特殊的处理,我们不久将看到这一点。
9443
tree
9444
xref_tag
(enum
tag_types tag_code, tree name,
in decl.c
9445
bool globalize, bool template_header_p)
9446
{
9447
enum
tree_code code;
9448
tree t;
9449
struct
cp_binding_level *b =
current_binding_level;
9450
tree context = NULL_TREE;
9451
9452
timevar_push (TV_NAME_LOOKUP);
9453
9454
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 0);
9455
9456
switch
(tag_code)
9457
{
9458
case
record_type:
9459
case
class_type:
9460
code = RECORD_TYPE;
9461
break
;
9462
case
union_type:
9463
code = UNION_TYPE;
9464
break
;
9465
case
enum_type:
9466
code = ENUMERAL_TYPE;
9467
break
;
9468
default
:
9469
abort ();
9470
}
9471
9472
if (! globalize)
9473
{
9474
/* If we know we are defining this tag, only
look it up in
9475
this scope and don't try to find it as a
type.
*/
9476
t = lookup_tag (code, name, b, 1);
9477
}
9478
else
9479
{
9480
tree decl = lookup_name (name, 2);
这里
globalize
是
true
,使用
lookup_name
来类型声明,因为其第二个参数表示抛弃非类型声明。
lookup_name
是一个复杂的函数,为了不使这里的过程太漫长,我们暂时跳过它。对于我们这里的情形,
lookup_name
应该返回
NULL
,因为这必须是第一次声明这个类型。
xref_tag
(continue)
9558
if (! t)
9559
{
9560
/* If no such tag is yet defined, create a
forward-reference node
9561
and record it as the
"definition".
9562
When a real declaration of this type is
found,
9563
the forward-reference will be altered
into a real type.
*/
9564
if (code == ENUMERAL_TYPE)
9565
{
9566
error ("use of enum `%#D'
without previous declaration", name);
9567
POP_TIMEVAR_AND_RETURN
(TV_NAME_LOOKUP, error_mark_node);
9568
}
9569
else
9570
{
9571
t = make_aggr_type
(code);
9572
TYPE_CONTEXT (t) = context;
9573
pushtag
(name,
t, globalize);
9574
}
9575
}
9576
else
9577
{
...
9587
}
9588
9589
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
9590
}
因为在
9480
行,没有标签(
tag
)被
lookup_name
所找出,那么将为之创建一个节点。并且由于参数
tag_code
是
class_type
,这个节点应该是
RECORD_TYPE
,而且它的上下文首先被设置为空(参见
9450
行的
NULL_TREE
)。
4589
void
4590
pushtag
(tree name, tree type, int
globalize)
in name-lookup.c
4591
{
4592
struct
cp_binding_level *b;
4593
4594
timevar_push (TV_NAME_LOOKUP);
4595
b = current_binding_level
;
4596
while
(/*
Cleanup scopes are not scopes from the point of view of
4597
the language.
*/
4598
b->kind == sk_cleanup
4599
/*
Neither are the scopes used to hold template parameters
4600
for an explicit specialization. For an
ordinary template
4601
declaration, these scopes are not scopes
from the point of
4602
view of the language -- but we need a
place to stash
4603
things that will go in the containing
namespace when the
4604
template is instantiated.
*/
4605
|| (b->kind ==
sk_template_parms && b->explicit_spec_p)
4606
|| (b->kind == sk_class
4607
&& (globalize
4608
/* We may be defining a new type in the initializer
4609
of a static member variable. We allow
this when
4610
not pedantic, and it is particularly
useful for
4611
type punning via an anonymous
union.
*/
4612
|| COMPLETE_TYPE_P (b->this_entity))))
4613
b = b->level_chain;
4614
4615
if (b->type_decls == NULL)
4616
b->type_decls = binding_table_new
(SCOPE_DEFAULT_HT_SIZE);
4617
binding_table_insert
(b->type_decls, name, type);
pushtag
首先把类型定义加入当前名字空间。我们已经看到,在一个绑定域中的用户定义类型,被保存在相应的
cp_binding_level
结构的
type_decls
域中。下面的
binding_table_insert
提供了这个处理。
190
static
void
191
binding_table_insert
(binding_table table, tree name,
tree type)
in name-lookup.c
192
{
193
const unsigned int hash = IDENTIFIER_HASH_VALUE (name);
194
const size_t i = ENTRY_INDEX (hash, table->chain_count);
195
binding_entry entry = binding_entry_make
(name, type);
196
197
entry->chain = table->chain[i];
198
table->chain[i] = entry;
199
++table->entry_count;
200
201
if (3 * table->chain_count < 5 * table->entry_count)
202
binding_table_expand (table);
203
}
注意到
type_decls
实际上是一个哈希表,所有具有同一哈希值的类型定义被链接在一起。为了控制链表的长度,如果链表的数目(域
chain_count
)与表项数(
entry_count
)具有如下关系时:
3*table->chain_count <
5*table->entry_count
,
binding_table_expand
将链表数目加倍,并重新哈希及链接已记录的类型。
67
static
inline
binding_entry
68
binding_entry_make
(tree name, tree type)
in name-lookup.c
69
{
70
binding_entry entry;
71
72
if (free_binding_entry
)
73
{
74
entry = free_binding_entry
;
75
free_binding_entry
= entry->chain;
76
}
77
else
78
entry = ggc_alloc (sizeof
(struct
binding_entry_s));
79
80
entry->name = name;
81
entry->type = type;
82
entry->chain = NULL;
83
84
return
entry;
85
}
在上面是
binding_entry_make
中,虽然标识符与类型定义通过
binding_entry
实例关联起来了,但标识符节点还没有与
TYPE_DECL
节点绑定。因此在下面,
IDENTIFIER_TYPE_VALUE
返回
NULL
。
1700
tree
1701
identifier_type_value
(tree id)
in name-lookup.c
1702
{
1703
timevar_push (TV_NAME_LOOKUP);
1704
/* There is no type with that name,
anywhere.
*/
1705
if (REAL_IDENTIFIER_TYPE_VALUE (id) == NULL_TREE)
1706
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
1707
/* This is not the type marker, but the real
thing.
*/
1708
if (REAL_IDENTIFIER_TYPE_VALUE (id) != global_type_node
)
1709
POP_TIMEVAR_AND_RETURN(TV_NAME_LOOKUP, REAL_IDENTIFIER_TYPE_VALUE (id));
1710
/* Have to search for it. It must be on the
global level, now.
1711
Ask lookup_name not to return
non-types.
*/
1712
id = lookup_name_real (id, 2, 1, 0, LOOKUP_COMPLAIN);
1713
if (id)
1714
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_TYPE (id));
1715
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
1716
}
IDENTIFIER_TYPE_VALUE
只是
identifier_type_value
的一个直接的封装。在这里,在我们的情形下,
REAL_IDENTIFIER_TYPE_VALUE
应该返回
NULL_TREE
,而下面
4622
行的
type
则是刚创建的
RECORD_TYPE
节点。
pushtag
(continue)
4619
if (name)
4620
{
4621
/* Do C++ gratuitous typedefing.
*/
4622
if (IDENTIFIER_TYPE_VALUE
(name) != type)
4623
{
4624
tree d = NULL_TREE;
4625
int in_class = 0;
4626
tree context = TYPE_CONTEXT
(type);
4627
4628
if (! context)
4629
{
4630
tree cs =
current_scope
();
4631
4632
if (! globalize)
4633
context = cs;
4634
else if (cs != NULL_TREE
&& TYPE_P (cs))
4635
/* When
declaring a friend class of a local class, we want
4636
to inject the newly named class
into the scope
4637
containing the local class, not the
namespace scope.
*/
4638
context = decl_function_context
(get_type_decl (cs));
4639
}
4640
if (!context)
4641
context = current_namespace
;
4642
4643
if (b->kind == sk_class
4644
|| (b->kind ==
sk_template_parms
4645
&& b->level_chain->kind ==
sk_class))
4646
in_class = 1;
4647
4648
if (current_lang_name ==
lang_name_java)
4649
TYPE_FOR_JAVA (type) = 1;
4650
4651
d = create_implicit_typedef
(name, type);
4652
DECL_CONTEXT (d) = FROB_CONTEXT
(context);
4653
if (! in_class)
4654
set_identifier_type_value_with_scope
(name, d, b);
回忆这个类型的上下文是
NULL
,因而在
4630
行,
current_scope
被调用。这是一个宏,视情况在
current_function_decl
和
current_class_type
中选择,对于名字空间作用域,它永远返回
NULL
。那么因为我们在
std
名字空间中,在
4641
行,类型上下文被设为当前名字空间作用域。
接着在
4651
行,由
create_implicit_typedef
为类型构建了一个
TYPE_DECL
节点。然后在
set_identifier_type_value_with_scope
里,这个
TYPE_DECL
节点(注意不是类型定义)将被记录入标识符节点的
namespace_bindings
域中。
1731
static
void
1732
set_identifier_type_value_with_scope
(tree id, tree decl, cxx_scope *b)
in name-lookup.c
1733
{
1734
tree type;
1735
1736
if (b->kind != sk_namespace)
1737
{
1738
/* Shadow the marker, not the real thing, so
that the marker
1739
gets
restored later.
*/
1740
tree old_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
1741
b->type_shadowed
1742
= tree_cons (id,
old_type_value, b->type_shadowed);
1743
type = decl ? TREE_TYPE (decl) : NULL_TREE;
1744
}
1745
else
1746
{
1747
cxx_binding *binding =
1748
binding_for_name
(NAMESPACE_LEVEL (current_namespace), id);
1749
if (decl)
1750
{
1751
if (binding->value)
1752
supplement_binding (binding, decl);
1753
else
1754
binding->value = decl;
1755
}
1756
else
1757
abort ();
1758
/* Store marker instead of real type.
*/
1759
type = global_type_node
;
1760
}
1761
SET_IDENTIFIER_TYPE_VALUE (id, type);
1762
}
在上面
1754
行的赋值操作设置了该标识符目前对应的声明(这是个类型声明)。自此,在当前作用域,该标识符就表示该类型。
pushtag
(continue)
4656
d =
maybe_process_template_type_declaration (type,
4657
globalize, b);
4658
4659
if (b->kind == sk_class)
4660
{
4661
if
(!PROCESSING_REAL_TEMPLATE_DECL_P ())
4662
/* Put this
TYPE_DECL on the TYPE_FIELDS list for the
4663
class. But if it's a member
template class, we
4664
want the TEMPLATE_DECL, not the
TYPE_DECL, so this
4665
is done later.
*/
4666
finish_member_declaration (d);
4667
else
4668
pushdecl_class_level (d);
4669
}
4670
else
4671
d = pushdecl_with_scope
(d, b);
4672
4673
/*
FIXME what if it gets a name from typedef?
*/
4674
if (ANON_AGGRNAME_P (name))
4675
DECL_IGNORED_P (d) = 1;
4676
4677
TYPE_CONTEXT (type) =
DECL_CONTEXT (d);
4678
4679
/* If
this is a local class, keep track of it. We need this
4680
information for name-mangling, and so
that it is possible to find
4681
all function definitions in a
translation unit in a convenient
4682
way. (It's otherwise tricky to find a
member function definition
4683
it's only pointed to from within a
local class.)
*/
4684
if (TYPE_CONTEXT (type)
4685
&& TREE_CODE
(TYPE_CONTEXT (type)) == FUNCTION_DECL
4686
&&
!processing_template_decl)
4687
VARRAY_PUSH_TREE (local_classes
,
type);
4688
}
4689
if (b->kind == sk_class
4690
&& !COMPLETE_TYPE_P (current_class_type
))
4691
{
4692
maybe_add_class_template_decl_list (current_class_type
,
4693
type, /*friend_p=*/
0);
4694
CLASSTYPE_NESTED_UTDS (current_class_type
)
= b->type_decls;
4695
}
4696
}
4697
4698
if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
4699
/* Use the canonical TYPE_DECL for this
node.
*/
4700
TYPE_STUB_DECL (type) = TYPE_NAME (type);
4701
else
4702
{
4703
/* Create a fake NULL-named TYPE_DECL node
whose TREE_TYPE
4704
will be the tagged type we just added to
the current
4705
binding level. This fake NULL-named
TYPE_DECL node helps
4706
dwarfout.c to know when it needs to
output a
4707
representation of a tagged type, and it
also gives us a
4708
convenient place to record the
"scope start" address for
4709
the tagged type.
*/
4710
4711
tree d = build_decl (TYPE_DECL, NULL_TREE, type);
4712
TYPE_STUB_DECL (type) = pushdecl_with_scope (d, b);
4713
}
4714
timevar_pop (TV_NAME_LOOKUP);
4715
}
现在我们已经把类型定义(
RECORD_TYPE
节点)加入到了绑定域中,还把对应的
TYPE_DECL
节点加入到标识符节点的绑定链里。下面的
1960
行,
pushdecl
只是调用
add_decl_to_level
把
TYPE_DECL
节点加入对应
cxx_scope
的
names
域。
1941
tree
1942
pushdecl_with_scope
(tree x, cxx_scope *level)
in name-lookup.c
1943
{
1944
struct
cp_binding_level *b;
1945
tree function_decl = current_function_decl
;
1946
1947
timevar_push (TV_NAME_LOOKUP);
1948
current_function_decl
= NULL_TREE;
1949
if (level->kind == sk_class)
1950
{
1951
b = class_binding_level;
1952
class_binding_level = level;
1953
pushdecl_class_level (x);
1954
class_binding_level = b;
1955
}
1956
else
1957
{
1958
b = current_binding_level
;
1959
current_binding_level
= level;
1960
x = pushdecl (x);
1961
current_binding_level
= b;
1962
}
1963
current_function_decl
=
function_decl;
1964
POP_TIMEVAR_AND_RETURN
(TV_NAME_LOOKUP, x);
1965
}
type_info
实际上是一个类型系列,编译器根据类的结构选择其一,结构相同的类所选用的
type_info
是一样的,但是不同的实例。因此,编译器在遇到使用
type_info
的地方,并不急着构建实例,而是在前端最后完成这个编译单元时,集中地构建。这些
type_info
所需要的缓存就是在
init_rtti_processing
的
130
行的
unemitted_tinfo_decls
。
相关文章推荐
- GCC-3.4.6源代码学习笔记(10)
- GCC-3.4.6源代码学习笔记(35)
- GCC-3.4.6源代码学习笔记(144)
- GCC-3.4.6源代码学习笔记(147-续2)
- GCC-3.4.6源代码学习笔记(74)
- GCC-3.4.6源代码学习笔记(80)
- GCC-3.4.6源代码学习笔记(25)
- GCC-3.4.6源代码学习笔记(26)
- GCC-3.4.6源代码学习笔记(91)
- GCC-3.4.6源代码学习笔记(31)
- GCC-3.4.6源代码学习笔记(94)
- GCC-3.4.6源代码学习笔记(129)
- GCC-3.4.6源代码学习笔记(71)
- GCC-3.4.6源代码学习笔记(124)
- GCC-3.4.6源代码学习笔记(154)
- GCC-3.4.6源代码学习笔记(22)
- GCC-3.4.6源代码学习笔记(176)
- GCC-3.4.6源代码学习笔记(3)
- GCC-3.4.6源代码学习笔记(136)
- GCC-3.4.6源代码学习笔记(56)