您的位置:首页 > 编程语言

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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: