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

GCC-3.4.6源代码学习笔记(135)

2010-12-25 13:55 351 查看
5.12.5.2.2.2.1.3.2.


具现基类——完成


在处理完所有的基类后(基类被串接起来),在
instantiate_class_template


5452
行,调用
xref_basetype

来填充其
binfo
部分,其中实参
ref

是派生类的
RECORD_TYPE
,而
base_list

包含了基类的
RECORD_TYPE
,及其访问属性。

基类的
RECORD_TYPE
是尚未完成的,因为其
type

域是空的,因此它需要首先通过在
xref_basetype

9645
行的
complete_type_or_else

来完成这个域。

4210

#define
complete_type_or_else
(T,V)
(complete_type_or_diagnostic ((T), (V), 0))

147

tree

148

complete_type_or_diagnostic

(tree type,
tree value, int diag_type)

in typeck.c

149

{

150

type = complete_type (type);

151

if (type == error_mark_node)

152

/* We already
issued an error.
*/

153

return
NULL_TREE;

154

else if (!COMPLETE_TYPE_P (type))

155

{

156

cxx_incomplete_type_diagnostic (value,
type, diag_type);

157

return
NULL_TREE;

158

}

159

else

160

return
type;

161

}

看到在函数的开头,
complete_type

被递归调用(我们从为派生类调用的
complete_type

中来到这里)。在
complete_type

中,为基类亦调用了
instantiate_class_template

来对其具现。如果基类亦是从某个模板类派生,这个过程亦为该基类重复。直到找到最底层的模板类(我们现在只看到具现模板类的前半部分,在后半部分模板类要调用
finish_struct

来完成
RECORD_TYPE
节点),或者最底层非模板类(这样的类型已经调用过
finish_struct

,其
RECORD_TYPE
节点已经完成处理)。在这里我们跳过在
complete_type

中基类处理的细节,假定之后其
RECORD_TYPE
已经完成处理。

xref_basetype

的细节可以参考前面的章节,对于我们的例子,执行深拷贝,因为基类是一个
RECORD_TYPE
节点。我们得到如下的布局。


点此打开



5.12.5.2.2.2.1.3.3.


完成派生类的

RECORD_TYPE



成员的替代


现在基类的具现体已经就绪,并且该派生类的
binfo
也已设置,接下来需要填入该类的成员,因为这里的
type

是一个对应具现体的空的
RECORD_TYPE
。进一步的派生类中的某些成员可能依赖于模板参数,它们也需要进行实参替换。如何产生这些类型值得了解。该处理函数虽然长,但相当明白。

instantiate_class_template (continue)

5458

/* Now that our
base classes are set up, enter the scope of the

5459

class, so that name lookups
into base classes, etc. will work

5460

correctly. This is precisely
analogous to what we do in

5461

begin_class_definition when
defining an ordinary non-template

5462

class.
*/

5463

pushclass
(type);

5464

5465

/* Now members are
processed in the order of declaration.

*/

5466

for
(member =
CLASSTYPE_DECL_LIST (pattern);

5467

member; member = TREE_CHAIN (member))

5468

