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

 

But what’s thunk? Following paragraphs are extracted from comment in the source of GCC.

A thunk is an alternate entry point for an ordinary FUNCTION_DECL. The address of the ordinary FUNCTION_DECL is given by the DECL_INITIAL, which is always an ADDR_EXPR whose operand is a FUNCTION_DECL. The job of the thunk is to either adjust the this pointer before transferring control to the FUNCTION_DECL, or call FUNCTION_DECL and then adjust the result value. Note, the result pointer adjusting thunk must perform a call to the thunked function, (or be implemented via passing some invisible parameter to the thunked function, which is modified to perform the adjustment just before returning).

A thunk may perform either, or both, of the following operations:

Ÿ           Adjust the this or result pointer by a constant offset.

Ÿ           Adjust the this or result pointer by looking up a vcall or vbase offset in the vtable.

A this pointer adjusting thunk converts from a base to a derived class, and hence adds the offsets. A result pointer adjusting thunk converts from a derived class to a base, and hence subtracts the offsets. If both operations are performed, then the constant adjustment is performed first for this pointer adjustment and last for the result pointer adjustment.

The constant adjustment is given by THUNK_FIXED_OFFSET. If the vcall or vbase offset is required, THUNK_VIRTUAL_OFFSET is used. For this pointer adjusting thunks, it is the vcall offset into the vtable. For result pointer adjusting thunk, it is the binfo of the virtual base to convert to. Use that binfo's vbase offset.

It is possible to have equivalent covariant thunks. These are distinct virtual covariant thunks whose vbase offsets happen to have the same value. THUNK_ALIAS is used to pick one as the canonical thunk, which will get all the this pointer adjusting thunks attached to it.

Consider following example:

A *pc = new C;

pc->f();

Remember that there is an implicit parameter of “const this*”, and for f above, this implicit parameter is “const C*”; however pc used as the implicit parameter is declared as “A*”, the compiler needs adjust pc to “const C*”. Here, thunk is needed, because A is virtual base, as we have seen in former sections, virtual base usually laid out at the tail of the class unless it is primary base. That means virtual base may have different offsets in derived classes. Later we will see for non-virtual primary base (it must contain vtable), there is no such trouble, as this base always laid out at 0 offset in derived class.

In case virtual_offset at line 2131 is NULL, it means the base defining fn hasn’t virtual base. It then further checks if the type of the returned value of both functions are the same by same_type_ignoring_top_level_qualifiers_p which indicated by its name, compares the main variant (TYPE_MAIN_VARIANT) of both types (that is ignores cv-qualifier). If these two types are not the same, the type returned by the virtual function of the derived type (over_return ) must derive from the type returned by the virtual function of the base (base_return ). It is the case require result adjusting thunk. So FOR loop at line 2164, it ensures base_return is the base of over_return . If so, following, checks if base_return is also the base of certain virtual base too.

Now if base_return is base of a virtual base (that is thunk_binfo is contained in virtual_offset ), or it is not placed at head of derived class; it calculates the fixed_offset accordingly. Notice that after handling by layout_class_type , all BINFO_OFFSET is from the beginning of the current class type.

Now for B1::f of A, fixed_offset (0) and virtual_offset (A) gotten at line 2130 and 2131 are not NULL. Then virtual_offset at line 2131 is updated to A in class C (see copy_base_binfos for extending CLASSTYPE_VBASECLASSES).

If fixed_offset or virtual_offset is epxected, a thunk is prepared by make_thunk at line 2206; this_adjusting indicates whether it is a this or result adjusting thunk. Note that thunk created here is a result adjustment one.

 

100    tree

101    make_thunk (tree function, bool this_adjusting,                                          in method.c

102               tree fixed_offset, tree virtual_offset)

103    {

104      HOST_WIDE_INT d;

105      tree thunk;

106     

107      my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 20021025);

108      /* We can have this thunks to covariant thunks, but not vice versa.  */

109      my_friendly_assert (!DECL_THIS_THUNK_P (function), 20021127);

