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
。
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
。
相关文章推荐
- GCC-3.4.6源代码学习笔记(139-续2)
- GCC-3.4.6源代码学习笔记(139)
- GCC-3.4.6源代码学习笔记(45)
- GCC-3.4.6源代码学习笔记(140 - 续)
- GCC-3.4.6源代码学习笔记 当前目录
- GCC-3.4.6源代码学习笔记(94)
- GCC-3.4.6源代码学习笔记 (100)
- GCC-3.4.6源代码学习笔记(72)
- GCC-3.4.6源代码学习笔记(40)
- GCC-3.4.6源代码学习笔记(51)
- GCC-3.4.6源代码学习笔记(119)
- GCC-3.4.6源代码学习笔记(1)
- GCC-3.4.6源代码学习笔记(82)
- GCC-3.4.6源代码学习笔记(165)
- GCC-3.4.6源代码学习笔记(112)
- GCC-3.4.6源代码学习笔记(61)
- GCC-3.4.6源代码学习笔记(31)
- GCC-3.4.6源代码学习笔记(37)
- GCC-3.4.6源代码学习笔记(149)
- GCC-3.4.6源代码学习笔记(48续)