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

GCC-3.4.6源代码学习笔记(139-续1)

2011-01-02 13:01 441 查看
layout_class_type (continue)

4664

/* Create a pointer
to our virtual function table.
*/

4665

vptr = create_vtable_ptr
(t, virtuals_p);

4666

4667

/* The vptr is
always the first thing in the class.
*/

4668

if (vptr)

4669

{

4670

TREE_CHAIN (vptr) = TYPE_FIELDS (t);

4671

TYPE_FIELDS (t) = vptr;

4672

next_field = &TREE_CHAIN (vptr);

4673

place_field
(rli, vptr);

4674

}

4675

else

4676

next_field = &TYPE_FIELDS (t);

回到
layout_class_type

,在对类进行了完整性检查并确定了主要基类后,编译器为
vptr
的生成做准备。这里在
create_vtable_ptr

中,参数
virtuals_p

来自
finish_struct_1

里的局部变量
virtuals

,参数
t

是类本身。注意到
TYPE_VFIELD (t)
不是空的,如果它的主要基类含有
vptr
(它在
set_primary_base

中设置)。因此只要该类能从其主要基类中得到
TYPE_VFIELD
,就不需要为其创建
vptr


4328
行的
FOR

循环对于
vtable
的构建是非常关键的,它把由该类声明的所有的虚函数拷贝到另一个链表
virtual_p

,并且注意
4245
行的赋值,被拷贝函数的
BV_DELTA
被设为
0

BV_DELTA
代表当调用该虚函数时,需要从
this
指针减去的字节数【这时得到声明该虚函数的基类
this
指针】)。

DECL_VINDEX

FUNCTION_DECL
中有两个用途。在包含该
FUNCTION_DECL
的类被编排前,
DECL_VINDEX
可能指向一个基类中的一个
FUNCTION_DECL
,它是当前的
FUNCTION_DECL
作为虚函数所要替代的。当类编排后,这个指针就改为一个
INTEGER_CST
节点,用作虚函数表的索引。那么对于未编排类的
FUNCTION_DECL
,它们被记录在
virtual_p

所指向的
tree_list
中。

4232

static
tree

4233

create_vtable_ptr

(tree t, tree*
virtuals_p)
in

class.c

4234

{

4235

tree fn;

4236

4237

/* Collect the
virtual functions declared in T.
*/

4238

for
(fn =
TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn))

4239

if (DECL_VINDEX (fn)
&& !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn)

4240

&& TREE_CODE (DECL_VINDEX (fn))
!= INTEGER_CST)

4241

{

4242

tree new_virtual = make_node
(TREE_LIST);

4243

4244

BV_FN (new_virtual) = fn;

4245

BV_DELTA (new_virtual) = integer_zero_node;

4246

4247

TREE_CHAIN (new_virtual) = *virtuals_p;

4248

*virtuals_p = new_virtual;

4249

}

4250

4251

/* If we couldn't
find an appropriate base class, create a new field

4252

here. Even if there weren't
any new virtual functions, we might need a

4253

new virtual function table if
we're supposed to include vptrs in

4254

all classes that need
them.
*/

4255

if (!TYPE_VFIELD (t) && (*virtuals_p
|| TYPE_CONTAINS_VPTR_P (t)))

4256