110       my_friendly_assert (!DECL_RESULT_THUNK_P (function) || this_adjusting,

111                       20031123);

112      

113       /* Scale the VIRTUAL_OFFSET to be in terms of bytes.  */

114       if (this_adjusting && virtual_offset)

115         virtual_offset

116           = size_binop (MULT_EXPR,

117                    virtual_offset,

118                    convert (ssizetype,

119                            TYPE_SIZE_UNIT (vtable_entry_type)));

120     

121      d = tree_low_cst (fixed_offset, 0);

122     

123      /* See if we already have the thunk in question. For this_adjusting

124        thunks VIRTUAL_OFFSET will be an INTEGER_CST, for covariant thunks it

125        will be a BINFO.  */

126      for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk))

127        if (DECL_THIS_THUNK_P (thunk) == this_adjusting

128           && THUNK_FIXED_OFFSET (thunk) == d

129           && !virtual_offset == !THUNK_VIRTUAL_OFFSET (thunk)

130           && (!virtual_offset

131                || (this_adjusting

132                    ? tree_int_cst_equal (THUNK_VIRTUAL_OFFSET (thunk),

133                                     virtual_offset)

134                    : THUNK_VIRTUAL_OFFSET (thunk) == virtual_offset)))

135          return thunk;

136     

137      /* All thunks must be created before FUNCTION is actually emitted;

138        the ABI requires that all thunks be emitted together with the

139        function to which they transfer control.  */

140      my_friendly_assert (!TREE_ASM_WRITTEN (function), 20021025);

141      /* Likewise, we can only be adding thunks to a function declared in

142        the class currently being laid out.  */

143      my_friendly_assert (TYPE_SIZE (DECL_CONTEXT (function))

144                       && TYPE_BEING_DEFINED (DECL_CONTEXT (function)),

145                        20031211);

146   

147      thunk = build_decl (FUNCTION_DECL, NULL_TREE, TREE_TYPE (function));

148      DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function);

149      cxx_dup_lang_specific_decl (thunk);

150      DECL_THUNKS (thunk) = NULL_TREE;

151     

152      DECL_CONTEXT (thunk) = DECL_CONTEXT (function);

153      TREE_READONLY (thunk) = TREE_READONLY (function);

154      TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (function);

155      TREE_PUBLIC (thunk) = TREE_PUBLIC (function);

156      if (flag_weak )

157        comdat_linkage (thunk);

158      SET_DECL_THUNK_P (thunk, this_adjusting);

159      THUNK_TARGET (thunk) = function;

160      THUNK_FIXED_OFFSET (thunk) = d;

161      THUNK_VIRTUAL_OFFSET (thunk) = virtual_offset;

162      THUNK_ALIAS (thunk) = NULL_TREE;

163     

164      /* The thunk itself is not a constructor or destructor, even if

165        the thing it is thunking to is.  */

166      DECL_INTERFACE_KNOWN (thunk) = 1;

167      DECL_NOT_REALLY_EXTERN (thunk) = 1;

168      DECL_SAVED_FUNCTION_DATA (thunk) = NULL;

169      DECL_DESTRUCTOR_P (thunk) = 0;

170      DECL_CONSTRUCTOR_P (thunk) = 0;

171      /* And neither is it a clone.  */

172      DECL_CLONED_FUNCTION (thunk) = NULL_TREE;

173      DECL_EXTERNAL (thunk) = 1;

174      DECL_ARTIFICIAL (thunk) = 1;

175      /* Even if this thunk is a member of a local class, we don't

176        need a static chain.  */

177      DECL_NO_STATIC_CHAIN (thunk) = 1;

178      /* The THUNK is not a pending inline, even if the FUNCTION is.  */

179      DECL_PENDING_INLINE_P (thunk) = 0;

180      DECL_INLINE (thunk) = 0;

181      DECL_DECLARED_INLINE_P (thunk) = 0;

182      /* Nor has it been deferred.  */

183      DECL_DEFERRED_FN (thunk) = 0;

184     

