注意参数 base 在我们的例子中指向的 BOUND_TEMPLATE_TEMPLATE_PARM 节点, access 是 access_public_node 。
2242 tree
2243 finish_base_specifier (tree base, tree access, bool virtual_p) in semantics.c
2244 {
2245 tree result;
2246
2247 if (base == error_mark_node)
2248 {
2249 error ("invalid base-class specification");
2250 result = NULL_TREE;
2251 }
2252 else if (! is_aggr_type (base, 1))
2253 result = NULL_TREE;
2254 else
2255 {
2256 if (cp_type_quals (base) != 0)
2257 {
2258 error ("base class `%T' has cv qualifiers", base);
2259 base = TYPE_MAIN_VARIANT (base);
2260 }
2261 result = build_tree_list (access, base);
2262 TREE_VIA_VIRTUAL (result) = virtual_p;
2263 }
2264
2265 return result;
2266 }
在为基类构建了节点后,在前端中这些基类被串接在一起来代表 base-clause 。
5.12.4.2.3.2.1. 填充 binfo
从 cp_parser_base_clause 返回,在 cp_parser_class_head 的 12339 行,由 bases 指向先前所构建的节点 BOUND_TEMPLATE_TEMPLATE_PARM ,而 type 则是代表“ SmallObject ”的 RECORD_TYPE 。记得在构建这个 RECORD_TYPE 时,还构建了一个空的 binfo 节点。现在这个节点将根据刚才解析的 base-clause 来填充。
9615 void
9616 xref_basetypes (tree ref, tree base_list) in decl.c
9617 {
9618 /* In the declaration `A : X, Y, ... Z' we mark all the types
9619 (A, X, Y, ..., Z) so we can check for duplicates. */
9620 tree *basep;
9621
9622 int i;
9623 enum tag_types tag_code;
9624
9625 if (ref == error_mark_node)
9626 return ;
9627
9628 if (TREE_CODE (ref) == UNION_TYPE)
9629 {
9630 error ("derived union `%T' invalid", ref);
9631 return ;
9632 }
9633
9634 tag_code = (CLASSTYPE_DECLARED_CLASS (ref) ? class_type : record_type);
9635
9636 /* First, make sure that any templates in base-classes are
9637 instantiated. This ensures that if we call ourselves recursively
9638 we do not get confused about which classes are marked and which
9639 are not. */
9640 basep = &base_list;
9641 while (*basep)
9642 {
9643 tree basetype = TREE_VALUE (*basep);
9644 if (!(processing_template_decl && uses_template_parms (basetype))
9645 && !complete_type_or_else (basetype, NULL))
9646 /* An incomplete type. Remove it from the list. */
9647 *basep = TREE_CHAIN (*basep);
9648 else
9649 basep = &TREE_CHAIN (*basep);
9650 }
9651
9652 SET_CLASSTYPE_MARKED (ref);
9653 i = list_length (base_list);
9654 if (i)
9655 {
9656 tree binfo = TYPE_BINFO (ref);
9657 tree binfos = make_tree_vec (i);
9658 tree accesses = make_tree_vec (i);
9659
9660 BINFO_BASETYPES (binfo) = binfos;
9661 BINFO_BASEACCESSES (binfo) = accesses;
9662
9663 for (i = 0; base_list; base_list = TREE_CHAIN (base_list))
9664 {
9665 tree access = TREE_PURPOSE (base_list);
9666 int via_virtual = TREE_VIA_VIRTUAL (base_list);
9667 tree basetype = TREE_VALUE (base_list);
9668 tree base_binfo;
9669
9670 if (access == access_default_node)
9671 /* The base of a derived struct is public by default. */
9672 access = (tag_code == class_type
9673 ? access_private_node : access_public_node);
9674
9675 if (basetype && TREE_CODE (basetype) == TYPE_DECL)
9676 basetype = TREE_TYPE (basetype);
9677 if (!basetype
9678 || (TREE_CODE (basetype) != RECORD_TYPE
9679 && TREE_CODE (basetype) != TYPENAME_TYPE
9680 && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
9681 && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM))
9682 {
9683 error ("base type `%T' fails to be a struct or class type",
9684 basetype);
9685 continue ;
9686 }
9687
9688 if (CLASSTYPE_MARKED (basetype))
9689 {
9690 if (basetype == ref)
9691 error ("recursive type `%T' undefined", basetype);
9692 else
9693 error ("duplicate base type `%T' invalid", basetype);
9694 continue ;
9695 }
9696
9697 if (TYPE_FOR_JAVA (basetype)
9698 && (current_lang_depth () == 0))
9699 TYPE_FOR_JAVA (ref) = 1;
9700
9701 if (CLASS_TYPE_P (basetype))
9702 {
9703 base_binfo = TYPE_BINFO (basetype);
9704 /* This flag will be in the binfo of the base type, we must
9705 clear it after copying the base binfos. */
9706 BINFO_DEPENDENT_BASE_P (base_binfo)
9707 = dependent_type_p (basetype);
9708 }
9709 else
9710 base_binfo = make_binfo (size_zero_node, basetype,
9711 NULL_TREE, NULL_TREE);
9712
9713 TREE_VEC_ELT (binfos, i) = base_binfo;
9714 TREE_VEC_ELT (accesses, i) = access;
9715 /* This flag will be in the binfo of the base type, we must
9716 clear it after copying the base binfos. */
9717 TREE_VIA_VIRTUAL (base_binfo) = via_virtual;
9718
9719 SET_CLASSTYPE_MARKED (basetype);
9720
9721 /* We are free to modify these bits because they are meaningless
9722 at top level, and BASETYPE is a top-level type. */
9723 if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
9724 {
9725 TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;
9726 /* Converting to a virtual base class requires looking
9727 up the offset of the virtual base. */
9728 TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
9729 }
9730
9731 if (CLASS_TYPE_P (basetype))
9732 {
9733 TYPE_HAS_NEW_OPERATOR (ref)
9734 |= TYPE_HAS_NEW_OPERATOR (basetype);
9735 TYPE_HAS_ARRAY_NEW_OPERATOR (ref)
9736 |= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype);
9737 TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
9738 /* If the base-class uses multiple inheritance, so do we. */
9739 TYPE_USES_MULTIPLE_INHERITANCE (ref)
9740 |= TYPE_USES_MULTIPLE_INHERITANCE (basetype);
9741 /* Likewise, if converting to a base of the base may require
9742 code, then we may need to generate code to convert to a
9743 base as well. */
9744 TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref)
9745 |= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype);
9746 }
9747 i++;
9748 }
9749 if (i)
9750 TREE_VEC_LENGTH (accesses) = TREE_VEC_LENGTH (binfos) = i;
9751 else
9752 BINFO_BASEACCESSES (binfo) = BINFO_BASETYPES (binfo) = NULL_TREE;
9753
9754 if (i > 1)
9755 {
9756 TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
9757 /* If there is more than one non-empty they cannot be at the same
9758 address. */
9759 TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
9760 }
9761 }
9762
9763 /* Copy the base binfos, collect the virtual bases and set the
9764 inheritance order chain. */
9765 copy_base_binfos (TYPE_BINFO (ref), ref, NULL_TREE);
9766 CLASSTYPE_VBASECLASSES (ref) = nreverse (CLASSTYPE_VBASECLASSES (ref));
9767
9768 if (TYPE_FOR_JAVA (ref))
9769 {
9770 if (TYPE_USES_MULTIPLE_INHERITANCE (ref))
9771 error ("Java class '%T' cannot have multiple bases", ref);
9772 if (CLASSTYPE_VBASECLASSES (ref))
9773 error ("Java class '%T' cannot have virtual bases", ref);
9774 }
9775
9776 /* Unmark all the types. */
9777 while (i--)
9778 {
9779 tree basetype = BINFO_TYPE (BINFO_BASETYPE (TYPE_BINFO (ref), i));
9780
9781 CLEAR_CLASSTYPE_MARKED (basetype);
9782 if (CLASS_TYPE_P (basetype))
9783 {
9784 TREE_VIA_VIRTUAL (TYPE_BINFO (basetype)) = 0;
9785 BINFO_DEPENDENT_BASE_P (TYPE_BINFO (basetype)) = 0;
9786 }
9787 }
9788 CLEAR_CLASSTYPE_MARKED (ref);
9789 }
注意在 9645 行,在 base-clause 不能出现未完成的类。而在 9765 行,基类本身有可能从其他类派生,因此需要深拷贝所有相关的 binfo 。看到对于指定的类, binfo 节点,以深度优先、由左至右为序,形成了一个链表。
577 tree
578 copy_base_binfos (tree binfo, tree t, tree prev) in tree.c
579 {
580 tree binfos = BINFO_BASETYPES (binfo);
581 int n, ix;
582
583 if (prev)
584 TREE_CHAIN (prev) = binfo;
585 prev = binfo;
586
587 if (binfos == NULL_TREE)
588 return prev;
589
590 n = TREE_VEC_LENGTH (binfos);
591
592 /* Now copy the structure beneath BINFO. */
593 for (ix = 0; ix != n; ix++)
594 {
595 tree base_binfo = TREE_VEC_ELT (binfos, ix);
596 tree new_binfo = NULL_TREE;
597
598 if (!CLASS_TYPE_P (BINFO_TYPE (base_binfo)))
599 {
600 my_friendly_assert (binfo == TYPE_BINFO (t), 20030204);
601
602 new_binfo = base_binfo;
603 TREE_CHAIN (prev) = new_binfo;
604 prev = new_binfo;
605 BINFO_INHERITANCE_CHAIN (new_binfo) = binfo;
606 BINFO_DEPENDENT_BASE_P (new_binfo) = 1;
607 }
608 else if (TREE_VIA_VIRTUAL (base_binfo))
609 {
610 new_binfo = purpose_member (BINFO_TYPE (base_binfo),
611 CLASSTYPE_VBASECLASSES (t));
612 if (new_binfo)
613 new_binfo = TREE_VALUE (new_binfo);
614 }
615
616 if (!new_binfo)
617 {
618 new_binfo = make_binfo (BINFO_OFFSET (base_binfo),
619 base_binfo, NULL_TREE,
620 BINFO_VIRTUALS (base_binfo));
621 prev = copy_base_binfos (new_binfo, t, prev);
622 if (TREE_VIA_VIRTUAL (base_binfo))
623 {
624 CLASSTYPE_VBASECLASSES (t)
625 = tree_cons (BINFO_TYPE (new_binfo), new_binfo,
626 CLASSTYPE_VBASECLASSES (t));
627 TREE_VIA_VIRTUAL (new_binfo) = 1;
628 BINFO_INHERITANCE_CHAIN (new_binfo) = TYPE_BINFO (t);
629 }
630 else
631 BINFO_INHERITANCE_CHAIN (new_binfo) = binfo;
632 }
633 TREE_VEC_ELT (binfos, ix) = new_binfo;
634 }
635
636 return prev;
637 }
虚拟继承是例外,在这个情形下,被虚拟继承的基类只能有一个实例出现在派生树中。因此如果该实例已经存在,创建一个引用而不是拷贝(注意每个类都有自己的派生树)。例如:
class A { … };
class B: virtual public A { … };
class C: virtual public A { … };
class D: public B, C { … };
在类 D 中,仅含有一个 A 的 binfo 。而在类 B 和 C 中,同样都有一个 A 的 binfo (类 D , C , B 具有不同的派生树,在 D 的派生树中,有 C 和 B 的 binfo 的拷贝)。
注意到对于 BOUND_TEMPLATE_TEMPLATE_PARM. 节点, CLASS_TYPE_P 返回 false 。这是隐含构建的聚合类型,不需要真正的拷贝。那么“ SmallObject ”和“ ThreadingModel ”的 binfo 填充如下。
( 点此打开 )
图 114 :填充 binfo
那么接下来,解析器将处理 class-definition 部分。它与我们在前面章节所看到处理过程几乎一样。这里我们跳过它。