static void check_for_override (tree, tree);
static tree dfs_modify_vtables (tree, void *);
static tree modify_all_vtables (tree, tree);
-static void determine_primary_base (tree);
+static void determine_primary_bases (tree);
static void finish_struct_methods (tree);
static void maybe_warn_about_overly_private_class (tree);
static int method_name_cmp (const void *, const void *);
static void layout_class_type (tree, tree *);
static void fixup_pending_inline (tree);
static void fixup_inline_methods (tree);
-static void set_primary_base (tree, tree);
static void propagate_binfo_offsets (tree, tree);
static void layout_virtual_bases (record_layout_info, splay_tree);
static void build_vbase_offset_vtbl_entries (tree, vtbl_init_data *);
static void build_rtti_vtbl_entries (tree, vtbl_init_data *);
static void build_vcall_and_vbase_vtbl_entries (tree,
vtbl_init_data *);
-static void mark_primary_bases (tree);
static void clone_constructors_and_destructors (tree);
static tree build_clone (tree, tree);
static void update_vtable_entry_for_fn (tree, tree, tree, tree *, unsigned);
d_binfo = probe;
if (is_empty_class (BINFO_TYPE (probe)))
has_empty = true;
- if (!v_binfo && TREE_VIA_VIRTUAL (probe))
+ if (!v_binfo && BINFO_VIRTUAL_P (probe))
v_binfo = probe;
}
if (want_pointer)
probe = TYPE_MAIN_VARIANT (TREE_TYPE (probe));
- my_friendly_assert (code == MINUS_EXPR
- ? same_type_p (BINFO_TYPE (binfo), probe)
- : code == PLUS_EXPR
- ? same_type_p (BINFO_TYPE (d_binfo), probe)
- : false, 20010723);
+ gcc_assert (code == MINUS_EXPR
+ ? same_type_p (BINFO_TYPE (binfo), probe)
+ : code == PLUS_EXPR
+ ? same_type_p (BINFO_TYPE (d_binfo), probe)
+ : false);
if (binfo == d_binfo)
/* Nothing to do. */
expr = build_indirect_ref (expr, NULL);
expr = build_simple_base_path (expr, binfo);
if (want_pointer)
- expr = build_unary_op (ADDR_EXPR, expr, 0);
+ expr = build_address (expr);
target_type = TREE_TYPE (expr);
goto out;
}
t = TREE_TYPE (TYPE_VFIELD (BINFO_TYPE (derived)));
t = build_pointer_type (t);
v_offset = convert (t, current_vtt_parm);
- v_offset = build (PLUS_EXPR, t, v_offset,
- BINFO_VPTR_INDEX (derived));
+ v_offset = build2 (PLUS_EXPR, t, v_offset,
+ BINFO_VPTR_INDEX (derived));
v_offset = build_indirect_ref (v_offset, NULL);
}
else
v_offset = build_vfield_ref (build_indirect_ref (expr, NULL),
TREE_TYPE (TREE_TYPE (expr)));
- v_offset = build (PLUS_EXPR, TREE_TYPE (v_offset),
- v_offset, BINFO_VPTR_FIELD (v_binfo));
+ v_offset = build2 (PLUS_EXPR, TREE_TYPE (v_offset),
+ v_offset, BINFO_VPTR_FIELD (v_binfo));
v_offset = build1 (NOP_EXPR,
build_pointer_type (ptrdiff_type_node),
v_offset);
BINFO_OFFSET (v_binfo)));
if (!integer_zerop (offset))
- v_offset = build (code, ptrdiff_type_node, v_offset, offset);
+ v_offset = build2 (code, ptrdiff_type_node, v_offset, offset);
if (fixed_type_p < 0)
/* Negative fixed_type_p means this is a constructor or destructor;
virtual base layout is fixed in in-charge [cd]tors, but not in
base [cd]tors. */
- offset = build (COND_EXPR, ptrdiff_type_node,
- build (EQ_EXPR, boolean_type_node,
- current_in_charge_parm, integer_zero_node),
- v_offset,
- BINFO_OFFSET (binfo));
+ offset = build3 (COND_EXPR, ptrdiff_type_node,
+ build2 (EQ_EXPR, boolean_type_node,
+ current_in_charge_parm, integer_zero_node),
+ v_offset,
+ BINFO_OFFSET (binfo));
else
offset = v_offset;
}
expr = build1 (NOP_EXPR, ptr_target_type, expr);
if (!integer_zerop (offset))
- expr = build (code, ptr_target_type, expr, offset);
+ expr = build2 (code, ptr_target_type, expr, offset);
else
null_test = NULL;
build_simple_base_path (tree expr, tree binfo)
{
tree type = BINFO_TYPE (binfo);
- tree d_binfo;
+ tree d_binfo = BINFO_INHERITANCE_CHAIN (binfo);
tree field;
- /* For primary virtual bases, we can't just follow
- BINFO_INHERITANCE_CHAIN. */
- d_binfo = BINFO_PRIMARY_BASE_OF (binfo);
- if (d_binfo == NULL_TREE)
- d_binfo = BINFO_INHERITANCE_CHAIN (binfo);
-
if (d_binfo == NULL_TREE)
{
- if (TYPE_MAIN_VARIANT (TREE_TYPE (expr)) != type)
- abort ();
+ gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (expr)) == type);
return expr;
}
field; field = TREE_CHAIN (field))
/* Is this the base field created by build_base_field? */
if (TREE_CODE (field) == FIELD_DECL
- && TREE_TYPE (field) == type
- && DECL_ARTIFICIAL (field)
- && DECL_IGNORED_P (field))
+ && DECL_FIELD_IS_BASE (field)
+ && TREE_TYPE (field) == type)
return build_class_member_access_expr (expr, field,
NULL_TREE, false);
/* Didn't find the base field?!? */
- abort ();
+ gcc_unreachable ();
}
/* Convert OBJECT to the base TYPE. If CHECK_ACCESS is true, an error
pointer_type = build_pointer_type (expr_type);
expr = build_unary_op (ADDR_EXPR, expr, /*noconvert=*/1);
if (!integer_zerop (BINFO_OFFSET (base)))
- expr = build (PLUS_EXPR, pointer_type, expr,
- build_nop (pointer_type, BINFO_OFFSET (base)));
+ expr = build2 (PLUS_EXPR, pointer_type, expr,
+ build_nop (pointer_type, BINFO_OFFSET (base)));
expr = build_nop (build_pointer_type (BINFO_TYPE (base)), expr);
expr = build1 (INDIRECT_REF, BINFO_TYPE (base), expr);
}
build_unary_op (ADDR_EXPR, aref, /*noconvert=*/1));
/* Remember this as a method reference, for later devirtualization. */
- aref = build (OBJ_TYPE_REF, TREE_TYPE (aref), aref, instance_ptr, idx);
+ aref = build3 (OBJ_TYPE_REF, TREE_TYPE (aref), aref, instance_ptr, idx);
return aref;
}
return mangle_vtt_for_type (type);
}
+/* DECL is an entity associated with TYPE, like a virtual table or an
+ implicitly generated constructor. Determine whether or not DECL
+ should have external or internal linkage at the object file
+ level. This routine does not deal with COMDAT linkage and other
+ similar complexities; it simply sets TREE_PUBLIC if it possible for
+ entities in other translation units to contain copies of DECL, in
+ the abstract. */
+
+void
+set_linkage_according_to_type (tree type, tree decl)
+{
+ /* If TYPE involves a local class in a function with internal
+ linkage, then DECL should have internal linkage too. Other local
+ classes have no linkage -- but if their containing functions
+ have external linkage, it makes sense for DECL to have external
+ linkage too. That will allow template definitions to be merged,
+ for example. */
+ if (no_linkage_check (type, /*relaxed_p=*/true))
+ {
+ TREE_PUBLIC (decl) = 0;
+ DECL_INTERFACE_KNOWN (decl) = 1;
+ }
+ else
+ TREE_PUBLIC (decl) = 1;
+}
+
/* Create a VAR_DECL for a primary or secondary vtable for CLASS_TYPE.
(For a secondary vtable for B-in-D, CLASS_TYPE should be D, not B.)
Use NAME for the name of the vtable, and VTABLE_TYPE for its type. */
DECL_VIRTUAL_P (decl) = 1;
DECL_ALIGN (decl) = TARGET_VTABLE_ENTRY_ALIGN;
DECL_VTABLE_OR_VTT_P (decl) = 1;
-
/* 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),
DECL_ALIGN (decl));
-
- import_export_vtable (decl, class_type, 0);
+ set_linkage_according_to_type (class_type, decl);
+ /* The vtable has not been defined -- yet. */
+ DECL_EXTERNAL (decl) = 1;
+ DECL_NOT_REALLY_EXTERN (decl) = 1;
+
+ if (write_symbols == DWARF2_DEBUG)
+ /* Mark the VAR_DECL node representing the vtable itself as a
+ "gratuitous" one, thereby forcing dwarfout.c to ignore it. It
+ is rather important that such things be ignored because any
+ effort to actually generate DWARF for them will run into
+ trouble when/if we encounter code like:
+
+ #pragma interface
+ struct S { virtual void member (); };
+
+ because the artificial declaration of the vtable itself (as
+ manufactured by the g++ front end) will say that the vtable is
+ a static member of `S' but only *after* the debug output for
+ the definition of `S' has already been output. This causes
+ grief because the DWARF entry for the definition of the vtable
+ will try to refer back to an earlier *declaration* of the
+ vtable as a static member of `S' and there won't be one. We
+ might be able to arrange to have the "vtable static member"
+ attached to the member list for `S' before the debug info for
+ `S' get written (which would solve the problem) but that would
+ require more intrusive changes to the g++ front end. */
+ DECL_IGNORED_P (decl) = 1;
return decl;
}
}
else
{
- my_friendly_assert (TREE_TYPE (decl) == vtbl_type_node, 20000118);
+ gcc_assert (TREE_TYPE (decl) == vtbl_type_node);
virtuals = NULL_TREE;
}
/* Initialize the association list for this type, based
on our first approximation. */
- TYPE_BINFO_VTABLE (type) = decl;
- TYPE_BINFO_VIRTUALS (type) = virtuals;
+ BINFO_VTABLE (TYPE_BINFO (type)) = decl;
+ BINFO_VIRTUALS (TYPE_BINFO (type)) = virtuals;
SET_BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (type));
return 1;
}
}
\f
-/* Add method METHOD to class TYPE. If ERROR_P is true, we are adding
- the method after the class has already been defined because a
- declaration for it was seen. (Even though that is erroneous, we
- add the method for improved error recovery.) */
+/* Add method METHOD to class TYPE. */
void
-add_method (tree type, tree method, int error_p)
+add_method (tree type, tree method)
{
int using;
- int len;
- int slot;
- tree method_vec;
+ unsigned slot;
+ tree overload;
int template_conv_p;
+ VEC(tree) *method_vec;
+ bool complete_p;
+ bool insert_p = false;
+ tree current_fns;
if (method == error_mark_node)
return;
-
+
+ complete_p = COMPLETE_TYPE_P (type);
using = (DECL_CONTEXT (method) != type);
template_conv_p = (TREE_CODE (method) == TEMPLATE_DECL
&& DECL_TEMPLATE_CONV_FN_P (method));
- if (!CLASSTYPE_METHOD_VEC (type))
- /* Make a new method vector. We start with 8 entries. We must
- allocate at least two (for constructors and destructors), and
- we're going to end up with an assignment operator at some point
- as well.
-
- We could use a TREE_LIST for now, and convert it to a TREE_VEC
- in finish_struct, but we would probably waste more memory
- making the links in the list than we would by over-allocating
- the size of the vector here. Furthermore, we would complicate
- all the code that expects this to be a vector. */
- CLASSTYPE_METHOD_VEC (type) = make_tree_vec (8);
-
method_vec = CLASSTYPE_METHOD_VEC (type);
- len = TREE_VEC_LENGTH (method_vec);
+ if (!method_vec)
+ {
+ /* Make a new method vector. We start with 8 entries. We must
+ allocate at least two (for constructors and destructors), and
+ we're going to end up with an assignment operator at some
+ point as well. */
+ method_vec = VEC_alloc (tree, 8);
+ /* Create slots for constructors and destructors. */
+ VEC_quick_push (tree, method_vec, NULL_TREE);
+ VEC_quick_push (tree, method_vec, NULL_TREE);
+ CLASSTYPE_METHOD_VEC (type) = method_vec;
+ }
/* Constructors and destructors go in special slots. */
if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (method))
}
else
{
- int have_template_convs_p = 0;
-
+ bool conv_p = DECL_CONV_FN_P (method);
+ tree m;
+
+ insert_p = true;
/* See if we already have an entry with this name. */
- for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; slot < len; ++slot)
+ for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ VEC_iterate (tree, method_vec, slot, m);
+ ++slot)
{
- tree m = TREE_VEC_ELT (method_vec, slot);
-
- if (!m)
- break;
m = OVL_CURRENT (m);
-
if (template_conv_p)
{
- have_template_convs_p = (TREE_CODE (m) == TEMPLATE_DECL
- && DECL_TEMPLATE_CONV_FN_P (m));
-
- /* If we need to move things up, see if there's
- space. */
- if (!have_template_convs_p)
- {
- slot = len - 1;
- if (TREE_VEC_ELT (method_vec, slot))
- slot++;
- }
+ if (TREE_CODE (m) == TEMPLATE_DECL
+ && DECL_TEMPLATE_CONV_FN_P (m))
+ insert_p = false;
break;
}
- if (DECL_NAME (m) == DECL_NAME (method))
+ if (conv_p && !DECL_CONV_FN_P (m))
break;
- }
-
- if (slot == len)
- {
- /* We need a bigger method vector. */
- int new_len;
- tree new_vec;
-
- /* In the non-error case, we are processing a class
- definition. Double the size of the vector to give room
- for new methods. */
- if (!error_p)
- new_len = 2 * len;
- /* In the error case, the vector is already complete. We
- don't expect many errors, and the rest of the front-end
- will get confused if there are empty slots in the vector. */
- else
- new_len = len + 1;
-
- new_vec = make_tree_vec (new_len);
- memcpy (&TREE_VEC_ELT (new_vec, 0), &TREE_VEC_ELT (method_vec, 0),
- len * sizeof (tree));
- len = new_len;
- method_vec = CLASSTYPE_METHOD_VEC (type) = new_vec;
- }
-
- if (DECL_CONV_FN_P (method) && !TREE_VEC_ELT (method_vec, slot))
- {
- /* Type conversion operators have to come before ordinary
- methods; add_conversions depends on this to speed up
- looking for conversion operators. So, if necessary, we
- slide some of the vector elements up. In theory, this
- makes this algorithm O(N^2) but we don't expect many
- conversion operators. */
- if (template_conv_p)
- slot = CLASSTYPE_FIRST_CONVERSION_SLOT;
- else
- for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; slot < len; ++slot)
- {
- tree fn = TREE_VEC_ELT (method_vec, slot);
-
- if (!fn)
- /* There are no more entries in the vector, so we
- can insert the new conversion operator here. */
- break;
-
- if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
- /* We can insert the new function right at the
- SLOTth position. */
- break;
- }
-
- if (template_conv_p && have_template_convs_p)
- /*OK*/;
- else if (!TREE_VEC_ELT (method_vec, slot))
- /* There is nothing in the Ith slot, so we can avoid
- moving anything. */
- ;
- else
+ if (DECL_NAME (m) == DECL_NAME (method))
{
- /* We know the last slot in the vector is empty
- because we know that at this point there's room
- for a new function. */
- memmove (&TREE_VEC_ELT (method_vec, slot + 1),
- &TREE_VEC_ELT (method_vec, slot),
- (len - slot - 1) * sizeof (tree));
- TREE_VEC_ELT (method_vec, slot) = NULL_TREE;
+ insert_p = false;
+ break;
}
+ if (complete_p
+ && !DECL_CONV_FN_P (m)
+ && DECL_NAME (m) > DECL_NAME (method))
+ break;
}
}
-
+ current_fns = insert_p ? NULL_TREE : VEC_index (tree, method_vec, slot);
+
if (processing_template_decl)
/* TYPE is a template class. Don't issue any errors now; wait
until instantiation time to complain. */
tree fns;
/* Check to see if we've already got this method. */
- for (fns = TREE_VEC_ELT (method_vec, slot);
- fns;
- fns = OVL_NEXT (fns))
+ for (fns = current_fns; fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
tree parms1;
}
}
- /* Actually insert the new method. */
- TREE_VEC_ELT (method_vec, slot)
- = build_overload (method, TREE_VEC_ELT (method_vec, slot));
-
/* Add the new binding. */
- if (!DECL_CONSTRUCTOR_P (method)
- && !DECL_DESTRUCTOR_P (method))
- push_class_level_binding (DECL_NAME (method),
- TREE_VEC_ELT (method_vec, slot));
+ overload = build_overload (method, current_fns);
+
+ if (slot >= CLASSTYPE_FIRST_CONVERSION_SLOT && !complete_p)
+ push_class_level_binding (DECL_NAME (method), overload);
+
+ if (insert_p)
+ {
+ /* We only expect to add few methods in the COMPLETE_P case, so
+ just make room for one more method in that case. */
+ if (VEC_reserve (tree, method_vec, complete_p ? 1 : -1))
+ CLASSTYPE_METHOD_VEC (type) = method_vec;
+ if (slot == VEC_length (tree, method_vec))
+ VEC_quick_push (tree, method_vec, overload);
+ else
+ VEC_quick_insert (tree, method_vec, slot, overload);
+ }
+ else
+ /* Replace the current slot. */
+ VEC_replace (tree, method_vec, slot, overload);
}
/* Subroutines of finish_struct. */
if (!DECL_LANG_SPECIFIC (fdecl))
retrofit_lang_decl (fdecl);
- my_friendly_assert (!DECL_DISCRIMINATOR_P (fdecl), 20030624);
+ gcc_assert (!DECL_DISCRIMINATOR_P (fdecl));
elem = purpose_member (t, DECL_ACCESS (fdecl));
if (elem)
/* Ignore base type this came from. */
fdecl = BASELINK_FUNCTIONS (fdecl);
- old_value = IDENTIFIER_CLASS_VALUE (name);
+ old_value = lookup_member (t, name, /*protect=*/0, /*want_type=*/false);
if (old_value)
{
if (is_overloaded_fn (old_value))
if (flist)
for (; flist; flist = OVL_NEXT (flist))
{
- add_method (t, OVL_CURRENT (flist), /*error_p=*/0);
+ add_method (t, OVL_CURRENT (flist));
alter_access (t, OVL_CURRENT (flist), access);
}
else
int* cant_have_const_ctor_p,
int* no_const_asn_ref_p)
{
- int n_baseclasses;
int i;
int seen_non_virtual_nearly_empty_base_p;
- tree binfos;
+ tree base_binfo;
+ tree binfo;
- binfos = TYPE_BINFO_BASETYPES (t);
- n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
seen_non_virtual_nearly_empty_base_p = 0;
- /* An aggregate cannot have baseclasses. */
- CLASSTYPE_NON_AGGREGATE (t) |= (n_baseclasses != 0);
-
- for (i = 0; i < n_baseclasses; ++i)
+ for (binfo = TYPE_BINFO (t), i = 0;
+ BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
{
- tree base_binfo;
- tree basetype;
-
- /* Figure out what base we're looking at. */
- base_binfo = TREE_VEC_ELT (binfos, i);
- basetype = TREE_TYPE (base_binfo);
-
- /* If the type of basetype is incomplete, then we already
- complained about that fact (and we should have fixed it up as
- well). */
- if (!COMPLETE_TYPE_P (basetype))
- {
- int j;
- /* The base type is of incomplete type. It is
- probably best to pretend that it does not
- exist. */
- if (i == n_baseclasses-1)
- TREE_VEC_ELT (binfos, i) = NULL_TREE;
- TREE_VEC_LENGTH (binfos) -= 1;
- n_baseclasses -= 1;
- for (j = i; j+1 < n_baseclasses; j++)
- TREE_VEC_ELT (binfos, j) = TREE_VEC_ELT (binfos, j+1);
- continue;
- }
+ tree basetype = TREE_TYPE (base_binfo);
+ gcc_assert (COMPLETE_TYPE_P (basetype));
+
/* Effective C++ rule 14. We only need to check TYPE_POLYMORPHIC_P
here because the case of virtual functions but non-virtual
dtor is handled in finish_struct_1. */
basetype);
}
- if (TREE_VIA_VIRTUAL (base_binfo))
+ if (BINFO_VIRTUAL_P (base_binfo))
/* A virtual base does not effect nearly emptiness. */
;
else if (CLASSTYPE_NEARLY_EMPTY_P (basetype))
}
}
-/* Set BINFO_PRIMARY_BASE_OF for all binfos in the hierarchy
- dominated by TYPE that are primary bases. */
+/* Determine all the primary bases within T. Sets BINFO_PRIMARY_BASE_P for
+ those that are primaries. Sets BINFO_LOST_PRIMARY_P for those
+ that have had a nearly-empty virtual primary base stolen by some
+ other base in the heirarchy. Determines CLASSTYPE_PRIMARY_BASE for
+ T. */
static void
-mark_primary_bases (tree type)
+determine_primary_bases (tree t)
{
- tree binfo;
-
- /* Walk the bases in inheritance graph order. */
- for (binfo = TYPE_BINFO (type); binfo; binfo = TREE_CHAIN (binfo))
+ unsigned i;
+ tree primary = NULL_TREE;
+ tree type_binfo = TYPE_BINFO (t);
+ tree base_binfo;
+
+ /* Determine the primary bases of our bases. */
+ for (base_binfo = TREE_CHAIN (type_binfo); base_binfo;
+ base_binfo = TREE_CHAIN (base_binfo))
{
- tree base_binfo = get_primary_binfo (binfo);
+ tree primary = CLASSTYPE_PRIMARY_BINFO (BINFO_TYPE (base_binfo));
- if (!base_binfo)
- /* Not a dynamic base. */;
- else if (BINFO_PRIMARY_P (base_binfo))
- BINFO_LOST_PRIMARY_P (binfo) = 1;
- else
+ /* See if we're the non-virtual primary of our inheritance
+ chain. */
+ if (!BINFO_VIRTUAL_P (base_binfo))
{
- BINFO_PRIMARY_BASE_OF (base_binfo) = binfo;
- /* A virtual binfo might have been copied from within
- another hierarchy. As we're about to use it as a primary
- base, make sure the offsets match. */
- if (TREE_VIA_VIRTUAL (base_binfo))
- {
- tree delta = size_diffop (convert (ssizetype,
- BINFO_OFFSET (binfo)),
- convert (ssizetype,
- BINFO_OFFSET (base_binfo)));
+ tree parent = BINFO_INHERITANCE_CHAIN (base_binfo);
+ tree parent_primary = CLASSTYPE_PRIMARY_BINFO (BINFO_TYPE (parent));
- propagate_binfo_offsets (base_binfo, delta);
- }
+ if (parent_primary
+ && BINFO_TYPE (base_binfo) == BINFO_TYPE (parent_primary))
+ /* We are the primary binfo. */
+ BINFO_PRIMARY_P (base_binfo) = 1;
}
- }
-}
-
-/* Make the BINFO the primary base of T. */
-
-static void
-set_primary_base (tree t, tree binfo)
-{
- tree basetype;
-
- CLASSTYPE_PRIMARY_BINFO (t) = binfo;
- basetype = BINFO_TYPE (binfo);
- TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype);
- TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
- TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
-}
-
-/* Determine the primary class for T. */
-
-static void
-determine_primary_base (tree t)
-{
- unsigned i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
- tree type_binfo;
- tree vbase_binfo;
-
- /* If there are no baseclasses, there is certainly no primary base. */
- if (n_baseclasses == 0)
- return;
-
- type_binfo = TYPE_BINFO (t);
-
- for (i = 0; i < n_baseclasses; i++)
- {
- tree base_binfo = BINFO_BASETYPE (type_binfo, i);
- tree basetype = BINFO_TYPE (base_binfo);
-
- if (TYPE_CONTAINS_VPTR_P (basetype))
+ /* Determine if we have a virtual primary base, and mark it so.
+ */
+ if (primary && BINFO_VIRTUAL_P (primary))
{
- /* We prefer a non-virtual base, although a virtual one will
- do. */
- if (TREE_VIA_VIRTUAL (base_binfo))
- continue;
+ tree this_primary = copied_binfo (primary, base_binfo);
- if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
- {
- set_primary_base (t, base_binfo);
- CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype));
- }
+ if (BINFO_PRIMARY_P (this_primary))
+ /* Someone already claimed this base. */
+ BINFO_LOST_PRIMARY_P (base_binfo) = 1;
else
{
- tree vfields;
-
- /* Only add unique vfields, and flatten them out as we go. */
- for (vfields = CLASSTYPE_VFIELDS (basetype);
- vfields;
- vfields = TREE_CHAIN (vfields))
- if (VF_BINFO_VALUE (vfields) == NULL_TREE
- || ! TREE_VIA_VIRTUAL (VF_BINFO_VALUE (vfields)))
- CLASSTYPE_VFIELDS (t)
- = tree_cons (base_binfo,
- VF_BASETYPE_VALUE (vfields),
- CLASSTYPE_VFIELDS (t));
+ tree delta;
+
+ BINFO_PRIMARY_P (this_primary) = 1;
+ BINFO_INHERITANCE_CHAIN (this_primary) = base_binfo;
+
+ /* A virtual binfo might have been copied from within
+ another hierarchy. As we're about to use it as a
+ primary base, make sure the offsets match. */
+ delta = size_diffop (convert (ssizetype,
+ BINFO_OFFSET (base_binfo)),
+ convert (ssizetype,
+ BINFO_OFFSET (this_primary)));
+
+ propagate_binfo_offsets (this_primary, delta);
}
}
}
- if (!TYPE_VFIELD (t))
- CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;
-
- /* Find the indirect primary bases - those virtual bases which are primary
- bases of something else in this hierarchy. */
- for (i = 0; (vbase_binfo = VEC_iterate
- (tree, CLASSTYPE_VBASECLASSES (t), i)); i++)
+ /* First look for a dynamic direct non-virtual base. */
+ for (i = 0; BINFO_BASE_ITERATE (type_binfo, i, base_binfo); i++)
{
- unsigned j;
+ tree basetype = BINFO_TYPE (base_binfo);
- /* See if this virtual base is an indirect primary base. To be
- so, it must be a primary base within the hierarchy of one of
- our direct bases. */
- for (j = 0; j != n_baseclasses; ++j)
+ if (TYPE_CONTAINS_VPTR_P (basetype) && !BINFO_VIRTUAL_P (base_binfo))
{
- unsigned k;
- tree base_vbase_binfo;
- tree basetype = TYPE_BINFO_BASETYPE (t, j);
-
- for (k = 0; (base_vbase_binfo = VEC_iterate
- (tree, CLASSTYPE_VBASECLASSES (basetype), k)); k++)
- {
- if (BINFO_PRIMARY_P (base_vbase_binfo)
- && same_type_p (BINFO_TYPE (base_vbase_binfo),
- BINFO_TYPE (vbase_binfo)))
- {
- BINFO_INDIRECT_PRIMARY_P (vbase_binfo) = 1;
- break;
- }
- }
-
- /* If we've discovered that this virtual base is an indirect
- primary base, then we can move on to the next virtual
- base. */
- if (BINFO_INDIRECT_PRIMARY_P (vbase_binfo))
- break;
+ primary = base_binfo;
+ goto found;
}
}
/* A "nearly-empty" virtual base class can be the primary base
- class, if no non-virtual polymorphic base can be found. */
- if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
+ class, if no non-virtual polymorphic base can be found. Look for
+ a nearly-empty virtual dynamic base that is not already a primary
+ base of something in the heirarchy. If there is no such base,
+ just pick the first nearly-empty virtual base. */
+
+ for (base_binfo = TREE_CHAIN (type_binfo); base_binfo;
+ base_binfo = TREE_CHAIN (base_binfo))
+ if (BINFO_VIRTUAL_P (base_binfo)
+ && CLASSTYPE_NEARLY_EMPTY_P (BINFO_TYPE (base_binfo)))
+ {
+ if (!BINFO_PRIMARY_P (base_binfo))
+ {
+ /* Found one that is not primary. */
+ primary = base_binfo;
+ goto found;
+ }
+ else if (!primary)
+ /* Remember the first candidate. */
+ primary = base_binfo;
+ }
+
+ found:
+ /* If we've got a primary base, use it. */
+ if (primary)
{
- /* If not NULL, this is the best primary base candidate we have
- found so far. */
- tree candidate = NULL_TREE;
- tree base_binfo;
-
- /* Loop over the baseclasses. */
- for (base_binfo = TYPE_BINFO (t);
- base_binfo;
- base_binfo = TREE_CHAIN (base_binfo))
+ tree basetype = BINFO_TYPE (primary);
+
+ CLASSTYPE_PRIMARY_BINFO (t) = primary;
+ if (BINFO_PRIMARY_P (primary))
+ /* We are stealing a primary base. */
+ BINFO_LOST_PRIMARY_P (BINFO_INHERITANCE_CHAIN (primary)) = 1;
+ BINFO_PRIMARY_P (primary) = 1;
+ if (BINFO_VIRTUAL_P (primary))
{
- tree basetype = BINFO_TYPE (base_binfo);
-
- if (TREE_VIA_VIRTUAL (base_binfo)
- && CLASSTYPE_NEARLY_EMPTY_P (basetype))
- {
- /* If this is not an indirect primary base, then it's
- definitely our primary base. */
- if (!BINFO_INDIRECT_PRIMARY_P (base_binfo))
- {
- candidate = base_binfo;
- break;
- }
+ tree delta;
- /* If this is an indirect primary base, it still could be
- our primary base -- unless we later find there's another
- nearly-empty virtual base that isn't an indirect
- primary base. */
- if (!candidate)
- candidate = base_binfo;
- }
+ BINFO_INHERITANCE_CHAIN (primary) = type_binfo;
+ /* A virtual binfo might have been copied from within
+ another hierarchy. As we're about to use it as a primary
+ base, make sure the offsets match. */
+ delta = size_diffop (ssize_int (0),
+ convert (ssizetype, BINFO_OFFSET (primary)));
+
+ propagate_binfo_offsets (primary, delta);
}
-
- /* If we've got a primary base, use it. */
- if (candidate)
- {
- set_primary_base (t, candidate);
- CLASSTYPE_VFIELDS (t)
- = copy_list (CLASSTYPE_VFIELDS (BINFO_TYPE (candidate)));
- }
+
+ primary = TYPE_BINFO (basetype);
+
+ TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
+ BINFO_VTABLE (type_binfo) = BINFO_VTABLE (primary);
+ BINFO_VIRTUALS (type_binfo) = BINFO_VIRTUALS (primary);
}
-
- /* Mark the primary base classes at this point. */
- mark_primary_bases (t);
}
\f
/* Set memoizing fields and bits of T (and its variants) for later
static void
finish_struct_bits (tree t)
{
- int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
-
+ tree variants;
+
/* Fix up variants (if any). */
- tree variants = TYPE_NEXT_VARIANT (t);
- while (variants)
+ for (variants = TYPE_NEXT_VARIANT (t);
+ variants;
+ variants = TYPE_NEXT_VARIANT (variants))
{
/* These fields are in the _TYPE part of the node, not in
the TYPE_LANG_SPECIFIC component, so they are not shared. */
TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (variants)
= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (t);
TYPE_POLYMORPHIC_P (variants) = TYPE_POLYMORPHIC_P (t);
- TYPE_USES_VIRTUAL_BASECLASSES (variants) = TYPE_USES_VIRTUAL_BASECLASSES (t);
+ TYPE_USES_VIRTUAL_BASECLASSES (variants)
+ = TYPE_USES_VIRTUAL_BASECLASSES (t);
+
+ TYPE_BINFO (variants) = TYPE_BINFO (t);
+
/* Copy whatever these are holding today. */
TYPE_VFIELD (variants) = TYPE_VFIELD (t);
TYPE_METHODS (variants) = TYPE_METHODS (t);
TYPE_FIELDS (variants) = TYPE_FIELDS (t);
TYPE_SIZE (variants) = TYPE_SIZE (t);
TYPE_SIZE_UNIT (variants) = TYPE_SIZE_UNIT (t);
- variants = TYPE_NEXT_VARIANT (variants);
}
- if (n_baseclasses && TYPE_POLYMORPHIC_P (t))
+ if (BINFO_N_BASE_BINFOS (TYPE_BINFO (t)) && TYPE_POLYMORPHIC_P (t))
/* For a class w/o baseclasses, `finish_struct' has set
- CLASS_TYPE_ABSTRACT_VIRTUALS correctly (by
- definition). Similarly for a class whose base classes do not
- have vtables. When neither of these is true, we might have
- removed abstract virtuals (by providing a definition), added
- some (by declaring new ones), or redeclared ones from a base
- class. We need to recalculate what's really an abstract virtual
- at this point (by looking in the vtables). */
- get_pure_virtuals (t);
-
- if (n_baseclasses)
- {
- /* Notice whether this class has type conversion functions defined. */
- tree binfo = TYPE_BINFO (t);
- tree binfos = BINFO_BASETYPES (binfo);
- tree basetype;
-
- for (i = n_baseclasses-1; i >= 0; i--)
- {
- basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
-
- TYPE_HAS_CONVERSION (t) |= TYPE_HAS_CONVERSION (basetype);
- }
- }
-
- /* If this type has a copy constructor or a destructor, force its mode to
- be BLKmode, and force its TREE_ADDRESSABLE bit to be nonzero. This
- will cause it to be passed by invisible reference and prevent it from
- being returned in a register. */
+ CLASS_TYPE_ABSTRACT_VIRTUALS correctly (by definition).
+ Similarly for a class whose base classes do not have vtables.
+ When neither of these is true, we might have removed abstract
+ virtuals (by providing a definition), added some (by declaring
+ new ones), or redeclared ones from a base class. We need to
+ recalculate what's really an abstract virtual at this point (by
+ looking in the vtables). */
+ get_pure_virtuals (t);
+
+ /* If this type has a copy constructor or a destructor, force its
+ mode to be BLKmode, and force its TREE_ADDRESSABLE bit to be
+ nonzero. This will cause it to be passed by invisible reference
+ and prevent it from being returned in a register. */
if (! TYPE_HAS_TRIVIAL_INIT_REF (t) || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t))
{
tree variants;
constructors/destructors we want to use the code below that
issues error messages specifically referring to
constructors/destructors.) */
- int i;
+ unsigned i;
tree binfo = TYPE_BINFO (t);
- for (i = 0; i < BINFO_N_BASETYPES (binfo); i++)
- if (BINFO_BASEACCESS (binfo, i) != access_private_node)
+ for (i = 0; i != BINFO_N_BASE_BINFOS (binfo); i++)
+ if (BINFO_BASE_ACCESS (binfo, i) != access_private_node)
{
has_nonprivate_method = 1;
break;
if (!TYPE_HAS_INIT_REF (t))
nonprivate_ctor = 1;
else
- for (fn = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0);
- fn;
- fn = OVL_NEXT (fn))
+ for (fn = CLASSTYPE_CONSTRUCTORS (t); fn; fn = OVL_NEXT (fn))
{
tree ctor = OVL_CURRENT (fn);
/* Ideally, we wouldn't count copy constructors (or, in
gt_pointer_operator new_value,
void* cookie)
{
- tree method_vec = obj;
- int len = TREE_VEC_LENGTH (method_vec);
- int slot;
+ VEC(tree) *method_vec = (VEC(tree) *) obj;
+ int len = VEC_length (tree, method_vec);
+ size_t slot;
+ tree fn;
/* The type conversion ops have to live at the front of the vec, so we
can't sort them. */
- for (slot = 2; slot < len; ++slot)
- {
- tree fn = TREE_VEC_ELT (method_vec, slot);
-
- if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
- break;
- }
+ for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ VEC_iterate (tree, method_vec, slot, fn);
+ ++slot)
+ if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
+ break;
+
if (len - slot > 1)
{
resort_data.new_value = new_value;
resort_data.cookie = cookie;
- qsort (&TREE_VEC_ELT (method_vec, slot), len - slot, sizeof (tree),
+ qsort (VEC_address (tree, method_vec) + slot, len - slot, sizeof (tree),
resort_method_name_cmp);
}
}
finish_struct_methods (tree t)
{
tree fn_fields;
- tree method_vec;
+ VEC(tree) *method_vec;
int slot, len;
- if (!TYPE_METHODS (t))
- {
- /* Clear these for safety; perhaps some parsing error could set
- these incorrectly. */
- TYPE_HAS_CONSTRUCTOR (t) = 0;
- TYPE_HAS_DESTRUCTOR (t) = 0;
- CLASSTYPE_METHOD_VEC (t) = NULL_TREE;
- return;
- }
-
method_vec = CLASSTYPE_METHOD_VEC (t);
- my_friendly_assert (method_vec != NULL_TREE, 19991215);
- len = TREE_VEC_LENGTH (method_vec);
+ if (!method_vec)
+ return;
+
+ len = VEC_length (tree, method_vec);
/* First fill in entry 0 with the constructors, entry 1 with destructors,
and the next few with type conversion operators (if any). */
no methods, then some public defaults are generated. */
maybe_warn_about_overly_private_class (t);
- /* Now sort the methods. */
- while (len > 2 && TREE_VEC_ELT (method_vec, len-1) == NULL_TREE)
- len--;
- TREE_VEC_LENGTH (method_vec) = len;
-
/* The type conversion ops have to live at the front of the vec, so we
can't sort them. */
- for (slot = 2; slot < len; ++slot)
- {
- tree fn = TREE_VEC_ELT (method_vec, slot);
-
- if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
- break;
- }
+ for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ VEC_iterate (tree, method_vec, slot, fn_fields);
+ ++slot)
+ if (!DECL_CONV_FN_P (OVL_CURRENT (fn_fields)))
+ break;
if (len - slot > 1)
- qsort (&TREE_VEC_ELT (method_vec, slot), len-slot, sizeof (tree),
- method_name_cmp);
+ qsort (VEC_address (tree, method_vec) + slot,
+ len-slot, sizeof (tree), method_name_cmp);
}
/* Make BINFO's vtable have N entries, including RTTI entries,
{
if (probe == derived)
return true;
- else if (TREE_VIA_VIRTUAL (probe))
+ else if (BINFO_VIRTUAL_P (probe))
/* If we meet a virtual base, we can't follow the inheritance
any more. See if the complete type of DERIVED contains
such a virtual base. */
return false;
}
+typedef struct count_depth_data {
+ /* The depth of the current subobject, with "1" as the depth of the
+ most derived object in the hierarchy. */
+ size_t depth;
+ /* The maximum depth found so far. */
+ size_t max_depth;
+} count_depth_data;
+
+/* Called from find_final_overrider via dfs_walk. */
+
+static tree
+dfs_depth_post (tree binfo ATTRIBUTE_UNUSED, void *data)
+{
+ count_depth_data *cd = (count_depth_data *) data;
+ if (cd->depth > cd->max_depth)
+ cd->max_depth = cd->depth;
+ cd->depth--;
+ return NULL_TREE;
+}
+
+/* Called from find_final_overrider via dfs_walk. */
+
+static tree
+dfs_depth_q (tree derived, int i, void *data)
+{
+ count_depth_data *cd = (count_depth_data *) data;
+ cd->depth++;
+ return BINFO_BASE_BINFO (derived, i);
+}
+
typedef struct find_final_overrider_data_s {
/* The function for which we are trying to find a final overrider. */
tree fn;
tree most_derived_type;
/* The candidate overriders. */
tree candidates;
- /* Binfos which inherited virtually on the current path. */
- tree vpath;
+ /* Each entry in this array is the next-most-derived class for a
+ virtual base class along the current path. */
+ tree *vpath_list;
+ /* A pointer one past the top of the VPATH_LIST. */
+ tree *vpath;
} find_final_overrider_data;
-/* Called from find_final_overrider via dfs_walk. */
+/* Add the overrider along the current path to FFOD->CANDIDATES.
+ Returns true if an overrider was found; false otherwise. */
-static tree
-dfs_find_final_overrider (tree binfo, void* data)
+static bool
+dfs_find_final_overrider_1 (tree binfo,
+ tree *vpath,
+ find_final_overrider_data *ffod)
{
- find_final_overrider_data *ffod = (find_final_overrider_data *) data;
+ tree method;
- if (binfo == ffod->declaring_base)
+ /* If BINFO is not the most derived type, try a more derived class.
+ A definition there will overrider a definition here. */
+ if (!same_type_p (BINFO_TYPE (binfo), ffod->most_derived_type))
{
- /* We've found a path to the declaring base. Walk the path from
- derived to base, looking for an overrider for FN. */
- tree path, probe, vpath;
+ tree derived;
+
+ if (BINFO_VIRTUAL_P (binfo))
+ derived = *--vpath;
+ else
+ derived = BINFO_INHERITANCE_CHAIN (binfo);
+ if (dfs_find_final_overrider_1 (derived, vpath, ffod))
+ return true;
+ }
- /* Build the path, using the inheritance chain and record of
- virtual inheritance. */
- for (path = NULL_TREE, probe = binfo, vpath = ffod->vpath;;)
+ method = look_for_overrides_here (BINFO_TYPE (binfo), ffod->fn);
+ if (method)
+ {
+ tree *candidate = &ffod->candidates;
+
+ /* Remove any candidates overridden by this new function. */
+ while (*candidate)
{
- path = tree_cons (NULL_TREE, probe, path);
- if (same_type_p (BINFO_TYPE (probe), ffod->most_derived_type))
- break;
- if (TREE_VIA_VIRTUAL (probe))
- {
- probe = TREE_VALUE (vpath);
- vpath = TREE_CHAIN (vpath);
- }
+ /* If *CANDIDATE overrides METHOD, then METHOD
+ cannot override anything else on the list. */
+ if (base_derived_from (TREE_VALUE (*candidate), binfo))
+ return true;
+ /* If METHOD overrides *CANDIDATE, remove *CANDIDATE. */
+ if (base_derived_from (binfo, TREE_VALUE (*candidate)))
+ *candidate = TREE_CHAIN (*candidate);
else
- probe = BINFO_INHERITANCE_CHAIN (probe);
- }
- /* Now walk path, looking for overrides. */
- for (; path; path = TREE_CHAIN (path))
- {
- tree method = look_for_overrides_here
- (BINFO_TYPE (TREE_VALUE (path)), ffod->fn);
-
- if (method)
- {
- tree *candidate = &ffod->candidates;
- path = TREE_VALUE (path);
-
- /* Remove any candidates overridden by this new function. */
- while (*candidate)
- {
- /* If *CANDIDATE overrides METHOD, then METHOD
- cannot override anything else on the list. */
- if (base_derived_from (TREE_VALUE (*candidate), path))
- return NULL_TREE;
- /* If METHOD overrides *CANDIDATE, remove *CANDIDATE. */
- if (base_derived_from (path, TREE_VALUE (*candidate)))
- *candidate = TREE_CHAIN (*candidate);
- else
- candidate = &TREE_CHAIN (*candidate);
- }
-
- /* Add the new function. */
- ffod->candidates = tree_cons (method, path, ffod->candidates);
- break;
- }
+ candidate = &TREE_CHAIN (*candidate);
}
+
+ /* Add the new function. */
+ ffod->candidates = tree_cons (method, binfo, ffod->candidates);
+ return true;
}
+ return false;
+}
+
+/* Called from find_final_overrider via dfs_walk. */
+
+static tree
+dfs_find_final_overrider (tree binfo, void* data)
+{
+ find_final_overrider_data *ffod = (find_final_overrider_data *) data;
+
+ if (binfo == ffod->declaring_base)
+ dfs_find_final_overrider_1 (binfo, ffod->vpath, ffod);
+
return NULL_TREE;
}
static tree
dfs_find_final_overrider_q (tree derived, int ix, void *data)
{
- tree binfo = BINFO_BASETYPE (derived, ix);
+ tree binfo = BINFO_BASE_BINFO (derived, ix);
find_final_overrider_data *ffod = (find_final_overrider_data *) data;
- if (TREE_VIA_VIRTUAL (binfo))
- ffod->vpath = tree_cons (NULL_TREE, derived, ffod->vpath);
+ if (BINFO_VIRTUAL_P (binfo))
+ *ffod->vpath++ = derived;
return binfo;
}
{
find_final_overrider_data *ffod = (find_final_overrider_data *) data;
- if (TREE_VIA_VIRTUAL (binfo) && TREE_CHAIN (ffod->vpath))
- ffod->vpath = TREE_CHAIN (ffod->vpath);
+ if (BINFO_VIRTUAL_P (binfo))
+ ffod->vpath--;
return NULL_TREE;
}
find_final_overrider (tree derived, tree binfo, tree fn)
{
find_final_overrider_data ffod;
+ count_depth_data cd;
/* Getting this right is a little tricky. This is valid:
different overriders along any two, then there is a problem. */
if (DECL_THUNK_P (fn))
fn = THUNK_TARGET (fn);
-
+
+ /* Determine the depth of the hierarchy. */
+ cd.depth = 0;
+ cd.max_depth = 0;
+ dfs_walk (derived, dfs_depth_post, dfs_depth_q, &cd);
+
ffod.fn = fn;
ffod.declaring_base = binfo;
ffod.most_derived_type = BINFO_TYPE (derived);
ffod.candidates = NULL_TREE;
- ffod.vpath = NULL_TREE;
+ ffod.vpath_list = (tree *) xcalloc (cd.max_depth, sizeof (tree));
+ ffod.vpath = ffod.vpath_list;
dfs_walk_real (derived,
dfs_find_final_overrider,
dfs_find_final_overrider_q,
&ffod);
+ free (ffod.vpath_list);
+
/* If there was no winner, issue an error message. */
if (!ffod.candidates || TREE_CHAIN (ffod.candidates))
{
static tree
get_vcall_index (tree fn, tree type)
{
- tree v;
+ VEC (tree_pair_s) *indices = CLASSTYPE_VCALL_INDICES (type);
+ tree_pair_p p;
+ unsigned ix;
- 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;
+ for (ix = 0; VEC_iterate (tree_pair_s, indices, ix, p); ix++)
+ if ((DECL_DESTRUCTOR_P (fn) && DECL_DESTRUCTOR_P (p->purpose))
+ || same_signature_p (fn, p->purpose))
+ return p->value;
/* There should always be an appropriate index. */
- my_friendly_assert (v, 20021103);
-
- return TREE_VALUE (v);
+ gcc_unreachable ();
}
/* Update an entry in the vtable for BINFO, which is in the hierarchy
calling FN through BINFO. */
for (b = binfo; ; b = get_primary_binfo (b))
{
- my_friendly_assert (b, 20021227);
+ gcc_assert (b);
if (look_for_overrides_here (BINFO_TYPE (b), target_fn))
break;
if (DECL_THUNK_P (fn))
{
- my_friendly_assert (DECL_RESULT_THUNK_P (fn), 20031211);
+ gcc_assert (DECL_RESULT_THUNK_P (fn));
fixed_offset = ssize_int (THUNK_FIXED_OFFSET (fn));
virtual_offset = THUNK_VIRTUAL_OFFSET (fn);
}
{
/* We convert via virtual base. Find the virtual
base and adjust the fixed offset to be from there. */
- while (!TREE_VIA_VIRTUAL (thunk_binfo))
+ while (!BINFO_VIRTUAL_P (thunk_binfo))
thunk_binfo = BINFO_INHERITANCE_CHAIN (thunk_binfo);
virtual_offset = thunk_binfo;
fixed_offset, virtual_offset);
}
else
- my_friendly_assert (!DECL_THUNK_P (fn), 20021231);
+ gcc_assert (!DECL_THUNK_P (fn));
/* Assume that we will produce a thunk that convert all the way to
the final overrider, and not to an intermediate virtual base. */
/* If we find a virtual base, and we haven't yet found the
overrider, then there is a virtual base between the
declaring base (first_defn) and the final overrider. */
- if (TREE_VIA_VIRTUAL (b))
+ if (BINFO_VIRTUAL_P (b))
{
virtual_base = b;
break;
while ((probe = get_primary_binfo (probe))
&& (unsigned) list_length (BINFO_VIRTUALS (probe)) > ix)
- if (TREE_VIA_VIRTUAL (probe))
+ if (BINFO_VIRTUAL_P (probe))
virtual_base = probe;
if (virtual_base)
static tree
dfs_modify_vtables (tree binfo, void* data)
{
+ tree t = (tree) data;
+
if (/* There's no need to modify the vtable for a non-virtual
primary base; we're not going to use that vtable anyhow.
We do still need to do this for virtual primary bases, as they
could become non-primary in a construction vtable. */
- (!BINFO_PRIMARY_P (binfo) || TREE_VIA_VIRTUAL (binfo))
+ (!BINFO_PRIMARY_P (binfo) || BINFO_VIRTUAL_P (binfo))
/* Similarly, a base without a vtable needs no modification. */
- && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
+ && TYPE_CONTAINS_VPTR_P (BINFO_TYPE (binfo))
+ /* Don't do the primary vtable, if it's new. */
+ && (BINFO_TYPE (binfo) != t || CLASSTYPE_HAS_PRIMARY_BASE_P (t)))
{
- tree t = (tree) data;
tree virtuals;
tree old_virtuals;
unsigned ix;
{
tree methods;
tree base_fndecls = NULL_TREE;
- int n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
+ int n_baseclasses = BINFO_N_BASE_BINFOS (TYPE_BINFO (t));
int i;
/* Find virtual functions in T with the indicated NAME. */
i = lookup_fnfields_1 (t, name);
if (i != -1)
- for (methods = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), i);
+ for (methods = VEC_index (tree, CLASSTYPE_METHOD_VEC (t), i);
methods;
methods = OVL_NEXT (methods))
{
for (i = 0; i < n_baseclasses; i++)
{
- tree basetype = TYPE_BINFO_BASETYPE (t, i);
+ tree basetype = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (t), i));
base_fndecls = chainon (get_basefndecls (name, basetype),
base_fndecls);
}
void
warn_hidden (tree t)
{
- tree method_vec = CLASSTYPE_METHOD_VEC (t);
- int n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0;
- int i;
+ VEC(tree) *method_vec = CLASSTYPE_METHOD_VEC (t);
+ tree fns;
+ size_t i;
/* We go through each separately named virtual function. */
- for (i = 2; i < n_methods && TREE_VEC_ELT (method_vec, i); ++i)
+ for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ VEC_iterate (tree, method_vec, i, fns);
+ ++i)
{
- tree fns;
+ tree fn;
tree name;
tree fndecl;
tree base_fndecls;
+ tree base_binfo;
+ tree binfo;
int j;
/* All functions in this slot in the CLASSTYPE_METHOD_VEC will
have the same name. Figure out what name that is. */
- name = DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, i)));
+ name = DECL_NAME (OVL_CURRENT (fns));
/* There are no possibly hidden functions yet. */
base_fndecls = NULL_TREE;
/* Iterate through all of the base classes looking for possibly
hidden functions. */
- for (j = 0; j < CLASSTYPE_N_BASECLASSES (t); j++)
+ for (binfo = TYPE_BINFO (t), j = 0;
+ BINFO_BASE_ITERATE (binfo, j, base_binfo); j++)
{
- tree basetype = TYPE_BINFO_BASETYPE (t, j);
+ tree basetype = BINFO_TYPE (base_binfo);
base_fndecls = chainon (get_basefndecls (name, basetype),
base_fndecls);
}
continue;
/* Remove any overridden functions. */
- for (fns = TREE_VEC_ELT (method_vec, i); fns; fns = OVL_NEXT (fns))
+ for (fn = fns; fn; fn = OVL_NEXT (fn))
{
- fndecl = OVL_CURRENT (fns);
+ fndecl = OVL_CURRENT (fn);
if (DECL_VINDEX (fndecl))
{
tree *prev = &base_fndecls;
{
/* Here we know it is a hider, and no overrider exists. */
cp_warning_at ("`%D' was hidden", TREE_VALUE (base_fndecls));
- cp_warning_at (" by `%D'",
- OVL_CURRENT (TREE_VEC_ELT (method_vec, i)));
+ cp_warning_at (" by `%D'", fns);
base_fndecls = TREE_CHAIN (base_fndecls);
}
}
/* Default constructor. */
if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor)
{
- default_fn = implicitly_declare_fn (sfk_constructor, t, /*const_p=*/0);
- TREE_CHAIN (default_fn) = implicit_fns;
- implicit_fns = default_fn;
+ TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 1;
+ CLASSTYPE_LAZY_DEFAULT_CTOR (t) = 1;
}
/* Copy constructor. */
if (! TYPE_HAS_INIT_REF (t) && ! TYPE_FOR_JAVA (t))
{
- /* ARM 12.18: You get either X(X&) or X(const X&), but
- not both. --Chip */
- default_fn
- = implicitly_declare_fn (sfk_copy_constructor, t,
- /*const_p=*/!cant_have_const_cctor);
- TREE_CHAIN (default_fn) = implicit_fns;
- implicit_fns = default_fn;
+ TYPE_HAS_INIT_REF (t) = 1;
+ TYPE_HAS_CONST_INIT_REF (t) = !cant_have_const_cctor;
+ CLASSTYPE_LAZY_COPY_CTOR (t) = 1;
+ TYPE_HAS_CONSTRUCTOR (t) = 1;
}
- /* Assignment operator. */
- if (! TYPE_HAS_ASSIGN_REF (t) && ! TYPE_FOR_JAVA (t))
+ /* If there is no assignment operator, one will be created if and
+ when it is needed. For now, just record whether or not the type
+ of the parameter to the assignment operator will be a const or
+ non-const reference. */
+ if (!TYPE_HAS_ASSIGN_REF (t) && !TYPE_FOR_JAVA (t))
{
- default_fn
- = implicitly_declare_fn (sfk_assignment_operator, t,
- /*const_p=*/!cant_have_const_assignment);
- TREE_CHAIN (default_fn) = implicit_fns;
- implicit_fns = default_fn;
+ TYPE_HAS_ASSIGN_REF (t) = 1;
+ TYPE_HAS_CONST_ASSIGN_REF (t) = !cant_have_const_assignment;
+ CLASSTYPE_LAZY_ASSIGNMENT_OP (t) = 1;
}
-
+
/* Now, hook all of the new functions on to TYPE_METHODS,
and add them to the CLASSTYPE_METHOD_VEC. */
for (f = &implicit_fns; *f; f = &TREE_CHAIN (*f))
{
- add_method (t, *f, /*error_p=*/0);
+ add_method (t, *f);
maybe_add_class_template_decl_list (current_class_type, *f, /*friend_p=*/0);
}
if (abi_version_at_least (2))
{
tree *field;
tree *next;
- int has_pointers;
+ bool has_pointers;
int any_default_members;
/* Assume there are no access declarations. */
*access_decls = NULL_TREE;
/* Assume this class has no pointer members. */
- has_pointers = 0;
+ has_pointers = false;
/* Assume none of the members of this class have default
initializations. */
any_default_members = 0;
}
type = strip_array_types (type);
-
- if (TYPE_PTR_P (type))
- has_pointers = 1;
+
+ /* This is used by -Weffc++ (see below). Warn only for pointers
+ to members which might hold dynamic memory. So do not warn
+ for pointers to functions or pointers to members. */
+ if (TYPE_PTR_P (type)
+ && !TYPE_PTRFN_P (type)
+ && !TYPE_PTR_TO_MEMBER_P (type))
+ has_pointers = true;
if (CLASS_TYPE_P (type))
{
&any_default_members);
}
- /* Effective C++ rule 11. */
- if (has_pointers && warn_ecpp && TYPE_HAS_CONSTRUCTOR (t)
- && ! (TYPE_HAS_INIT_REF (t) && TYPE_HAS_ASSIGN_REF (t)))
+ /* Effective C++ rule 11: if a class has dynamic memory held by pointers,
+ it should also define a copy constructor and an assignment operator to
+ implement the correct copy semantic (deep vs shallow, etc.). As it is
+ not feasible to check whether the constructors do allocate dynamic memory
+ and store it within members, we approximate the warning like this:
+
+ -- Warn only if there are members which are pointers
+ -- Warn only if there is a non-trivial constructor (otherwise,
+ there cannot be memory allocated).
+ -- Warn only if there is a non-trivial destructor. We assume that the
+ user at least implemented the cleanup correctly, and a destructor
+ is needed to free dynamic memory.
+
+ This seems enough for pratical purposes. */
+ if (warn_ecpp
+ && has_pointers
+ && TYPE_HAS_CONSTRUCTOR (t)
+ && TYPE_HAS_DESTRUCTOR (t)
+ && !(TYPE_HAS_INIT_REF (t) && TYPE_HAS_ASSIGN_REF (t)))
{
warning ("`%#T' has pointer data members", t);
/* Iterate through the direct base classes of TYPE. */
if (!type_binfo)
type_binfo = TYPE_BINFO (type);
- for (i = 0; i < BINFO_N_BASETYPES (type_binfo); ++i)
+ for (i = 0; BINFO_BASE_ITERATE (type_binfo, i, binfo); i++)
{
tree binfo_offset;
- binfo = BINFO_BASETYPE (type_binfo, i);
-
if (abi_version_at_least (2)
- && TREE_VIA_VIRTUAL (binfo))
+ && BINFO_VIRTUAL_P (binfo))
continue;
if (!vbases_p
- && TREE_VIA_VIRTUAL (binfo)
+ && BINFO_VIRTUAL_P (binfo)
&& !BINFO_PRIMARY_P (binfo))
continue;
/* We cannot rely on BINFO_OFFSET being set for the base
class yet, but the offsets for direct non-virtual
bases can be calculated by going back to the TYPE. */
- orig_binfo = BINFO_BASETYPE (TYPE_BINFO (type), i);
+ orig_binfo = BINFO_BASE_BINFO (TYPE_BINFO (type), i);
binfo_offset = size_binop (PLUS_EXPR,
offset,
BINFO_OFFSET (orig_binfo));
if (abi_version_at_least (2) && CLASSTYPE_VBASECLASSES (type))
{
unsigned ix;
+ VEC (tree) *vbases;
/* Iterate through the virtual base classes of TYPE. In G++
3.2, we included virtual bases in the direct base class
correct offsets for virtual bases are only known when
working with the most derived type. */
if (vbases_p)
- for (ix = 0; (binfo = VEC_iterate
- (tree, CLASSTYPE_VBASECLASSES (type), ix)); ix++)
+ for (vbases = CLASSTYPE_VBASECLASSES (type), ix = 0;
+ VEC_iterate (tree, vbases, ix, binfo); ix++)
{
r = walk_subobject_offsets (binfo,
f,
above.) */
tree vbase = get_primary_binfo (type_binfo);
- if (vbase && TREE_VIA_VIRTUAL (vbase)
- && BINFO_PRIMARY_BASE_OF (vbase) == type_binfo)
+ if (vbase && BINFO_VIRTUAL_P (vbase)
+ && BINFO_PRIMARY_P (vbase)
+ && BINFO_INHERITANCE_CHAIN (vbase) == type_binfo)
{
r = (walk_subobject_offsets
(vbase, f, offset,
break;
/* G++ 3.2 did not check for overlaps when placing a non-empty
virtual base. */
- if (!abi_version_at_least (2) && binfo && TREE_VIA_VIRTUAL (binfo))
+ if (!abi_version_at_least (2) && binfo && BINFO_VIRTUAL_P (binfo))
break;
if (layout_conflict_p (field_p ? type : binfo, offset,
offsets, field_p))
bool atend = false;
/* This routine should only be used for empty classes. */
- my_friendly_assert (is_empty_class (basetype), 20000321);
+ gcc_assert (is_empty_class (basetype));
alignment = ssize_int (CLASSTYPE_ALIGN_UNIT (basetype));
if (!integer_zerop (BINFO_OFFSET (binfo)))
DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
DECL_IGNORED_P (decl) = 1;
+ DECL_FIELD_IS_BASE (decl) = 1;
/* Try to place the field. It may take more than one try if we
have a hard time placing the field without putting two
atend = layout_empty_base (binfo, eoc, offsets);
/* A nearly-empty class "has no proper base class that is empty,
not morally virtual, and at an offset other than zero." */
- if (!TREE_VIA_VIRTUAL (binfo) && CLASSTYPE_NEARLY_EMPTY_P (t))
+ if (!BINFO_VIRTUAL_P (binfo) && CLASSTYPE_NEARLY_EMPTY_P (t))
{
if (atend)
CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
/* Chain to hold all the new FIELD_DECLs which stand in for base class
subobjects. */
tree t = rli->t;
- int n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
+ int n_baseclasses = BINFO_N_BASE_BINFOS (TYPE_BINFO (t));
int i;
/* The primary base class is always allocated first. */
{
tree base_binfo;
- base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
+ base_binfo = BINFO_BASE_BINFO (TYPE_BINFO (t), i);
/* The primary base was already allocated above, so we don't
need to allocate it again here. */
/* Virtual bases are added at the end (a primary virtual base
will have already been added). */
- if (TREE_VIA_VIRTUAL (base_binfo))
+ if (BINFO_VIRTUAL_P (base_binfo))
continue;
next_field = build_base_field (rli, base_binfo,
check_for_override (x, t);
if (DECL_PURE_VIRTUAL_P (x) && ! DECL_VINDEX (x))
cp_error_at ("initializer specified for non-virtual method `%D'", x);
-
/* The name of the field is the original field name
Save this in auxiliary field for later overloading. */
if (DECL_VINDEX (x))
/* Create the RTL for this function. */
SET_DECL_RTL (clone, NULL_RTX);
- rest_of_decl_compilation (clone, NULL, /*top_level=*/1, at_eof);
+ rest_of_decl_compilation (clone, /*top_level=*/1, at_eof);
/* Make it easy to find the CLONE given the FN. */
TREE_CHAIN (clone) = TREE_CHAIN (fn);
and a not-in-charge version. */
clone = build_clone (fn, complete_ctor_identifier);
if (update_method_vec_p)
- add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
+ add_method (DECL_CONTEXT (clone), clone);
clone = build_clone (fn, base_ctor_identifier);
if (update_method_vec_p)
- add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
+ add_method (DECL_CONTEXT (clone), clone);
}
else
{
- my_friendly_assert (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn), 20000411);
+ gcc_assert (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn));
/* For each destructor, we need three variants: an in-charge
version, a not-in-charge version, and an in-charge deleting
{
clone = build_clone (fn, deleting_dtor_identifier);
if (update_method_vec_p)
- add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
+ add_method (DECL_CONTEXT (clone), clone);
}
clone = build_clone (fn, complete_dtor_identifier);
if (update_method_vec_p)
- add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
+ add_method (DECL_CONTEXT (clone), clone);
clone = build_clone (fn, base_dtor_identifier);
if (update_method_vec_p)
- add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
+ add_method (DECL_CONTEXT (clone), clone);
}
/* Note that this is an abstract function that is never emitted. */
decl_parms = TREE_CHAIN (decl_parms),
clone_parms = TREE_CHAIN (clone_parms))
{
- my_friendly_assert (same_type_p (TREE_TYPE (decl_parms),
- TREE_TYPE (clone_parms)), 20010424);
+ gcc_assert (same_type_p (TREE_TYPE (decl_parms),
+ TREE_TYPE (clone_parms)));
if (TREE_PURPOSE (decl_parms) && !TREE_PURPOSE (clone_parms))
{
break;
}
}
- my_friendly_assert (!clone_parms, 20010424);
+ gcc_assert (!clone_parms);
}
}
tree fns;
bool has_two_argument_delete_p = false;
- my_friendly_assert (CLASS_TYPE_P (type), 20010712);
+ gcc_assert (CLASS_TYPE_P (type));
/* If there's a non-trivial destructor, we need a cookie. In order
to iterate through the array calling the destructor for each
CLASSTYPE_NON_POD_P (t)
|= (CLASSTYPE_NON_AGGREGATE (t) || TYPE_HAS_DESTRUCTOR (t)
|| TYPE_HAS_ASSIGN_REF (t));
- TYPE_HAS_REAL_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t);
TYPE_HAS_COMPLEX_ASSIGN_REF (t)
|= TYPE_HAS_ASSIGN_REF (t) || TYPE_CONTAINS_VPTR_P (t);
/* This class is non-empty. */
CLASSTYPE_EMPTY_P (t) = 0;
- if (CLASSTYPE_N_BASECLASSES (t))
+ if (BINFO_N_BASE_BINFOS (TYPE_BINFO (t)))
/* If there were any baseclasses, they can't possibly be at
offset zero any more, because that's where the vtable
pointer is. So, converting to a base class is going to
{
int i;
tree primary_binfo;
+ tree base_binfo;
/* Update BINFO's offset. */
BINFO_OFFSET (binfo)
/* Find the primary base class. */
primary_binfo = get_primary_binfo (binfo);
+ if (primary_binfo && BINFO_INHERITANCE_CHAIN (primary_binfo) == binfo)
+ propagate_binfo_offsets (primary_binfo, offset);
+
/* Scan all of the bases, pushing the BINFO_OFFSET adjust
downwards. */
- for (i = -1; i < BINFO_N_BASETYPES (binfo); ++i)
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
{
- tree base_binfo;
-
- /* On the first time through the loop, do the primary base.
- Because the primary base need not be an immediate base, we
- must handle the primary base specially. */
- if (i == -1)
- {
- if (!primary_binfo)
- continue;
-
- base_binfo = primary_binfo;
- }
- else
- {
- base_binfo = BINFO_BASETYPE (binfo, i);
- /* Don't do the primary base twice. */
- if (base_binfo == primary_binfo)
- continue;
- }
+ /* Don't do the primary base twice. */
+ if (base_binfo == primary_binfo)
+ continue;
- /* Skip virtual bases that aren't our canonical primary base. */
- if (TREE_VIA_VIRTUAL (base_binfo)
- && BINFO_PRIMARY_BASE_OF (base_binfo) != binfo)
+ if (BINFO_VIRTUAL_P (base_binfo))
continue;
propagate_binfo_offsets (base_binfo, offset);
bool first_vbase = true;
tree *next_field;
- if (CLASSTYPE_N_BASECLASSES (t) == 0)
+ if (BINFO_N_BASE_BINFOS (TYPE_BINFO (t)) == 0)
return;
if (!abi_version_at_least(2))
allocated in inheritance graph order. */
for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase))
{
- if (!TREE_VIA_VIRTUAL (vbase))
+ if (!BINFO_VIRTUAL_P (vbase))
continue;
if (!BINFO_PRIMARY_P (vbase))
end_of_class (tree t, int include_virtuals_p)
{
tree result = size_zero_node;
+ VEC (tree) *vbases;
tree binfo;
+ tree base_binfo;
tree offset;
int i;
- for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
+ for (binfo = TYPE_BINFO (t), i = 0;
+ BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
{
- binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
-
if (!include_virtuals_p
- && TREE_VIA_VIRTUAL (binfo)
- && BINFO_PRIMARY_BASE_OF (binfo) != TYPE_BINFO (t))
+ && BINFO_VIRTUAL_P (base_binfo)
+ && (!BINFO_PRIMARY_P (base_binfo)
+ || BINFO_INHERITANCE_CHAIN (base_binfo) != TYPE_BINFO (t)))
continue;
- offset = end_of_base (binfo);
+ offset = end_of_base (base_binfo);
if (INT_CST_LT_UNSIGNED (result, offset))
result = offset;
}
/* G++ 3.2 did not check indirect virtual bases. */
if (abi_version_at_least (2) && include_virtuals_p)
- for (i = 0; (binfo = VEC_iterate
- (tree, CLASSTYPE_VBASECLASSES (t), i)); i++)
+ for (vbases = CLASSTYPE_VBASECLASSES (t), i = 0;
+ VEC_iterate (tree, vbases, i, base_binfo); i++)
{
- offset = end_of_base (binfo);
+ offset = end_of_base (base_binfo);
if (INT_CST_LT_UNSIGNED (result, offset))
result = offset;
}
warn_about_ambiguous_bases (tree t)
{
int i;
+ VEC (tree) *vbases;
tree basetype;
tree binfo;
+ tree base_binfo;
/* Check direct bases. */
- for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
+ for (binfo = TYPE_BINFO (t), i = 0;
+ BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
{
- basetype = TYPE_BINFO_BASETYPE (t, i);
+ basetype = BINFO_TYPE (base_binfo);
if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
/* Check for ambiguous virtual bases. */
if (extra_warnings)
- for (i = 0; (binfo = VEC_iterate
- (tree, CLASSTYPE_VBASECLASSES (t), i)); i++)
+ for (vbases = CLASSTYPE_VBASECLASSES (t), i = 0;
+ VEC_iterate (tree, vbases, i, binfo); i++)
{
basetype = BINFO_TYPE (binfo);
rli->bitpos = round_down (rli->bitpos, BITS_PER_UNIT);
else
/* The size should have been rounded to a whole byte. */
- my_friendly_assert (tree_int_cst_equal (rli->bitpos,
- round_down (rli->bitpos,
- BITS_PER_UNIT)),
- 20030903);
+ gcc_assert (tree_int_cst_equal
+ (rli->bitpos, round_down (rli->bitpos, BITS_PER_UNIT)));
rli->bitpos
= size_binop (PLUS_EXPR,
rli->bitpos,
/* Start laying out the record. */
rli = start_record_layout (t);
- /* If possible, we reuse the virtual function table pointer from one
- of our base classes. */
- determine_primary_base (t);
+ /* Mark all the primary bases in the hierarchy. */
+ determine_primary_bases (t);
/* Create a pointer to our virtual function table. */
vptr = create_vtable_ptr (t, virtuals_p);
if (COMPLETE_TYPE_P (t))
{
- if (IS_AGGR_TYPE (t))
- error ("redefinition of `%#T'", t);
- else
- abort ();
+ gcc_assert (IS_AGGR_TYPE (t));
+ error ("redefinition of `%#T'", t);
popclass ();
return;
}
{
tree primary = CLASSTYPE_PRIMARY_BINFO (t);
- my_friendly_assert (same_type_p (DECL_FIELD_CONTEXT (vfield),
- BINFO_TYPE (primary)),
- 20010726);
+ gcc_assert (same_type_p (DECL_FIELD_CONTEXT (vfield),
+ BINFO_TYPE (primary)));
/* The vtable better be at the start. */
- my_friendly_assert (integer_zerop (DECL_FIELD_OFFSET (vfield)),
- 20010726);
- my_friendly_assert (integer_zerop (BINFO_OFFSET (primary)),
- 20010726);
+ gcc_assert (integer_zerop (DECL_FIELD_OFFSET (vfield)));
+ gcc_assert (integer_zerop (BINFO_OFFSET (primary)));
vfield = copy_decl (vfield);
DECL_FIELD_CONTEXT (vfield) = t;
TYPE_VFIELD (t) = vfield;
}
else
- my_friendly_assert (!vfield || DECL_FIELD_CONTEXT (vfield) == t, 20010726);
+ gcc_assert (!vfield || DECL_FIELD_CONTEXT (vfield) == t);
virtuals = modify_all_vtables (t, nreverse (virtuals));
- /* If we created a new vtbl pointer for this class, add it to the
- list. */
- if (TYPE_VFIELD (t) && !CLASSTYPE_HAS_PRIMARY_BASE_P (t))
- CLASSTYPE_VFIELDS (t)
- = chainon (CLASSTYPE_VFIELDS (t), build_tree_list (NULL_TREE, t));
-
/* If necessary, create the primary vtable for this class. */
if (virtuals || TYPE_CONTAINS_VPTR_P (t))
{
int vindex;
tree fn;
- if (TYPE_BINFO_VTABLE (t))
- my_friendly_assert (DECL_VIRTUAL_P (TYPE_BINFO_VTABLE (t)),
- 20000116);
+ if (BINFO_VTABLE (TYPE_BINFO (t)))
+ gcc_assert (DECL_VIRTUAL_P (BINFO_VTABLE (TYPE_BINFO (t))));
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
- my_friendly_assert (TYPE_BINFO_VIRTUALS (t) == NULL_TREE,
- 20000116);
+ gcc_assert (BINFO_VIRTUALS (TYPE_BINFO (t)) == NULL_TREE);
/* Add entries for virtual functions introduced by this class. */
- TYPE_BINFO_VIRTUALS (t) = chainon (TYPE_BINFO_VIRTUALS (t), virtuals);
+ BINFO_VIRTUALS (TYPE_BINFO (t))
+ = chainon (BINFO_VIRTUALS (TYPE_BINFO (t)), virtuals);
/* Set DECL_VINDEX for all functions declared in this class. */
for (vindex = 0, fn = BINFO_VIRTUALS (TYPE_BINFO (t));
thunk base function. */
DECL_VINDEX (fndecl) = NULL_TREE;
else if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
- DECL_VINDEX (fndecl) = build_shared_int_cst (vindex);
+ DECL_VINDEX (fndecl) = build_int_cst (NULL_TREE, vindex);
}
}
n_fields = count_fields (TYPE_FIELDS (t));
if (n_fields > 7)
{
- struct sorted_fields_type *field_vec = ggc_alloc (sizeof (struct sorted_fields_type)
- + n_fields * sizeof (tree));
+ struct sorted_fields_type *field_vec = GGC_NEWVAR
+ (struct sorted_fields_type,
+ sizeof (struct sorted_fields_type) + n_fields * sizeof (tree));
field_vec->len = n_fields;
add_fields_to_record_type (TYPE_FIELDS (t), field_vec, 0);
qsort (field_vec->elts, n_fields, sizeof (tree),
DECL_SORTED_FIELDS (TYPE_MAIN_DECL (t)) = field_vec;
}
- if (TYPE_HAS_CONSTRUCTOR (t))
- {
- tree vfields = CLASSTYPE_VFIELDS (t);
-
- for (vfields = CLASSTYPE_VFIELDS (t);
- vfields; vfields = TREE_CHAIN (vfields))
- /* Mark the fact that constructor for T could affect anybody
- inheriting from T who wants to initialize vtables for
- VFIELDS's type. */
- if (VF_BINFO_VALUE (vfields))
- TREE_ADDRESSABLE (vfields) = 1;
- }
-
/* Make the rtl for any new vtables we have created, and unmark
the base types we marked. */
finish_vtbls (t);
build_vtt (t);
if (warn_nonvdtor && TYPE_POLYMORPHIC_P (t) && TYPE_HAS_DESTRUCTOR (t)
- && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1)) == NULL_TREE)
+ && !DECL_VINDEX (CLASSTYPE_DESTRUCTORS (t)))
{
- tree dtor = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1);
+ tree dtor = CLASSTYPE_DESTRUCTORS (t);
/* Warn only if the dtor is non-private or the class has friends */
if (!TREE_PRIVATE (dtor) ||
if (processing_template_decl)
{
+ tree x;
+
finish_struct_methods (t);
TYPE_SIZE (t) = bitsize_zero_node;
+
+ /* We need to emit an error message if this type was used as a parameter
+ and it is an abstract type, even if it is a template. We construct
+ a simple CLASSTYPE_PURE_VIRTUALS list without taking bases into
+ account and we call complete_vars with this type, which will check
+ the PARM_DECLS. Note that while the type is being defined,
+ CLASSTYPE_PURE_VIRTUALS contains the list of the inline friends
+ (see CLASSTYPE_INLINE_FRIENDS) so we need to clear it. */
+ CLASSTYPE_PURE_VIRTUALS (t) = NULL_TREE;
+ for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
+ if (DECL_PURE_VIRTUAL_P (x))
+ CLASSTYPE_PURE_VIRTUALS (t)
+ = tree_cons (NULL_TREE, x, CLASSTYPE_PURE_VIRTUALS (t));
+ complete_vars (t);
}
else
finish_struct_1 (t);
}
return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
- case RTL_EXPR:
- return NULL_TREE;
-
case PLUS_EXPR:
case MINUS_EXPR:
if (TREE_CODE (TREE_OPERAND (instance, 0)) == ADDR_EXPR)
return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
case ADDR_EXPR:
+ instance = TREE_OPERAND (instance, 0);
if (nonnull)
- *nonnull = 1;
- return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
+ {
+ /* Just because we see an ADDR_EXPR doesn't mean we're dealing
+ with a real object -- given &p->f, p can still be null. */
+ tree t = get_base_address (instance);
+ /* ??? Probably should check DECL_WEAK here. */
+ if (t && DECL_P (t))
+ *nonnull = 1;
+ }
+ return fixed_type_or_null (instance, nonnull, cdtorp);
case COMPONENT_REF:
+ /* If this component is really a base class reference, then the field
+ itself isn't definitive. */
+ if (DECL_FIELD_IS_BASE (TREE_OPERAND (instance, 1)))
+ return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
return fixed_type_or_null (TREE_OPERAND (instance, 1), nonnull, cdtorp);
case VAR_DECL:
ridpointers[(int) RID_PROTECTED] = access_protected_node;
}
+/* Restore the cached PREVIOUS_CLASS_LEVEL. */
+
+static void
+restore_class_cache (void)
+{
+ tree type;
+
+ /* We are re-entering the same class we just left, so we don't
+ have to search the whole inheritance matrix to find all the
+ decls to bind again. Instead, we install the cached
+ class_shadowed list and walk through it binding names. */
+ push_binding_level (previous_class_level);
+ class_binding_level = previous_class_level;
+ /* Restore IDENTIFIER_TYPE_VALUE. */
+ for (type = class_binding_level->type_shadowed;
+ type;
+ type = TREE_CHAIN (type))
+ SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (type), TREE_TYPE (type));
+}
+
/* Set global variables CURRENT_CLASS_NAME and CURRENT_CLASS_TYPE as
appropriate for TYPE.
nodes of local TYPE_DECLs in the TREE_TYPE field of the name.
For multiple inheritance, we perform a two-pass depth-first search
- of the type lattice. The first pass performs a pre-order search,
- marking types after the type has had its fields installed in
- the appropriate IDENTIFIER_CLASS_VALUE slot. The second pass merely
- unmarks the marked types. If a field or member function name
- appears in an ambiguous way, the IDENTIFIER_CLASS_VALUE of
- that name becomes `error_mark_node'. */
+ of the type lattice. */
void
pushclass (tree type)
? access_private_node
: access_public_node);
- if (previous_class_type != NULL_TREE
- && (type != previous_class_type
- || !COMPLETE_TYPE_P (previous_class_type))
+ if (previous_class_level
+ && type != previous_class_level->this_entity
&& current_class_depth == 1)
{
/* Forcibly remove any old class remnants. */
invalidate_class_lookup_cache ();
}
- /* If we're about to enter a nested class, clear
- IDENTIFIER_CLASS_VALUE for the enclosing classes. */
- if (current_class_depth > 1)
- clear_identifier_class_values ();
-
- pushlevel_class ();
-
- if (type != previous_class_type || current_class_depth > 1)
- {
- push_class_decls (type);
- if (CLASSTYPE_TEMPLATE_INFO (type) && !CLASSTYPE_USE_TEMPLATE (type))
- {
- /* If we are entering the scope of a template declaration (not a
- specialization), we need to push all the using decls with
- dependent scope too. */
- tree fields;
-
- for (fields = TYPE_FIELDS (type);
- fields; fields = TREE_CHAIN (fields))
- if (TREE_CODE (fields) == USING_DECL && !TREE_TYPE (fields))
- pushdecl_class_level (fields);
- }
- }
+ if (!previous_class_level
+ || type != previous_class_level->this_entity
+ || current_class_depth > 1)
+ pushlevel_class ();
else
- {
- tree item;
-
- /* We are re-entering the same class we just left, so we don't
- have to search the whole inheritance matrix to find all the
- decls to bind again. Instead, we install the cached
- class_shadowed list, and walk through it binding names and
- setting up IDENTIFIER_TYPE_VALUEs. */
- set_class_shadows (previous_class_values);
- for (item = previous_class_values; item; item = TREE_CHAIN (item))
- {
- tree id = TREE_PURPOSE (item);
- tree decl = TREE_TYPE (item);
-
- push_class_binding (id, decl);
- if (TREE_CODE (decl) == TYPE_DECL)
- set_identifier_type_value (id, decl);
- }
- unuse_fields (type);
- }
+ restore_class_cache ();
cxx_remember_type_decls (CLASSTYPE_NESTED_UTDS (type));
}
-/* When we exit a toplevel class scope, we save the
- IDENTIFIER_CLASS_VALUEs so that we can restore them quickly if we
- reenter the class. Here, we've entered some other class, so we
- must invalidate our cache. */
+/* When we exit a toplevel class scope, we save its binding level so
+ that we can restore it quickly. Here, we've entered some other
+ class, so we must invalidate our cache. */
void
invalidate_class_lookup_cache (void)
{
- tree t;
-
- /* The IDENTIFIER_CLASS_VALUEs are no longer valid. */
- for (t = previous_class_values; t; t = TREE_CHAIN (t))
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE;
-
- previous_class_values = NULL_TREE;
- previous_class_type = NULL_TREE;
+ previous_class_level = NULL;
}
/* Get out of the current class scope. If we were in a class scope
popclass (void)
{
poplevel_class ();
- pop_class_decls ();
current_class_depth--;
current_class_name = current_class_stack[current_class_depth].name;
/* By the time we get here, we should be seeing only real
pointer-to-member types, not the internal POINTER_TYPE to
METHOD_TYPE representation. */
- my_friendly_assert (!(TREE_CODE (target_type) == POINTER_TYPE
- && (TREE_CODE (TREE_TYPE (target_type))
- == METHOD_TYPE)), 0);
+ gcc_assert (TREE_CODE (target_type) != POINTER_TYPE
+ || TREE_CODE (TREE_TYPE (target_type)) != METHOD_TYPE);
- my_friendly_assert (is_overloaded_fn (overload), 20030910);
+ gcc_assert (is_overloaded_fn (overload));
/* Check that the TARGET_TYPE is reasonable. */
if (TYPE_PTRFN_P (target_type))
case CONVERT_EXPR:
case SAVE_EXPR:
case CONSTRUCTOR:
- case BUFFER_REF:
- abort ();
- return error_mark_node;
+ gcc_unreachable ();
case INDIRECT_REF:
case ARRAY_REF:
if (addr != error_mark_node
&& TREE_SIDE_EFFECTS (TREE_OPERAND (rhs, 0)))
/* Do not lose object's side effects. */
- addr = build (COMPOUND_EXPR, TREE_TYPE (addr),
- TREE_OPERAND (rhs, 0), addr);
+ addr = build2 (COMPOUND_EXPR, TREE_TYPE (addr),
+ TREE_OPERAND (rhs, 0), addr);
return addr;
}
/* This can happen if we are forming a pointer-to-member for a
member template. */
- my_friendly_assert (TREE_CODE (rhs) == TEMPLATE_ID_EXPR, 0);
+ gcc_assert (TREE_CODE (rhs) == TEMPLATE_ID_EXPR);
/* Fall through. */
case TREE_LIST:
/* Now we should have a baselink. */
- my_friendly_assert (BASELINK_P (rhs), 990412);
+ gcc_assert (BASELINK_P (rhs));
return instantiate_type (lhstype, BASELINK_FUNCTIONS (rhs), flags);
case CALL_EXPR:
/* This is too hard for now. */
- abort ();
- return error_mark_node;
+ gcc_unreachable ();
case PLUS_EXPR:
case MINUS_EXPR:
return instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags);
}
- case ENTRY_VALUE_EXPR:
- abort ();
- return error_mark_node;
case ERROR_MARK:
return error_mark_node;
default:
- abort ();
- return error_mark_node;
+ gcc_unreachable ();
}
+ return error_mark_node;
}
\f
/* Return the name of the virtual function pointer field
static tree
get_vfield_name (tree type)
{
- tree binfo = TYPE_BINFO (type);
+ tree binfo, base_binfo;
char *buf;
- while (BINFO_BASETYPES (binfo)
- && TYPE_CONTAINS_VPTR_P (BINFO_TYPE (BINFO_BASETYPE (binfo, 0)))
- && ! TREE_VIA_VIRTUAL (BINFO_BASETYPE (binfo, 0)))
- binfo = BINFO_BASETYPE (binfo, 0);
+ for (binfo = TYPE_BINFO (type);
+ BINFO_N_BASE_BINFOS (binfo);
+ binfo = base_binfo)
+ {
+ base_binfo = BINFO_BASE_BINFO (binfo, 0);
+ if (BINFO_VIRTUAL_P (base_binfo)
+ || !TYPE_CONTAINS_VPTR_P (BINFO_TYPE (base_binfo)))
+ break;
+ }
+
type = BINFO_TYPE (binfo);
buf = alloca (sizeof (VFIELD_NAME_FORMAT) + TYPE_NAME_LENGTH (type) + 2);
sprintf (buf, VFIELD_NAME_FORMAT,
if (CLASS_TYPE_P (type))
{
tree field;
+ tree binfo;
+ tree base_binfo;
int i;
- for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i)
- if (contains_empty_class_p (TYPE_BINFO_BASETYPE (type, i)))
+ for (binfo = TYPE_BINFO (type), i = 0;
+ BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
+ if (contains_empty_class_p (BINFO_TYPE (base_binfo)))
return true;
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
return NULL_TREE;
splay_tree names_used;
/* If we're not defining a class, there's nothing to do. */
- if (innermost_scope_kind() != sk_class)
+ if (!(innermost_scope_kind() == sk_class
+ && TYPE_BEING_DEFINED (current_class_type)))
return;
/* If there's already a binding for this NAME, then we don't have
anything to worry about. */
- if (IDENTIFIER_CLASS_VALUE (name))
+ if (lookup_member (current_class_type, name,
+ /*protect=*/0, /*want_type=*/false))
return;
if (!current_class_stack[current_class_depth - 1].names_used)
decl = BINFO_VTABLE (binfo);
if (decl && TREE_CODE (decl) == PLUS_EXPR)
{
- my_friendly_assert (TREE_CODE (TREE_OPERAND (decl, 0)) == ADDR_EXPR,
- 2000403);
+ gcc_assert (TREE_CODE (TREE_OPERAND (decl, 0)) == ADDR_EXPR);
decl = TREE_OPERAND (TREE_OPERAND (decl, 0), 0);
}
if (decl)
- my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 20000403);
+ gcc_assert (TREE_CODE (decl) == VAR_DECL);
return decl;
}
int indent)
{
int indented = 0;
- tree base_binfos;
+ tree base_binfo;
+ int i;
indented = maybe_indent_hierarchy (stream, indent, 0);
fprintf (stream, "%s (0x%lx) ",
- type_as_string (binfo, TFF_PLAIN_IDENTIFIER),
+ type_as_string (BINFO_TYPE (binfo), TFF_PLAIN_IDENTIFIER),
(unsigned long) binfo);
if (binfo != igo)
{
fprintf (stream, " empty");
else if (CLASSTYPE_NEARLY_EMPTY_P (BINFO_TYPE (binfo)))
fprintf (stream, " nearly-empty");
- if (TREE_VIA_VIRTUAL (binfo))
+ if (BINFO_VIRTUAL_P (binfo))
fprintf (stream, " virtual");
fprintf (stream, "\n");
indented = 0;
- if (BINFO_PRIMARY_BASE_OF (binfo))
+ if (BINFO_PRIMARY_P (binfo))
{
indented = maybe_indent_hierarchy (stream, indent + 3, indented);
fprintf (stream, " primary-for %s (0x%lx)",
- type_as_string (BINFO_PRIMARY_BASE_OF (binfo),
+ type_as_string (BINFO_TYPE (BINFO_INHERITANCE_CHAIN (binfo)),
TFF_PLAIN_IDENTIFIER),
- (unsigned long)BINFO_PRIMARY_BASE_OF (binfo));
+ (unsigned long)BINFO_INHERITANCE_CHAIN (binfo));
}
if (BINFO_LOST_PRIMARY_P (binfo))
{
if (indented)
fprintf (stream, "\n");
}
-
- base_binfos = BINFO_BASETYPES (binfo);
- if (base_binfos)
- {
- int ix, n;
- n = TREE_VEC_LENGTH (base_binfos);
- for (ix = 0; ix != n; ix++)
- {
- tree base_binfo = TREE_VEC_ELT (base_binfos, ix);
-
- igo = dump_class_hierarchy_r (stream, flags, base_binfo,
- igo, indent + 2);
- }
- }
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+ igo = dump_class_hierarchy_r (stream, flags, base_binfo, igo, indent + 2);
return igo;
}
fprintf (stream, "%s for %s",
ctor_vtbl_p ? "Construction vtable" : "Vtable",
- type_as_string (binfo, TFF_PLAIN_IDENTIFIER));
+ type_as_string (BINFO_TYPE (binfo), TFF_PLAIN_IDENTIFIER));
if (ctor_vtbl_p)
{
- if (!TREE_VIA_VIRTUAL (binfo))
+ if (!BINFO_VIRTUAL_P (binfo))
fprintf (stream, " (0x%lx instance)", (unsigned long)binfo);
fprintf (stream, " in %s", type_as_string (t, TFF_PLAIN_IDENTIFIER));
}
/* We lay out the primary and secondary vtables in one contiguous
vtable. The primary vtable is first, followed by the non-virtual
secondary vtables in inheritance graph order. */
- list = build_tree_list (TYPE_BINFO_VTABLE (t), NULL_TREE);
+ list = build_tree_list (BINFO_VTABLE (TYPE_BINFO (t)), NULL_TREE);
accumulate_vtbl_inits (TYPE_BINFO (t), TYPE_BINFO (t),
TYPE_BINFO (t), t, list);
/* Then come the virtual bases, also in inheritance graph order. */
for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase))
{
- if (!TREE_VIA_VIRTUAL (vbase))
+ if (!BINFO_VIRTUAL_P (vbase))
continue;
accumulate_vtbl_inits (vbase, vbase, TYPE_BINFO (t), t, list);
}
- if (TYPE_BINFO_VTABLE (t))
+ if (BINFO_VTABLE (TYPE_BINFO (t)))
initialize_vtable (TYPE_BINFO (t), TREE_VALUE (list));
}
static void
initialize_array (tree decl, tree inits)
{
- tree context;
-
- context = DECL_CONTEXT (decl);
- DECL_CONTEXT (decl) = NULL_TREE;
DECL_INITIAL (decl) = build_constructor (NULL_TREE, inits);
cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
- DECL_CONTEXT (decl) = context;
}
/* Build the VTT (virtual table table) for T.
vt = BINFO_VTABLE (binfo);
if (TREE_CODE (vt) == TREE_LIST)
vt = TREE_VALUE (vt);
- if (TREE_CODE (vt) == TREE_VEC)
+ if (TREE_CODE (vt) == TREE_BINFO)
binfo = vt;
else
break;
inits = &TREE_CHAIN (*inits);
if (top_level_p)
{
- my_friendly_assert (!BINFO_VPTR_INDEX (binfo), 20010129);
+ gcc_assert (!BINFO_VPTR_INDEX (binfo));
BINFO_VPTR_INDEX (binfo) = *index;
}
*index = size_binop (PLUS_EXPR, *index, TYPE_SIZE_UNIT (ptr_type_node));
/* Recursively add the secondary VTTs for non-virtual bases. */
- for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
- {
- b = BINFO_BASETYPE (binfo, i);
- if (!TREE_VIA_VIRTUAL (b))
- inits = build_vtt_inits (BINFO_BASETYPE (binfo, i), t,
- inits, index);
- }
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, b); ++i)
+ if (!BINFO_VIRTUAL_P (b))
+ inits = build_vtt_inits (BINFO_BASE_BINFO (binfo, i), t, inits, index);
/* Add secondary virtual pointers for all subobjects of BINFO with
either virtual bases or reachable along a virtual path, except
{
*inits = nreverse (secondary_vptrs);
inits = &TREE_CHAIN (secondary_vptrs);
- my_friendly_assert (*inits == NULL_TREE, 20000517);
+ gcc_assert (*inits == NULL_TREE);
}
/* Add the secondary VTTs for virtual bases. */
if (top_level_p)
for (b = TYPE_BINFO (BINFO_TYPE (binfo)); b; b = TREE_CHAIN (b))
{
- if (!TREE_VIA_VIRTUAL (b))
+ if (!BINFO_VIRTUAL_P (b))
continue;
inits = build_vtt_inits (b, t, inits, index);
return NULL_TREE;
/* We're not interested in non-virtual primary bases. */
- if (!TREE_VIA_VIRTUAL (binfo) && BINFO_PRIMARY_P (binfo))
+ if (!BINFO_VIRTUAL_P (binfo) && BINFO_PRIMARY_P (binfo))
return NULL_TREE;
/* If BINFO has virtual bases or is reachable via a virtual path
index = TREE_TYPE (l);
if (top_level_p)
{
- my_friendly_assert (!BINFO_VPTR_INDEX (binfo), 20010129);
+ gcc_assert (!BINFO_VPTR_INDEX (binfo));
BINFO_VPTR_INDEX (binfo) = index;
}
TREE_TYPE (l) = size_binop (PLUS_EXPR, index,
TYPE_SIZE_UNIT (ptr_type_node));
/* Add the initializer for the secondary vptr itself. */
- if (top_level_p && TREE_VIA_VIRTUAL (binfo))
+ if (top_level_p && BINFO_VIRTUAL_P (binfo))
{
/* It's a primary virtual base, and this is not the construction
vtable. Find the base this is primary of in the inheritance graph,
and use that base's vtable now. */
- while (BINFO_PRIMARY_BASE_OF (binfo))
- binfo = BINFO_PRIMARY_BASE_OF (binfo);
+ while (BINFO_PRIMARY_P (binfo))
+ binfo = BINFO_INHERITANCE_CHAIN (binfo);
}
init = binfo_ctor_vtable (binfo);
TREE_VALUE (l) = tree_cons (NULL_TREE, init, TREE_VALUE (l));
dfs_ctor_vtable_bases_queue_p (tree derived, int ix,
void* data)
{
- tree binfo = BINFO_BASETYPE (derived, ix);
+ tree binfo = BINFO_BASE_BINFO (derived, ix);
if (!BINFO_MARKED (binfo) == VTT_MARKED_BINFO_P ((tree) data))
return NULL_TREE;
if (IDENTIFIER_GLOBAL_VALUE (id))
return;
- my_friendly_assert (!same_type_p (BINFO_TYPE (binfo), t), 20010124);
+ gcc_assert (!same_type_p (BINFO_TYPE (binfo), t));
/* Build a version of VTBL (with the wrong type) for use in
constructing the addresses of secondary vtables in the
construction vtable group. */
{
tree b;
- if (!TREE_VIA_VIRTUAL (vbase))
+ if (!BINFO_VIRTUAL_P (vbase))
continue;
b = copied_binfo (vbase, binfo);
tree inits)
{
int i;
+ tree base_binfo;
int ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
- my_friendly_assert (same_type_p (BINFO_TYPE (binfo),
- BINFO_TYPE (orig_binfo)),
- 20000517);
+ gcc_assert (same_type_p (BINFO_TYPE (binfo), BINFO_TYPE (orig_binfo)));
/* If it doesn't have a vptr, we don't do anything. */
if (!TYPE_CONTAINS_VPTR_P (BINFO_TYPE (binfo)))
secondary vtable lies from the primary vtable. We can't use
dfs_walk here because we need to iterate through bases of BINFO
and RTTI_BINFO simultaneously. */
- for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
{
- tree base_binfo = BINFO_BASETYPE (binfo, i);
-
/* Skip virtual bases. */
- if (TREE_VIA_VIRTUAL (base_binfo))
+ if (BINFO_VIRTUAL_P (base_binfo))
continue;
accumulate_vtbl_inits (base_binfo,
- BINFO_BASETYPE (orig_binfo, i),
+ BINFO_BASE_BINFO (orig_binfo, i),
rtti_binfo, t,
inits);
}
int ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
if (ctor_vtbl_p
- && TREE_VIA_VIRTUAL (orig_binfo) && BINFO_PRIMARY_P (orig_binfo))
+ && BINFO_VIRTUAL_P (orig_binfo) && BINFO_PRIMARY_P (orig_binfo))
{
/* In the hierarchy of BINFO_TYPE (RTTI_BINFO), this is a
primary virtual base. If it is not the same primary in
RTTI_BINFO.
3) We are primary to something not a base of RTTI_BINFO. */
- tree b = BINFO_PRIMARY_BASE_OF (binfo);
+ tree b;
tree last = NULL_TREE;
/* First, look through the bases we are primary to for RTTI_BINFO
or a virtual base. */
- for (; b; b = BINFO_PRIMARY_BASE_OF (b))
+ b = binfo;
+ while (BINFO_PRIMARY_P (b))
{
+ b = BINFO_INHERITANCE_CHAIN (b);
last = b;
- if (TREE_VIA_VIRTUAL (b) || b == rtti_binfo)
- break;
+ if (BINFO_VIRTUAL_P (b) || b == rtti_binfo)
+ goto found;
}
/* If we run out of primary links, keep looking down our
inheritance chain; we might be an indirect primary. */
- if (b == NULL_TREE)
- for (b = last; b; b = BINFO_INHERITANCE_CHAIN (b))
- if (TREE_VIA_VIRTUAL (b) || b == rtti_binfo)
- break;
-
+ for (b = last; b; b = BINFO_INHERITANCE_CHAIN (b))
+ if (BINFO_VIRTUAL_P (b) || b == rtti_binfo)
+ break;
+ found:
+
/* If we found RTTI_BINFO, this is case 1. If we found a virtual
base B and it is a base of RTTI_BINFO, this is case 2. In
either case, we share our vtable with LAST, i.e. the
index = size_binop (MULT_EXPR,
TYPE_SIZE_UNIT (vtable_entry_type),
index);
- vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);
+ vtbl = build2 (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);
}
if (ctor_vtbl_p)
So, we make a TREE_LIST. Later, dfs_fixup_binfo_vtbls will
straighten this out. */
BINFO_VTABLE (binfo) = tree_cons (rtti_binfo, vtbl, BINFO_VTABLE (binfo));
- else if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo))
+ else if (BINFO_PRIMARY_P (binfo) && BINFO_VIRTUAL_P (binfo))
inits = NULL_TREE;
else
/* For an ordinary vtable, set BINFO_VTABLE. */
vtbl_init_data vid;
unsigned ix;
tree vbinfo;
-
+ VEC (tree) *vbases;
+
/* Initialize VID. */
memset (&vid, 0, sizeof (vid));
vid.binfo = binfo;
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);
+ vid.index = ssize_int(-3 * TARGET_VTABLE_DATA_ENTRY_DISTANCE);
/* Add entries to the vtable for RTTI. */
build_rtti_vtbl_entries (binfo, &vid);
/* Clear BINFO_VTABLE_PATH_MARKED; it's set by
build_vbase_offset_vtbl_entries. */
- for (ix = 0; (vbinfo = VEC_iterate
- (tree, CLASSTYPE_VBASECLASSES (t), ix)); ix++)
+ for (vbases = CLASSTYPE_VBASECLASSES (t), ix = 0;
+ VEC_iterate (tree, vbases, ix, vbinfo); ix++)
BINFO_VTABLE_PATH_MARKED (vbinfo) = 0;
/* If the target requires padding between data entries, add that now. */
delta = BV_DELTA (v);
vcall_index = BV_VCALL_INDEX (v);
- my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727);
- my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 19990727);
+ gcc_assert (TREE_CODE (delta) == INTEGER_CST);
+ gcc_assert (TREE_CODE (fn) == FUNCTION_DECL);
/* You can't call an abstract virtual function; it's abstract.
So, we replace these functions with __pure_virtual. */
else
for (i = 0; i < TARGET_VTABLE_USES_DESCRIPTORS; ++i)
{
- tree fdesc = build (FDESC_EXPR, vfunc_ptr_type_node,
- TREE_OPERAND (init, 0),
- build_int_2 (i, 0));
+ tree fdesc = build2 (FDESC_EXPR, vfunc_ptr_type_node,
+ TREE_OPERAND (init, 0),
+ build_int_cst (NULL_TREE, i));
TREE_CONSTANT (fdesc) = 1;
TREE_INVARIANT (fdesc) = 1;
base (possibly multi-level) of vid->binfo, or we wouldn't
have called build_vcall_and_vbase_vtbl_entries for it. But it
might be a lost primary, so just skip down to vid->binfo. */
- if (TREE_VIA_VIRTUAL (non_primary_binfo))
+ if (BINFO_VIRTUAL_P (non_primary_binfo))
{
non_primary_binfo = vid->binfo;
break;
tree b;
tree delta;
- if (!TREE_VIA_VIRTUAL (vbase))
+ if (!BINFO_VIRTUAL_P (vbase))
continue;
/* Find the instance of this virtual base in the complete
BINFO_VPTR_FIELD (b) = delta;
if (binfo != TYPE_BINFO (t))
- {
- /* The vbase offset had better be the same. */
- my_friendly_assert (tree_int_cst_equal (delta,
- BINFO_VPTR_FIELD (vbase)),
- 20030202);
- }
+ /* The vbase offset had better be the same. */
+ gcc_assert (tree_int_cst_equal (delta, BINFO_VPTR_FIELD (vbase)));
/* The next vbase will come at a more negative offset. */
vid->index = size_binop (MINUS_EXPR, vid->index,
/* 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))
+ if (BINFO_VIRTUAL_P (binfo) || binfo == TYPE_BINFO (vid->derived))
{
/* We need a vcall offset for each of the virtual functions in this
vtable. For example:
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))
+ if (!BINFO_VIRTUAL_P (binfo))
vid->generate_vcall_entries = false;
/* Now, walk through the non-virtual bases, adding vcall offsets. */
add_vcall_offset_vtbl_entries_r (binfo, vid);
{
int i;
tree primary_binfo;
+ tree base_binfo;
/* Don't walk into virtual bases -- except, of course, for the
virtual base for which we are building vcall offsets. Any
primary virtual base will have already had its offsets generated
through the recursion in build_vcall_and_vbase_vtbl_entries. */
- if (TREE_VIA_VIRTUAL (binfo) && vid->vbase != binfo)
+ if (BINFO_VIRTUAL_P (binfo) && vid->vbase != binfo)
return;
/* If BINFO has a primary base, process it first. */
add_vcall_offset_vtbl_entries_1 (binfo, vid);
/* Scan the non-primary bases of BINFO. */
- for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
- {
- tree base_binfo;
-
- base_binfo = BINFO_BASETYPE (binfo, i);
- if (base_binfo != primary_binfo)
- add_vcall_offset_vtbl_entries_r (base_binfo, vid);
- }
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
+ if (base_binfo != primary_binfo)
+ add_vcall_offset_vtbl_entries_r (base_binfo, vid);
}
/* Called from build_vcall_offset_vtbl_entries_r. */
base (possibly multi-level) of vid->binfo, or we wouldn't
have called build_vcall_and_vbase_vtbl_entries for it. But it
might be a lost primary, so just skip down to vid->binfo. */
- if (TREE_VIA_VIRTUAL (non_primary_binfo))
+ if (BINFO_VIRTUAL_P (non_primary_binfo))
{
- if (non_primary_binfo != vid->vbase)
- abort ();
+ gcc_assert (non_primary_binfo == vid->vbase);
non_primary_binfo = vid->binfo;
break;
}
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 (orig_fn, vid->index,
- CLASSTYPE_VCALL_INDICES (vid->derived));
-
+ {
+ tree_pair_p elt = VEC_safe_push (tree_pair_s,
+ CLASSTYPE_VCALL_INDICES (vid->derived),
+ NULL);
+ elt->purpose = orig_fn;
+ elt->value = vid->index;
+ }
+
/* The next vcall offset will be found at a more negative
offset. */
vid->index = size_binop (MINUS_EXPR, vid->index,
tree primary_base;
primary_base = get_primary_binfo (b);
- my_friendly_assert (BINFO_PRIMARY_BASE_OF (primary_base) == b, 20010127);
+ gcc_assert (BINFO_PRIMARY_P (primary_base)
+ && BINFO_INHERITANCE_CHAIN (primary_base) == b);
b = primary_base;
}
offset = size_diffop (BINFO_OFFSET (vid->rtti_binfo), BINFO_OFFSET (b));
{
HOST_WIDE_INT index = tree_low_cst (OBJ_TYPE_REF_TOKEN (ref), 1);
HOST_WIDE_INT i = 0;
- tree v = TYPE_BINFO_VIRTUALS (known_type);
+ tree v = BINFO_VIRTUALS (TYPE_BINFO (known_type));
tree fndecl;
while (i != index)
fndecl = BV_FN (v);
#ifdef ENABLE_CHECKING
- if (!tree_int_cst_equal (OBJ_TYPE_REF_TOKEN (ref), DECL_VINDEX (fndecl)))
- abort ();
+ gcc_assert (tree_int_cst_equal (OBJ_TYPE_REF_TOKEN (ref),
+ DECL_VINDEX (fndecl)));
#endif
return build_address (fndecl);
}
+