185      /* Add it to the list of thunks associated with FUNCTION.  */

186      TREE_CHAIN (thunk) = DECL_THUNKS (function);

187      DECL_THUNKS (function) = thunk;

188   

189      return thunk;

190    }

 

Thunk is itself a FUNCTION_DECL. Note that it is nameless and artificial. And the value of fixed offset is set in THUNK_FIXED_OFFSET. Further this thunk is applied to the specified virtual function (more precisely, the returned type); it is linked by DECL_THUNKS of the node of the virtual function.

Remember below b is the nearest primary base which defines the function and gotten by get_primary_binfo , it is binfo of B1 for C in our example. At line 2218, the FOR block fetches the closest virtual class deriving from b in current class type if there is. Here we get virtual_base as NULL. See at line 2236, if overrider_fn is not equal to overrider_target , it means there is a thunk for the overrider, and if no virtual derived class is found, it further checks if there is any primary virtual base. If primary virtual base is found, that means following class structure:

And if virtual derived class is found, the class structure should be:

Studying note of GCC-3.4.6 source (140 - continue)_第1张图片

Thunk is generated by above code, and delta and vcall offset are determined by following code. For our example B::f with thunk in A, condition at line 2236 is not satisfied. And delta would be 0 (C – A).

 

update_vtable_entry_for_fn (continue)

 

2212     /* Assume that we will produce a thunk that convert all the way to

2213       the final overrider, and not to an intermediate virtual base.  */

2214     virtual_base = NULL_TREE;

2215  

2216     /* See if we can convert to an intermediate virtual base first, and then

2217       use the vcall offset located there to finish the conversion.  */

2218     for (; b; b = BINFO_INHERITANCE_CHAIN (b))

2219     {

2220       /* If we find the final overrider, then we can stop

2221         walking.  */

2222        if (same_type_p (BINFO_TYPE (b),

2223                      BINFO_TYPE (TREE_VALUE (overrider))))

2224         break ;

2225  

2226       /* If we find a virtual base, and we haven't yet found the

2227          overrider, then there is a virtual base between the

2228          declaring base (first_defn) and the final overrider.  */

2229       if (TREE_VIA_VIRTUAL (b))

2230       {

2231          virtual_base = b;

2232          break ;

2233       }

2234     }

2235  

2236     if (overrider_fn != overrider_target && !virtual_base)

2237     {

2238       /* The ABI specifies that a covariant thunk includes a mangling

2239          for a this pointer adjustment. This-adjusting thunks that

2240          override a function from a virtual base have a vcall

2241          adjustment. When the virtual base in question is a primary

2242          virtual base, we know the adjustments are zero, (and in the

2243         non-covariant case, we would not use the thunk).

2244          Unfortunately we didn't notice this could happen, when

2245          designing the ABI and so never mandated that such a covariant

2246          thunk should be emitted. Because we must use the ABI mandated

2247          name, we must continue searching from the binfo where we

2248          found the most recent definition of the function, towards the

2249          primary binfo which first introduced the function into the

2250          vtable. If that enters a virtual base, we must use a vcall

2251          this-adjusting thunk. Bleah! */

2252       tree probe = first_defn;

2253  

2254       while ((probe = get_primary_binfo (probe))

2255             && (unsigned) list_length (BINFO_VIRTUALS (probe)) > ix)

2256         if (TREE_VIA_VIRTUAL (probe))

2257           virtual_base = probe;

2258        

2259       if (virtual_base)

2260         /* Even if we find a virtual base, the correct delta is

2261            between the overrider and the binfo we're building a vtable

2262            for.  */

2263         goto virtual_covariant;

2264     }

2265    

2266     /* Compute the constant adjustment to the `this' pointer. The

2267      `this' pointer, when this function is called, will point at BINFO

2268      (or one of its primary bases, which are at the same offset).  */

2269     if (virtual_base)

2270        /* The `this' pointer needs to be adjusted from the declaration to

2271         the nearest virtual base.  */