{

4257

/* We build this
decl with vtbl_ptr_type_node, which is a

4258

`vtable_entry_type*'. It
might seem more precise to use

4259

`vtable_entry_type (*)
'
where N is the number of firtual

4260

functions. However, that
would require the vtable pointer in

4261

base classes to have a
different type than the vtable pointer

4262

i
n derived classes. We could make that happen,
but that

4263

still wouldn't solve all the
problems. In particular, the

4264

type-based alias analysis
code would decide that assignments

4265

to the base class vtable
pointer can't alias assignments to

4266

the derived class vtable pointer, since
they have different

4267

types. Thus, in a derived
class destructor, where the base

4268

class constructor was
inlined, we could generate bad code for

4269

setting up the vtable
pointer.

4270

4271

Therefore, we use one type
for all vtable pointers. We still

4272

use a type-correct type;
it's just doesn't indicate the array

4273

bounds. That's better than
using `void*' or some such; it's

4274

cleaner, and it let's the alias
analysis code know that these

4275

stores cannot alias stores
to void*!
*/

4276

tree field;

4277

4278

field = build_decl
(FIELD_DECL, get_vfield_name (t), vtbl_ptr_type_node

);

4279

SET_DECL_ASSEMBLER_NAME (field,
get_identifier (VFIELD_BASE));

4280

DECL_VIRTUAL_P (field) = 1;

4281

DECL_ARTIFICIAL (field) = 1;

4282

DECL_FIELD_CONTEXT (field) = t;

4283

DECL_FCONTEXT (field) = t;

4284

4285

TYPE_VFIELD (t) = field;

4286

4287

/* This class is
non-empty.
*/

4288

CLASSTYPE_EMPTY_P (t) = 0;

4289

4290

if (CLASSTYPE_N_BASECLASSES (t))

4291

/* If there
were any baseclasses, they can't possibly be at

4292

offset zero any more,
because that's where the vtable

4293

pointer is. So, converting
to a base class is going to

4294

take work.
*/

4295

TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (t) =
1;

4296

4297

return
field;

4298

}

4299

4300

return
NULL_TREE;

4301

}

如果主要基类没有
vtable
(或者压根没有主要基类),但派生类本身有虚函数,那么在这里编译器为其生成。在
4279
行的
VFIELD_BASE
是字符串“
$vf
”。而在
4295
行,如果类有基类,编译器还将需要产生转换操作符来执行派生类到基类间的转换。在
4278
行,在
cxx_init_decl_processing


vtbl_ptr_type_node

被初始化为
vtable_entry_type

*
,也即具有类型
int(*)()


看到在
layout_class_type


4673
行,如果要新建
vtable
,调用
place_field

首先在类里布局这个
vtable


layout_class_type (continue)

4678

/* Build
FIELD_DECLs for all of the non-virtual base-types.
*/

4679

empty_base_offsets = splay_tree_new
(splay_tree_compare_integer_csts,

4680

NULL, NULL);

4681

build_base_fields
(rli, empty_base_offsets, next_field);

