GCC-3.4.6源代码学习笔记(139-续1)
来源:互联网 发布:norse attack map源码 编辑:程序博客网 时间:2024/06/08 09:23
layout_class_type (continue)
4664 /* Create a pointerto our virtual function table. */
4665 vptr = create_vtable_ptr(t, virtuals_p);
4666
4667 /* The vptr isalways 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) inclass.c
4234 {
4235 tree fn;
4236
4237 /* Collect thevirtual 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'tfind an appropriate base class, create a new field
4252 here. Even if there weren'tany new virtual functions, we might need a
4253 new virtual function table ifwe're supposed to include vptrs in
4254 all classes that needthem. */
4255 if (!TYPE_VFIELD (t) && (*virtuals_p|| TYPE_CONTAINS_VPTR_P (t)))
4256 {
4257 /* We build thisdecl with vtbl_ptr_type_node, which is a
4258 `vtable_entry_type*'. Itmight seem more precise to use
4259 `vtable_entry_type (*)[N]'where N is the number of firtual
4260 functions. However, thatwould require the vtable pointer in
4261 base classes to have adifferent type than the vtable pointer
4262 in derived classes. We could make that happen,but that
4263 still wouldn't solve all theproblems. In particular, the
4264 type-based alias analysiscode would decide that assignments
4265 to the base class vtablepointer can't alias assignments to
4266 the derived class vtable pointer, sincethey have different
4267 types. Thus, in a derivedclass destructor, where the base
4268 class constructor wasinlined, we could generate bad code for
4269 setting up the vtablepointer.
4270
4271 Therefore, we use one typefor all vtable pointers. We still
4272 use a type-correct type;it's just doesn't indicate the array
4273 bounds. That's better thanusing `void*' or some such; it's
4274 cleaner, and it let's the aliasanalysis code know that these
4275 stores cannot alias storesto 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 isnon-empty. */
4288 CLASSTYPE_EMPTY_P (t) = 0;
4289
4290 if (CLASSTYPE_N_BASECLASSES (t))
4291 /* If therewere any baseclasses, they can't possibly be at
4292 offset zero any more,because that's where the vtable
4293 pointer is. So, convertingto a base class is going to
4294 take work. */
4295 TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (t) =1;
4296
4297 returnfield;
4298 }
4299
4300 returnNULL_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 /* BuildFIELD_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_inforli, inclass.c
3731 splay_tree offsets, tree*next_field)
3732 {
3733 /* Chain to holdall 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 baseclass 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 therest 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 primarybase was already allocated above, so we don't
3752 need to allocate it againhere. */
3753 if (base_binfo == CLASSTYPE_PRIMARY_BINFO(t))
3754 continue;
3755
3756 /* Virtual basesare added at the end (a primary virtual base
3757 will have already beenadded). */
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, inclass.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 isnow reported in xref_tag, thus giving better
3637 location information. */
3638 returnnext_field;
3639
3640 /* Place the baseclass. */
3641 if (!is_empty_class (basetype))
3642 {
3643 tree decl;
3644
3645 /* The containingclass is non-empty because it has a non-empty
3646 base class. */
3647 CLASSTYPE_EMPTY_P (t) = 0;
3648
3649 /* Create theFIELD_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 morethan one try if we
3660 have a hard time placing thefield without putting two
3661 objects of the same type atthe same address. */
3662 layout_nonempty_base_or_field(rli, decl, binfo, offsets);
3663 /* Add the newFIELD_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 thepurposes 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 thefield. It may take more than one try if we have
3487 a hard time placing the field without puttingtwo objects of the
3488 same type at the sameaddress. */
3489 while (1)
3490 {
3491 structrecord_layout_info_s old_rli = *rli;
3492
3493 /* Place thisfield. */
3494 place_field(rli, decl);
3495 offset = byte_position(decl);
3496
3497 /* We have tocheck to see whether or not there is already
3498 something of the same typeat the offset we're about to use.
3499 For example, consider:
3500
3501 struct S {};
3502 struct T : public S { inti; };
3503 struct U : public S, publicT {};
3504
3505 Here, we put S at offset zero in U. Then,we can't put T at
3506 offset zero -- its Scomponent would be at the same address
3507 as the S we alreadyallocated. So, we have to skip ahead.
3508 Since all data members,including those whose type is an
3509 empty class, have nonzerosize, any overlap can happen only
3510 with a direct or indirectbase-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 didnot 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 offthe size allocated to this field. That puts us
3524 at the first place wecould have put the field with
3525 proper alignment. */
3526 *rli = old_rli;
3527
3528 /* Bump up bythe 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 noconflict. We're done laying out this field. */
3538 break;
3539 }
3540
3541 /* Now that we knowwhere it will be placed, update its
3542 BINFO_OFFSET. */
3543 if (binfo && CLASS_TYPE_P (BINFO_TYPE(binfo)))
3544 /* Indirectvirtual bases may have a nonzero BINFO_OFFSET at
3545 this point because theirBINFO_OFFSET is copied from another
3546 hierarchy. Therefore, we maynot 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) intree.c
1177 {
1178 returnbyte_from_pos (DECL_FIELD_OFFSET (field),
1179 DECL_FIELD_BIT_OFFSET (field));
1180 }
在C++里,在布局过程中,空的基类可能不占空间。例如:
class A {}; sizeof (A)给出1,但在以下的语句中:
class B: publicA { 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, inclass.c
3436 tree offset,
3437 splay_tree offsets,
3438 int vbases_p)
3439 {
3440 splay_tree_node max_node;
3441
3442 /* Get the node inOFFSETS that indicates the maximum offset where
3443 an empty subobject islocated. */
3444 max_node = splay_tree_max (offsets);
3445 /* If there aren'tany 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, treeoffset, splay_tree offsets) inclass.c
3195 {
3196 splay_tree_node n;
3197 tree t;
3198
3199 if (!is_empty_class (type))
3200 return 0;
3201
3202 /* Record thelocation 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, inclass.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 isbigger 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 /* Avoidrecursing 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 /* Iteratethrough 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 cannotrely on BINFO_OFFSET being set for the base
3289 class yet, but theoffsets for direct non-virtual
3290 bases can be calculatedby 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 returnr;
3306 }
3307
3308 if (abi_version_at_least (2))
3309 {
3310 tree vbase;
3311
3312 /* Iterate through the virtual base classes ofTYPE. In G++
3313 3.2, we included virtualbases in the direct base class
3314 loop above, which resultsin incorrect results; the
3315 correct offsets forvirtual bases are only known when
3316 working with the mostderived 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 returnr;
3333 }
3334 else
3335 {
3336 /* We stillhave to walk the primary base, if it is
3337 virtual. (If it isnon-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 returnr;
3348 }
3349 }
3350 }
3351
3352 /* Iteratethrough 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 returnr;
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 /* Avoidrecursing 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 througheach of the elements in the array. */
3388 for (index= size_zero_node;
3389 /* G++ 3.2had 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 returnr;
3403 offset = size_binop (PLUS_EXPR, offset,
3404 TYPE_SIZE_UNIT(TREE_TYPE (type)));
3405 /* If this newOFFSET is bigger than the MAX_OFFSET, then
3406 there's no point initerating through the remaining
3407 elements of thearray. */
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 someplatforms (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-emptyclass "has no proper base class that is empty,
3679 not morally virtual, and atan 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 checkabove (used in G++ 3.2) is insufficient because
3685 an empty class placed atoffset zero might itself have an
3686 empty base at a nonzerooffset. */
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 beconsidered nearly empty in a "
3698 "future version ofGCC", t);
3699 }
3700 }
3701
3702 /* We do notcreate a FIELD_DECL for empty base classes because
3703 it might overlap some otherfield. We want to be able to
3704 create CONSTRUCTORs for theclass by iterating over the
3705 FIELD_DECLs, and the backend does not handle overlapping
3706 FIELD_DECLs. */
3707
3708 /* An emptyvirtual base causes a class to be non-empty
3709 -- but in that case we donot need to clear CLASSTYPE_EMPTY_P
3710 here because that wasalready done when the virtual table
3711 pointer was created. */
3712 }
3713
3714 /* Record theoffsets of BINFO and its base subobjects. */
3715 record_subobject_offsets(binfo,
3716 BINFO_OFFSET (binfo),
3717 offsets,
3718 /*vbases_p=*/0);
3719
3720 returnnext_field;
3721 }
空的基类最好能放在偏移量为0(因为它们可以和主要基类共享空间)。在G++v.3.4,版本以后,空的基类总是被强制放在偏移量为0的地方。
3570 static bool
3571 layout_empty_base (tree binfo, tree eoc,splay_tree offsets) inclass.c
3572 {
3573 tree alignment;
3574 tree basetype = BINFO_TYPE (binfo);
3575 bool atend = false;
3576
3577 /* This routineshould 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 versionof GCC",
3589 BINFO_TYPE (binfo));
3590 }
3591
3592 /* This is an emptybase 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'twork. Now, we move forward from the next
3600 available spot in theclass. */
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 finallyfound a spot where there's no overlap. */
3610 break;
3611
3612 /* There'soverlap 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, inclass.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, treeoffset, splay_tree offsets) inclass.c
3170 {
3171 splay_tree_node n;
3172
3173 if (!is_empty_class (type))
3174 return 0;
3175
3176 /* Record thelocation 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-续1)
- GCC-3.4.6源代码学习笔记(139-续2)
- GCC-3.4.6源代码学习笔记(10续1)
- GCC-3.4.6源代码学习笔记(25续1)
- GCC-3.4.6源代码学习笔记(26续1)
- GCC-3.4.6源代码学习笔记(141-续1)
- GCC-3.4.6源代码学习笔记(142-续1)
- GCC-3.4.6源代码学习笔记(147-续1)
- GCC-3.4.6源代码学习笔记(139)
- GCC-3.4.6源代码学习笔记(10续2)
- GCC-3.4.6源代码学习笔记(10续3)
- GCC-3.4.6源代码学习笔记(10续4)
- GCC-3.4.6源代码学习笔记(19续)
- GCC-3.4.6源代码学习笔记(24续)
- GCC-3.4.6源代码学习笔记(25续2)
- GCC-3.4.6源代码学习笔记(26续2)
- GCC-3.4.6源代码学习笔记(48续)
- GCC-3.4.6源代码学习笔记(48续2)
- 如何联机调试和发布程序(99$)
- 字符集与编码
- CMS gc实践总结
- 50张极面全景画 [摄影作品] [转]
- 辛辛苦苦做了CRM,一切都OK了,公司突然说不用了。不甘心,自己继续。
- GCC-3.4.6源代码学习笔记(139-续1)
- 增加home空间
- 一:PHP语言基础_自定义函数
- 一:PHP语言基础_自定义函数
- 一:PHP语言基础_自定义函数
- linux 下安装eclipse无法启动,找不到jdk的解决办法
- 二:字符串和正则表达式_字符串处理
- 二:字符串和正则表达式_字符串处理
- 二:字符串和正则表达式_字符串处理