2272       delta = size_diffop (convert (ssizetype, BINFO_OFFSET (virtual_base)),

2273                        convert (ssizetype, BINFO_OFFSET (first_defn)));

2274     else if (lost)

2275       /* If the nearest definition is in a lost primary, we don't need an

2276         entry in our vtable. Except possibly in a constructor vtable,

2277         if we happen to get our primary back. In that case, the offset

2278         will be zero, as it will be a primary base.  */

2279       delta = size_zero_node;

2280     else

2281        /* The `this' pointer needs to be adjusted from pointing to

2282         BINFO to pointing at the base where the final overrider

2283         appears.  */

2284   virtual_covariant:

2285       delta = size_diffop (convert (ssizetype,

2286                        BINFO_OFFSET (TREE_VALUE (overrider))),

2287                        convert (ssizetype, BINFO_OFFSET (binfo)));

2288  

2289     modify_vtable_entry (t, binfo, overrider_fn, delta, virtuals);

2290  

2291     if (virtual_base)

2292       BV_VCALL_INDEX (*virtuals)

2293         = get_vcall_index (overrider_target, BINFO_TYPE (virtual_base));

2294   }

 

For virtual base, in construction vtable of the most derived class (see next section for building VTT), there is an entry called vcall offset to record the offset from the virtual base to this final overriding class. This offset will be also used by virtual functions to adjust the this pointer, and saved within field BV_VCALL_INDEX.

At line 2293, get_vcall_index checks and fetches this vcall offset, which stored in field CLASSTYPE_VCALL_INDICES of the binfo of the class of the virtual base (this data is generated by finish_vtbls in following section).

 

2051   static tree

2052   get_vcall_index (tree fn, tree type)                                                            in class.c

2053   {

2054     tree v;

2055  

2056     for (v = CLASSTYPE_VCALL_INDICES (type); v; v = TREE_CHAIN (v))

2057       if ((DECL_DESTRUCTOR_P (fn) && DECL_DESTRUCTOR_P (TREE_PURPOSE (v)))

2058          || same_signature_p (fn, TREE_PURPOSE (v)))

2059         break ;

2060  

2061     /* There should always be an appropriate index.  */

2062     my_friendly_assert (v, 20021103);

2063  

2064     return TREE_VALUE (v);

2065   }

 

Remember lost at line 2274 can only be found for base containing virtual primary base, and the virtual base is also the primary base in current type, which has offset 0. And modify_vtable_entry records this adjustment within BV_DELTA. Especially, argument fndecl here is the overrider_fn in update_vtable_entry_for_fn , which is the final overrider. See it is filled into the corresponding vtable entry in the bases that defined the virtual to ensure correct function to be invoked.

 

683    static void

684    modify_vtable_entry (tree t,                                                                     in class.c

685                      tree binfo,

686                      tree fndecl,

687                      tree delta,

688                      tree *virtuals)

689    {

690      tree v;

691   

692      v = *virtuals;

693   

694      if (fndecl != BV_FN (v)

695          || !tree_int_cst_equal (delta, BV_DELTA (v)))

696      {

697        /* We need a new vtable for BINFO.  */

698        if (make_new_vtable (t, binfo))

699        {

700          /* If we really did make a new vtable, we also made a copy

701            of the BINFO_VIRTUALS list. Now, we have to find the

702            corresponding entry in that list.  */

703          *virtuals = BINFO_VIRTUALS (binfo);

704          while (BV_FN (*virtuals) != BV_FN (v))

705            *virtuals = TREE_CHAIN (*virtuals);

706          v = *virtuals;

707        }

708   

709        BV_DELTA (v) = delta;

710        BV_VCALL_INDEX (v) = NULL_TREE;

711         BV_FN (v) = fndecl;

712      }

713    }

 