而对于其他部分,一棵伸展树(
splaying tree

empty_base_offsets

被创建在布局过程中保存空基类的偏移量。把这个伸展树作为
offsets

实参,
build_base_fields

开始布局类的基类。

3729

static
void

3730

build_base_fields

(record_layout_info
rli,
in

class.c

3731

splay_tree offsets, tree
*next_field)

3732

{

3733

/* Chain to hold
all the new FIELD_DECLs which stand in for base class

3734

subobjects.

*/

3735

tree t = rli->t;

3736

int n_baseclasses = CLASSTYPE_N_BASECLASSES (t);

3737

int i;

3738

3739

/* The primary base
class is always allocated first.
*/

3740

if (CLASSTYPE_HAS_PRIMARY_BASE_P (t))

3741

next_field = build_base_field
(rli, CLASSTYPE_PRIMARY_BINFO (t),

3742

offsets,
next_field);

3743

3744

/* Now allocate the
rest of the bases.

*/

3745

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

3746

{

3747

tree base_binfo;

3748

3749

base_binfo = BINFO_BASETYPE (TYPE_BINFO
(t), i);

3750

3751

/* The primary
base was already allocated above, so we don't

3752

need to allocate it again
here.
*/

3753

if (base_binfo == CLASSTYPE_PRIMARY_BINFO
(t))

3754

continue
;

3755

3756

/* Virtual bases
are added at the end (a primary virtual base

3757

will have already been
added).
*/

3758

if (TREE_VIA_VIRTUAL (base_binfo))

3759

continue
;

3760

3761

next_field = build_base_field
(rli, base_binfo,

3762

offsets,
next_field);

3763

}

3764

}

看到主要基类是首先被布局的(不管它是否是虚拟基类)——这就是为什么它被称为主要基类。然后其他基类按继承顺序处理。注意在
3758
行的条件,看到非主要虚拟基类不在这里编排,而是在后面的
layout_virtual_bases

里。

接着编译器要为这些基类构建对应的域,这样可以在派生类中采用统一的访问方式。

3628

static
tree *

3629

build_base_field

(record_layout_info rli,
tree binfo,
in

class.c

3630

splay_tree offsets, tree
*next_field)

3631

{

3632

tree t = rli->t;

3633

tree basetype = BINFO_TYPE (binfo);

3634

3635

if (!COMPLETE_TYPE_P (basetype))

3636

/* This error is
now reported in xref_tag, thus giving better

3637

location information.
*/

3638

return
next_field;

3639

3640

/* Place the base
class.
*/

3641

if (!is_empty_class (basetype))

3642

{

3643

tree decl;

3644

3645

/* The containing
class is non-empty because it has a non-empty

3646

base class.
*/

3647

CLASSTYPE_EMPTY_P (t) = 0;

3648

3649

/* Create the
FIELD_DECL.
*/

3650

decl = build_decl
(FIELD_DECL, NULL_TREE, CLASSTYPE_AS_BASE
(basetype));

3651

DECL_ARTIFICIAL (decl) = 1;

3652

DECL_FIELD_CONTEXT (decl) = t;

3653

DECL_SIZE (decl) = CLASSTYPE_SIZE
(basetype);

3654

DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT
(basetype);

3655

DECL_ALIGN (decl) = CLASSTYPE_ALIGN
(basetype);

3656

DECL_USER_ALIGN (decl) =
CLASSTYPE_USER_ALIGN (basetype);

3657

DECL_IGNORED_P (decl) = 1;

3658

3659

/* Try to place the field. It may take more
than one try if we

3660

have a hard time placing the
field without putting two

3661

objects of the same type at
the same address.
*/

3662

layout_nonempty_base_or_field
(rli, decl, binfo, offsets);

3663

/* Add the new
FIELD_DECL to the list of fields for T.

*/

3664

TREE_CHAIN (decl) = *next_field;

3665

*next_field = decl;

3666

next_field = &TREE_CHAIN (decl);

3667

}


3650
行的
CLASSTYPE_AS_BASE
给出了
basetype

作为基类的类型(后面在
layout_class_type

中,我们将看到这是个什么类型)。这些代表着基类的域,在派生类中如同其他普通域那样,需要布局,确定其位置。

3461

static
void

3462

layout_nonempty_base_or_field

(record_layout_info
rli,
in
class.c

3463

tree decl,

3464

tree binfo,

3465

splay_tree offsets)

3466

{

3467

tree offset = NULL_TREE;

3468

bool field_p;

3469

tree type;

3470

3471

if (binfo)

3472

{

3473

/* For the
purposes of determining layout conflicts, we want to

3474

use the class type of BINFO;
TREE_TYPE (DECL) will be the

3475

CLASSTYPE_AS_BASE version,
which does not contain entries for

3476

zero-sized bases.
*/

3477

type = TREE_TYPE (binfo);

3478

field_p = false;

3479

}

3480

else

3481

{

3482

type = TREE_TYPE (decl);

3483

field_p = true;

3484

}

3485

3486

/* Try to place the
field. It may take more than one try if we have

3487

a hard time placing the field without putting
two objects of the

3488

same type at the same
address.
*/

3489

while
(1)

3490

{

3491

struct
record_layout_info_s old_rli = *rli;

3492

3493

/* Place this
field.
*/

3494

place_field
(rli, decl);

3495

offset = byte_position
(decl);

3496

3497

/* We have to
check to see whether or not there is already

3498

something of the same type
at the offset we're about to use.

3499

For example, consider:

3500

3501

struct S {};

3502

struct T : public S { int
i; };

3503

struct U : public S, public
T {};

3504

3505

Here, we put S at offset zero in U. Then,
we can't put T at

3506

offset zero -- its S
component would be at the same address

3507

as the S we already
allocated. So, we have to skip ahead.

3508

Since all data members,
including those whose type is an

3509

empty class, have nonzero
size, any overlap can happen only

3510

with a direct or indirect
base-class -- it can't happen with

3511

a data member.

*/

3512

/* In a union,
overlap is permitted; all members are placed at

3513

offset zero.
*/

3514

if (TREE_CODE (rli->t) == UNION_TYPE)

3515

break
;

3516

/* G++ 3.2 did
not check for overlaps when placing a non-empty

3517

virtual base.
*/

3518

if (!abi_version_at_least (2) &&
binfo && TREE_VIA_VIRTUAL (binfo))

3519

break
;

3520

if (layout_conflict_p
(field_p ? type : binfo, offset,

3521

offsets, field_p))

3522

{

3523

/* Strip off
the size allocated to this field. That puts us

3524

at the first place we
could have put the field with

3525

proper alignment.
*/

3526

*rli = old_rli;

3527

3528

/* Bump up by
the alignment required for the type.

*/

3529

rli->bitpos

3530

= size_binop (PLUS_EXPR, rli->bitpos,

3531

bitsize_int (binfo

3532

?
CLASSTYPE_ALIGN (type)

3533

: TYPE_ALIGN
(type)));

3534

normalize_rli
(rli);

3535

}

3536

else

3537

/* There was no
conflict. We're done laying out this field.

*/

3538

break
;

3539

}

3540

3541

/* Now that we know
where it will be placed, update its

3542

BINFO_OFFSET.
*/

3543

if (binfo && CLASS_TYPE_P (BINFO_TYPE
(binfo)))

3544

/* Indirect
virtual bases may have a nonzero BINFO_OFFSET at

3545

this point because their
BINFO_OFFSET is copied from another

3546

hierarchy. Therefore, we may
not need to add the entire

3547

OFFSET.

*/

3548

propagate_binfo_offsets
(binfo,

3549

size_diffop (convert
(ssizetype, offset),

3550

convert (ssizetype,

3551

BINFO_OFFSET
(binfo))));

3552

}


RECORD_TYPE中的

FIELD_DECL

一节中已经给出了域布置的细节,它给处理的域填充
DECL_FIELD_OFFSET
(以字节为单位的偏移量)及
DECL_FIELD_BIT_OFFSET
(以比特为单位的偏移量),并在
3530
行更新
rli


bitpos

域,以显示到类头部偏移的比特数(注意它不总是等于刚布置域的
DECL_FIELD_BIT_OFFSET
,因为可能有填充字节)。

1175

tree

1176

byte_position

(tree field)
in

tree.c

1177

{

1178

return
byte_from_pos
(DECL_FIELD_OFFSET (field),

1179

DECL_FIELD_BIT_OFFSET (field));

1180

}


C++
里,在布局过程中,空的基类可能不占空间。例如:

class

A {}; sizeof

(A)
给出
1
,但在以下的语句中:

class

B: public

A { public

:
int temp; };

class

C { public

:
int temp; }; sizeof

(B)

sizeof

(C)
都给出了
4


另外还有
class
D: public
A, C {}; sizeof

(D)
亦给出了
4
。空类
A
不占空间,基类
C
可以与
A
共享同一个偏移位置。但是
class

D {A a; C c}; sizeof

(D)
则给出了
8
。空类
A
与类
C
独自占有自己的空间。出现这种差异的根本原因在于,基类的布局首先考虑非空的基类,然后到空的基类,再到虚拟基类;但域的布局必须按照声明的次序。为了检验新布置的域是否与已有的域发生冲突,调用函数
layout_conflict_p



3434

static
int

3435

layout_conflict_p

(tree type,
in

class.c

3436

tree offset,

3437

splay_tree offsets,

3438

int vbases_p)

3439

{

3440

splay_tree_node max_node;

3441

3442

/* Get the node in
OFFSETS that indicates the maximum offset where

3443

an empty subobject is
located.
*/

3444

max_node = splay_tree_max (offsets);

3445

/* If there aren't
any empty subobjects, then there's no point in

3446

performing this check.
*/

3447

if (!max_node)

3448

return
0;

3449

3450

return
walk_subobject_offsets
(type, check_subobject_offset
, offset,

3451

offsets, (tree)
(max_node->key),

3452

vbases_p);

3453

}

我们略过伸展树(
splay tree
)的细节。大致的,在这棵伸展树中,其节点以偏移量来排序(保存在
key
域中),具有同一偏移量的类域(
field
)或基类被链接在同一个树节点的
value
域中。在
3444
行,
splay_tree_max

返回当前已布置的最大偏移。这个偏移量划定了
walk_subobject_offsets

的查找范围。而函数
check_subobject_offset

给定一个偏移量,检查该位置是否已经放置了同样的一个类型。如果是,表明发生冲突,返回
1


3193

static
int

3194

check_subobject_offset

(tree type, tree
offset, splay_tree offsets)
in

class.c

3195

{

3196

splay_tree_node n;

3197

tree t;

3198

3199

if (!is_empty_class (type))

3200

return
0;

3201

3202

/* Record the
location of this empty object in OFFSETS.

*/

3203

n = splay_tree_lookup (offsets,
(splay_tree_key) offset);

3204

if (!n)

3205

return
0;

3206

3207

for
(t =
(tree) n->value; t; t = TREE_CHAIN (t))

3208

if (same_type_p (TREE_VALUE (t), type))

3209

return
1;

3210

3211

return
0;

3212

}

在调用
walk_subobject_offsets

时的参数
type
可以是
binfo
(基类),或者是
RECORD_TYPE
(类类型的域(
field
)),或者内建类型。这
3
种情况并无本质的差别。注意这个时候,该
type

对象已经在前面由
place_fields

做了布局。

3225

static
int

3226

walk_subobject_offsets

(tree type,
in

class.c

3227

subobject_offset_fn f,

3228

tree offset,

3229

splay_tree offsets,

3230

tree max_offset,

3231

int vbases_p)

3232

{

3233

int r = 0;

3234

tree type_binfo = NULL_TREE;

3235

3236

/* If this OFFSET is
bigger than the MAX_OFFSET, then we should

3237

stop.
*/

3238

if (max_offset && INT_CST_LT
(max_offset, offset))

3239

return
0;

3240

3241

if (!TYPE_P (type))

3242

{

3243

if (abi_version_at_least (2))

3244

type_binfo = type;

3245

type = BINFO_TYPE (type);

3246

}

3247

3248

if (CLASS_TYPE_P (type))

3249

{

3250

tree field;

3251

tree binfo;

3252

int i;

3253

3254

/* Avoid
recursing into objects that are not interesting.
*/

3255

if (!CLASSTYPE_CONTAINS_EMPTY_CLASS_P
(type))

3256

return
0;

3257

3258

/* Record the location of TYPE.
*/

3259

r = (*f) (type, offset, offsets);

3260

if (r)

3261

return
r;

3262

3263

/* Iterate
through the direct base classes of TYPE.

*/

3264

if (!type_binfo)

3265

type_binfo = TYPE_BINFO (type);

3266

for
(i = 0; i < BINFO_N_BASETYPES (type_binfo);
++i)

3267

{

3268

tree binfo_offset;

3269

3270

binfo = BINFO_BASETYPE (type_binfo, i);

3271

3272

if (abi_version_at_least (2)

3273

&& TREE_VIA_VIRTUAL (binfo))

3274

continue
;

3275

3276

if (!vbases_p

3277

&& TREE_VIA_VIRTUAL (binfo)

3278

&& !BINFO_PRIMARY_P (binfo))

3279

continue
;

3280

3281

if (!abi_version_at_least (2))

3282

binfo_offset = size_binop (PLUS_EXPR,

3283

offset,

3284

BINFO_OFFSET
(binfo));

3285

else

3286

{

3287

tree orig_binfo;

3288

/* We cannot
rely on BINFO_OFFSET being set for the base

3289

class yet, but the
offsets for direct non-virtual

3290

bases can be calculated
by going back to the TYPE.

*/

3291

orig_binfo = BINFO_BASETYPE (TYPE_BINFO (type), i);

3292

binfo_offset = size_binop (PLUS_EXPR,

3293

offset,

3294

BINFO_OFFSET
(orig_binfo));

3295

}

3296

3297

r = walk_subobject_offsets
(binfo,

3298

f,

3299

binfo_offset,

3300

offsets,

3301

max_offset,

3302

(abi_version_at_least (2)

3303

? /*vbases_p=*/
0
: vbases_p));

3304

if (r)

3305

return
r;

3306

}

3307

3308

if (abi_version_at_least (2))

3309

{

3310

tree vbase;

3311

3312

/* Iterate through the virtual base classes of
TYPE. In G++

3313

3.2, we included virtual
bases in the direct base class

3314

loop above, which results
in incorrect results; the

3315

correct offsets for
virtual bases are only known when

3316

working with the most
derived type.
*/

3317

if (vbases_p)

3318

for
(vbase = CLASSTYPE_VBASECLASSES (type);

3319

vbase;

3320

vbase = TREE_CHAIN (vbase))

3321

{

3322

binfo = TREE_VALUE (vbase);

3323

r = walk_subobject_offsets
(binfo,

3324

f,

3325

size_binop
(PLUS_EXPR,

3326

offset,

3327

BINFO_OFFSET (binfo)),

3328

offsets,

3329

max_offset,

3330

/*vbases_p=*/
0);

3331

if (r)

3332

return
r;

3333

}

3334

else

3335

{

3336

/* We still
have to walk the primary base, if it is

3337

virtual. (If it is
non-virtual, then it was walked

3338

above.)
*/

3339

vbase = get_primary_binfo
(type_binfo);

3340

if (vbase && TREE_VIA_VIRTUAL
(vbase)

3341

&& BINFO_PRIMARY_BASE_OF
(vbase) == type_binfo)

3342

{

3343

r = (walk_subobject_offsets

3344

(vbase, f, offset,

3345

offsets, max_offset, /*vbases_p=*/
0));

3346

if (r)

3347

return
r;

3348

}

3349

}

3350

}

3351

3352

/* Iterate
through the fields of TYPE.
*/

3353

for
(field
= TYPE_FIELDS (type); field; field = TREE_CHAIN (field))

3354

if (TREE_CODE (field) == FIELD_DECL
&& !DECL_ARTIFICIAL (field))

3355

{

3356

tree field_offset;

3357

3358

if (abi_version_at_least (2))

3359

field_offset = byte_position
(field);

3360

else

3361

/* In G++
3.2, DECL_FIELD_OFFSET was used.
*/

3362

field_offset = DECL_FIELD_OFFSET
(field);

3363

3364

r = walk_subobject_offsets
(TREE_TYPE (field),

3365

f,

3366

size_binop
(PLUS_EXPR,

3367

offset,

3368

field_offset),

3369

offsets,

3370

max_offset,

3371

/*vbases_p=*/
1);

3372

if (r)

3373

return
r;

3374

}

3375

}

3376

else if (TREE_CODE (type) == ARRAY_TYPE)

3377

{

3378

tree element_type = strip_array_types
(type);

3379

tree domain = TYPE_DOMAIN (type);

3380

tree index;

3381

3382

/* Avoid
recursing into objects that are not interesting.
*/

3383

if (!CLASS_TYPE_P (element_type)

3384

|| !CLASSTYPE_CONTAINS_EMPTY_CLASS_P
(element_type))

3385

return
0;

3386

3387

/* Step through
each of the elements in the array.
*/

3388

for
(index
= size_zero_node;

3389

/* G++ 3.2
had an off-by-one error here.
*/

3390

(abi_version_at_least (2)

3391

? !INT_CST_LT (TYPE_MAX_VALUE
(domain), index)

3392

: INT_CST_LT (index, TYPE_MAX_VALUE
(domain)));

3393

index = size_binop (PLUS_EXPR, index,
size_one_node))

3394

{

3395

r = walk_subobject_offsets
(TREE_TYPE (type),

3396

f,

3397

offset,

3398

offsets,

3399

max_offset,

3400

/*vbases_p=*/
1);

3401

if (r)

3402

return
r;

3403

offset = size_binop (PLUS_EXPR, offset,

3404

TYPE_SIZE_UNIT
(TREE_TYPE (type)));

3405

/* If this new
OFFSET is bigger than the MAX_OFFSET, then

3406

there's no point in
iterating through the remaining

3407

elements of the
array.
*/

3408

if (max_offset && INT_CST_LT
(max_offset, offset))

3409

break
;

3410

}

3411

}

3412

3413

return
0;

3414

}

上面的
abi_version_at_least (2)

返回非
0
值,如果
G++
是不早于
3.4.0
的版本。
3312
行的注释解释了
G++3.4.0
之后及之前版本间的差别。类的非直接基类的偏移量通过其在该基类的偏移量加上基类的偏移量得到。并且这个处理适用于非虚拟基类及类域(
field
)。

非空类型不在考虑之列,因为它们必定要独占一个空间。如果指定位置已经放置了同一类型的对象,
layout_conflict_p

返回
1
,这将使得偏移量上浮到基类的下一个对齐地址边界(对于类类型,对齐量通常是
4
字节)。

而在
build_base_field

中,空类具有特殊的处理。下面的
rli_size_unit_so_far

计算出已经布置的对象或域的字节大小(忽略多余的比特)因此
eoc

是最靠近已布局大小的对齐边界。

build_base_field (continue)

3668

else

3669

{

3670

tree eoc;

3671

bool atend;

3672

3673

/* On some
platforms (ARM), even empty classes will not be

3674

byte-aligned.
*/

3675

eoc = round_up
(rli_size_unit_so_far
(rli),

3676

CLASSTYPE_ALIGN_UNIT
(basetype));

3677

atend = layout_empty_base
(binfo, eoc, offsets);

3678

/* A nearly-empty
class "has no proper base class that is empty,

3679

not morally virtual, and at
an offset other than zero."
*/

3680

if (!TREE_VIA_VIRTUAL (binfo) &&
CLASSTYPE_NEARLY_EMPTY_P (t))

3681

{

3682

if (atend)

3683

CLASSTYPE_NEARLY_EMPTY_P (t) = 0;

3684

/* The check
above (used in G++ 3.2) is insufficient because

3685

an empty class placed at
offset zero might itself have an

3686

empty base at a nonzero
offset.
*/

3687

else if (walk_subobject_offsets
(basetype,

3688

empty_base_at_nonzero_offset_p,

3689

size_zero_node,

3690

/*offsets=*/
NULL,

3691

/*max_offset=*/
NULL_TREE,

3692

/*vbases_p=*/
true))

3693

{

3694

if (abi_version_at_least (2))

3695

CLASSTYPE_NEARLY_EMPTY_P (t) = 0;

3696

else if (warn_abi

)

3697

warning ("class `%T' will be
considered nearly empty in a "

3698

"future version of
GCC", t);

3699

}

3700

}

3701

3702

/* We do not
create a FIELD_DECL for empty base classes because

3703

it might overlap some other
field. We want to be able to

3704

create CONSTRUCTORs for the
class by iterating over the

3705

FIELD_DECLs, and the back
end does not handle overlapping

3706

FIELD_DECLs.
*/

3707

3708

/* An empty
virtual base causes a class to be non-empty

3709

-- but in that case we do
not need to clear CLASSTYPE_EMPTY_P

3710

here because that was
already done when the virtual table

3711

pointer was created.
*/

3712

}

3713

3714

/* Record the
offsets of BINFO and its base subobjects.

*/

3715

record_subobject_offsets
(binfo,

3716

BINFO_OFFSET (binfo),

3717

offsets,

3718

/*vbases_p=*/
0);

3719

3720

return
next_field;

3721

}

空的基类最好能放在偏移量为
0
(因为它们可以和主要基类共享空间)。在
G++v.3.4,
版本以后,空的基类总是被强制放在偏移量为
0
的地方。

3570

static
bool

3571

layout_empty_base

(tree binfo, tree eoc,
splay_tree offsets)
in

class.c

3572

{

3573

tree alignment;

3574

tree basetype = BINFO_TYPE (binfo);

3575

bool atend = false;

3576

3577

/* This routine
should only be used for empty classes.

*/

3578

my_friendly_assert (is_empty_class
(basetype), 20000321);

3579

alignment = ssize_int (CLASSTYPE_ALIGN_UNIT
(basetype));

3580

3581

if (!integer_zerop

(BINFO_OFFSET (binfo)))

3582

{

3583

if (abi_version_at_least (2))

3584

propagate_binfo_offsets

3585

(binfo, size_diffop
(size_zero_node, BINFO_OFFSET (binfo)));

3586

else if (warn_abi

)

3587

warning ("offset of empty base `%T'
may not be ABI-compliant and may"

3588

"change in a future version
of GCC",

3589

BINFO_TYPE (binfo));

3590

}

3591

3592

/* This is an empty
base class. We first try to put it at offset

3593

zero.
*/

3594

if (layout_conflict_p
(binfo,

3595

BINFO_OFFSET (binfo),

3596

offsets,

3597

/*vbases_p=*/
0))

3598

{

3599

/* That didn't
work. Now, we move forward from the next

3600

available spot in the
class.
*/

3601

atend = true;

3602

propagate_binfo_offsets
(binfo, convert (ssizetype, eoc));

3603

while
(1)

3604

{

3605

if (!layout_conflict_p
(binfo,

3606

BINFO_OFFSET (binfo),

3607

offsets,

3608

/*vbases_p=*/
0))

3609

/* We finally
found a spot where there's no overlap.

*/

3610

break
;

3611

3612

/* There's
overlap here, too. Bump along to the next spot.

*/

3613

propagate_binfo_offsets
(binfo, alignment);

3614

}

3615

}

3616

return
atend;

3617

}

如果偏移量为
0
的地方已经被同样的类型占据了,这个空的基类就要被放在上面计算出来的偏移量为
eoc

的地方。如果
eoc

也被占据了,把偏移量加上对齐量再尝试,直到这个空的基类可以被放置。注意到如果该空的基类不能放在偏移量为
0
的地方,该函数返回非
0
值。这时,即便该类包含的只是空基类,也被视为非空。不过即便该空基类被放在偏移量为
0
的位置,这也不保证该类是空的。考虑以下例子:

class
A {};

class
B: public
A {};

class
C: public
A, B {};

基类
B
可以放在
C
中偏移量为
0
的地方,但是它的基类
A
不能放在偏移量为
0
的地方,因为
C
的基类
A
已经在那里了。
C
,按上面的规则,是非空类。
empty_base_at_nonzero_offset_p

检查是否有空基类具有非
0
的偏移量。

3702
行的注释解释了为什么不能为空的基类构建
FIELD_DECL
节点。最后,在解决了冲突之后,需要以下函数把偏移量更新入伸展树。

3420

static
void

3421

record_subobject_offsets

(tree type,
in

class.c

3422

tree offset,

3423

splay_tree offsets,

3424

int vbases_p)

3425

{

3426

walk_subobject_offsets
(type, record_subobject_offset
, offset,

3427

offsets, /*max_offset=*/
NULL_TREE, vbases_p);

3428

}

注意我们仅记录空基类的偏移量。

3168

static
int

3169

record_subobject_offset

(tree type, tree
offset, splay_tree offsets)
in

class.c

3170

{

3171

splay_tree_node n;

3172

3173

if (!is_empty_class (type))

3174

return
0;

3175

3176

/* Record the
location of this empty object in OFFSETS.

*/

3177

n = splay_tree_lookup (offsets,
(splay_tree_key) offset);

3178

if (!n)

3179

n = splay_tree_insert (offsets,

3180

(splay_tree_key) offset,

3181

(splay_tree_value) NULL_TREE);

3182

n->value = ((splay_tree_value)

3183

tree_cons (NULL_TREE,

3184

type,

3185

(tree)
n->value));

3186

3187

return
0;

3188

}

在放置了所有的基类之后,接着是数据成员。记得对于非空基类,它们的
FIELD_DECL
被创建并位于
non_static_data_members

之前链入
TYPE_FIELDS
链,因此下面的
FOR

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