Studying note of GCC-3.4.6 source (142 - continue)

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.

 

你可能感兴趣的:(list,tree,null,Build,inheritance,construction)