If condition at line 694 is satisfied, it means fndecl is overrided or thunk; and if condition at line 695 is satisfied, it indicates BV_DETLA needs update. These 3 situations (includes case 694, 695 line condition both satisfied) mean need to update corresponding entry in vtable, so first see if vtable is ready or not. If vtable is ready before, the binfo has BINFO_NEW_VTABLE_MARKED set, and make_new_vtable returns 0. For our example Class C, it will enter the function 3 times, by A, B2 and C in order. They all invoked make_new_vtable in dfs_modify_vtables , and argument virtuals came from binfo of this base, so direct update is all. Also note that find_final_overrider will check if ambiguous exists, for example, removing f in C, then calling f via C is ambiguous.

After handling base A, dfs_walk in modify_all_vtables , then climbs up to B1 (as we come in order C à B1 à A). As B1 is a non-virtual primary base, dfs_modify_vtables skips this type (note that make_new_vtable is not invoked as result, and BINFO_NEW_VTABLE_MARKED in the binfo is unset). Then next object is B2, the handling of this base is similar with what we have seen. At last, we arrive at C. Remember BINFO_VIRTUALS (C) contains B1::f with thunk exactly the same as that in A in C, which followed by B1::f. Here for this first function, it is replaced by C::f (delta : 0) with thunk with virual-offset: A in C, fix-offset: 0. Then for B1::f next, it will get C::f without thunk as result as it is the non-virtual primary base for C.

Finially after exitting the walk, remember there virtuals gets its content from TYPE_METHOD of C, which is C::f. And now in BINFO_VIRTUALS (C) are, 1) C::f with thunk of virtual-offset (A in C), fix-offset (0); 2) C::f. So in modify_all_vtables , C::f is removed from virtuals , which is now empty.

 

finish_struct_1 (continue)

 

5081     /* If necessary, create the primary vtable for this class.  */

5082     if (virtuals || TYPE_CONTAINS_VPTR_P (t))

5083     {

5084        /* We must enter these virtuals into the table.  */

5085       if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))

5086         build_primary_vtable (NULL_TREE, t);

5087       else if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t)))

5088         /* Here we know enough to change the type of our virtual

5089            function table, but we will wait until later this function.  */

5090         build_primary_vtable (CLASSTYPE_PRIMARY_BINFO (t), t);

5091     }

5092  

5093     if (TYPE_CONTAINS_VPTR_P (t))

5094     {

5095       int vindex;

5096       tree fn;

5097  

5098       if (TYPE_BINFO_VTABLE (t))

5099         my_friendly_assert (DECL_VIRTUAL_P (TYPE_BINFO_VTABLE (t)),

5100                          20000116);

5101       if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))

5102         my_friendly_assert (TYPE_BINFO_VIRTUALS (t) == NULL_TREE,

5103                          20000116);

5104  

5105       /* Add entries for virtual functions introduced by this class.  */

5106       TYPE_BINFO_VIRTUALS (t) = chainon (TYPE_BINFO_VIRTUALS (t), virtuals);

5107  

5108       /* Set DECL_VINDEX for all functions declared in this class.  */

5109       for (vindex = 0, fn = BINFO_VIRTUALS (TYPE_BINFO (t));

5110            fn;

5111            fn = TREE_CHAIN (fn),

5112                vindex += (TARGET_VTABLE_USES_DESCRIPTORS

5113                           ? TARGET_VTABLE_USES_DESCRIPTORS : 1))

5114       {

5115         tree fndecl = BV_FN (fn);

5116  

5117         if (DECL_THUNK_P (fndecl))

5118           /* A thunk. We should never be calling this entry directly

5119             from this vtable -- we'd use the entry for the non

5120             thunk base function.  */

5121           DECL_VINDEX (fndecl) = NULL_TREE;

5122         else if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)

5123           DECL_VINDEX (fndecl) = build_shared_int_cst (vindex);

5124        }

5125     }

5126  

5127     finish_struct_bits (t);

 

Then at line 5106 in finish_struct_1 , virtuals are virtual functions declared within class t and survived. Appending them to TYPE_BINFO_VIRTUALS forms the complete list.