{

5469

tree t = TREE_VALUE (member);

5470

5471

if (TREE_PURPOSE (member))

5472

{

5473

if (TYPE_P (t))

5474

{

5475

/* Build new CLASSTYPE_NESTED_UTDS.
*/

5476

5477

tree tag = t;

5478

tree name = TYPE_IDENTIFIER (tag);

5479

tree newtag;

5480

bool class_template_p;

5481

5482

class_template_p = (TREE_CODE (tag) !=
ENUMERAL_TYPE

5483

&&
TYPE_LANG_SPECIFIC (tag)

5484

&&
CLASSTYPE_IS_TEMPLATE (tag));

5485

/* If the
member is a class template, then -- even after

5486

substituition -- there
may be dependent types in the

5487

template argument list
for the class. We increment

5488

PROCESSING_TEMPLATE_DECL
so that dependent_type_p, as

5489

that function will
assume that no types are dependent

5490

when outside of a
template.
*/

5491

if (class_template_p)

5492

++processing_template_decl;

5493

newtag = tsubst (tag, args, tf_error,
NULL_TREE);

5494

if (class_template_p)

5495

--processing_template_decl;

5496

if (newtag == error_mark_node)

5497

continue
;

5498

5499

if (TREE_CODE (newtag) !=
ENUMERAL_TYPE)

5500

{

5501

if (class_template_p)

5502

/*
Unfortunately, lookup_template_class sets

5503

CLASSTYPE_IMPLICIT_INSTANTIATION for a partial

5504

instantiation
(i.e., for the type of a member

5505

template class
nested within a template class.)

5506

This behavior is
required for

5507

maybe_process_partial_specialization to work

5508

correctly, but is
not accurate in this case;

5509

the TAG is not an
instantiation of anything.

5510

(The corresponding
TEMPLATE_DECL is an

5511

instantiation, but
the TYPE is not.) */

5512

CLASSTYPE_USE_TEMPLATE (newtag) =
0;

5513

5514

/* Now, we
call pushtag to put this NEWTAG into the scope of

5515

TYPE. We first set up
the IDENTIFIER_TYPE_VALUE to avoid

5516

pushtag calling
push_template_decl. We don't have to do

5517

this for enums because
it will already have been done in

5518

tsubst_enum.
*/

5519

if (name)

5520

SET_IDENTIFIER_TYPE_VALUE (name,
newtag);

5521

pushtag
(name,
newtag, /*globalize=*/
0);

5522

}

5523

}
// end if (TYPE_P (t))

5524

else if (TREE_CODE (t) == FUNCTION_DECL

5525

|| DECL_FUNCTION_TEMPLATE_P (t))

5526

{

5527

/* Build new
TYPE_METHODS.
*/

5528

tree r;

5529

5530

if (TREE_CODE (t) == TEMPLATE_DECL)

5531

++processing_template_decl;

5532

r = tsubst (t, args, tf_error,
NULL_TREE);

5533

if (TREE_CODE (t) == TEMPLATE_DECL)

5534

--processing_template_decl;

5535

set_current_access_from_decl (r);

5536

grok_special_member_properties (r);

5537

finish_member_declaration
(r);

5538

}

5539

else

5540

{

5541

/* Build new TYPE_FIELDS.
*/

5542

5543

if (TREE_CODE (t) != CONST_DECL)

5544

{

5545

tree r;

5546

5547

/* The the file and line for this declaration,
to

5548

assist in error
message reporting. Since we

5549

called
push_tinst_level above, we don't need to

5550

restore these.
*/

5551

input_location

= DECL_SOURCE_LOCATION (t);

5552

5553

if (TREE_CODE (t) == TEMPLATE_DECL)

5554

++processing_template_decl;

5555

r = tsubst (t, args, tf_error |
tf_warning, NULL_TREE);

5556

if (TREE_CODE (t) == TEMPLATE_DECL)

5557

--processing_template_decl;

5558

if (TREE_CODE (r) == VAR_DECL)

5559

{

5560

tree init;

5561

5562

if (DECL_INITIALIZED_IN_CLASS_P
(r))

5563

init = tsubst_expr (DECL_INITIAL
(t), args,

5564

tf_error |
tf_warning, NULL_TREE);

5565

else

5566

init = NULL_TREE;

5567

5568

finish_static_data_member_decl

5569

(r, init, /*asmspec_tree=*/
NULL_TREE, /*flags=*/
0);

5570

5571

if (DECL_INITIALIZED_IN_CLASS_P
(r))

5572

check_static_variable_definition
(r, TREE_TYPE (r));

5573

}

5574

else if (TREE_CODE (r) == FIELD_DECL)

5575

{

5576

/*
Determine whether R has a valid type and can be

5577

completed later. If
R is invalid, then it is

5578

replaced by
error_mark_node so that it will not be

5579

added to
TYPE_FIELDS.
*/

5580

tree rtype = TREE_TYPE (r);

5581

if
(can_complete_type_without_circularity (rtype))

5582

complete_type
(rtype);

5583

5584

if (!COMPLETE_TYPE_P (rtype))

5585

{

5586

cxx_incomplete_type_error (r,
rtype);

5587

r = error_mark_node;

5588

}

5589

}

5590

5591

/* If it is
a TYPE_DECL for a class-scoped ENUMERAL_TYPE,

5592

such a thing will
already have been added to the field

5593

list by tsubst_enum in
finish_member_declaration in the

5594

CLASSTYPE_NESTED_UTDS
case above.
*/

5595

if (!(TREE_CODE (r) == TYPE_DECL

5596

&& TREE_CODE (TREE_TYPE
(r)) == ENUMERAL_TYPE

5597

&& DECL_ARTIFICIAL (r)))

5598

{

5599

set_current_access_from_decl (r);

5600

finish_member_declaration
(r);

5601

}

5602

}

5603

}

5604

}
// if (TREE_PURPOSE (member))

5605

else

5606

{

5607

if (TYPE_P (t) || DECL_CLASS_TEMPLATE_P
(t))

5608

{

5609

/* Build new
CLASSTYPE_FRIEND_CLASSES.
*/

5610

5611

tree friend_type = t;

5612

tree new_friend_type;

5613

5614

if (TREE_CODE (friend_type) ==
TEMPLATE_DECL)

5615

new_friend_type = tsubst_friend_class
(friend_type, args);

5616

else if (uses_template_parms
(friend_type))

5617

new_friend_type = tsubst
(friend_type, args,

5618

tf_error |
tf_warning, NULL_TREE);

5619

else if (CLASSTYPE_USE_TEMPLATE
(friend_type))

5620

new_friend_type = friend_type;

5621

else

5622

{

5623

tree ns = decl_namespace_context
(TYPE_MAIN_DECL
(friend_type));

5624

5625

/* The call
to xref_tag_from_type does injection for friend

5626

classes.
*/

5627

push_nested_namespace
(ns);

5628

new_friend_type =

5629

xref_tag_from_type (friend_type,
NULL_TREE, 1);

5630

pop_nested_namespace (ns);

5631

}

5632

5633

if (TREE_CODE (friend_type) ==
TEMPLATE_DECL)

5634

/* Trick
make_friend_class into realizing that the friend

5635

we're adding is a
template, not an ordinary class. It's

5636

important that we use
make_friend_class since it will

5637

perform some
error-checking and output cross-reference

5638

information.
*/

5639

++processing_template_decl;

5640

5641

if (new_friend_type != error_mark_node)

5642

make_friend_class (type,
new_friend_type,

5643

/*complain=*/
false);

5644

5645

if (TREE_CODE (friend_type) ==
TEMPLATE_DECL)

5646

--processing_template_decl;

5647

}

5648

else

5649

{

5650

/* Build new
DECL_FRIENDLIST.
*/

5651

tree r;

5652

5653

if (TREE_CODE (t) == TEMPLATE_DECL)

5654

++processing_template_decl;

5655

r = tsubst_friend_function (t, args);

5656

if (TREE_CODE (t) == TEMPLATE_DECL)

5657

--processing_template_decl;

5658

add_friend (type, r, /*complain=*/
false);

5659

}

5660

}

5661

}

