#include "rtl.h"
#include "output.h"
#include "toplev.h"
-#include "lex.h"
#include "target.h"
#include "convert.h"
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;
}
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;
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);
}
return aref;
}
-/* Given an object INSTANCE, return an expression which yields a
- function pointer corresponding to vtable element INDEX. */
+/* Given a stable object pointer INSTANCE_PTR, return an expression which
+ yields a function pointer corresponding to vtable element INDEX. */
tree
-build_vfn_ref (tree instance, tree idx)
+build_vfn_ref (tree instance_ptr, tree idx)
{
- tree aref = build_vtbl_ref_1 (instance, idx);
+ tree aref;
+
+ aref = build_vtbl_ref_1 (build_indirect_ref (instance_ptr, 0), idx);
/* When using function descriptors, the address of the
vtable entry is treated as a function pointer. */
aref = build1 (NOP_EXPR, TREE_TYPE (aref),
build_unary_op (ADDR_EXPR, aref, /*noconvert=*/1));
+ /* Remember this as a method reference, for later devirtualization. */
+ 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;
}
/* 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. */
/* 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);
+ my_friendly_assert (COMPLETE_TYPE_P (basetype), 20040714);
+
/* 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))
/* 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))
+ if (BINFO_VIRTUAL_P (base_binfo))
{
tree delta = size_diffop (convert (ssizetype,
BINFO_OFFSET (binfo)),
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);
+ BINFO_VTABLE (TYPE_BINFO (t)) = BINFO_VTABLE (TYPE_BINFO (basetype));
+ BINFO_VIRTUALS (TYPE_BINFO (t)) = BINFO_VIRTUALS (TYPE_BINFO (basetype));
TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
}
static void
determine_primary_base (tree t)
{
- int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
- tree vbases;
- tree type_binfo;
+ unsigned i, n_baseclasses = BINFO_N_BASE_BINFOS (TYPE_BINFO (t));
+ tree type_binfo = TYPE_BINFO (t);
+ tree vbase_binfo;
+ tree base_binfo;
+ VEC(tree) *vbases;
/* 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++)
+ for (i = 0; BINFO_BASE_ITERATE (type_binfo, i, base_binfo); i++)
{
- tree base_binfo = BINFO_BASETYPE (type_binfo, i);
tree basetype = BINFO_TYPE (base_binfo);
if (TYPE_CONTAINS_VPTR_P (basetype))
{
/* We prefer a non-virtual base, although a virtual one will
do. */
- if (TREE_VIA_VIRTUAL (base_binfo))
+ if (BINFO_VIRTUAL_P (base_binfo))
continue;
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
- {
- set_primary_base (t, base_binfo);
- CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype));
- }
- 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));
- }
+ set_primary_base (t, base_binfo);
}
}
/* Find the indirect primary bases - those virtual bases which are primary
bases of something else in this hierarchy. */
- for (vbases = CLASSTYPE_VBASECLASSES (t);
- vbases;
- vbases = TREE_CHAIN (vbases))
+ for (vbases = CLASSTYPE_VBASECLASSES (t), i = 0;
+ VEC_iterate (tree, vbases, i, vbase_binfo); i++)
{
- tree vbase_binfo = TREE_VALUE (vbases);
+ unsigned j;
- /* 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 (i = 0; i < n_baseclasses; ++i)
+ /* 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; BINFO_BASE_ITERATE (type_binfo, j, base_binfo); j++)
{
- tree basetype = TYPE_BINFO_BASETYPE (t, i);
- tree v;
-
- for (v = CLASSTYPE_VBASECLASSES (basetype);
- v;
- v = TREE_CHAIN (v))
+ unsigned k;
+ VEC (tree) *base_vbases;
+ tree base_vbase_binfo;
+ tree basetype = BINFO_TYPE (base_binfo);
+
+ for (base_vbases = CLASSTYPE_VBASECLASSES (basetype), k = 0;
+ VEC_iterate (tree, base_vbases, k, base_vbase_binfo); k++)
{
- tree base_vbase = TREE_VALUE (v);
-
- if (BINFO_PRIMARY_P (base_vbase)
- && same_type_p (BINFO_TYPE (base_vbase),
- BINFO_TYPE (vbase_binfo)))
+ 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;
{
tree basetype = BINFO_TYPE (base_binfo);
- if (TREE_VIA_VIRTUAL (base_binfo)
+ if (BINFO_VIRTUAL_P (base_binfo)
&& CLASSTYPE_NEARLY_EMPTY_P (basetype))
{
/* If this is not an indirect primary base, then it's
/* 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)));
- }
+ set_primary_base (t, candidate);
}
/* Mark the primary base classes at this point. */
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 purpose_member (BINFO_TYPE (probe),
- CLASSTYPE_VBASECLASSES (BINFO_TYPE (derived)))
- != NULL_TREE;
+ return (binfo_for_vbase (BINFO_TYPE (probe), BINFO_TYPE (derived))
+ != NULL_TREE);
}
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);
+ abort ();
- return TREE_VALUE (v);
+ return NULL_TREE;
}
/* Update an entry in the vtable for BINFO, which is in the hierarchy
/* Find the equivalent binfo within the return type of the
overriding function. We will want the vbase offset from
there. */
- virtual_offset =
- TREE_VALUE (purpose_member
- (BINFO_TYPE (virtual_offset),
- CLASSTYPE_VBASECLASSES (TREE_TYPE (over_return))));
+ virtual_offset = binfo_for_vbase (BINFO_TYPE (virtual_offset),
+ TREE_TYPE (over_return));
else if (!same_type_p (TREE_TYPE (over_return),
TREE_TYPE (base_return)))
{
{
/* 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;
/* 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);
}
}
tree virtual_dtor = NULL_TREE;
tree *f;
- ++adding_implicit_members;
-
/* Destructor. */
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t))
{
/* 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))
*f = TYPE_METHODS (t);
TYPE_METHODS (t) = implicit_fns;
}
-
- --adding_implicit_members;
}
/* Subroutine of finish_struct_1. Recursively count the number of fields
{
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));
return r;
}
- if (abi_version_at_least (2))
+ if (abi_version_at_least (2) && CLASSTYPE_VBASECLASSES (type))
{
- tree vbase;
+ 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 (vbase = CLASSTYPE_VBASECLASSES (type);
- vbase;
- vbase = TREE_CHAIN (vbase))
+ for (vbases = CLASSTYPE_VBASECLASSES (type), ix = 0;
+ VEC_iterate (tree, vbases, ix, binfo); ix++)
{
- binfo = TREE_VALUE (vbase);
r = walk_subobject_offsets (binfo,
f,
size_binop (PLUS_EXPR,
/* We still have to walk the primary base, if it is
virtual. (If it is non-virtual, then it was walked
above.) */
- vbase = get_primary_binfo (type_binfo);
- if (vbase && TREE_VIA_VIRTUAL (vbase)
+ tree vbase = get_primary_binfo (type_binfo);
+
+ if (vbase && BINFO_VIRTUAL_P (vbase)
&& BINFO_PRIMARY_BASE_OF (vbase) == type_binfo)
{
r = (walk_subobject_offsets
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))
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
{
{
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. */
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);
- /* Synthesize any needed methods. Note that methods will be synthesized
- for anonymous unions; grok_x_components undoes that. */
+ /* Synthesize any needed methods. */
add_implicitly_declared_members (t, cant_have_default_ctor,
cant_have_const_ctor,
no_const_asn_ref);
/* 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_PRIMARY_BASE_OF (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_BASE_OF (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 (binfo = CLASSTYPE_VBASECLASSES (t);
- binfo;
- binfo = TREE_CHAIN (binfo))
+ for (vbases = CLASSTYPE_VBASECLASSES (t), i = 0;
+ VEC_iterate (tree, vbases, i, base_binfo); i++)
{
- offset = end_of_base (TREE_VALUE (binfo));
+ offset = end_of_base (base_binfo);
if (INT_CST_LT_UNSIGNED (result, offset))
result = offset;
}
warn_about_ambiguous_bases (tree t)
{
int i;
- tree vbases;
+ 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 (vbases = CLASSTYPE_VBASECLASSES (t);
- vbases;
- vbases = TREE_CHAIN (vbases))
+ for (vbases = CLASSTYPE_VBASECLASSES (t), i = 0;
+ VEC_iterate (tree, vbases, i, binfo); i++)
{
- basetype = BINFO_TYPE (TREE_VALUE (vbases));
+ basetype = BINFO_TYPE (binfo);
if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
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)),
+ if (BINFO_VTABLE (TYPE_BINFO (t)))
+ my_friendly_assert (DECL_VIRTUAL_P (BINFO_VTABLE (TYPE_BINFO (t))),
20000116);
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
- my_friendly_assert (TYPE_BINFO_VIRTUALS (t) == NULL_TREE,
+ my_friendly_assert (BINFO_VIRTUALS (TYPE_BINFO (t)) == NULL_TREE,
20000116);
/* 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)
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;
case CONVERT_EXPR:
case SAVE_EXPR:
case CONSTRUCTOR:
- case BUFFER_REF:
abort ();
return error_mark_node;
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;
}
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;
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
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)
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) ",
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");
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;
}
type_as_string (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;
*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
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
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,
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;
{
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),
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
for (; b; b = BINFO_PRIMARY_BASE_OF (b))
{
last = b;
- if (TREE_VIA_VIRTUAL (b) || b == rtti_binfo)
+ if (BINFO_VIRTUAL_P (b) || b == rtti_binfo)
break;
}
/* 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)
+ if (BINFO_VIRTUAL_P (b) || b == rtti_binfo)
break;
/* If we found RTTI_BINFO, this is case 1. If we found a virtual
either case, we share our vtable with LAST, i.e. the
derived-most base within B of which we are a primary. */
if (b == rtti_binfo
- || (b && purpose_member (BINFO_TYPE (b),
- CLASSTYPE_VBASECLASSES (BINFO_TYPE (rtti_binfo)))))
+ || (b && binfo_for_vbase (BINFO_TYPE (b), BINFO_TYPE (rtti_binfo))))
/* Just set our BINFO_VTABLE to point to LAST, as we may not have
set LAST's BINFO_VTABLE yet. We'll extract the actual vptr in
binfo_ctor_vtable after everything's been set up. */
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. */
{
tree v, b;
tree vfun_inits;
- tree vbase;
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 = build_int_cst (ssizetype,
+ -3 * TARGET_VTABLE_DATA_ENTRY_DISTANCE);
/* Add entries to the vtable for RTTI. */
build_rtti_vtbl_entries (binfo, &vid);
VARRAY_TREE_INIT (vid.fns, 32, "fns");
/* Add the vcall and vbase offset entries. */
build_vcall_and_vbase_vtbl_entries (binfo, &vid);
+
/* Clear BINFO_VTABLE_PATH_MARKED; it's set by
build_vbase_offset_vtbl_entries. */
- for (vbase = CLASSTYPE_VBASECLASSES (t);
- vbase;
- vbase = TREE_CHAIN (vbase))
- BINFO_VTABLE_PATH_MARKED (TREE_VALUE (vbase)) = 0;
+ 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. */
if (TARGET_VTABLE_DATA_ENTRY_DISTANCE > 1)
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
/* 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 ();
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,
*vid->last_init = build_tree_list (NULL_TREE, init);
vid->last_init = &TREE_CHAIN (*vid->last_init);
}
+
+/* Fold a OBJ_TYPE_REF expression to the address of a function.
+ KNOWN_TYPE carries the true type of OBJ_TYPE_REF_OBJECT(REF). */
+
+tree
+cp_fold_obj_type_ref (tree ref, tree known_type)
+{
+ HOST_WIDE_INT index = tree_low_cst (OBJ_TYPE_REF_TOKEN (ref), 1);
+ HOST_WIDE_INT i = 0;
+ tree v = BINFO_VIRTUALS (TYPE_BINFO (known_type));
+ tree fndecl;
+
+ while (i != index)
+ {
+ i += (TARGET_VTABLE_USES_DESCRIPTORS
+ ? TARGET_VTABLE_USES_DESCRIPTORS : 1);
+ v = TREE_CHAIN (v);
+ }
+
+ fndecl = BV_FN (v);
+
+#ifdef ENABLE_CHECKING
+ if (!tree_int_cst_equal (OBJ_TYPE_REF_TOKEN (ref), DECL_VINDEX (fndecl)))
+ abort ();
+#endif
+
+ return build_address (fndecl);
+}
+