At line 5112, TARGET_VTABLE_USES_DESCRIPTORS is defined if function descriptors are used in the vtable entries and it says how many words wide the descriptor is (normally 2). By default, the C++ compiler will use function addresses in the vtable entries. Till now DECL_VINDEX still points to a FUNCTION_DECL in a base class which is the FUNCTION_DECL this FUNCTION_DECL will replace as a virtual function. It is time to change the pointer to an INTEGER_CST. In GCC, integer constant less than 256 is shared and kept within global array shared_int_cache .

 

1409   static void

1410   finish_struct_bits (tree t)                                                                          in class.c

1411   {

1412     int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);

1413  

1414     /* Fix up variants (if any).  */

1415     tree variants = TYPE_NEXT_VARIANT (t);

1416     while (variants)

1417     {

1418       /* These fields are in the _TYPE part of the node, not in

1419         the TYPE_LANG_SPECIFIC component, so they are not shared.  */

1420       TYPE_HAS_CONSTRUCTOR (variants) = TYPE_HAS_CONSTRUCTOR (t);

1421       TYPE_HAS_DESTRUCTOR (variants) = TYPE_HAS_DESTRUCTOR (t);

1422       TYPE_NEEDS_CONSTRUCTING (variants) = TYPE_NEEDS_CONSTRUCTING (t);

1423       TYPE_HAS_NONTRIVIAL_DESTRUCTOR (variants)

1424            = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t);

1425  

1426       TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (variants)

1427            = TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (t);

1428       TYPE_POLYMORPHIC_P (variants) = TYPE_POLYMORPHIC_P (t);

1429       TYPE_USES_VIRTUAL_BASECLASSES (variants) = TYPE_USES_VIRTUAL_BASECLASSES (t);

1430       /* Copy whatever these are holding today.  */

1431       TYPE_MIN_VALUE (variants) = TYPE_MIN_VALUE (t);

1432       TYPE_MAX_VALUE (variants) = TYPE_MAX_VALUE (t);

1433       TYPE_FIELDS (variants) = TYPE_FIELDS (t);

1434       TYPE_SIZE (variants) = TYPE_SIZE (t);

1435       TYPE_SIZE_UNIT (variants) = TYPE_SIZE_UNIT (t);

1436       variants = TYPE_NEXT_VARIANT (variants);

1437     }

1438  

1439     if (n_baseclasses && TYPE_POLYMORPHIC_P (t))

1440       /* For a class w/o baseclasses, `finish_struct' has set

1441         CLASS_TYPE_ABSTRACT_VIRTUALS correctly (by

1442         definition). Similarly for a class whose base classes do not

1443         have vtables. When neither of these is true, we might have

1444         removed abstract virtuals (by providing a definition), added

1445         some (by declaring new ones), or redeclared ones from a base

1446         class. We need to recalculate what's really an abstract virtual

1447         at this point (by looking in the vtables).  */

1448       get_pure_virtuals (t);

1449  

1450     if (n_baseclasses)

1451     {

1452       /* Notice whether this class has type conversion functions defined.  */

1453       tree binfo = TYPE_BINFO (t);

1454       tree binfos = BINFO_BASETYPES (binfo);

1455       tree basetype;

1456  

1457       for (i = n_baseclasses-1; i >= 0; i--)

1458       {

1459         basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));

1460  

1461         TYPE_HAS_CONVERSION (t) |= TYPE_HAS_CONVERSION (basetype);

1462       }

1463     }

1464  

1465     /* If this type has a copy constructor or a destructor, force its mode to

1466       be BLKmode, and force its TREE_ADDRESSABLE bit to be nonzero. This

1467       will cause it to be passed by invisible reference and prevent it from

1468       being returned in a register.  */

1469     if (! TYPE_HAS_TRIVIAL_INIT_REF (t) || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t))

1470     {

1471       tree variants;

1472       DECL_MODE (TYPE_MAIN_DECL (t)) = BLKmode;

1473       for (variants = t; variants; variants = TYPE_NEXT_VARIANT (variants))

1474       {

1475         TYPE_MODE (variants) = BLKmode;

1476         TREE_ADDRESSABLE (variants) = 1;

1477       }

1478     }