5662

5663

/* Set the file and
line number information to whatever is given for

5664

the class itself. This puts
error messages involving generated

5665

implicit functions at a
predictable point, and the same point

5666

that would be used for
non-template classes.
*/

5667

typedecl = TYPE_MAIN_DECL (type);

5668

input_location

= DECL_SOURCE_LOCATION (typedecl);

5669

5670

unreverse_member_declarations
(type);

5671

finish_struct_1
(type);

注意到在该类中声明的成员被
CLASSTYPE_DECL_LIST
域以
tree_list
节点的形式记录起来。在这些
tree_list
节点中,
TREE_PURPOSE
域记录了其所属的类(如果是友元声明则是
NULL
),而
TREE_VALUE
域保存了声明本身。

在前面的章节中看到,在模板类中声明的实体亦被视为模板声明,连同产生
TEMPLATE_DECL
。在具现的过程中,模板实参将替换模板形参。

5.12.5.2.2.2.1.3.4.


完成派生类的

RECORD_TYPE



修正内联方法


因为模板类的具现对应的
RECORD_TYPE
是一个普通的类,在
5671
行必须调用
finish_struct_1

来完成其定义。

4997

void

4998

finish_struct_1

(tree t)

in class.c

4999

{

5001

tree x;

5002

/* A TREE_LIST. The
TREE_VALUE of each node is a FUNCTION_DECL.

*/

5003

tree virtuals = NULL_TREE;

5004

int n_fields = 0;

5005

tree vfield;

5006

5007

if (COMPLETE_TYPE_P (t))

5008

{

5009

if (IS_AGGR_TYPE (t))

5010

error ("redefinition of `%#T'",
t);

5011

else

5012

abort ();

5013

popclass ();

5014

return
;

5015

}

5016

5017

/* If this type was
previously laid out as a forward reference,

5018

make sure we lay it out
again.
*/

5019

TYPE_SIZE (t) = NULL_TREE;

5020

CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;

5021

5022

fixup_inline_methods
(t);

5023

5024

/* Make assumptions
about the class; we'll reset the flags if

5025

necessary.
*/

5026

CLASSTYPE_EMPTY_P (t) = 1;

5027

CLASSTYPE_NEARLY_EMPTY_P (t) = 1;

5028

CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t) = 0;

