OK. Now let’s see the output of GCC for our instance 1.
Example 1:
Vtable for C
C::_ZTV1C: 12u entries
0 0u // vbase offset
4 0u // vcall offset
8 (int (*)(...))0
12 (int (*)(...))(& _ZTI1C)
16 C ::_ZTcv0_n12_v0_n16_N1C1fEv // slot for C::B1::A::f
20 C ::f // slot for C::f
24 -4u
28 -4u
32 (int (*)(...))-0x000000004
36 (int (*)(...))(& _ZTI1C)
40 C ::_ZTcvn4_n12_v0_n16_N1C1fEv // slot for C::B2::A::f
44 C ::_ZTchn4_h4_N1C1fEv // slot for C::B2::f
… // no VTT for A
VTT for B1
B1::_ZTT2B1: 2u entries
0 ((& B1::_ZTV2B1) + 16u)
4 ((& B1::_ZTV2B1) + 16u)
…
VTT for B2
B2::_ZTT2B2: 2u entries
0 ((& B2::_ZTV2B2) + 16u)
4 ((& B2::_ZTV2B2) + 16u)
…
Construction vtable for B1 (0xb7f2d980 instance) in C
C::_ZTC1C0_2B1: 6u entries
0 0u
4 0u
8 (int (*)(...))0
12 (int (*)(...))(& _ZTI2B1)
16 B1::_ZTcv0_n12_v0_n16_N2B11fEv // C::B1::f
20 B1::f
Construction vtable for B2 (0xb7f2da00 instance) in C
C::_ZTC1C4_2B2: 10u entries
0 -4u
4 0u
8 (int (*)(...))0
12 (int (*)(...))(& _ZTI2B2)
16 B2::_ZTcv0_n12_v0_n16_N2B21fEv // C::B2::f
20 B2::f
24 4u
28 (int (*)(...))4
32 (int (*)(...))(& _ZTI2B2)
36 B2::_ZTcv0_n12_v0_n16_N2B21fEv // C::B2::f
VTT for C
C::_ZTT1C: 7u entries
0 ((& C::_ZTV1C) + 16u) // vptr for C
4 ((& C::_ZTC1C0_2B1) + 16u) // construction vtable used for B1
8 ((& C::_ZTC1C0_2B1) + 16u) // construction vtable used for B1::A
12 ((& C::_ZTC1C4_2B2) + 16u) // construction vtable used for B2
16 ((& C::_ZTC1C4_2B2) + 36u) // construction vtable used for B2::A
20 ((& C::_ZTV1C) + 16u) // vptr for secondary vtable of B2
24 ((& C::_ZTV1C) + 40u) // vptr for secondary vtable of A
Constructing VTT is done by below function.
6829 static void
6830 build_vtt (tree t) in class.c
6831 {
6832 tree inits;
6833 tree type;
6834 tree vtt;
6835 tree index;
6836
6837 /* Build up the initializers for the VTT. */
6838 inits = NULL_TREE;
6839 index = size_zero_node;
6840 build_vtt_inits (TYPE_BINFO (t), t, &inits, &index);
6841
6842 /* If we didn't need a VTT, we're done. */
6843 if (!inits)
6844 return ;
6845
6846 /* Figure out the type of the VTT. */
6847 type = build_index_type (size_int (list_length (inits) - 1));
6848 type = build_cplus_array_type (const_ptr_type_node, type);
6849
6850 /* Now, build the VTT object itself. */
6851 vtt = build_vtable (t, get_vtt_name (t), type);
6852 initialize_array (vtt, inits);
6853 /* Add the VTT to the vtables list. */
6854 TREE_CHAIN (vtt) = TREE_CHAIN (CLASSTYPE_VTABLES (t));
6855 TREE_CHAIN (CLASSTYPE_VTABLES (t)) = vtt;
6856
6857 dump_vtt (t, vtt);
6858 }
So for our example, for class B1, B2 and C, VTT is expected, and its body is constructed by build_vtt_init bleow, in which argument binfo is the binfo of the most derived class, t is the most derived class, and index is the last index the VTT entries occupied.
6892 static tree *
6893 build_vtt_inits (tree binfo, tree t, tree* inits, tree* index) in class.c
6894 {
6895 int i;
6896 tree b;
6897 tree init;
6898 tree secondary_vptrs;
6899 int top_level_p = same_type_p (TREE_TYPE (binfo), t);
6900
6901 /* We only need VTTs for subobjects with virtual bases. */
6902 if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
6903 return inits;
6904
6905 /* We need to use a construction vtable if this is not the primary
6906 VTT. */
6907 if (!top_level_p)
6908 {
6909 build_ctor_vtbl_group (binfo, t);
6910
6911 /* Record the offset in the VTT where this sub-VTT can be found. */
6912 BINFO_SUBVTT_INDEX (binfo) = *index;
6913 }
6914
6915 /* Add the address of the primary vtable for the complete object. */
6916 init = binfo_ctor_vtable (binfo);
6917 *inits = build_tree_list (NULL_TREE, init);
6918 inits = &TREE_CHAIN (*inits);
6919 if (top_level_p)
6920 {
6921 my_friendly_assert (!BINFO_VPTR_INDEX (binfo), 20010129);
6922 BINFO_VPTR_INDEX (binfo) = *index;
6923 }
6924 *index = size_binop (PLUS_EXPR, *index, TYPE_SIZE_UNIT (ptr_type_node));
6925
6926 /* Recursively add the secondary VTTs for non-virtual bases. */
6927 for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
6928 {
6929 b = BINFO_BASETYPE (binfo, i);
6930 if (!TREE_VIA_VIRTUAL (b))
6931 inits = build_vtt_inits (BINFO_BASETYPE (binfo, i), t,
6932 inits, index);
6933 }
In previous section, BINFO_VTABLE of the class is set in dfs_accumulate_vtbl_inits with vtable initializers. It is a PLUS_EXPR specifies the position in the initializers for the start point of vtable. At line 6916 above, binfo_ctor_vtable gets this expression from the class.
6865 static tree
6866 binfo_ctor_vtable (tree binfo) in class.c
6867 {
6868 tree vt;
6869
6870 while (1)
6871 {
6872 vt = BINFO_VTABLE (binfo);
6873 if (TREE_CODE (vt) == TREE_LIST)
6874 vt = TREE_VALUE (vt);
6875 if (TREE_CODE (vt) == TREE_VEC)
6876 binfo = vt;
6877 else
6878 break ;
6879 }
6880
6881 return vt;
6882 }
Above at line 6917, init returned by binfo_ctor_vtable is built in a tree_list; and at line 6917, inits points to the address of chain field of this tree_list, so in recursion at line 6931, new nodes will be added into this chain. Above argument index is the VTT index where the next element will be replaced (it is also number of bytes), at beginning it is size_zero_node .
BINFO_VPTR_INDEX holds the index in the VTT where the vptr for the subobject can be found. For the most derived class C, its vptr is saved at index 0. And to non-virtual bases, build_ctor_vtbl_group does below processing.
7098 static void
7099 build_ctor_vtbl_group (tree binfo, tree t) in class.c
7100 {
7101 tree list;
7102 tree type;
7103 tree vtbl;
7104 tree inits;
7105 tree id;
7106 tree vbase;
7107
7108 /* See if we've already created this construction vtable group. */
7109 id = mangle_ctor_vtbl_for_type (t, binfo);
7110 if (IDENTIFIER_GLOBAL_VALUE (id))
7111 return ;
7112
7113 my_friendly_assert (!same_type_p (BINFO_TYPE (binfo), t), 20010124);
7114 /* Build a version of VTBL (with the wrong type) for use in
7115 constructing the addresses of secondary vtables in the
7116 construction vtable group. */
7117 vtbl = build_vtable (t, id, ptr_type_node);
7118 list = build_tree_list (vtbl, NULL_TREE);
7119 accumulate_vtbl_inits (binfo, TYPE_BINFO (TREE_TYPE (binfo)),
7120 binfo, t, list);
7121
7122 /* Add the vtables for each of our virtual bases using the vbase in T
7123 binfo. */
7124 for (vbase = TYPE_BINFO (BINFO_TYPE (binfo));
7125 vbase;
7126 vbase = TREE_CHAIN (vbase))
7127 {
7128 tree b;
7129
7130 if (!TREE_VIA_VIRTUAL (vbase))
7131 continue ;
7132 b = copied_binfo (vbase, binfo);
7133
7134 accumulate_vtbl_inits (b, vbase, binfo, t, list);
7135 }
7136 inits = TREE_VALUE (list);
7137
7138 /* Figure out the type of the construction vtable. */
7139 type = build_index_type (size_int (list_length (inits) - 1));
7140 type = build_cplus_array_type (vtable_entry_type, type);
7141 TREE_TYPE (vtbl) = type;
7142
7143 /* Initialize the construction vtable. */
7144 CLASSTYPE_VTABLES (t) = chainon (CLASSTYPE_VTABLES (t), vtbl);
7145 initialize_array (vtbl, inits);
7146 dump_vtable (t, binfo, vtbl);
7147 }
Above at line 7109, mangle_ctor_vtbl_for_type returns the mangled name for the vtable for linkage purpose. Assertion following makes sure that only bases will go into this function. Then a new created vtable object is wrapped into a tree_list node, and at line 7119 passed to the below function as the last argument. See rtti_binfo is the binfo of qualified direct base, the function will prepare the intializers for the base.
Here accumulate_vtbl_inits handles the base in interesting and its non-virtual base in pre-order order, and then the virtual base in order of appearing within inheritance tree later in build_ctor_vblt_group . We reshow related functions in below for convenience.
7159 static void
7160 accumulate_vtbl_inits (tree binfo, in class.c
7161 tree orig_binfo,
7162 tree rtti_binfo,
7163 tree t,
7164 tree inits)
7165 {
7166 int i;
7167 int ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
7168
7169 my_friendly_assert (same_type_p (BINFO_TYPE (binfo),
7170 BINFO_TYPE (orig_binfo)),
7171 20000517);
7172
7173 /* If it doesn't have a vptr, we don't do anything. */
7174 if (!TYPE_CONTAINS_VPTR_P (BINFO_TYPE (binfo)))
7175 return ;
7176
7177 /* If we're building a construction vtable, we're not interested in
7178 subobjects that don't require construction vtables. */
7179 if (ctor_vtbl_p
7180 && !TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo))
7181 && !binfo_via_virtual (orig_binfo, BINFO_TYPE (rtti_binfo)))
7182 return ;
7183
7184 /* Build the initializers for the BINFO-in-T vtable. */
7185 TREE_VALUE (inits)
7186 = chainon (TREE_VALUE (inits),
7187 dfs_accumulate_vtbl_inits (binfo, orig_binfo,
7188 rtti_binfo, t, inits));
7189
7190 /* Walk the BINFO and its bases. We walk in preorder so that as we
7191 initialize each vtable we can figure out at what offset the
7192 secondary vtable lies from the primary vtable. We can't use
7193 dfs_walk here because we need to iterate through bases of BINFO
7194 and RTTI_BINFO simultaneously. */
7195 for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
7196 {
7197 tree base_binfo = BINFO_BASETYPE (binfo, i);
7198
7199 /* Skip virtual bases. */
7200 if (TREE_VIA_VIRTUAL (base_binfo))
7201 continue ;
7202 accumulate_vtbl_inits (base_binfo,
7203 BINFO_BASETYPE (orig_binfo, i),
7204 rtti_binfo, t,
7205 inits);
7206 }
7207 }
This time, ctor_vtbl_p at line 7167 above is true as argument t always refers to the most derived class but rtti_binfo should never. And condition at line 7179 filters out base that doesn’t derive from virutal base and non-virtual.
7212 static tree
7213 dfs_accumulate_vtbl_inits (tree binfo, in class.c
7214 tree orig_binfo,
7215 tree rtti_binfo,
7216 tree t,
7217 tree l)
7218 {
7219 tree inits = NULL_TREE;
7220 tree vtbl = NULL_TREE;
7221 int ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
7222
7223 if (ctor_vtbl_p
7224 && TREE_VIA_VIRTUAL (orig_binfo) && BINFO_PRIMARY_P (orig_binfo))
7225 {
7226 /* In the hierarchy of BINFO_TYPE (RTTI_BINFO), this is a
7227 primary virtual base. If it is not the same primary in
7228 the hierarchy of T, we'll need to generate a ctor vtable
7229 for it, to place at its location in T. If it is the same
7230 primary, we still need a VTT entry for the vtable, but it
7231 should point to the ctor vtable for the base it is a
7232 primary for within the sub-hierarchy of RTTI_BINFO.
7233
7234 There are three possible cases:
7235
7236 1) We are in the same place.
7237 2) We are a primary base within a lost primary virtual base of
7238 RTTI_BINFO.
7239 3) We are primary to something not a base of RTTI_BINFO. */
7240
7241 tree b = BINFO_PRIMARY_BASE_OF (binfo);
7242 tree last = NULL_TREE;
7243
7244 /* First, look through the bases we are primary to for RTTI_BINFO
7245 or a virtual base. */
7246 for (; b; b = BINFO_PRIMARY_BASE_OF (b))
7247 {
7248 last = b;
7249 if (TREE_VIA_VIRTUAL (b) || b == rtti_binfo)
7250 break ;
7251 }
7252 /* If we run out of primary links, keep looking down our
7253 inheritance chain; we might be an indirect primary. */
7254 if (b == NULL_TREE)
7255 for (b = last; b; b = BINFO_INHERITANCE_CHAIN (b))
7256 if (TREE_VIA_VIRTUAL (b) || b == rtti_binfo)
7257 break ;
7258
7259 /* If we found RTTI_BINFO, this is case 1. If we found a virtual
7260 base B and it is a base of RTTI_BINFO, this is case 2. In
7261 either case, we share our vtable with LAST, i.e. the
7262 derived-most base within B of which we are a primary. */
7263 if (b == rtti_binfo
7264 || (b && purpose_member (BINFO_TYPE (b),
7265 CLASSTYPE_VBASECLASSES (BINFO_TYPE (rtti_binfo)))))
7266 /* Just set our BINFO_VTABLE to point to LAST, as we may not have
7267 set LAST's BINFO_VTABLE yet. We'll extract the actual vptr in
7268 binfo_ctor_vtable after everything's been set up. */
7269 vtbl = last;
7270
7271 /* Otherwise, this is case 3 and we get our own. */
7272 }
7273 else if (!BINFO_NEW_VTABLE_MARKED (orig_binfo))
7274 return inits;
7275
7276 if (!vtbl)
7277 {
7278 tree index;
7279 int non_fn_entries;
7280
7281 /* Compute the initializer for this vtable. */
7282 inits = build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo,
7283 &non_fn_entries);
7284
7285 /* Figure out the position to which the VPTR should point. */
7286 vtbl = TREE_PURPOSE (l);
7287 vtbl = build1 (ADDR_EXPR,
7288 vtbl_ptr_type_node,
7289 vtbl);
7290 TREE_CONSTANT (vtbl) = 1;
7291 index = size_binop (PLUS_EXPR,
7292 size_int (non_fn_entries),
7293 size_int (list_length (TREE_VALUE (l))));
7294 index = size_binop (MULT_EXPR,
7295 TYPE_SIZE_UNIT (vtable_entry_type),
7296 index);
7297 vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);
7298 TREE_CONSTANT (vtbl) = 1;
7299 }
7300
7301 if (ctor_vtbl_p)
7302 /* For a construction vtable, we can't overwrite BINFO_VTABLE.
7303 So, we make a TREE_LIST. Later, dfs_fixup_binfo_vtbls will
7304 straighten this out. */
7305 BINFO_VTABLE (binfo) = tree_cons (rtti_binfo, vtbl, BINFO_VTABLE (binfo));
7306 else if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo))
7307 inits = NULL_TREE;
7308 else
7309 /* For an ordinary vtable, set BINFO_VTABLE. */
7310 BINFO_VTABLE (binfo) = vtbl;
7311
7312 return inits;
7313 }
Note that argument orig_binfo should always refer to the binfo of the type of base in interesting. And at line 7273 predicate BINFO_NEW_VTABLE_MARKED returns true if the type has its own vtable. Now rtti_binfo is the binfo of the direct base in interesting. In our example, B1, B2 are such bases when handling C. And t refers to the binfo of the most derived class, in our example, it is class C. Next binfo is the binfo of the base we are processing.
If handles B1 in accumulate_vtbl_inits , in dfs_accumulate_vtbl_inits , to orig_binfo (here it is binfo of B1), at line 7224, condition TREE_VIA_VIRTUAL and BINFO_PRIMARY_P are not hold; But at line 7273, orig_binfo of course has its own vtable, which breaks the condition. So it will enters IF block at line 7276, in which the treatment has been seen in previous section and simliar. As ctor_vtbl_p is true, code at line 7305 is run, see that binfo is binfo of B1-in-C, which has empty BINFO_VTABLE. Because vtable built here is construction vtable, which can only borrow BINFO_VTABLE temperarily, as result it is built in a tree_list. Functions cooperative include: binfo_ctor_vtable , dfs_fixup_binfo_vtbls .
Exitting from accumulate_vtbl_inits at line 7119, B1 in C in example 1 should have following entries in construction vtable (kept in TREE_PURPOSE slot of list at line 7118 in build_ctor_vtbl_group , and BINFO_VTABLE (binfo of B1-in-C)).
Construction vtable for B1 (0xb7f2d980 instance) in C
C::_ZTC1C0_2B1: 6u entries
0 0u
4 0u
8 (int (*)(...))0
12 (int (*)(...))(& _ZTI2B1)
16 B1::_ZTcv0_n12_v0_n16_N2B11fEv // slot of B1::A::f
20 B1::f // slot of B1::f
Then in invoking accumulate_vtbl_inits at line 7134, binfo is binfo of C::B1, and line 7124 fetches the binfo of type B1, so vbase is binfo of B1::A, but b is binfo of C::B1::A, and t is still type C. They are passed to dfs_accumulate_vtbl_inits as the mapping: binfo (b ), orig_binfo (vbase ), rtti_binfo (binfo ), and t (t ).
Next in the function, b at line 7241 is binfo of C::B1; and last gets binfo of C::B1 at line 7248. As result, vtbl is set by the binfo of C::B1 at line 7269. Finally, at line 7305, BINFO_VTABLE(binfo of C::B1::A) is extended by a tree_list containing binfo of C::B1. And NULL inits is returned.
However thing is a little different for B2-in-C. Also at exitting from accumulate_vtbl_inits at line 7119, B2-in-C in example 1 should have following extra entries in construction vtable (kept in TREE_PURPOSE slot of list at line 7118 in build_ctor_vtbl_group ).
Construction vtable for B2 (0xb7f2da00 instance) in C
C::_ZTC1C4_2B2: 10u entries
0 -4u
4 0u
8 (int (*)(...))0
12 (int (*)(...))(& _ZTI2B2)
16 B2::_ZTcv0_n12_v0_n16_N2B21fEv
20 B2::f // slot of B2::f
But in dfs_accumulate_vtbl_inits for B2::A, it gets binfo : binfo of C::B2 (arg: rtti_binfo ), vbase : binfo of B2::A (arg: orig_binfo ), b : binfo of C::B2::A (arg: binfo ), and t : C (arg: t ).
Then b at line 7241 this time is binfo of C::B2; and last at line 7248 gets NULL as it climbs up via path A à B1 à C. So vtbl keeps NULL in condition at line 7276. Thus the construction vtable generated for B2::A has below entries:
24 4u // part of A in B2 - begin
28 (int (*)(...))4
32 (int (*)(...))(& _ZTI2B2)
36 B2::_ZTcv0_n12_v0_n16_N2B21fEv // part of A in B2 - end
Line 7140 in build_ctor_vtbl_group rebuilds the array type for those construction vtables. Next at line 7144, this construction vtable for base is linked into CLASSTYPE_VTABLES of the most derived class. And initialize_array at line 7145 prepares initializers with exact types for vtable entry.
Return build_vtt_inits from build_ctor_vtbl_group , at line 6916 binfo_ctor_vtable gets construction vtable from binfo of C::B1 (recorded at index 1).
FOR block at line 6927 does nothing for B1 or B2, it then arrives below code.
build_vtt_inits (continue)
6935 /* Add secondary virtual pointers for all subobjects of BINFO with
6936 either virtual bases or reachable along a virtual path, except
6937 subobjects that are non-virtual primary bases. */
6938 secondary_vptrs = tree_cons (t, NULL_TREE, BINFO_TYPE (binfo));
6939 TREE_TYPE (secondary_vptrs) = *index;
6940 VTT_TOP_LEVEL_P (secondary_vptrs) = top_level_p;
6941 VTT_MARKED_BINFO_P (secondary_vptrs) = 0;
6942
6943 dfs_walk_real (binfo,
6944 dfs_build_secondary_vptr_vtt_inits ,
6945 NULL,
6946 dfs_ctor_vtable_bases_queue_p,
6947 secondary_vptrs);
6948 VTT_MARKED_BINFO_P (secondary_vptrs) = 1;
6949 dfs_walk (binfo, dfs_unmark, dfs_ctor_vtable_bases_queue_p,
6950 secondary_vptrs);
6951
6952 *index = TREE_TYPE (secondary_vptrs);
6953
6954 /* The secondary vptrs come back in reverse order. After we reverse
6955 them, and add the INITS, the last init will be the first element
6956 of the chain. */
6957 secondary_vptrs = TREE_VALUE (secondary_vptrs);
6958 if (secondary_vptrs)
6959 {
6960 *inits = nreverse (secondary_vptrs);
6961 inits = &TREE_CHAIN (secondary_vptrs);
6962 my_friendly_assert (*inits == NULL_TREE, 20000517);
6963 }
6964
6965 /* Add the secondary VTTs for virtual bases. */
6966 if (top_level_p)
6967 for (b = TYPE_BINFO (BINFO_TYPE (binfo)); b; b = TREE_CHAIN (b))
6968 {
6969 if (!TREE_VIA_VIRTUAL (b))
6970 continue ;
6971
6972 inits = build_vtt_inits (b, t, inits, index);
6973 }
6974
6975 if (!top_level_p)
6976 {
6977 tree data = tree_cons (t, binfo, NULL_TREE);
6978 VTT_TOP_LEVEL_P (data) = 0;
6979 VTT_MARKED_BINFO_P (data) = 0;
6980
6981 dfs_walk (binfo, dfs_fixup_binfo_vtbls ,
6982 dfs_ctor_vtable_bases_queue_p,
6983 data);
6984 }
6985
6986 return inits;
6987 }
Above secondary_vptrs as indicates by its name, is the pointer to secondary vtable in the VTT of the most derived class (that is C for our example); and index tells the slot of the VTT this pointer lies in. The transverse at line 6943, begins at the binfo of base referred by binfo (here, i.e., either binfo of C::B1 or binfo of C::B2) and steps into this node. Routine below then processes the nodes visited in pre-order, see argument data is secondary_vptrs .
6996 static tree
6997 dfs_build_secondary_vptr_vtt_inits (tree binfo, void* data) in class.c
6998 {
6999 tree l;
7000 tree t;
7001 tree init;
7002 tree index;
7003 int top_level_p;
7004
7005 l = (tree) data;
7006 t = TREE_CHAIN (l);
7007 top_level_p = VTT_TOP_LEVEL_P (l);
7008
7009 BINFO_MARKED (binfo) = 1;
7010
7011 /* We don't care about bases that don't have vtables. */
7012 if (!TYPE_VFIELD (BINFO_TYPE (binfo)))
7013 return NULL_TREE;
7014
7015 /* We're only interested in proper subobjects of T. */
7016 if (same_type_p (BINFO_TYPE (binfo), t))
7017 return NULL_TREE;
7018
7019 /* We're not interested in non-virtual primary bases. */
7020 if (!TREE_VIA_VIRTUAL (binfo) && BINFO_PRIMARY_P (binfo))
7021 return NULL_TREE;
7022
7023 /* If BINFO has virtual bases or is reachable via a virtual path
7024 from T, it'll have a secondary vptr. */
7025 if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo))
7026 && !binfo_via_virtual (binfo, t))
7027 return NULL_TREE;
7028
7029 /* Record the index where this secondary vptr can be found. */
7030 index = TREE_TYPE (l);
7031 if (top_level_p)
7032 {
7033 my_friendly_assert (!BINFO_VPTR_INDEX (binfo), 20010129);
7034 BINFO_VPTR_INDEX (binfo) = index;
7035 }
7036 TREE_TYPE (l) = size_binop (PLUS_EXPR, index,
7037 TYPE_SIZE_UNIT (ptr_type_node));
7038
7039 /* Add the initializer for the secondary vptr itself. */
7040 if (top_level_p && TREE_VIA_VIRTUAL (binfo))
7041 {
7042 /* It's a primary virtual base, and this is not the construction
7043 vtable. Find the base this is primary of in the inheritance graph,
7044 and use that base's vtable now. */
7045 while (BINFO_PRIMARY_BASE_OF (binfo))
7046 binfo = BINFO_PRIMARY_BASE_OF (binfo);
7047 }
7048 init = binfo_ctor_vtable (binfo);
7049 TREE_VALUE (l) = tree_cons (NULL_TREE, init, TREE_VALUE (l));
7050
7051 return NULL_TREE;
7052 }
When iterating sub-tree headed by binfo of C::B1, top_level_p above is false, t at line 7006 is the type of B1. This node is skipped as condition at line 7016 is hold; At visiting binfo of C::B1::A, as in binfo BINFO_VTABLE of C::B1::A is the binfo of C::B1, at line 7048 binfo_ctor_vtable gets construction vtable of C::B1 again (kept at index 2). Note this function always returns NULL which forces a full walk within the (sub-)tree. To C::B2, it gets nothing too.
Remember in dfs_accumulate_vtbl_inits at line 7305, construction vtable temperarily stays in BINFO_VTABLE. Now construction vtable has been recorded into VTT, no needs rely upon BINFO_VTABLE any more. Now it is time to restore BINFO_VTABLE. Pay attention to the constructing of its argument data. Here, node temperarily appended by C::B1::A is removed (it is C::B2::A for C::B2).
7075 static tree
7076 dfs_fixup_binfo_vtbls (tree binfo, void* data) in class.c
7077 {
7078 BINFO_MARKED (binfo) = 0;
7079
7080 /* We don't care about bases that don't have vtables. */
7081 if (!TYPE_VFIELD (BINFO_TYPE (binfo)))
7082 return NULL_TREE;
7083
7084 /* If we scribbled the construction vtable vptr into BINFO, clear it
7085 out now. */
7086 if (BINFO_VTABLE (binfo)
7087 && TREE_CODE (BINFO_VTABLE (binfo)) == TREE_LIST
7088 && (TREE_PURPOSE (BINFO_VTABLE (binfo))
7089 == TREE_VALUE ((tree) data)))
7090 BINFO_VTABLE (binfo) = TREE_CHAIN (BINFO_VTABLE (binfo));
7091
7092 return NULL_TREE;
7093 }
In treatment of C::B2 mentioned above, when back build_vtt_inits from build_ctor_vtbl_group , its construction vtable is saved in VTT by index 3. Then in dfs_build_secondary_vptr_vtt_inits for C::B2, binfo_ctor_vtable at line 7048 gets construction vtable of B2::A (at index 4 in VTT).
After finishes handling B1 and B2, it continues on handling C at line 6938 in build_vtt_inits . It begins to transerve inheritance tree rooted by C at line 6943. So dfs_build_secondary_vptr_vtt_inits in, top_level_p is true, and t is the most derived class C. During this pre-order walk, C satisfies condtion at line 7016, C::B1 meets condition at line 7020, and exit the function. For C::B2, index 5 in VTT is set as vptr of C::B2, and its vtable’s (it’s a secondary vtable) initializer is what we got in previous section; similarly for C::B1::A, its vptr is in VTT with index 6, also its vtable’s (secondary vtable too) initialzier is what in BINFO_VTABLE(A-in-C) prepared in previous section. At last, C::B2::A is skipped, as A has been visited via C::B1::A.
A is processed in build_vtt_inits at line 6972 at last, as A hasn’t virtual base, build_vtt_inits does nothing.
Returns build_vtt , if success, inits should not be NULL. Following builds appropriate type for VTT and constructs its static object, then links this object into head of CLASSTYPE_VTABLES of the most derived class.