1479   }

 

As we have finished layout of the class, we can synchronize the node of cv-qualifier variant. At line 1439, TYPE_POLYMORPHIC_P set for the type that overrides a vritual function of base. Routine get_pure_virtuals fetches all pure virtuals of non-primary base (the most derived class is also non-primary base, whose vtable contains virtual functions of bases along the primary base path). Remember that pure virtual function has been bound with the final overrider if it has been overrided in update_vtable_entry_for_fn .

 

1965   void

1966   get_pure_virtuals (tree type)                                                                     in search.c

1967   {

1968     tree vbases;

1969  

1970     /* Clear the CLASSTYPE_PURE_VIRTUALS list; whatever is already there

1971       is going to be overridden.  */

1972     CLASSTYPE_PURE_VIRTUALS (type) = NULL_TREE;

1973     /* Now, run through all the bases which are not primary bases, and

1974       collect the pure virtual functions. We look at the vtable in

1975       each class to determine what pure virtual functions are present.

1976       (A primary base is not interesting because the derived class of

1977       which it is a primary base will contain vtable entries for the

1978       pure virtuals in the base class.  */

1979     dfs_walk (TYPE_BINFO (type), dfs_get_pure_virtuals , unmarkedp , type);

1980     dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, type);

1981  

1982     /* Put the pure virtuals in dfs order.  */

1983     CLASSTYPE_PURE_VIRTUALS (type) = nreverse (CLASSTYPE_PURE_VIRTUALS (type));

1984  

1985     for (vbases = CLASSTYPE_VBASECLASSES (type);

1986         vbases;

1987         vbases = TREE_CHAIN (vbases))

1988     {

1989       tree virtuals;

1990  

1991       for (virtuals = BINFO_VIRTUALS (TREE_VALUE (vbases));

1992           virtuals;

1993           virtuals = TREE_CHAIN (virtuals))

1994       {

1995         tree base_fndecl = BV_FN (virtuals);

1996         if (DECL_NEEDS_FINAL_OVERRIDER_P (base_fndecl))

1997           error ("`%#D' needs a final overrider", base_fndecl);

1998       }

1999     }

2000   }

 

All pure virtual functions are put into CLASSTYPE_PURE_VIRTUALS field of current class (then if CLASSTYPE_PURE_VIRTUALS is not empty, this type can’t be instantiated).

 

1937   static tree

1938   dfs_get_pure_virtuals (tree binfo, void *data)                                             in search.c

1939   {

1940     tree type = (tree) data;

1941  

1942     /* We're not interested in primary base classes; the derived class

1943       of which they are a primary base will contain the information we

1944       need.  */

1945     if (!BINFO_PRIMARY_P (binfo))

1946     {

1947       tree virtuals;

1948        

1949       for (virtuals = BINFO_VIRTUALS (binfo);

1950           virtuals;

1951           virtuals = TREE_CHAIN (virtuals))

1952         if (DECL_PURE_VIRTUAL_P (BV_FN (virtuals)))

1953           CLASSTYPE_PURE_VIRTUALS (type)

1954               = tree_cons (NULL_TREE, BV_FN (virtuals),

1955                           CLASSTYPE_PURE_VIRTUALS (type));

1956     }

1957    

1958     BINFO_MARKED (binfo) = 1;

1959  

1960     return NULL_TREE;

1961   }

 

Next, if base defines convertor, then it can be used by the derived. At line 1469, if TYPE_HAS_TRIVIAL_INIT_REF is nonzero, means copy initialization of this type can use a bitwise copy. And if TYPE_HAS_NONTRIVIAL_DESTRUCTOR is nonzero, means this type does not have a trivial destructor. A destructor is trivial if it is an implicitly declared destructor and if:

- all of the direct base classes of its class have trivial destructors,

- for all of the non-static data members of its class that are of class type (or array thereof), each such class has a trivial destructor.

 

你可能感兴趣的:(function,tree,null,Class,Constructor,destructor)