5029

5030

/* Do end-of-class
semantic processing: checking the validity of the

5031

bases and members and add
implicitly generated methods.
*/

5032

check_bases_and_members
(t);

同样,记得对于内联方法,在对应的
FUNCTION_DECL
节点中,其
template_info

域填充有模板信息。上面的成员替换为成员正确地进行了实参替换,但是某些关系尚未相应地更新。

4323

static
void

4324

fixup_inline_methods

(tree type)

in class.

4325

{

4326

tree method = TYPE_METHODS (type);

4327

4328

if (method && TREE_CODE (method) ==
TREE_VEC)

4329

{

4330

if (TREE_VEC_ELT (method, 1))

4331

method = TREE_VEC_ELT (method, 1);

4332

else if (TREE_VEC_ELT (method, 0))

4333

method = TREE_VEC_ELT (method, 0);

4334

else

4335

method = TREE_VEC_ELT (method, 2);

4336

}

4337

4338

/* Do inline member
functions.
*/

4339

for
(;
method; method = TREE_CHAIN (method))

4340

fixup_pending_inline
(method);

4341

4342

/* Do friends.
*/

4343

for
(method =
CLASSTYPE_INLINE_FRIENDS (type);

4344

method;

4345

method = TREE_CHAIN (method))

4346

fixup_pending_inline (TREE_VALUE (method));

4347

CLASSTYPE_INLINE_FRIENDS (type) = NULL_TREE;

4348

}

记得内联方法的函数体被缓存在
DECL_PENDING_INLINE_INFO
中。在具现时,内联方法的实参已经被替换入其函数体,但其
context

域并未触及,在完成替换后,需要为内联方法将其更新(构建的新节点)。

4306

static
void

4307

fixup_pending_inline

(tree fn)

in class.

4308

{

4309

if (DECL_PENDING_INLINE_INFO (fn))

4310

{

4311

tree args = DECL_ARGUMENTS (fn);

4312

while
(args)

4313

{

4314

DECL_CONTEXT (args) = fn;

4315

args = TREE_CHAIN (args);

4316

}

4317

}

4318

}

5.12.5.2.2.2.1.3.5.


完成派生类的

RECORD_TYPE



验证基类


在这一点上,基类及成员的实参替换被恰当地完成了,不过没有对模板的具现进行类级别的语义检查。这个语义检查应尽快进行。这里就是尽早执行语义检查的点。

4145

static
void

4146

check_bases_and_members

(tree t)

in class.c

4147

