/* Nonzero if we are building the initializer for a construction
vtable. */
int ctor_vtbl_p;
+ /* True when adding vcall offset entries to the vtable. False when
+ merely computing the indices. */
+ bool generate_vcall_entries;
} vtbl_init_data;
/* The type of a function passed to walk_subobject_offsets. */
static bool base_derived_from (tree, tree);
static int empty_base_at_nonzero_offset_p (tree, tree, splay_tree);
static tree end_of_base (tree);
+static tree get_vcall_index (tree, tree);
/* Macros for dfs walking during vtt construction. See
dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits
tree type;
int complete;
{
- tree name = get_vtable_name (type);
- tree decl = IDENTIFIER_GLOBAL_VALUE (name);
-
- if (decl)
- {
- my_friendly_assert (TREE_CODE (decl) == VAR_DECL
- && DECL_VIRTUAL_P (decl), 20000118);
- return decl;
- }
-
- decl = build_vtable (type, name, void_type_node);
- decl = pushdecl_top_level (decl);
- my_friendly_assert (IDENTIFIER_GLOBAL_VALUE (name) == decl,
- 20000517);
+ tree decl;
+
+ if (CLASSTYPE_VTABLES (type))
+ return CLASSTYPE_VTABLES (type);
+ decl = build_vtable (type, get_vtable_name (type), void_type_node);
+ CLASSTYPE_VTABLES (type) = decl;
+
/* At one time the vtable info was grabbed 2 words at a time. This
fails on sparc unless you have 8-byte alignment. (tiemann) */
DECL_ALIGN (decl) = MAX (TYPE_ALIGN (double_type_node),
copies = copy_list (BINFO_VIRTUALS (binfo));
for (t = copies; t; t = TREE_CHAIN (t))
- {
- BV_VCALL_INDEX (t) = NULL_TREE;
- BV_USE_VCALL_INDEX_P (t) = 0;
- }
+ BV_VCALL_INDEX (t) = NULL_TREE;
return copies;
}
TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype);
TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
- CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype);
}
/* Determine the primary class for T. */
if (TYPE_CONTAINS_VPTR_P (basetype))
{
- /* Even a virtual baseclass can contain our RTTI
- information. But, we prefer a non-virtual polymorphic
- baseclass. */
- if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
- CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype);
-
/* We prefer a non-virtual base, although a virtual one will
do. */
if (TREE_VIA_VIRTUAL (base_binfo))
return ffod.candidates;
}
-/* Returns the function from the BINFO_VIRTUALS entry in T which matches
- the signature of FUNCTION_DECL FN, or NULL_TREE if none. In other words,
- the function that the slot in T's primary vtable points to. */
+/* Return the index of the vcall offset for FN when TYPE is used as a
+ virtual base. */
-static tree get_matching_virtual PARAMS ((tree, tree));
static tree
-get_matching_virtual (t, fn)
- tree t, fn;
+get_vcall_index (tree fn, tree type)
{
- tree f;
+ tree v;
- for (f = BINFO_VIRTUALS (TYPE_BINFO (t)); f; f = TREE_CHAIN (f))
- if (same_signature_p (BV_FN (f), fn))
- return BV_FN (f);
- return NULL_TREE;
+ for (v = CLASSTYPE_VCALL_INDICES (type); v; v = TREE_CHAIN (v))
+ if ((DECL_DESTRUCTOR_P (fn) && DECL_DESTRUCTOR_P (TREE_PURPOSE (v)))
+ || same_signature_p (fn, TREE_PURPOSE (v)))
+ break;
+
+ /* There should always be an appropriate index. */
+ my_friendly_assert (v, 20021103);
+
+ return TREE_VALUE (v);
}
/* Update an entry in the vtable for BINFO, which is in the hierarchy
/* Compute the constant adjustment to the `this' pointer. The
`this' pointer, when this function is called, will point at BINFO
(or one of its primary bases, which are at the same offset). */
-
if (virtual_base)
/* The `this' pointer needs to be adjusted from the declaration to
the nearest virtual base. */
will be zero, as it will be a primary base. */
delta = size_zero_node;
else
- {
- /* The `this' pointer needs to be adjusted from pointing to
- BINFO to pointing at the base where the final overrider
- appears. */
- delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)),
- BINFO_OFFSET (binfo));
-
- if (! integer_zerop (delta))
- {
- /* We'll need a thunk. But if we have a (perhaps formerly)
- primary virtual base, we have a vcall slot for this function,
- so we can use it rather than create a non-virtual thunk. */
-
- b = get_primary_binfo (first_defn);
- for (; b; b = get_primary_binfo (b))
- {
- tree f = get_matching_virtual (BINFO_TYPE (b), fn);
- if (!f)
- /* b doesn't have this function; no suitable vbase. */
- break;
- if (TREE_VIA_VIRTUAL (b))
- {
- /* Found one; we can treat ourselves as a virtual base. */
- virtual_base = binfo;
- delta = size_zero_node;
- break;
- }
- }
- }
- }
+ /* The `this' pointer needs to be adjusted from pointing to
+ BINFO to pointing at the base where the final overrider
+ appears. */
+ delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)),
+ BINFO_OFFSET (binfo));
modify_vtable_entry (t,
binfo,
virtuals);
if (virtual_base)
- BV_USE_VCALL_INDEX_P (*virtuals) = 1;
+ BV_VCALL_INDEX (*virtuals)
+ = get_vcall_index (TREE_PURPOSE (overrider),
+ BINFO_TYPE (virtual_base));
}
/* Called from modify_all_vtables via dfs_walk. */
splay_tree_delete (empty_base_offsets);
}
-/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
- (or C++ class declaration).
-
- For C++, we must handle the building of derived classes.
- Also, C++ allows static class members. The way that this is
- handled is to keep the field name where it is (as the DECL_NAME
- of the field), and place the overloaded decl in the bit position
- of the field. layout_record and layout_union will know about this.
-
- More C++ hair: inline functions have text in their
- DECL_PENDING_INLINE_INFO nodes which must somehow be parsed into
- meaningful tree structure. After the struct has been laid out, set
- things up so that this can happen.
-
- And still more: virtual functions. In the case of single inheritance,
- when a new virtual function is seen which redefines a virtual function
- from the base class, the new virtual function is placed into
- the virtual function table at exactly the same address that
- it had in the base class. When this is extended to multiple
- inheritance, the same thing happens, except that multiple virtual
- function tables must be maintained. The first virtual function
- table is treated in exactly the same way as in the case of single
- inheritance. Additional virtual function tables have different
- DELTAs, which tell how to adjust `this' to point to the right thing.
-
- ATTRIBUTES is the set of decl attributes to be applied, if any. */
+/* Perform processing required when the definition of T (a class type)
+ is complete. */
void
finish_struct_1 (t)
TYPE_SIZE (t) = NULL_TREE;
CLASSTYPE_GOT_SEMICOLON (t) = 0;
CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;
- CLASSTYPE_RTTI (t) = NULL_TREE;
fixup_inline_methods (t);
/* Here we know enough to change the type of our virtual
function table, but we will wait until later this function. */
build_primary_vtable (CLASSTYPE_PRIMARY_BINFO (t), t);
-
- /* If this type has basetypes with constructors, then those
- constructors might clobber the virtual function table. But
- they don't if the derived class shares the exact vtable of the base
- class. */
- CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
- }
- /* If we didn't need a new vtable, see if we should copy one from
- the base. */
- else if (CLASSTYPE_HAS_PRIMARY_BASE_P (t))
- {
- tree binfo = CLASSTYPE_PRIMARY_BINFO (t);
-
- /* If this class uses a different vtable than its primary base
- then when we will need to initialize our vptr after the base
- class constructor runs. */
- if (TYPE_BINFO_VTABLE (t) != BINFO_VTABLE (binfo))
- CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
}
if (TYPE_CONTAINS_VPTR_P (t))
? TARGET_VTABLE_USES_DESCRIPTORS : 1))
if (TREE_CODE (DECL_VINDEX (BV_FN (fn))) != INTEGER_CST)
DECL_VINDEX (BV_FN (fn)) = build_shared_int_cst (vindex);
+
+ /* Add this class to the list of dynamic classes. */
+ dynamic_classes = tree_cons (NULL_TREE, t, dynamic_classes);
}
finish_struct_bits (t);
/* Now, build the VTT object itself. */
vtt = build_vtable (t, get_vtt_name (t), type);
- pushdecl_top_level (vtt);
initialize_array (vtt, inits);
+ /* Add the VTT to the vtables list. */
+ TREE_CHAIN (vtt) = TREE_CHAIN (CLASSTYPE_VTABLES (t));
+ TREE_CHAIN (CLASSTYPE_VTABLES (t)) = vtt;
dump_vtt (t, vtt);
}
TREE_TYPE (vtbl) = type;
/* Initialize the construction vtable. */
- pushdecl_top_level (vtbl);
+ CLASSTYPE_VTABLES (t) = chainon (CLASSTYPE_VTABLES (t), vtbl);
initialize_array (vtbl, inits);
dump_vtable (t, binfo, vtbl);
}
vid.last_init = &vid.inits;
vid.primary_vtbl_p = (binfo == TYPE_BINFO (t));
vid.ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
+ vid.generate_vcall_entries = true;
/* The first vbase or vcall offset is at index -3 in the vtable. */
vid.index = ssize_int (-3 * TARGET_VTABLE_DATA_ENTRY_DISTANCE);
/* Pull the offset for `this', and the function to call, out of
the list. */
delta = BV_DELTA (v);
-
- if (BV_USE_VCALL_INDEX_P (v))
- {
- vcall_index = BV_VCALL_INDEX (v);
- my_friendly_assert (vcall_index != NULL_TREE, 20000621);
- }
- else
- vcall_index = NULL_TREE;
+ vcall_index = BV_VCALL_INDEX (v);
my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727);
my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 19990727);
tree binfo;
vtbl_init_data *vid;
{
- /* We only need these entries if this base is a virtual base. */
- if (!TREE_VIA_VIRTUAL (binfo))
- return;
-
- /* We need a vcall offset for each of the virtual functions in this
- vtable. For example:
+ /* We only need these entries if this base is a virtual base. We
+ compute the indices -- but do not add to the vtable -- when
+ building the main vtable for a class. */
+ if (TREE_VIA_VIRTUAL (binfo) || binfo == TYPE_BINFO (vid->derived))
+ {
+ /* We need a vcall offset for each of the virtual functions in this
+ vtable. For example:
- class A { virtual void f (); };
- class B1 : virtual public A { virtual void f (); };
- class B2 : virtual public A { virtual void f (); };
- class C: public B1, public B2 { virtual void f (); };
+ class A { virtual void f (); };
+ class B1 : virtual public A { virtual void f (); };
+ class B2 : virtual public A { virtual void f (); };
+ class C: public B1, public B2 { virtual void f (); };
- A C object has a primary base of B1, which has a primary base of A. A
- C also has a secondary base of B2, which no longer has a primary base
- of A. So the B2-in-C construction vtable needs a secondary vtable for
- A, which will adjust the A* to a B2* to call f. We have no way of
- knowing what (or even whether) this offset will be when we define B2,
- so we store this "vcall offset" in the A sub-vtable and look it up in
- a "virtual thunk" for B2::f.
+ A C object has a primary base of B1, which has a primary base of A. A
+ C also has a secondary base of B2, which no longer has a primary base
+ of A. So the B2-in-C construction vtable needs a secondary vtable for
+ A, which will adjust the A* to a B2* to call f. We have no way of
+ knowing what (or even whether) this offset will be when we define B2,
+ so we store this "vcall offset" in the A sub-vtable and look it up in
+ a "virtual thunk" for B2::f.
- We need entries for all the functions in our primary vtable and
- in our non-virtual bases' secondary vtables. */
- vid->vbase = binfo;
- /* Now, walk through the non-virtual bases, adding vcall offsets. */
- add_vcall_offset_vtbl_entries_r (binfo, vid);
+ We need entries for all the functions in our primary vtable and
+ in our non-virtual bases' secondary vtables. */
+ vid->vbase = binfo;
+ /* If we are just computing the vcall indices -- but do not need
+ the actual entries -- not that. */
+ if (!TREE_VIA_VIRTUAL (binfo))
+ vid->generate_vcall_entries = false;
+ /* Now, walk through the non-virtual bases, adding vcall offsets. */
+ add_vcall_offset_vtbl_entries_r (binfo, vid);
+ }
}
/* Build vcall offsets, starting with those for BINFO. */
{
tree orig_fn;
tree fn;
- tree base;
- tree base_binfo;
size_t i;
tree vcall_offset;
even though there are two virtual table entries. */
|| (DECL_DESTRUCTOR_P (BV_FN (derived_entry))
&& DECL_DESTRUCTOR_P (fn)))
- {
- if (!vid->ctor_vtbl_p)
- BV_VCALL_INDEX (derived_virtuals)
- = BV_VCALL_INDEX (derived_entry);
- break;
- }
+ break;
}
if (i != VARRAY_ACTIVE_SIZE (vid->fns))
continue;
- /* The FN comes from BASE. So, we must calculate the adjustment from
- vid->vbase to BASE. We can just look for BASE in the complete
- object because we are converting from a virtual base, so if there
- were multiple copies, there would not be a unique final overrider
- and vid->derived would be ill-formed. */
- base = DECL_CONTEXT (fn);
- base_binfo = lookup_base (vid->derived, base, ba_any, NULL);
-
- /* Compute the vcall offset. */
- /* As mentioned above, the vbase we're working on is a primary base of
- vid->binfo. But it might be a lost primary, so its BINFO_OFFSET
- might be wrong, so we just use the BINFO_OFFSET from vid->binfo. */
- vcall_offset = BINFO_OFFSET (vid->binfo);
- vcall_offset = size_diffop (BINFO_OFFSET (base_binfo),
- vcall_offset);
- vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type,
- vcall_offset));
-
- *vid->last_init = build_tree_list (NULL_TREE, vcall_offset);
- vid->last_init = &TREE_CHAIN (*vid->last_init);
-
- /* Keep track of the vtable index where this vcall offset can be
- found. For a construction vtable, we already made this
- annotation when we built the original vtable. */
- if (!vid->ctor_vtbl_p)
- BV_VCALL_INDEX (derived_virtuals) = vid->index;
+ /* If we are building these vcall offsets as part of building
+ the vtable for the most derived class, remember the vcall
+ offset. */
+ if (vid->binfo == TYPE_BINFO (vid->derived))
+ CLASSTYPE_VCALL_INDICES (vid->derived)
+ = tree_cons (fn, vid->index, CLASSTYPE_VCALL_INDICES (vid->derived));
/* The next vcall offset will be found at a more negative
offset. */
/* Keep track of this function. */
VARRAY_PUSH_TREE (vid->fns, derived_virtuals);
+
+ if (vid->generate_vcall_entries)
+ {
+ tree base;
+ tree base_binfo;
+
+ /* The FN comes from BASE. So, we must calculate the
+ adjustment from vid->vbase to BASE. We can just look for
+ BASE in the complete object because we are converting
+ from a virtual base, so if there were multiple copies,
+ there would not be a unique final overrider and
+ vid->derived would be ill-formed. */
+ base = DECL_CONTEXT (fn);
+ base_binfo = lookup_base (vid->derived, base, ba_any, NULL);
+
+ /* Compute the vcall offset. */
+ /* As mentioned above, the vbase we're working on is a
+ primary base of vid->binfo. But it might be a lost
+ primary, so its BINFO_OFFSET might be wrong, so we just
+ use the BINFO_OFFSET from vid->binfo. */
+ vcall_offset = BINFO_OFFSET (vid->binfo);
+ vcall_offset = size_diffop (BINFO_OFFSET (base_binfo),
+ vcall_offset);
+ vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type,
+ vcall_offset));
+
+ *vid->last_init = build_tree_list (NULL_TREE, vcall_offset);
+ vid->last_init = &TREE_CHAIN (*vid->last_init);
+ }
}
}
ICS_USER_FLAG (in _CONV)
CLEANUP_P (in TRY_BLOCK)
AGGR_INIT_VIA_CTOR_P (in AGGR_INIT_EXPR)
- BV_USE_VCALL_INDEX_P (in the BINFO_VIRTUALS TREE_LIST)
PTRMEM_OK_P (in ADDR_EXPR, OFFSET_REF)
PARMLIST_ELLIPSIS_P (in PARMLIST)
1: IDENTIFIER_VIRTUAL_P.
of the base class.
The BV_VCALL_INDEX of each node, if non-NULL, gives the vtable
- index of the vcall offset for this entry. If
- BV_USE_VCALL_INDEX_P then the corresponding vtable entry should
- use a virtual thunk, as opposed to an ordinary thunk.
+ index of the vcall offset for this entry.
The BV_FN is the declaration for the virtual function itself.
CPTI_DSO_HANDLE,
CPTI_DCAST,
+ CPTI_DYNAMIC_CLASSES,
+
CPTI_MAX
};
destructors. */
#define vtt_parm_type cp_global_trees[CPTI_VTT_PARM_TYPE]
+/* A TREE_LIST of all of the dynamic classes in the program. */
+
+#define dynamic_classes cp_global_trees[CPTI_DYNAMIC_CLASSES]
+
/* Global state. */
struct saved_scope GTY(())
tree primary_base;
tree vfields;
+ tree vcall_indices;
+ tree vtables;
tree vbases;
tree tags;
tree as_base;
tree pure_virtuals;
tree friend_classes;
- tree rtti;
tree methods;
tree decl_list;
tree template_info;
convenient, don't reprocess any methods that appear in its redefinition. */
#define TYPE_REDEFINED(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->redefined)
-/* The is the basetype that contains NODE's rtti. */
-#define CLASSTYPE_RTTI(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->rtti)
-
/* Nonzero means that this _CLASSTYPE node overloads operator(). */
#define TYPE_OVERLOADS_CALL_EXPR(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->has_call_overloaded)
/* Nonzero means that this aggr type has been `closed' by a semicolon. */
#define CLASSTYPE_GOT_SEMICOLON(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->got_semicolon)
-/* Nonzero means that the main virtual function table pointer needs to be
- set because base constructors have placed the wrong value there.
- If this is zero, it means that they placed the right value there,
- and there is no need to change it. */
-#define CLASSTYPE_NEEDS_VIRTUAL_REINIT(NODE) \
- (LANG_TYPE_CLASS_CHECK (NODE)->needs_virtual_reinit)
-
/* Nonzero means that this type has an X() constructor. */
#define TYPE_HAS_DEFAULT_CONSTRUCTOR(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->h.has_default_ctor)
/* Used by various search routines. */
#define IDENTIFIER_MARKED(NODE) TREE_LANG_FLAG_0 (NODE)
\f
+/* A TREE_LIST of the vcall indices associated with the class NODE.
+ The TREE_PURPOSE of each node is a FUNCTION_DECL for a virtual
+ function. The TREE_VALUE is the index into the virtual table where
+ the vcall offset for that function is stored, when NODE is a
+ virtual base. */
+#define CLASSTYPE_VCALL_INDICES(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->vcall_indices)
+
+/* The various vtables for the class NODE. The primary vtable will be
+ first, followed by the construction vtables and VTT, if any. */
+#define CLASSTYPE_VTABLES(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->vtables)
+
/* Accessor macros for the vfield slots in structures. */
/* List of virtual table fields that this type contains (both the primary
/* The function to call. */
#define BV_FN(NODE) (TREE_VALUE (NODE))
-/* Nonzero if we should use a virtual thunk for this entry. */
-#define BV_USE_VCALL_INDEX_P(NODE) (TREE_LANG_FLAG_0 (NODE))
\f
/* Nonzero for TREE_LIST node means that this list of things
is a list of parameters, as opposed to a list of expressions. */
/* in class.c */
extern tree build_base_path PARAMS ((enum tree_code, tree, tree, int));
extern tree convert_to_base (tree, tree, bool);
-extern tree build_vbase_path PARAMS ((enum tree_code, tree, tree, tree, int));
extern tree build_vtbl_ref PARAMS ((tree, tree));
extern tree build_vfn_ref PARAMS ((tree, tree));
extern tree get_vtable_decl PARAMS ((tree, int));
static void mark_vtable_entries PARAMS ((tree));
static void grok_function_init PARAMS ((tree, tree));
-static int finish_vtable_vardecl PARAMS ((tree *, void *));
+static int maybe_emit_vtables (tree);
static int is_namespace_ancestor PARAMS ((tree, tree));
static void add_using_namespace PARAMS ((tree, tree, int));
static tree ambiguous_decl PARAMS ((tree, tree, tree,int));
method = TREE_CHAIN (method))
if (DECL_VINDEX (method) != NULL_TREE
&& ! DECL_DECLARED_INLINE_P (method)
- && (! DECL_PURE_VIRTUAL_P (method)
-#if 0
- /* This would be nice, but we didn't think of it in time. */
- || DECL_DESTRUCTOR_P (method)
-#endif
- ))
+ && ! DECL_PURE_VIRTUAL_P (method))
return method;
return NULL_TREE;
assemble_vtable_inherit (child_rtx, parent_rtx);
}
+/* If necessary, write out the vtables for the dynamic class CTYPE.
+ Returns non-zero if any vtables were emitted. */
+
static int
-finish_vtable_vardecl (t, data)
- tree *t;
- void *data ATTRIBUTE_UNUSED;
+maybe_emit_vtables (tree ctype)
{
- tree vars = *t;
- tree ctype = DECL_CONTEXT (vars);
+ tree vtbl;
+ tree primary_vtbl;
+
+ /* If the vtables for this class have already been emitted there is
+ nothing more to do. */
+ primary_vtbl = CLASSTYPE_VTABLES (ctype);
+ if (TREE_ASM_WRITTEN (primary_vtbl))
+ return 0;
+ /* Ignore dummy vtables made by get_vtable_decl. */
+ if (TREE_TYPE (primary_vtbl) == void_type_node)
+ return 0;
+
import_export_class (ctype);
- import_export_vtable (vars, ctype, 1);
+ import_export_vtable (primary_vtbl, ctype, 1);
- if (! DECL_EXTERNAL (vars)
- && DECL_NEEDED_P (vars)
- && ! TREE_ASM_WRITTEN (vars))
+ /* See if any of the vtables are needed. */
+ for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
+ if (!DECL_EXTERNAL (vtbl) && DECL_NEEDED_P (vtbl))
+ break;
+
+ if (!vtbl)
+ {
+ /* If the references to this class' vtables are optimized away,
+ still emit the appropriate debugging information. See
+ dfs_debug_mark. */
+ if (DECL_COMDAT (primary_vtbl)
+ && CLASSTYPE_DEBUG_REQUESTED (ctype))
+ note_debug_info_needed (ctype);
+ return 0;
+ }
+
+ /* The ABI requires that we emit all of the vtables if we emit any
+ of them. */
+ for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
{
- if (TREE_TYPE (vars) == void_type_node)
- /* It is a dummy vtable made by get_vtable_decl. Ignore it. */
- return 0;
-
/* Write it out. */
- mark_vtable_entries (vars);
- if (TREE_TYPE (DECL_INITIAL (vars)) == 0)
- store_init_value (vars, DECL_INITIAL (vars));
+ import_export_vtable (vtbl, ctype, 1);
+ mark_vtable_entries (vtbl);
+ if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
+ store_init_value (vtbl, DECL_INITIAL (vtbl));
if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG)
{
`S' get written (which would solve the problem) but that would
require more intrusive changes to the g++ front end. */
- DECL_IGNORED_P (vars) = 1;
+ DECL_IGNORED_P (vtbl) = 1;
}
/* Always make vtables weak. */
if (flag_weak)
- comdat_linkage (vars);
+ comdat_linkage (vtbl);
- rest_of_decl_compilation (vars, NULL, 1, 1);
+ rest_of_decl_compilation (vtbl, NULL, 1, 1);
if (flag_vtable_gc)
- output_vtable_inherit (vars);
+ output_vtable_inherit (vtbl);
/* Because we're only doing syntax-checking, we'll never end up
actually marking the variable as written. */
if (flag_syntax_only)
- TREE_ASM_WRITTEN (vars) = 1;
-
- /* Since we're writing out the vtable here, also write the debug
- info. */
- note_debug_info_needed (ctype);
-
- return 1;
+ TREE_ASM_WRITTEN (vtbl) = 1;
}
- /* If the references to this class' vtables were optimized away, still
- emit the appropriate debugging information. See dfs_debug_mark. */
- if (DECL_COMDAT (vars)
- && CLASSTYPE_DEBUG_REQUESTED (ctype))
- note_debug_info_needed (ctype);
+ /* Since we're writing out the vtable here, also write the debug
+ info. */
+ note_debug_info_needed (ctype);
- return 0;
+ return 1;
}
/* Determines the proper settings of TREE_PUBLIC and DECL_EXTERNAL for an
do
{
+ tree t;
+
reconsider = 0;
/* If there are templates that we've put off instantiating, do
/* Write out virtual tables as required. Note that writing out
the virtual table for a template class may cause the
instantiation of members of that class. */
- if (walk_vtables (vtable_decl_p,
- finish_vtable_vardecl,
- /*data=*/0))
- reconsider = 1;
+ for (t = dynamic_classes; t; t = TREE_CHAIN (t))
+ if (maybe_emit_vtables (TREE_VALUE (t)))
+ reconsider = 1;
/* Write out needed type info variables. Writing out one variable
might cause others to be needed. */