在上面854行,rli->t是正在被布局的类的树节点,能到这里,field一定是一个FIELD_DECL。如果rli->t不是一个RECORD_TYPE,在C++里,它一定是一个代表union的节点。它有和class及struct不同的布局方案。
778 static void
779 place_union_field (record_layout_info rli, tree field) in stor-layout.c
780 {
781 update_alignment_for_field (rli, field, /*known_align=*/0);
782
783 DECL_FIELD_OFFSET (field) = size_zero_node;
784 DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
785 SET_DECL_OFFSET_ALIGN (field, BIGGEST_ALIGNMENT);
786
787 /* We assume the union's size will be a multiple of a byte so we don't
788 bother with BITPOS. */
789 if (TREE_CODE (rli->t) == UNION_TYPE)
790 rli->offset = size_binop (MAX_EXPR, rli->offset, DECL_SIZE_UNIT (field));
791 else if (TREE_CODE (rli->t) == QUAL_UNION_TYPE)
792 rli->offset = fold (build (COND_EXPR, sizetype,
793 DECL_QUALIFIER (field),
794 DECL_SIZE_UNIT (field), rli->offset));
795 }
函数update_alignment_for_field更新rli中的各个有关对齐的域,并返回给field 的对齐量。注意在上面785行,BIGGEST_ALIGNMENT,对于x86是128。
687 update_alignment_for_field (record_layout_info rli, tree field, in stor-layout.c
688 unsigned int known_align)
689 {
690 /* The alignment required for FIELD. */
691 unsigned int desired_align;
692 /* The type of this field. */
693 tree type = TREE_TYPE (field);
694 /* True if the field was explicitly aligned by the user. */
695 bool user_align;
696 bool is_bitfield;
697
698 /* Lay out the field so we know what alignment it needs. */
699 layout_decl (field, known_align);
2.2.3.1.5.2.2.5.1. FIELD_DECL的布局
在前面,我们看到为变量,参数及函数返回值声明创建节点的时候,layout_decl就会被调用。这个函数会为节点设置大小,模式和对齐量。然而在build_decl中,FIELD_DECL没有被立即布局,它延后到现在。注意到在这里known_align是0,意味着“对齐量随你喜欢”。
352 void
353 layout_decl (tree decl, unsigned int known_align) in stor-layout.c
354 {
355 tree type = TREE_TYPE (decl);
356 enum tree_code code = TREE_CODE (decl);
357 rtx rtl = NULL_RTX;
358
359 if (code == CONST_DECL)
360 return;
361 else if (code != VAR_DECL && code != PARM_DECL && code != RESULT_DECL
362 && code != TYPE_DECL && code != FIELD_DECL)
363 abort ();
364
365 rtl = DECL_RTL_IF_SET (decl);
366
367 if (type == error_mark_node)
368 type = void_type_node;
369
370 /* Usually the size and mode come from the data type without change,
371 however, the front-end may set the explicit width of the field, so its
372 size may not be the same as the size of its type. This happens with
373 bitfields, of course (an `int' bitfield may be only 2 bits, say), but it
374 also happens with other fields. For example, the C++ front-end creates
375 zero-sized fields corresponding to empty base classes, and depends on
376 layout_type setting DECL_FIELD_BITPOS correctly for the field. Set the
377 size in bytes from the size in bits. If we have already set the mode,
378 don't set it again since we can be called twice for FIELD_DECLs. */
379
380 TREE_UNSIGNED (decl) = TREE_UNSIGNED (type);
381 if (DECL_MODE (decl) == VOIDmode)
382 DECL_MODE (decl) = TYPE_MODE (type);
383
384 if (DECL_SIZE (decl) == 0)
385 {
386 DECL_SIZE (decl) = TYPE_SIZE (type);
387 DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (type);
388 }
389 else if (DECL_SIZE_UNIT (decl) == 0)
390 DECL_SIZE_UNIT (decl)
391 = convert (sizetype, size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl),
392 bitsize_unit_node));
函数的第一部分仅是按照伴随的TYPE节点,初始化DECL节点的部分域。
在下面402行,如果FIELD_DECL是位域,DECL_BIT_FIELD返回非零值。
layout_decl (continue)
394 if (code != FIELD_DECL)
395 /* For non-fields, update the alignment from the type. */
396 do_type_align (type, decl);
397 else
398 /* For fields, it's a bit more complicated... */
399 {
400 bool old_user_align = DECL_USER_ALIGN (decl);
401
402 if (DECL_BIT_FIELD (decl))
403 {
404 DECL_BIT_FIELD_TYPE (decl) = type;
405
406 /* A zero-length bit-field affects the alignment of the next
407 field. */
408 if (integer_zerop (DECL_SIZE (decl))
409 && ! DECL_PACKED (decl)
410 && ! (*targetm.ms_bitfield_layout_p) (DECL_FIELD_CONTEXT (decl)))
411 {
412 #ifdef PCC_BITFIELD_TYPE_MATTERS
413 if (PCC_BITFIELD_TYPE_MATTERS)
414 do_type_align (type, decl);
415 else
416 #endif
417 {
418 #ifdef EMPTY_FIELD_BOUNDARY
419 if (EMPTY_FIELD_BOUNDARY > DECL_ALIGN (decl))
420 {
421 DECL_ALIGN (decl) = EMPTY_FIELD_BOUNDARY;
422 DECL_USER_ALIGN (decl) = 0;
423 }
424 #endif
425 }
426 }
在位域声明中,有声明大小为0的特殊情况(408行)。如果该域不要求紧凑布局在比特边界,那么需要进一步检查这个聚集类的属性。注意在410行,DECL_FIELD_CONTEXT获取包含这个FIELD_DECL的UNION_TYPE或RECORD_TYPE节点。对象targetm是目标平台相关的,对于x86系统,函数指针ms_bitfield_layout_p指向ix86_ms_bitfield_layout_p。
[2]对此的解释如下:
这个目标平台钩子返回