{

4148

/* Nonzero if we
are not allowed to generate a default constructor

4149

for this case.
*/

4150

int cant_have_default_ctor;

4151

/* Nonzero if the
implicitly generated copy constructor should take

4152

a non-const reference argument.
*/

4153

int cant_have_const_ctor;

4154

/* Nonzero if the
the implicitly generated assignment operator

4155

should take a non-const
reference argument.
*/

4156

int no_const_asn_ref;

4157

tree access_decls;

4158

4159

/* By default, we
use const reference arguments and generate default

4160

constructors.
*/

4161

cant_have_default_ctor = 0;

4162

cant_have_const_ctor = 0;

4163

no_const_asn_ref = 0;

4164

4165

/* Check all the
base-classes.
*/

4166

check_bases
(t,
&cant_have_default_ctor, &cant_have_const_ctor,

4167

&no_const_asn_ref);

如果模板类包含(派生)基类(记得基类也可以是模板类,比如我们的“
SmallObject
”),是时候检查派生类与基类间是否有不符合的地方。

1109

static
void

1110

check_bases

(tree t,

in class.c

1111

int* cant_have_default_ctor_p,

1112

int* cant_have_const_ctor_p,

1113

int* no_const_asn_ref_p)

1114

{

1115

int n_baseclasses;

1116

int i;

1117

int seen_non_virtual_nearly_empty_base_p;

1118

tree binfos;

1119

1120

binfos = TYPE_BINFO_BASETYPES (t);

1121

n_baseclasses = CLASSTYPE_N_BASECLASSES (t);

1122

seen_non_virtual_nearly_empty_base_p = 0;

1123

1124

/* An aggregate
cannot have baseclasses.

*/

1125

CLASSTYPE_NON_AGGREGATE (t) |= (n_baseclasses !=
0);

1126

1127

for
(i = 0; i < n_baseclasses; ++i)

1128

{

1129

tree base_binfo;

1130

tree basetype;

1131

1132

/* Figure out
what base we're looking at.

*/

1133

base_binfo = TREE_VEC_ELT (binfos, i);

1134

basetype = TREE_TYPE (base_binfo);

1135

1136

/* If the type of
basetype is incomplete, then we already

1137

complained about that fact
(and we should have fixed it up as

1138

well).
*/

1139

if (!COMPLETE_TYPE_P (basetype))

1140

{

1141

int j;

1142

/* The base
type is of incomplete type. It is

1143

probably best to pretend
that it does not

1144

exist.
*/

1145

if (i == n_baseclasses-1)

1146

TREE_VEC_ELT (binfos, i) = NULL_TREE;

1147

TREE_VEC_LENGTH (binfos) -= 1;

1148

n_baseclasses -= 1;

1149

for
(j = i; j+1 < n_baseclasses; j++)

1150

TREE_VEC_ELT (binfos, j) = TREE_VEC_ELT (binfos, j+1);

1151

continue
;

1152

}

1153

1154

/* Effective C++
rule 14. We only need to check TYPE_POLYMORPHIC_P

1155

here because the case of
virtual functions but non-virtual

1156

dtor is handled in
finish_struct_1.
*/

1157

if (warn_ecpp

&& ! TYPE_POLYMORPHIC_P
(basetype)

1158

&& TYPE_HAS_DESTRUCTOR
(basetype))

1159

warning ("base class `%#T' has a
non-virtual destructor",

1160

basetype);

1161

1162

/* If the base
class doesn't have copy constructors or

1163

assignment operators that
take const references, then the

1164

derived class cannot have
such a member automatically

1165

generated.
*/

1166

if (! TYPE_HAS_CONST_INIT_REF (basetype))

1167

*cant_have_const_ctor_p = 1;

1168

if (TYPE_HAS_ASSIGN_REF (basetype)

1169

&& !TYPE_HAS_CONST_ASSIGN_REF
(basetype))

1170

*no_const_asn_ref_p = 1;

1171

/* Similarly, if
the base class doesn't have a default

1172

constructor, then the derived
class won't have an

1173

automatically generated
default constructor.
*/

1174

if (TYPE_HAS_CONSTRUCTOR (basetype)

1175

&& !
TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype))

1176

{

1177

*cant_have_default_ctor_p = 1;

1178

if (! TYPE_HAS_CONSTRUCTOR (t))

1179

pedwarn ("base
`%T' with only non-default constructor in class without a constructor",

1180

basetype);

1181

}

1182

1183

if (TREE_VIA_VIRTUAL (base_binfo))

1184

/* A virtual
base does not effect nearly emptiness.

*/

1185

;

1186

else if (CLASSTYPE_NEARLY_EMPTY_P
(basetype))

1187

{

1188

if (seen_non_virtual_nearly_empty_base_p)

1189

/* And if
there is more than one nearly empty base, then the

1190

derived class is not nearly empty either.
*/

1191

CLASSTYPE_NEARLY_EMPTY_P (t) = 0;

1192

else

1193

/* Remember
we've seen one.
*/

1194

seen_non_virtual_nearly_empty_base_p =
1;

1195

}

1196

else if (!is_empty_class (basetype))

1197

/* If the base
class is not empty or nearly empty, then this

1198

class cannot be nearly
empty.
*/

1199

CLASSTYPE_NEARLY_EMPTY_P (t) = 0;

1200

1201

/* A lot of
properties from the bases also apply to the derived

1202

class.
*/

1203

TYPE_NEEDS_CONSTRUCTING
(t) |= TYPE_NEEDS_CONSTRUCTING (basetype);

1204

TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)

1205

|= TYPE_HAS_NONTRIVIAL_DESTRUCTOR
(basetype);

1206

TYPE_HAS_COMPLEX_ASSIGN_REF (t)

1207

|= TYPE_HAS_COMPLEX_ASSIGN_REF (basetype);

1208

TYPE_HAS_COMPLEX_INIT_REF
(t) |= TYPE_HAS_COMPLEX_INIT_REF (basetype);

1209

TYPE_POLYMORPHIC_P (t) |=
TYPE_POLYMORPHIC_P (basetype);

1210

CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t)

1211

|= CLASSTYPE_CONTAINS_EMPTY_CLASS_P
(basetype);

1212

}

1213

}

在该次调用的实参中,
cant_have_default_ctor

是非
0
值,如果基类没有缺省构造函数;
cant_have_const_ctor

是非
0
值,如果基类没有使用引用常量的拷贝构造函数,而
no_const_asn_ref

是非
0
值,如果基类没有使用引用常量的赋值操作符。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: