/* Functions related to building classes and their related objects.
Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
#include "tree.h"
#include "cp-tree.h"
#include "flags.h"
-#include "rtl.h"
#include "output.h"
#include "toplev.h"
#include "target.h"
#include "convert.h"
#include "cgraph.h"
#include "tree-dump.h"
+#include "splay-tree.h"
/* The number of nested classes being processed. If we are not in the
scope of any class, this is zero. */
tree rtti_binfo;
/* The negative-index vtable initializers built up so far. These
are in order from least negative index to most negative index. */
- tree inits;
- /* The last (i.e., most negative) entry in INITS. */
- tree* last_init;
+ VEC(constructor_elt,gc) *inits;
/* The binfo for the virtual base for which we're building
vcall offset initializers. */
tree vbase;
static tree fixed_type_or_null (tree, int *, int *);
static tree build_simple_base_path (tree expr, tree binfo);
static tree build_vtbl_ref_1 (tree, tree);
-static tree build_vtbl_initializer (tree, tree, tree, tree, int *);
+static void build_vtbl_initializer (tree, tree, tree, tree, int *,
+ VEC(constructor_elt,gc) **);
static int count_fields (tree);
static int add_fields_to_record_type (tree, struct sorted_fields_type*, int);
static bool check_bitfield_decl (tree);
static void dump_vtt (tree, tree);
static void dump_thunk (FILE *, int, tree);
static tree build_vtable (tree, tree, tree);
-static void initialize_vtable (tree, tree);
+static void initialize_vtable (tree, VEC(constructor_elt,gc) *);
static void layout_nonempty_base_or_field (record_layout_info,
tree, tree, splay_tree);
static tree end_of_class (tree, int);
static bool layout_empty_base (record_layout_info, tree, tree, splay_tree);
-static void accumulate_vtbl_inits (tree, tree, tree, tree, tree);
-static tree dfs_accumulate_vtbl_inits (tree, tree, tree, tree,
- tree);
+static void accumulate_vtbl_inits (tree, tree, tree, tree, tree,
+ VEC(constructor_elt,gc) **);
+static void dfs_accumulate_vtbl_inits (tree, tree, tree, tree, tree,
+ VEC(constructor_elt,gc) **);
static void build_rtti_vtbl_entries (tree, vtbl_init_data *);
static void build_vcall_and_vbase_vtbl_entries (tree, vtbl_init_data *);
static void clone_constructors_and_destructors (tree);
static void build_ctor_vtbl_group (tree, tree);
static void build_vtt (tree);
static tree binfo_ctor_vtable (tree);
-static tree *build_vtt_inits (tree, tree, tree *, tree *);
+static void build_vtt_inits (tree, tree, VEC(constructor_elt,gc) **, tree *);
static tree dfs_build_secondary_vptr_vtt_inits (tree, void *);
static tree dfs_fixup_binfo_vtbls (tree, void *);
static int record_subobject_offset (tree, tree, splay_tree);
{
expr = build_nop (build_pointer_type (target_type), expr);
if (!want_pointer)
- expr = build_indirect_ref (EXPR_LOCATION (expr), expr, NULL);
+ expr = build_indirect_ref (EXPR_LOCATION (expr), expr, RO_NULL);
return expr;
}
interesting to the optimizers anyway. */
&& !has_empty)
{
- expr = cp_build_indirect_ref (expr, NULL, tf_warning_or_error);
+ expr = cp_build_indirect_ref (expr, RO_NULL, tf_warning_or_error);
expr = build_simple_base_path (expr, binfo);
if (want_pointer)
expr = build_address (expr);
t = TREE_TYPE (TYPE_VFIELD (current_class_type));
t = build_pointer_type (t);
v_offset = convert (t, current_vtt_parm);
- v_offset = cp_build_indirect_ref (v_offset, NULL,
+ v_offset = cp_build_indirect_ref (v_offset, RO_NULL,
tf_warning_or_error);
}
else
- v_offset = build_vfield_ref (cp_build_indirect_ref (expr, NULL,
+ v_offset = build_vfield_ref (cp_build_indirect_ref (expr, RO_NULL,
tf_warning_or_error),
TREE_TYPE (TREE_TYPE (expr)));
v_offset = build1 (NOP_EXPR,
build_pointer_type (ptrdiff_type_node),
v_offset);
- v_offset = cp_build_indirect_ref (v_offset, NULL, tf_warning_or_error);
+ v_offset = cp_build_indirect_ref (v_offset, RO_NULL, tf_warning_or_error);
TREE_CONSTANT (v_offset) = 1;
offset = convert_to_integer (ptrdiff_type_node,
null_test = NULL;
if (!want_pointer)
- expr = cp_build_indirect_ref (expr, NULL, tf_warning_or_error);
+ expr = cp_build_indirect_ref (expr, RO_NULL, tf_warning_or_error);
out:
if (null_test)
in the back end. */
temp = unary_complex_lvalue (ADDR_EXPR, expr);
if (temp)
- expr = cp_build_indirect_ref (temp, NULL, tf_warning_or_error);
+ expr = cp_build_indirect_ref (temp, RO_NULL, tf_warning_or_error);
return expr;
}
assumed to be non-NULL. */
tree
-convert_to_base (tree object, tree type, bool check_access, bool nonnull)
+convert_to_base (tree object, tree type, bool check_access, bool nonnull,
+ tsubst_flags_t complain)
{
tree binfo;
tree object_type;
+ base_access access;
if (TYPE_PTR_P (TREE_TYPE (object)))
{
else
object_type = TREE_TYPE (object);
+ access = check_access ? ba_check : ba_unique;
+ if (!(complain & tf_error))
+ access |= ba_quiet;
binfo = lookup_base (object_type, type,
- check_access ? ba_check : ba_unique,
+ access,
NULL);
if (!binfo || binfo == error_mark_node)
return error_mark_node;
/* First, convert to the requested type. */
if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (datum), type))
datum = convert_to_base (datum, type, /*check_access=*/false,
- /*nonnull=*/true);
+ /*nonnull=*/true, tf_warning_or_error);
/* Second, the requested type may not be the owner of its own vptr.
If not, convert to the base class that owns it. We cannot use
{
tree aref;
- aref = build_vtbl_ref_1 (cp_build_indirect_ref (instance_ptr, 0,
+ aref = build_vtbl_ref_1 (cp_build_indirect_ref (instance_ptr, RO_NULL,
tf_warning_or_error),
idx);
&& ! DECL_STATIC_FUNCTION_P (method)
&& TREE_TYPE (TREE_VALUE (parms1)) != error_mark_node
&& TREE_TYPE (TREE_VALUE (parms2)) != error_mark_node
- && (TYPE_QUALS (TREE_TYPE (TREE_VALUE (parms1)))
- != TYPE_QUALS (TREE_TYPE (TREE_VALUE (parms2)))))
+ && (cp_type_quals (TREE_TYPE (TREE_VALUE (parms1)))
+ != cp_type_quals (TREE_TYPE (TREE_VALUE (parms2)))))
continue;
/* For templates, the return type and template parameters
tree types, base_types;
types = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
base_types = TYPE_ARG_TYPES (TREE_TYPE (base_fndecl));
- if ((TYPE_QUALS (TREE_TYPE (TREE_VALUE (base_types)))
- == TYPE_QUALS (TREE_TYPE (TREE_VALUE (types))))
+ if ((cp_type_quals (TREE_TYPE (TREE_VALUE (base_types)))
+ == cp_type_quals (TREE_TYPE (TREE_VALUE (types))))
&& compparms (TREE_CHAIN (base_types), TREE_CHAIN (types)))
return 1;
}
CLASSTYPE_LAZY_COPY_CTOR (t) = 1;
}
- /* Currently only lambdas get a lazy move ctor. */
+ /* Currently only lambdas get a lazy move ctor, but N2987 adds them for
+ other classes. */
if (LAMBDA_TYPE_P (t))
CLASSTYPE_LAZY_MOVE_CTOR (t) = 1;
&& TREE_CODE (type) != BOOLEAN_TYPE)
warning (0, "width of %q+D exceeds its type", field);
else if (TREE_CODE (type) == ENUMERAL_TYPE
- && (0 > compare_tree_int (w,
- tree_int_cst_min_precision
- (TYPE_MIN_VALUE (type),
- TYPE_UNSIGNED (type)))
- || 0 > compare_tree_int (w,
- tree_int_cst_min_precision
- (TYPE_MAX_VALUE (type),
- TYPE_UNSIGNED (type)))))
+ && (0 > (compare_tree_int
+ (w, TYPE_PRECISION (ENUM_UNDERLYING_TYPE (type))))))
warning (0, "%q+D is too small to hold all values of %q#T", field, type);
}
if (! zero_init_p (type))
CLASSTYPE_NON_ZERO_INIT_P (t) = 1;
+ /* We set DECL_C_BIT_FIELD in grokbitfield.
+ If the type and width are valid, we'll also set DECL_BIT_FIELD. */
+ if (! DECL_C_BIT_FIELD (x) || ! check_bitfield_decl (x))
+ check_field_decl (x, t,
+ cant_have_const_ctor_p,
+ no_const_asn_ref_p,
+ &any_default_members);
+
/* If any field is const, the structure type is pseudo-const. */
if (CP_TYPE_CONST_P (type))
{
if (constructor_name_p (DECL_NAME (x), t)
&& TYPE_HAS_USER_CONSTRUCTOR (t))
permerror (input_location, "field %q+#D with same name as class", x);
-
- /* We set DECL_C_BIT_FIELD in grokbitfield.
- If the type and width are valid, we'll also set DECL_BIT_FIELD. */
- if (! DECL_C_BIT_FIELD (x) || ! check_bitfield_decl (x))
- check_field_decl (x, t,
- cant_have_const_ctor_p,
- no_const_asn_ref_p,
- &any_default_members);
}
/* Effective C++ rule 11: if a class has dynamic memory held by pointers,
}
/* Create the RTL for this function. */
- SET_DECL_RTL (clone, NULL_RTX);
+ SET_DECL_RTL (clone, NULL);
rest_of_decl_compilation (clone, /*top_level=*/1, at_eof);
if (pch_file)
/* A default parameter has been added. Adjust the
clone's parameters. */
tree exceptions = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (clone));
+ tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (clone));
tree basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (clone));
tree type;
clone_parms);
if (exceptions)
type = build_exception_variant (type, exceptions);
+ if (attrs)
+ type = cp_build_type_attribute_variant (type, attrs);
TREE_TYPE (clone) = type;
clone_parms = NULL_TREE;
return false;
}
+/* Returns the defaulted constructor if T has one. Otherwise, returns
+ NULL_TREE. */
+
+tree
+in_class_defaulted_default_constructor (tree t)
+{
+ tree fns, args;
+
+ if (!TYPE_HAS_USER_CONSTRUCTOR (t))
+ return NULL_TREE;
+
+ for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns))
+ {
+ tree fn = OVL_CURRENT (fns);
+
+ if (DECL_DEFAULTED_IN_CLASS_P (fn))
+ {
+ args = FUNCTION_FIRST_USER_PARMTYPE (fn);
+ while (args && TREE_PURPOSE (args))
+ args = TREE_CHAIN (args);
+ if (!args || args == void_list_node)
+ return fn;
+ }
+ }
+
+ return NULL_TREE;
+}
+
/* Returns true iff FN is a user-provided function, i.e. user-declared
and not defaulted at its first declaration; or explicit, private,
protected, or non-const. */
{
if (TREE_CODE (*fieldsp) == FIELD_DECL
&& DECL_C_BIT_FIELD (*fieldsp)
- && DECL_INITIAL (*fieldsp))
+ /* We should not be confused by the fact that grokbitfield
+ temporarily sets the width of the bit field into
+ DECL_INITIAL (*fieldsp).
+ check_bitfield_decl eventually sets DECL_SIZE (*fieldsp)
+ to that width. */
+ && integer_zerop (DECL_SIZE (*fieldsp)))
*fieldsp = TREE_CHAIN (*fieldsp);
else
fieldsp = &TREE_CHAIN (*fieldsp);
DECL_ARTIFICIAL (field) = 1;
DECL_FIELD_CONTEXT (field) = t;
DECL_FCONTEXT (field) = t;
+ if (TYPE_PACKED (t))
+ DECL_PACKED (field) = 1;
TYPE_VFIELD (t) = field;
of the field. Then, we are supposed to use the left over
bits as additional padding. */
for (itk = itk_char; itk != itk_none; ++itk)
- if (INT_CST_LT (DECL_SIZE (field),
- TYPE_SIZE (integer_types[itk])))
+ if (integer_types[itk] != NULL_TREE
+ && (INT_CST_LT (size_int (MAX_FIXED_MODE_SIZE),
+ TYPE_SIZE (integer_types[itk]))
+ || INT_CST_LT (DECL_SIZE (field),
+ TYPE_SIZE (integer_types[itk]))))
break;
/* ITK now indicates a type that is too large for the
field. We have to back up by one to find the largest
type that fits. */
- integer_type = integer_types[itk - 1];
+ do
+ {
+ --itk;
+ integer_type = integer_types[itk];
+ } while (itk > 0 && integer_type == NULL_TREE);
/* Figure out how much additional padding is required. GCC
3.2 always created a padding field, even if it had zero
/* G++ used to use DECL_FIELD_OFFSET as if it were the byte
offset of the field. */
if (warn_abi
+ && !abi_version_at_least (2)
&& !tree_int_cst_equal (DECL_FIELD_OFFSET (field),
byte_position (field))
&& contains_empty_class_p (TREE_TYPE (field)))
TYPE_UNSIGNED (ftype));
TREE_TYPE (field)
= cp_build_qualified_type (TREE_TYPE (field),
- TYPE_QUALS (ftype));
+ cp_type_quals (ftype));
}
}
build_decl (input_location,
FIELD_DECL, NULL_TREE, char_type_node));
+ /* If this is a non-POD, declaring it packed makes a difference to how it
+ can be used as a field; don't let finalize_record_size undo it. */
+ if (TYPE_PACKED (t) && !layout_pod_type_p (t))
+ rli->packed_maybe_necessary = true;
+
/* Let the back end lay out the type. */
finish_record_layout (rli, /*free_p=*/true);
if (DECL_PURE_VIRTUAL_P (x))
VEC_safe_push (tree, gc, CLASSTYPE_PURE_VIRTUALS (t), x);
complete_vars (t);
+
+ /* Remember current #pragma pack value. */
+ TYPE_PRECISION (t) = maximum_field_alignment;
}
else
finish_struct_1 (t);
return NULL_TREE;
}
+/* Returns the innermost class type which is not a lambda closure type. */
+
+tree
+current_nonlambda_class_type (void)
+{
+ int i;
+
+ /* We start looking from 1 because entry 0 is from global scope,
+ and has no type. */
+ for (i = current_class_depth; i > 0; --i)
+ {
+ tree c;
+ if (i == current_class_depth)
+ c = current_class_type;
+ else
+ {
+ if (current_class_stack[i].hidden)
+ break;
+ c = current_class_stack[i].type;
+ }
+ if (!c)
+ continue;
+ if (!LAMBDA_TYPE_P (c))
+ return c;
+ }
+ return NULL_TREE;
+}
+
/* When entering a class scope, all enclosing class scopes' names with
static meaning (static variables, static functions, types and
enumerators) have to be visible. This recursive function calls
selected function. */
int is_ptrmem = 0;
- int is_reference = 0;
/* We store the matches in a TREE_LIST rooted here. The functions
are the TREE_PURPOSE, not the TREE_VALUE, in this list, for easy
interoperability with most_specialized_instantiation. */
tree matches = NULL_TREE;
tree fn;
+ tree target_fn_type;
/* By the time we get here, we should be seeing only real
pointer-to-member types, not the internal POINTER_TYPE to
/* This is OK, too. */
is_ptrmem = 1;
else if (TREE_CODE (target_type) == FUNCTION_TYPE)
- {
- /* This is OK, too. This comes from a conversion to reference
- type. */
- target_type = build_reference_type (target_type);
- is_reference = 1;
- }
+ /* This is OK, too. This comes from a conversion to reference
+ type. */
+ target_type = build_reference_type (target_type);
else
{
if (flags & tf_error)
return error_mark_node;
}
+ /* Non-member functions and static member functions match targets of type
+ "pointer-to-function" or "reference-to-function." Nonstatic member
+ functions match targets of type "pointer-to-member-function;" the
+ function type of the pointer to member is used to select the member
+ function from the set of overloaded member functions.
+
+ So figure out the FUNCTION_TYPE that we want to match against. */
+ target_fn_type = static_fn_type (target_type);
+
/* If we can find a non-template function that matches, we can just
use it. There's no point in generating template instantiations
if we're just going to throw them out anyhow. But, of course, we
for (fns = overload; fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
- tree fntype;
if (TREE_CODE (fn) == TEMPLATE_DECL)
/* We're not looking for templates just yet. */
continue;
/* See if there's a match. */
- fntype = TREE_TYPE (fn);
- if (is_ptrmem)
- fntype = build_ptrmemfunc_type (build_pointer_type (fntype));
- else if (!is_reference)
- fntype = build_pointer_type (fntype);
-
- if (can_convert_arg (target_type, fntype, fn, LOOKUP_NORMAL))
+ if (same_type_p (target_fn_type, static_fn_type (fn)))
matches = tree_cons (fn, NULL_TREE, matches);
}
}
match we need to look at them, too. */
if (!matches)
{
- tree target_fn_type;
tree target_arg_types;
tree target_ret_type;
tree fns;
unsigned int nargs, ia;
tree arg;
- if (is_ptrmem)
- target_fn_type
- = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (target_type));
- else
- target_fn_type = TREE_TYPE (target_type);
target_arg_types = TYPE_ARG_TYPES (target_fn_type);
target_ret_type = TREE_TYPE (target_fn_type);
- /* Never do unification on the 'this' parameter. */
- if (TREE_CODE (target_fn_type) == METHOD_TYPE)
- target_arg_types = TREE_CHAIN (target_arg_types);
-
nargs = list_length (target_arg_types);
args = XALLOCAVEC (tree, nargs);
for (arg = target_arg_types, ia = 0;
{
tree fn = OVL_CURRENT (fns);
tree instantiation;
- tree instantiation_type;
tree targs;
if (TREE_CODE (fn) != TEMPLATE_DECL)
continue;
/* See if there's a match. */
- instantiation_type = TREE_TYPE (instantiation);
- if (is_ptrmem)
- instantiation_type =
- build_ptrmemfunc_type (build_pointer_type (instantiation_type));
- else if (!is_reference)
- instantiation_type = build_pointer_type (instantiation_type);
- if (can_convert_arg (target_type, instantiation_type, instantiation,
- LOOKUP_NORMAL))
+ if (same_type_p (target_fn_type, static_fn_type (instantiation)))
matches = tree_cons (instantiation, fn, matches);
}
flags &= ~tf_ptrmem_ok;
- if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
+ if (lhstype == unknown_type_node)
{
if (flags & tf_error)
error ("not enough type information");
DECL_CONTEXT (value) = current_class_type;
DECL_ARTIFICIAL (value) = 1;
SET_DECL_SELF_REFERENCE_P (value);
+ cp_set_underlying_type (value);
if (processing_template_decl)
value = push_template_decl (value);
static void
finish_vtbls (tree t)
{
- tree list;
tree vbase;
+ VEC(constructor_elt,gc) *v = NULL;
+ tree vtable = BINFO_VTABLE (TYPE_BINFO (t));
/* 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 (BINFO_VTABLE (TYPE_BINFO (t)), NULL_TREE);
- accumulate_vtbl_inits (TYPE_BINFO (t), TYPE_BINFO (t),
- TYPE_BINFO (t), t, list);
+ accumulate_vtbl_inits (TYPE_BINFO (t), TYPE_BINFO (t), TYPE_BINFO (t),
+ vtable, t, &v);
/* Then come the virtual bases, also in inheritance graph order. */
for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase))
{
if (!BINFO_VIRTUAL_P (vbase))
continue;
- accumulate_vtbl_inits (vbase, vbase, TYPE_BINFO (t), t, list);
+ accumulate_vtbl_inits (vbase, vbase, TYPE_BINFO (t), vtable, t, &v);
}
if (BINFO_VTABLE (TYPE_BINFO (t)))
- initialize_vtable (TYPE_BINFO (t), TREE_VALUE (list));
+ initialize_vtable (TYPE_BINFO (t), v);
}
/* Initialize the vtable for BINFO with the INITS. */
static void
-initialize_vtable (tree binfo, tree inits)
+initialize_vtable (tree binfo, VEC(constructor_elt,gc) *inits)
{
tree decl;
- layout_vtable_decl (binfo, list_length (inits));
+ layout_vtable_decl (binfo, VEC_length (constructor_elt, inits));
decl = get_vtbl_decl_for_binfo (binfo);
initialize_artificial_var (decl, inits);
dump_vtable (BINFO_TYPE (binfo), binfo, decl);
static void
build_vtt (tree t)
{
- tree inits;
tree type;
tree vtt;
tree index;
+ VEC(constructor_elt,gc) *inits;
/* Build up the initializers for the VTT. */
- inits = NULL_TREE;
+ inits = NULL;
index = size_zero_node;
build_vtt_inits (TYPE_BINFO (t), t, &inits, &index);
return;
/* Figure out the type of the VTT. */
- type = build_index_type (size_int (list_length (inits) - 1));
+ type = build_index_type (size_int (VEC_length (constructor_elt, inits) - 1));
type = build_cplus_array_type (const_ptr_type_node, type);
/* Now, build the VTT object itself. */
/* Current index into the VTT. */
tree index;
- /* TREE_LIST of initializers built up. */
- tree inits;
+ /* Vector of initializers built up. */
+ VEC(constructor_elt,gc) *inits;
/* The type being constructed by this secondary VTT. */
tree type_being_constructed;
for virtual bases of T. When it is not so, we build the constructor
vtables for the BINFO-in-T variant. */
-static tree *
-build_vtt_inits (tree binfo, tree t, tree *inits, tree *index)
+static void
+build_vtt_inits (tree binfo, tree t, VEC(constructor_elt,gc) **inits, tree *index)
{
int i;
tree b;
tree init;
- tree secondary_vptrs;
secondary_vptr_vtt_init_data data;
int top_level_p = SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), t);
/* We only need VTTs for subobjects with virtual bases. */
if (!CLASSTYPE_VBASECLASSES (BINFO_TYPE (binfo)))
- return inits;
+ return;
/* We need to use a construction vtable if this is not the primary
VTT. */
/* Add the address of the primary vtable for the complete object. */
init = binfo_ctor_vtable (binfo);
- *inits = build_tree_list (NULL_TREE, init);
- inits = &TREE_CHAIN (*inits);
+ CONSTRUCTOR_APPEND_ELT (*inits, NULL_TREE, init);
if (top_level_p)
{
gcc_assert (!BINFO_VPTR_INDEX (binfo));
/* Recursively add the secondary VTTs for non-virtual bases. */
for (i = 0; BINFO_BASE_ITERATE (binfo, i, b); ++i)
if (!BINFO_VIRTUAL_P (b))
- inits = build_vtt_inits (b, t, inits, index);
+ build_vtt_inits (b, t, inits, index);
/* Add secondary virtual pointers for all subobjects of BINFO with
either virtual bases or reachable along a virtual path, except
subobjects that are non-virtual primary bases. */
data.top_level_p = top_level_p;
data.index = *index;
- data.inits = NULL;
+ data.inits = *inits;
data.type_being_constructed = BINFO_TYPE (binfo);
dfs_walk_once (binfo, dfs_build_secondary_vptr_vtt_inits, NULL, &data);
*index = data.index;
- /* The secondary vptrs come back in reverse order. After we reverse
- them, and add the INITS, the last init will be the first element
- of the chain. */
- secondary_vptrs = data.inits;
- if (secondary_vptrs)
- {
- *inits = nreverse (secondary_vptrs);
- inits = &TREE_CHAIN (secondary_vptrs);
- gcc_assert (*inits == NULL_TREE);
- }
+ /* data.inits might have grown as we added secondary virtual pointers.
+ Make sure our caller knows about the new vector. */
+ *inits = data.inits;
if (top_level_p)
/* Add the secondary VTTs for virtual bases in inheritance graph
if (!BINFO_VIRTUAL_P (b))
continue;
- inits = build_vtt_inits (b, t, inits, index);
+ build_vtt_inits (b, t, inits, index);
}
else
/* Remove the ctor vtables we created. */
dfs_walk_all (binfo, dfs_fixup_binfo_vtbls, NULL, binfo);
-
- return inits;
}
/* Called from build_vtt_inits via dfs_walk. BINFO is the binfo for the base
}
/* Add the initializer for the secondary vptr itself. */
- data->inits = tree_cons (NULL_TREE, binfo_ctor_vtable (binfo), data->inits);
+ CONSTRUCTOR_APPEND_ELT (data->inits, NULL_TREE, binfo_ctor_vtable (binfo));
/* Advance the vtt index. */
data->index = size_binop (PLUS_EXPR, data->index,
static void
build_ctor_vtbl_group (tree binfo, tree t)
{
- tree list;
tree type;
tree vtbl;
- tree inits;
tree id;
tree vbase;
+ VEC(constructor_elt,gc) *v;
/* See if we've already created this construction vtable group. */
id = mangle_ctor_vtbl_for_type (t, binfo);
construction vtable group. */
vtbl = build_vtable (t, id, ptr_type_node);
DECL_CONSTRUCTION_VTABLE_P (vtbl) = 1;
- list = build_tree_list (vtbl, NULL_TREE);
+
+ v = NULL;
accumulate_vtbl_inits (binfo, TYPE_BINFO (TREE_TYPE (binfo)),
- binfo, t, list);
+ binfo, vtbl, t, &v);
/* Add the vtables for each of our virtual bases using the vbase in T
binfo. */
continue;
b = copied_binfo (vbase, binfo);
- accumulate_vtbl_inits (b, vbase, binfo, t, list);
+ accumulate_vtbl_inits (b, vbase, binfo, vtbl, t, &v);
}
- inits = TREE_VALUE (list);
/* Figure out the type of the construction vtable. */
- type = build_index_type (size_int (list_length (inits) - 1));
+ type = build_index_type (size_int (VEC_length (constructor_elt, v) - 1));
type = build_cplus_array_type (vtable_entry_type, type);
layout_type (type);
TREE_TYPE (vtbl) = type;
/* Initialize the construction vtable. */
CLASSTYPE_VTABLES (t) = chainon (CLASSTYPE_VTABLES (t), vtbl);
- initialize_artificial_var (vtbl, inits);
+ initialize_artificial_var (vtbl, v);
dump_vtable (t, binfo, vtbl);
}
accumulate_vtbl_inits (tree binfo,
tree orig_binfo,
tree rtti_binfo,
+ tree vtbl,
tree t,
- tree inits)
+ VEC(constructor_elt,gc) **inits)
{
int i;
tree base_binfo;
return;
/* Build the initializers for the BINFO-in-T vtable. */
- TREE_VALUE (inits)
- = chainon (TREE_VALUE (inits),
- dfs_accumulate_vtbl_inits (binfo, orig_binfo,
- rtti_binfo, t, inits));
+ dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, vtbl, t, inits);
/* Walk the BINFO and its bases. We walk in preorder so that as we
initialize each vtable we can figure out at what offset the
continue;
accumulate_vtbl_inits (base_binfo,
BINFO_BASE_BINFO (orig_binfo, i),
- rtti_binfo, t,
+ rtti_binfo, vtbl, t,
inits);
}
}
-/* Called from accumulate_vtbl_inits. Returns the initializers for
- the BINFO vtable. */
+/* Called from accumulate_vtbl_inits. Adds the initializers for the
+ BINFO vtable to L. */
-static tree
+static void
dfs_accumulate_vtbl_inits (tree binfo,
tree orig_binfo,
tree rtti_binfo,
+ tree orig_vtbl,
tree t,
- tree l)
+ VEC(constructor_elt,gc) **l)
{
- tree inits = NULL_TREE;
tree vtbl = NULL_TREE;
int ctor_vtbl_p = !SAME_BINFO_TYPE_P (BINFO_TYPE (rtti_binfo), t);
+ int n_inits;
if (ctor_vtbl_p
&& BINFO_VIRTUAL_P (orig_binfo) && BINFO_PRIMARY_P (orig_binfo))
/* Otherwise, this is case 3 and we get our own. */
}
else if (!BINFO_NEW_VTABLE_MARKED (orig_binfo))
- return inits;
+ return;
+
+ n_inits = VEC_length (constructor_elt, *l);
if (!vtbl)
{
tree index;
int non_fn_entries;
- /* Compute the initializer for this vtable. */
- inits = build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo,
- &non_fn_entries);
+ /* Add the initializer for this vtable. */
+ build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo,
+ &non_fn_entries, l);
/* Figure out the position to which the VPTR should point. */
- vtbl = TREE_PURPOSE (l);
- vtbl = build1 (ADDR_EXPR, vtbl_ptr_type_node, vtbl);
+ vtbl = build1 (ADDR_EXPR, vtbl_ptr_type_node, orig_vtbl);
index = size_binop (PLUS_EXPR,
size_int (non_fn_entries),
- size_int (list_length (TREE_VALUE (l))));
+ size_int (n_inits));
index = size_binop (MULT_EXPR,
TYPE_SIZE_UNIT (vtable_entry_type),
index);
straighten this out. */
BINFO_VTABLE (binfo) = tree_cons (rtti_binfo, vtbl, BINFO_VTABLE (binfo));
else if (BINFO_PRIMARY_P (binfo) && BINFO_VIRTUAL_P (binfo))
- inits = NULL_TREE;
+ /* Throw away any unneeded intializers. */
+ VEC_truncate (constructor_elt, *l, n_inits);
else
/* For an ordinary vtable, set BINFO_VTABLE. */
BINFO_VTABLE (binfo) = vtbl;
-
- return inits;
}
static GTY(()) tree abort_fndecl_addr;
primary bases; we need these while the primary base is being
constructed. */
-static tree
+static void
build_vtbl_initializer (tree binfo,
tree orig_binfo,
tree t,
tree rtti_binfo,
- int* non_fn_entries_p)
+ int* non_fn_entries_p,
+ VEC(constructor_elt,gc) **inits)
{
tree v, b;
- tree vfun_inits;
vtbl_init_data vid;
- unsigned ix;
+ unsigned ix, jx;
tree vbinfo;
VEC(tree,gc) *vbases;
+ constructor_elt *e;
/* Initialize VID. */
memset (&vid, 0, sizeof (vid));
vid.binfo = binfo;
vid.derived = t;
vid.rtti_binfo = rtti_binfo;
- vid.last_init = &vid.inits;
vid.primary_vtbl_p = SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), t);
vid.ctor_vtbl_p = !SAME_BINFO_TYPE_P (BINFO_TYPE (rtti_binfo), t);
vid.generate_vcall_entries = true;
/* If the target requires padding between data entries, add that now. */
if (TARGET_VTABLE_DATA_ENTRY_DISTANCE > 1)
{
- tree cur, *prev;
+ int n_entries = VEC_length (constructor_elt, vid.inits);
+
+ VEC_safe_grow (constructor_elt, gc, vid.inits,
+ TARGET_VTABLE_DATA_ENTRY_DISTANCE * n_entries);
- for (prev = &vid.inits; (cur = *prev); prev = &TREE_CHAIN (cur))
+ /* Move data entries into their new positions and add padding
+ after the new positions. Iterate backwards so we don't
+ overwrite entries that we would need to process later. */
+ for (ix = n_entries - 1;
+ VEC_iterate (constructor_elt, vid.inits, ix, e);
+ ix--)
{
- tree add = cur;
- int i;
+ int j;
+ int new_position = TARGET_VTABLE_DATA_ENTRY_DISTANCE * ix;
+
+ VEC_replace (constructor_elt, vid.inits, new_position, e);
- for (i = 1; i < TARGET_VTABLE_DATA_ENTRY_DISTANCE; ++i)
- add = tree_cons (NULL_TREE,
- build1 (NOP_EXPR, vtable_entry_type,
- null_pointer_node),
- add);
- *prev = add;
+ for (j = 1; j < TARGET_VTABLE_DATA_ENTRY_DISTANCE; ++j)
+ {
+ constructor_elt *f = VEC_index (constructor_elt, *inits,
+ new_position + j);
+ f->index = NULL_TREE;
+ f->value = build1 (NOP_EXPR, vtable_entry_type,
+ null_pointer_node);
+ }
}
}
if (non_fn_entries_p)
- *non_fn_entries_p = list_length (vid.inits);
+ *non_fn_entries_p = VEC_length (constructor_elt, vid.inits);
+
+ /* The initializers for virtual functions were built up in reverse
+ order. Straighten them out and add them to the running list in one
+ step. */
+ jx = VEC_length (constructor_elt, *inits);
+ VEC_safe_grow (constructor_elt, gc, *inits,
+ (jx + VEC_length (constructor_elt, vid.inits)));
+
+ for (ix = VEC_length (constructor_elt, vid.inits) - 1;
+ VEC_iterate (constructor_elt, vid.inits, ix, e);
+ ix--, jx++)
+ VEC_replace (constructor_elt, *inits, jx, e);
/* Go through all the ordinary virtual functions, building up
initializers. */
- vfun_inits = NULL_TREE;
for (v = BINFO_VIRTUALS (orig_binfo); v; v = TREE_CHAIN (v))
{
tree delta;
int i;
if (init == size_zero_node)
for (i = 0; i < TARGET_VTABLE_USES_DESCRIPTORS; ++i)
- vfun_inits = tree_cons (NULL_TREE, init, vfun_inits);
+ CONSTRUCTOR_APPEND_ELT (*inits, NULL_TREE, init);
else
for (i = 0; i < TARGET_VTABLE_USES_DESCRIPTORS; ++i)
{
build_int_cst (NULL_TREE, i));
TREE_CONSTANT (fdesc) = 1;
- vfun_inits = tree_cons (NULL_TREE, fdesc, vfun_inits);
+ CONSTRUCTOR_APPEND_ELT (*inits, NULL_TREE, fdesc);
}
}
else
- vfun_inits = tree_cons (NULL_TREE, init, vfun_inits);
+ CONSTRUCTOR_APPEND_ELT (*inits, NULL_TREE, init);
}
-
- /* The initializers for virtual functions were built up in reverse
- order; straighten them out now. */
- vfun_inits = nreverse (vfun_inits);
-
- /* The negative offset initializers are also in reverse order. */
- vid.inits = nreverse (vid.inits);
-
- /* Chain the two together. */
- return chainon (vid.inits, vfun_inits);
}
/* Adds to vid->inits the initializers for the vbase and vcall
delta = size_diffop_loc (input_location,
BINFO_OFFSET (b), BINFO_OFFSET (non_primary_binfo));
- *vid->last_init
- = build_tree_list (NULL_TREE,
- fold_build1_loc (input_location, NOP_EXPR,
- vtable_entry_type,
- delta));
- vid->last_init = &TREE_CHAIN (*vid->last_init);
+ CONSTRUCTOR_APPEND_ELT (vid->inits, NULL_TREE,
+ fold_build1_loc (input_location, NOP_EXPR,
+ vtable_entry_type, delta));
}
}
vcall_offset);
}
/* Add the initializer to the vtable. */
- *vid->last_init = build_tree_list (NULL_TREE, vcall_offset);
- vid->last_init = &TREE_CHAIN (*vid->last_init);
+ CONSTRUCTOR_APPEND_ELT (vid->inits, NULL_TREE, vcall_offset);
}
}
{
tree b;
tree t;
- tree basetype;
tree offset;
tree decl;
tree init;
- basetype = BINFO_TYPE (binfo);
t = BINFO_TYPE (vid->rtti_binfo);
/* To find the complete object, we will first convert to our most
/* Convert the declaration to a type that can be stored in the
vtable. */
init = build_nop (vfunc_ptr_type_node, decl);
- *vid->last_init = build_tree_list (NULL_TREE, init);
- vid->last_init = &TREE_CHAIN (*vid->last_init);
+ CONSTRUCTOR_APPEND_ELT (vid->inits, NULL_TREE, init);
/* Add the offset-to-top entry. It comes earlier in the vtable than
the typeinfo entry. Convert the offset to look like a
function pointer, so that we can put it in the vtable. */
init = build_nop (vfunc_ptr_type_node, offset);
- *vid->last_init = build_tree_list (NULL_TREE, init);
- vid->last_init = &TREE_CHAIN (*vid->last_init);
+ CONSTRUCTOR_APPEND_ELT (vid->inits, NULL_TREE, init);
}
/* Fold a OBJ_TYPE_REF expression to the address of a function.