#include "toplev.h"
#include "ggc.h"
#include "lex.h"
-
-#include "obstack.h"
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
+#include "target.h"
/* The number of nested classes being processed. If we are not in the
scope of any class, this is zero. */
static int build_secondary_vtable PARAMS ((tree, tree));
static void finish_vtbls PARAMS ((tree));
static void modify_vtable_entry PARAMS ((tree, tree, tree, tree, tree *));
-static void add_virtual_function PARAMS ((tree *, tree *, int *, tree, tree));
static tree delete_duplicate_fields_1 PARAMS ((tree, tree));
static void delete_duplicate_fields PARAMS ((tree));
static void finish_struct_bits PARAMS ((tree));
static void remove_zero_width_bit_fields PARAMS ((tree));
static void check_bases PARAMS ((tree, int *, int *, int *));
static void check_bases_and_members PARAMS ((tree, int *));
-static tree create_vtable_ptr PARAMS ((tree, int *, int *, tree *, tree *));
-static void layout_class_type PARAMS ((tree, int *, int *, tree *, tree *));
+static tree create_vtable_ptr PARAMS ((tree, int *, tree *));
+static void layout_class_type PARAMS ((tree, int *, int *, tree *));
static void fixup_pending_inline PARAMS ((tree));
static void fixup_inline_methods PARAMS ((tree));
static void set_primary_base PARAMS ((tree, tree, int *));
}
fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull);
- if (fixed_type_p < 0)
- /* Virtual base layout is not fixed, even in ctors and dtors. */
- fixed_type_p = 0;
- if (!fixed_type_p && TREE_SIDE_EFFECTS (expr))
+ if (fixed_type_p <= 0 && TREE_SIDE_EFFECTS (expr))
expr = save_expr (expr);
-
+
if (!want_pointer)
expr = build_unary_op (ADDR_EXPR, expr, 0);
else if (!nonnull)
offset = BINFO_OFFSET (binfo);
- if (v_binfo && !fixed_type_p)
+ if (v_binfo && fixed_type_p <= 0)
{
/* Going via virtual base V_BINFO. We need the static offset
from V_BINFO to BINFO, and the dynamic offset from D_BINFO to
build_pointer_type (ptrdiff_type_node),
v_offset);
v_offset = build_indirect_ref (v_offset, NULL);
-
+ TREE_CONSTANT (v_offset) = 1;
+
offset = cp_convert (ptrdiff_type_node,
size_diffop (offset, BINFO_OFFSET (v_binfo)));
if (!integer_zerop (offset))
- offset = build (code, ptrdiff_type_node, v_offset, offset);
+ v_offset = build (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));
else
offset = v_offset;
}
expr = build (COND_EXPR, target_type, null_test,
build1 (NOP_EXPR, target_type, integer_zero_node),
expr);
-
+
return expr;
}
+/* Convert OBJECT to the base TYPE. If CHECK_ACCESS is true, an error
+ message is emitted if TYPE is inaccessible. OBJECT is assumed to
+ be non-NULL. */
+
+tree
+convert_to_base (tree object, tree type, bool check_access)
+{
+ tree binfo;
+
+ binfo = lookup_base (TREE_TYPE (object), type,
+ check_access ? ba_check : ba_ignore,
+ NULL);
+ if (!binfo || binfo == error_mark_node)
+ return error_mark_node;
+
+ return build_base_path (PLUS_EXPR, object, binfo, /*nonnull=*/1);
+}
+
\f
/* Virtual function things. */
build_vtbl_ref_1 (instance, idx)
tree instance, idx;
{
- tree vtbl, aref;
- tree basetype = TREE_TYPE (instance);
+ tree aref;
+ tree vtbl = NULL_TREE;
+
+ /* Try to figure out what a reference refers to, and
+ access its virtual function table directly. */
+
+ int cdtorp = 0;
+ tree fixed_type = fixed_type_or_null (instance, NULL, &cdtorp);
+ tree basetype = TREE_TYPE (instance);
if (TREE_CODE (basetype) == REFERENCE_TYPE)
basetype = TREE_TYPE (basetype);
- if (instance == current_class_ref)
- vtbl = build_vfield_ref (instance, basetype);
- else
+ if (fixed_type && !cdtorp)
{
- if (optimize)
- {
- /* Try to figure out what a reference refers to, and
- access its virtual function table directly. */
- tree ref = NULL_TREE;
-
- if (TREE_CODE (instance) == INDIRECT_REF
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (instance, 0))) == REFERENCE_TYPE)
- ref = TREE_OPERAND (instance, 0);
- else if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
- ref = instance;
-
- if (ref && TREE_CODE (ref) == VAR_DECL
- && DECL_INITIAL (ref))
- {
- tree init = DECL_INITIAL (ref);
-
- while (TREE_CODE (init) == NOP_EXPR
- || TREE_CODE (init) == NON_LVALUE_EXPR)
- init = TREE_OPERAND (init, 0);
- if (TREE_CODE (init) == ADDR_EXPR)
- {
- init = TREE_OPERAND (init, 0);
- if (IS_AGGR_TYPE (TREE_TYPE (init))
- && (TREE_CODE (init) == PARM_DECL
- || TREE_CODE (init) == VAR_DECL))
- instance = init;
- }
- }
- }
+ tree binfo = lookup_base (fixed_type, basetype,
+ ba_ignore|ba_quiet, NULL);
+ if (binfo)
+ vtbl = BINFO_VTABLE (binfo);
+ }
- if (IS_AGGR_TYPE (TREE_TYPE (instance))
- && (TREE_CODE (instance) == RESULT_DECL
- || TREE_CODE (instance) == PARM_DECL
- || TREE_CODE (instance) == VAR_DECL))
- {
- vtbl = TYPE_BINFO_VTABLE (basetype);
- /* Knowing the dynamic type of INSTANCE we can easily obtain
- the correct vtable entry. We resolve this back to be in
- terms of the primary vtable. */
- if (TREE_CODE (vtbl) == PLUS_EXPR)
- {
- idx = fold (build (PLUS_EXPR,
- TREE_TYPE (idx),
- idx,
- build (EXACT_DIV_EXPR,
- TREE_TYPE (idx),
- TREE_OPERAND (vtbl, 1),
- TYPE_SIZE_UNIT (vtable_entry_type))));
- vtbl = get_vtbl_decl_for_binfo (TYPE_BINFO (basetype));
- }
- }
- else
- vtbl = build_vfield_ref (instance, basetype);
+ if (!vtbl)
+ {
+ vtbl = build_vfield_ref (instance, basetype);
}
assemble_external (vtbl);
aref = build_array_ref (vtbl, idx);
+ TREE_CONSTANT (aref) = 1;
return aref;
}
TREE_STATIC (decl) = 1;
TREE_READONLY (decl) = 1;
DECL_VIRTUAL_P (decl) = 1;
+ DECL_ALIGN (decl) = TARGET_VTABLE_ENTRY_ALIGN;
+
import_export_vtable (decl, class_type, 0);
return decl;
? TARGET_VTABLE_USES_DESCRIPTORS : 1);
DECL_VINDEX (decl) = build_shared_int_cst (vindex);
}
-
-/* Add a virtual function to all the appropriate vtables for the class
- T. DECL_VINDEX(X) should be error_mark_node, if we want to
- allocate a new slot in our table. If it is error_mark_node, we
- know that no other function from another vtable is overridden by X.
- VFUNS_P keeps track of how many virtuals there are in our
- main vtable for the type, and we build upon the NEW_VIRTUALS list
- and return it. */
-
-static void
-add_virtual_function (new_virtuals_p, overridden_virtuals_p,
- vfuns_p, fndecl, t)
- tree *new_virtuals_p;
- tree *overridden_virtuals_p;
- int *vfuns_p;
- tree fndecl;
- tree t; /* Structure type. */
-{
- tree new_virtual;
-
- /* If this function doesn't override anything from a base class, we
- can just assign it a new DECL_VINDEX now. Otherwise, if it does
- override something, we keep it around and assign its DECL_VINDEX
- later, in modify_all_vtables. */
- if (TREE_CODE (DECL_VINDEX (fndecl)) == INTEGER_CST)
- /* We've already dealt with this function. */
- return;
-
- new_virtual = make_node (TREE_LIST);
- BV_FN (new_virtual) = fndecl;
- BV_DELTA (new_virtual) = integer_zero_node;
-
- if (DECL_VINDEX (fndecl) == error_mark_node)
- {
- /* FNDECL is a new virtual function; it doesn't override any
- virtual function in a base class. */
-
- /* We remember that this was the base sub-object for rtti. */
- CLASSTYPE_RTTI (t) = t;
-
- /* Now assign virtual dispatch information. */
- set_vindex (fndecl, vfuns_p);
- DECL_VIRTUAL_CONTEXT (fndecl) = t;
-
- /* Save the state we've computed on the NEW_VIRTUALS list. */
- TREE_CHAIN (new_virtual) = *new_virtuals_p;
- *new_virtuals_p = new_virtual;
- }
- else
- {
- /* FNDECL overrides a function from a base class. */
- TREE_CHAIN (new_virtual) = *overridden_virtuals_p;
- *overridden_virtuals_p = new_virtual;
- }
-}
\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
int len;
int slot;
tree method_vec;
+ int 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
slot = CLASSTYPE_DESTRUCTOR_SLOT;
else
{
+ int have_template_convs_p = 0;
+
/* See if we already have an entry with this name. */
for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; slot < len; ++slot)
- if (!TREE_VEC_ELT (method_vec, slot)
- || (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec,
- slot)))
- == DECL_NAME (method)))
- break;
-
+ {
+ 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++;
+ }
+ break;
+ }
+ if (DECL_NAME (m) == DECL_NAME (method))
+ break;
+ }
+
if (slot == len)
{
/* We need a bigger method vector. */
slide some of the vector elements up. In theory, this
makes this algorithm O(N^2) but we don't expect many
conversion operators. */
- for (slot = 2; slot < len; ++slot)
- {
- tree fn = TREE_VEC_ELT (method_vec, slot);
+ 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 (!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 (!TREE_VEC_ELT (method_vec, slot))
+ 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. */
;
fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
-
+ tree parms1;
+ tree parms2;
+ bool same = 1;
+
if (TREE_CODE (fn) != TREE_CODE (method))
continue;
- if (TREE_CODE (method) != TEMPLATE_DECL)
+ /* [over.load] Member function declarations with the
+ same name and the same parameter types cannot be
+ overloaded if any of them is a static member
+ function declaration.
+
+ [namespace.udecl] When a using-declaration brings names
+ from a base class into a derived class scope, member
+ functions in the derived class override and/or hide member
+ functions with the same name and parameter types in a base
+ class (rather than conflicting). */
+ parms1 = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ parms2 = TYPE_ARG_TYPES (TREE_TYPE (method));
+
+ /* Compare the quals on the 'this' parm. Don't compare
+ the whole types, as used functions are treated as
+ coming from the using class in overload resolution. */
+ if (! DECL_STATIC_FUNCTION_P (fn)
+ && ! DECL_STATIC_FUNCTION_P (method)
+ && (TYPE_QUALS (TREE_TYPE (TREE_VALUE (parms1)))
+ != TYPE_QUALS (TREE_TYPE (TREE_VALUE (parms2)))))
+ same = 0;
+ if (! DECL_STATIC_FUNCTION_P (fn))
+ parms1 = TREE_CHAIN (parms1);
+ if (! DECL_STATIC_FUNCTION_P (method))
+ parms2 = TREE_CHAIN (parms2);
+
+ if (same && compparms (parms1, parms2)
+ && (!DECL_CONV_FN_P (fn)
+ || same_type_p (TREE_TYPE (TREE_TYPE (fn)),
+ TREE_TYPE (TREE_TYPE (method)))))
{
- /* [over.load] Member function declarations with the
- same name and the same parameter types cannot be
- overloaded if any of them is a static member
- function declaration.
-
- [namespace.udecl] When a using-declaration brings names
- from a base class into a derived class scope, member
- functions in the derived class override and/or hide member
- functions with the same name and parameter types in a base
- class (rather than conflicting). */
- if ((DECL_STATIC_FUNCTION_P (fn)
- != DECL_STATIC_FUNCTION_P (method))
- || using)
+ if (using && DECL_CONTEXT (fn) == type)
+ /* Defer to the local function. */
+ return;
+ else
{
- tree parms1 = TYPE_ARG_TYPES (TREE_TYPE (fn));
- tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (method));
- int same = 1;
-
- /* Compare the quals on the 'this' parm. Don't compare
- the whole types, as used functions are treated as
- coming from the using class in overload resolution. */
- if (using
- && ! DECL_STATIC_FUNCTION_P (fn)
- && ! DECL_STATIC_FUNCTION_P (method)
- && (TYPE_QUALS (TREE_TYPE (TREE_VALUE (parms1)))
- != TYPE_QUALS (TREE_TYPE (TREE_VALUE (parms2)))))
- same = 0;
- if (! DECL_STATIC_FUNCTION_P (fn))
- parms1 = TREE_CHAIN (parms1);
- if (! DECL_STATIC_FUNCTION_P (method))
- parms2 = TREE_CHAIN (parms2);
-
- if (same && compparms (parms1, parms2))
- {
- if (using && DECL_CONTEXT (fn) == type)
- /* Defer to the local function. */
- return;
- else
- error ("`%#D' and `%#D' cannot be overloaded",
- fn, method);
- }
+ cp_error_at ("`%#D' and `%#D' cannot be overloaded",
+ method, fn, method);
+
+ /* We don't call duplicate_decls here to merge
+ the declarations because that will confuse
+ things if the methods have inline
+ definitions. In particular, we will crash
+ while processing the definitions. */
+ return;
}
}
-
- if (!decls_match (fn, method))
- continue;
-
- /* There has already been a declaration of this method
- or member template. */
- cp_error_at ("`%D' has already been declared in `%T'",
- method, type);
-
- /* We don't call duplicate_decls here to merge the
- declarations because that will confuse things if the
- methods have inline definitions. In particular, we
- will crash while processing the definitions. */
- return;
}
}
TREE_VEC_ELT (method_vec, slot)
= build_overload (method, TREE_VEC_ELT (method_vec, slot));
- /* Add the new binding. */
+ /* Add the new binding. */
if (!DECL_CONSTRUCTOR_P (method)
&& !DECL_DESTRUCTOR_P (method))
push_class_level_binding (DECL_NAME (method),
if (! binfo)
return;
- if (name == constructor_name (ctype)
- || name == constructor_name_full (ctype))
+ if (constructor_name_p (name, ctype))
{
cp_error_at ("`%D' names constructor", using_decl);
return;
}
- if (name == constructor_name (t)
- || name == constructor_name_full (t))
+ if (constructor_name_p (name, t))
{
cp_error_at ("`%D' invalid in `%T'", using_decl, t);
return;
if (BASELINK_P (fdecl))
/* Ignore base type this came from. */
- fdecl = TREE_VALUE (fdecl);
+ fdecl = BASELINK_FUNCTIONS (fdecl);
old_value = IDENTIFIER_CLASS_VALUE (name);
if (old_value)
}
}
- /* If this type has a copy constructor, 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.
-
- Also do this if the class has BLKmode but can still be returned in
- registers, since function_cannot_inline_p won't let us inline
- functions returning such a type. This affects the HP-PA. */
- if (! TYPE_HAS_TRIVIAL_INIT_REF (t)
- || (TYPE_MODE (t) == BLKmode && ! aggregate_value_p (t)
- && CLASSTYPE_NON_AGGREGATE (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;
DECL_MODE (TYPE_MAIN_DECL (t)) = BLKmode;
memset ((char *) TYPE_LANG_SPECIFIC (t), 0, sizeof (struct lang_type));
BINFO_BASETYPES(binfo) = NULL_TREE;
+ TYPE_LANG_SPECIFIC (t)->u.h.is_lang_type_class = 1;
TYPE_BINFO (t) = binfo;
CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
{
find_final_overrider_data ffod;
- /* Getting this right is a little tricky. This is legal:
+ /* Getting this right is a little tricky. This is valid:
struct S { virtual void f (); };
struct T { virtual void f (); };
if (overrider == error_mark_node)
return;
+ /* Check for unsupported covariant returns again now that we've
+ calculated the base offsets. */
+ check_final_overrider (TREE_PURPOSE (overrider), fn);
+
/* Assume that we will produce a thunk that convert all the way to
the final overrider, and not to an intermediate virtual base. */
virtual_base = NULL_TREE;
/* Update all of the primary and secondary vtables for T. Create new
vtables as required, and initialize their RTTI information. Each
- of the functions in OVERRIDDEN_VIRTUALS overrides a virtual
- function from a base class; find and modify the appropriate entries
- to point to the overriding functions. Returns a list, in
- declaration order, of the functions that are overridden in this
- class, but do not appear in the primary base class vtable, and
- which should therefore be appended to the end of the vtable for T. */
+ of the functions in VIRTUALS is declared in T and may override a
+ virtual function from a base class; find and modify the appropriate
+ entries to point to the overriding functions. Returns a list, in
+ declaration order, of the virtual functions that are declared in T,
+ but do not appear in the primary base class vtable, and which
+ should therefore be appended to the end of the vtable for T. */
static tree
-modify_all_vtables (t, vfuns_p, overridden_virtuals)
+modify_all_vtables (t, vfuns_p, virtuals)
tree t;
int *vfuns_p;
- tree overridden_virtuals;
+ tree virtuals;
{
tree binfo = TYPE_BINFO (t);
tree *fnsp;
t);
dfs_walk (binfo, dfs_unmark, dfs_marked_real_bases_queue_p, t);
- /* Include overriding functions for secondary vtables in our primary
- vtable. */
- for (fnsp = &overridden_virtuals; *fnsp; )
+ /* Add virtual functions not already in our primary vtable. These
+ will be both those introduced by this class, and those overridden
+ from secondary bases. It does not include virtuals merely
+ inherited from secondary bases. */
+ for (fnsp = &virtuals; *fnsp; )
{
tree fn = TREE_VALUE (*fnsp);
- if (!BINFO_VIRTUALS (binfo)
- || !value_member (fn, BINFO_VIRTUALS (binfo)))
+ if (!value_member (fn, BINFO_VIRTUALS (binfo))
+ || DECL_VINDEX (fn) == error_mark_node)
{
/* Set the vtable index. */
set_vindex (fn, vfuns_p);
BV_DELTA (*fnsp) = integer_zero_node;
BV_VCALL_INDEX (*fnsp) = NULL_TREE;
- /* This is an overridden function not already in our
- vtable. Keep it. */
+ /* This is a function not already in our vtable. Keep it. */
fnsp = &TREE_CHAIN (*fnsp);
}
else
*fnsp = TREE_CHAIN (*fnsp);
}
- return overridden_virtuals;
+ return virtuals;
}
/* Here, we already know that they match in every respect.
|| IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)))
&& look_for_overrides (ctype, decl)
&& !DECL_STATIC_FUNCTION_P (decl))
- {
- /* Set DECL_VINDEX to a value that is neither an
- INTEGER_CST nor the error_mark_node so that
- add_virtual_function will realize this is an
- overriding function. */
- DECL_VINDEX (decl) = decl;
- }
+ /* Set DECL_VINDEX to a value that is neither an INTEGER_CST nor
+ the error_mark_node so that we know it is an overriding
+ function. */
+ DECL_VINDEX (decl) = decl;
+
if (DECL_VIRTUAL_P (decl))
{
- if (DECL_VINDEX (decl) == NULL_TREE)
+ if (!DECL_VINDEX (decl))
DECL_VINDEX (decl) = error_mark_node;
IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1;
}
DECL_SIZE (field) = convert (bitsizetype, w);
DECL_BIT_FIELD (field) = 1;
- if (integer_zerop (w))
+ if (integer_zerop (w)
+ && ! (* targetm.ms_bitfield_layout_p) (DECL_FIELD_CONTEXT (field)))
{
#ifdef EMPTY_FIELD_BOUNDARY
DECL_ALIGN (field) = MAX (DECL_ALIGN (field),
tree x = *field;
tree type = TREE_TYPE (x);
- GNU_xref_member (current_class_name, x);
-
next = &TREE_CHAIN (x);
if (TREE_CODE (x) == FIELD_DECL)
to be allowed in POD structs. */
CLASSTYPE_NON_POD_P (t) = 1;
+ if (! zero_init_p (type))
+ CLASSTYPE_NON_ZERO_INIT_P (t) = 1;
+
/* If any field is const, the structure type is pseudo-const. */
if (CP_TYPE_CONST_P (type))
{
DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
+ /* Tell the backend not to round up to TYPE_ALIGN. */
+ DECL_PACKED (decl) = 1;
if (!integer_zerop (DECL_SIZE (decl)))
{
for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
{
- GNU_xref_member (current_class_name, x);
-
/* If this was an evil function, don't keep it in class. */
if (DECL_ASSEMBLER_NAME_SET_P (x)
&& IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x)))
for (parms = DECL_ARGUMENTS (clone); parms; parms = TREE_CHAIN (parms))
{
DECL_CONTEXT (parms) = clone;
- copy_lang_decl (parms);
+ cxx_dup_lang_specific_decl (parms);
}
}
if (!fns || fns == error_mark_node)
return false;
/* Loop through all of the functions. */
- for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns))
+ for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns))
{
tree fn;
tree second_parm;
/* Figure out whether or not we will need a cookie when dynamically
allocating an array of this type. */
- TYPE_LANG_SPECIFIC (t)->vec_new_uses_cookie
+ TYPE_LANG_SPECIFIC (t)->u.c.vec_new_uses_cookie
= type_requires_array_cookie (t);
}
accordingly. If a new vfield was created (because T doesn't have a
primary base class), then the newly created field is returned. It
is not added to the TYPE_FIELDS list; it is the caller's
- responsibility to do that. */
+ responsibility to do that. Accumulate declared virtual functions
+ on VIRTUALS_P. */
static tree
-create_vtable_ptr (t, empty_p, vfuns_p,
- new_virtuals_p, overridden_virtuals_p)
+create_vtable_ptr (t, empty_p, virtuals_p)
tree t;
int *empty_p;
- int *vfuns_p;
- tree *new_virtuals_p;
- tree *overridden_virtuals_p;
+ tree *virtuals_p;
{
tree fn;
- /* Loop over the virtual functions, adding them to our various
- vtables. */
+ /* Collect the virtual functions declared in T. */
for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn))
- if (DECL_VINDEX (fn) && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn))
- add_virtual_function (new_virtuals_p, overridden_virtuals_p,
- vfuns_p, fn, t);
+ if (DECL_VINDEX (fn) && !DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn)
+ && TREE_CODE (DECL_VINDEX (fn)) != INTEGER_CST)
+ {
+ tree new_virtual = make_node (TREE_LIST);
+
+ BV_FN (new_virtual) = fn;
+ BV_DELTA (new_virtual) = integer_zero_node;
+ TREE_CHAIN (new_virtual) = *virtuals_p;
+ *virtuals_p = new_virtual;
+ }
+
/* If we couldn't find an appropriate base class, create a new field
here. Even if there weren't any new virtual functions, we might need a
new virtual function table if we're supposed to include vptrs in
all classes that need them. */
- if (!TYPE_VFIELD (t) && (*vfuns_p || TYPE_CONTAINS_VPTR_P (t)))
+ if (!TYPE_VFIELD (t) && (*virtuals_p || TYPE_CONTAINS_VPTR_P (t)))
{
/* We build this decl with vtbl_ptr_type_node, which is a
`vtable_entry_type*'. It might seem more precise to use
tree t;
splay_tree offsets;
{
- tree vbases;
- unsigned HOST_WIDE_INT dsize;
+ tree vbases, dsize;
unsigned HOST_WIDE_INT eoc;
if (CLASSTYPE_N_BASECLASSES (t) == 0)
#endif
/* DSIZE is the size of the class without the virtual bases. */
- dsize = tree_low_cst (TYPE_SIZE (t), 1);
+ dsize = TYPE_SIZE (t);
/* Make every class have alignment of at least one. */
TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), BITS_PER_UNIT);
{
/* This virtual base is not a primary base of any class in the
hierarchy, so we have to add space for it. */
- tree basetype;
+ tree basetype, usize;
unsigned int desired_align;
basetype = BINFO_TYPE (vbase);
/* Add padding so that we can put the virtual base class at an
appropriately aligned offset. */
- dsize = CEIL (dsize, desired_align) * desired_align;
+ dsize = round_up (dsize, desired_align);
+
+ usize = size_binop (CEIL_DIV_EXPR, dsize, bitsize_unit_node);
/* We try to squish empty virtual bases in just like
ordinary empty bases. */
if (is_empty_class (basetype))
layout_empty_base (vbase,
- size_int (CEIL (dsize, BITS_PER_UNIT)),
+ convert (sizetype, usize),
offsets, t);
else
{
tree offset;
- offset = ssize_int (CEIL (dsize, BITS_PER_UNIT));
+ offset = convert (ssizetype, usize);
offset = size_diffop (offset,
convert (ssizetype,
BINFO_OFFSET (vbase)));
/* Every virtual baseclass takes a least a UNIT, so that
we can take it's address and get something different
for each base. */
- dsize += MAX (BITS_PER_UNIT,
- tree_low_cst (CLASSTYPE_SIZE (basetype), 0));
+ dsize = size_binop (PLUS_EXPR, dsize,
+ size_binop (MAX_EXPR, bitsize_unit_node,
+ CLASSTYPE_SIZE (basetype)));
}
/* Keep track of the offsets assigned to this virtual base. */
class, we didn't update DSIZE above; we were hoping to overlay
multiple such bases at the same location. */
eoc = end_of_class (t, /*include_virtuals_p=*/1);
- if (eoc * BITS_PER_UNIT > dsize)
- dsize = eoc * BITS_PER_UNIT;
+ dsize = size_binop (MAX_EXPR, dsize, bitsize_int (eoc * BITS_PER_UNIT));
/* Now, make sure that the total size of the type is a multiple of
its alignment. */
- dsize = CEIL (dsize, TYPE_ALIGN (t)) * TYPE_ALIGN (t);
- TYPE_SIZE (t) = bitsize_int (dsize);
+ dsize = round_up (dsize, TYPE_ALIGN (t));
+ TYPE_SIZE (t) = dsize;
TYPE_SIZE_UNIT (t) = convert (sizetype,
size_binop (CEIL_DIV_EXPR, TYPE_SIZE (t),
bitsize_unit_node));
/* Calculate the TYPE_SIZE, TYPE_ALIGN, etc for T. Calculate
BINFO_OFFSETs for all of the base-classes. Position the vtable
- pointer. */
+ pointer. Accumulate declared virtual functions on VIRTUALS_P. */
static void
-layout_class_type (t, empty_p, vfuns_p,
- new_virtuals_p, overridden_virtuals_p)
+layout_class_type (t, empty_p, vfuns_p, virtuals_p)
tree t;
int *empty_p;
int *vfuns_p;
- tree *new_virtuals_p;
- tree *overridden_virtuals_p;
+ tree *virtuals_p;
{
tree non_static_data_members;
tree field;
determine_primary_base (t, vfuns_p);
/* Create a pointer to our virtual function table. */
- vptr = create_vtable_ptr (t, empty_p, vfuns_p,
- new_virtuals_p, overridden_virtuals_p);
+ vptr = create_vtable_ptr (t, empty_p, virtuals_p);
/* The vptr is always the first thing in the class. */
if (vptr)
if (TREE_CODE (field) != FIELD_DECL)
{
place_field (rli, field);
+ /* If the static data member has incomplete type, keep track
+ of it so that it can be completed later. (The handling
+ of pending statics in finish_record_layout is
+ insufficient; consider:
+
+ struct S1;
+ struct S2 { static S1 s1; };
+
+ At this point, finish_record_layout will be called, but
+ S1 is still incomplete.) */
+ if (TREE_CODE (field) == VAR_DECL)
+ maybe_register_incomplete_var (field);
continue;
}
CLASSTYPE_SIZE (t) = bitsize_zero_node;
CLASSTYPE_SIZE_UNIT (t) = size_zero_node;
}
+ /* If this is a POD, we can't reuse its tail padding. */
+ else if (!CLASSTYPE_NON_POD_P (t))
+ {
+ CLASSTYPE_SIZE (t) = TYPE_SIZE (t);
+ CLASSTYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (t);
+ }
else
{
CLASSTYPE_SIZE (t) = TYPE_BINFO_SIZE (t);
{
tree x;
int vfuns;
- /* The NEW_VIRTUALS is a TREE_LIST. The TREE_VALUE of each node is
- a FUNCTION_DECL. Each of these functions is a virtual function
- declared in T that does not override any virtual function from a
- base class. */
- tree new_virtuals = NULL_TREE;
- /* The OVERRIDDEN_VIRTUALS list is like the NEW_VIRTUALS list,
- except that each declaration here overrides the declaration from
- a base class. */
- tree overridden_virtuals = NULL_TREE;
+ /* A TREE_LIST. The TREE_VALUE of each node is a FUNCTION_DECL. */
+ tree virtuals = NULL_TREE;
int n_fields = 0;
tree vfield;
int empty = 1;
return;
}
- GNU_xref_decl (current_function_decl, t);
-
/* If this type was previously laid out as a forward reference,
make sure we lay it out again. */
TYPE_SIZE (t) = NULL_TREE;
check_bases_and_members (t, &empty);
/* Layout the class itself. */
- layout_class_type (t, &empty, &vfuns,
- &new_virtuals, &overridden_virtuals);
+ layout_class_type (t, &empty, &vfuns, &virtuals);
/* Make sure that we get our own copy of the vfield FIELD_DECL. */
vfield = TYPE_VFIELD (t);
else
my_friendly_assert (!vfield || DECL_FIELD_CONTEXT (vfield) == t, 20010726);
- overridden_virtuals
- = modify_all_vtables (t, &vfuns, nreverse (overridden_virtuals));
+ virtuals = modify_all_vtables (t, &vfuns, nreverse (virtuals));
/* If we created a new vtbl pointer for this class, add it to the
list. */
= chainon (CLASSTYPE_VFIELDS (t), build_tree_list (NULL_TREE, t));
/* If necessary, create the primary vtable for this class. */
- if (new_virtuals || overridden_virtuals || TYPE_CONTAINS_VPTR_P (t))
+ if (virtuals || TYPE_CONTAINS_VPTR_P (t))
{
- new_virtuals = nreverse (new_virtuals);
/* We must enter these virtuals into the table. */
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
build_primary_vtable (NULL_TREE, t);
constructors might clobber the virtual function table. But
they don't if the derived class shares the exact vtable of the base
class. */
-
CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
}
/* If we didn't need a new vtable, see if we should copy one from
20000116);
CLASSTYPE_VSIZE (t) = vfuns;
- /* Entries for virtual functions defined in the primary base are
- followed by entries for new functions unique to this class. */
- TYPE_BINFO_VIRTUALS (t)
- = chainon (TYPE_BINFO_VIRTUALS (t), new_virtuals);
- /* Finally, add entries for functions that override virtuals
- from non-primary bases. */
- TYPE_BINFO_VIRTUALS (t)
- = chainon (TYPE_BINFO_VIRTUALS (t), overridden_virtuals);
+ /* Add entries for virtual functions introduced by this class. */
+ TYPE_BINFO_VIRTUALS (t) = chainon (TYPE_BINFO_VIRTUALS (t), virtuals);
}
finish_struct_bits (t);
working on. */
for (x = TYPE_FIELDS (t); x; x = TREE_CHAIN (x))
if (TREE_CODE (x) == VAR_DECL && TREE_STATIC (x)
- && TREE_TYPE (x) == t)
+ && same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (x)), t))
DECL_MODE (x) = TYPE_MODE (t);
/* Done with FIELDS...now decide whether to sort these for
{
tree vfields = CLASSTYPE_VFIELDS (t);
- while (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_DERIVED_VALUE (vfields))
- TREE_ADDRESSABLE (vfields) = 1;
- vfields = TREE_CHAIN (vfields);
- }
+ 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
&& DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1)) == NULL_TREE)
warning ("`%#T' has virtual functions but non-virtual destructor", t);
- hack_incomplete_structures (t);
+ complete_vars (t);
if (warn_overloaded_virtual)
warn_hidden (t);
else
error ("trying to finish struct, but kicked out due to previous parse errors");
- if (processing_template_decl)
- {
- tree scope = current_scope ();
- if (scope && TREE_CODE (scope) == FUNCTION_DECL)
- add_stmt (build_min (TAG_DEFN, t));
- }
+ if (processing_template_decl && at_function_scope_p ())
+ add_stmt (build_min (TAG_DEFN, t));
return t;
}
return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
if (TREE_CODE (TREE_OPERAND (instance, 1)) == INTEGER_CST)
/* Propagate nonnull. */
- fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
+ return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
return NULL_TREE;
case NOP_EXPR:
/* fall through... */
case TARGET_EXPR:
case PARM_DECL:
+ case RESULT_DECL:
if (IS_AGGR_TYPE (TREE_TYPE (instance)))
{
if (nonnull)
/* Reference variables should be references to objects. */
if (nonnull)
*nonnull = 1;
+
+ if (TREE_CODE (instance) == VAR_DECL
+ && DECL_INITIAL (instance))
+ return fixed_type_or_null (DECL_INITIAL (instance),
+ nonnull, cdtorp);
}
return NULL_TREE;
= (class_stack_node_t) xmalloc (current_class_stack_size
* sizeof (struct class_stack_node));
VARRAY_TREE_INIT (local_classes, 8, "local_classes");
- ggc_add_tree_varray_root (&local_classes, 1);
access_default_node = build_int_2 (0, 0);
access_public_node = build_int_2 (ak_public, 0);
popclass ()
{
poplevel_class ();
- /* Since poplevel_class does the popping of class decls nowadays,
- this really only frees the obstack used for these decls. */
pop_class_decls ();
current_class_depth--;
/* The target must be a REFERENCE_TYPE. Above, build_unary_op
will mark the function as addressed, but here we must do it
explicitly. */
- mark_addressable (fn);
+ cxx_mark_addressable (fn);
return fn;
}
tree
instantiate_type (lhstype, rhs, flags)
tree lhstype, rhs;
- enum instantiate_type_flags flags;
+ tsubst_flags_t flags;
{
- int complain = (flags & itf_complain);
- int strict = (flags & itf_no_attributes)
+ int complain = (flags & tf_error);
+ int strict = (flags & tf_no_attributes)
? COMPARE_NO_ATTRIBUTES : COMPARE_STRICT;
- int allow_ptrmem = flags & itf_ptrmem_ok;
+ int allow_ptrmem = flags & tf_ptrmem_ok;
- flags &= ~itf_ptrmem_ok;
+ flags &= ~tf_ptrmem_ok;
if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
{
return error_mark_node;
}
+ if (TREE_CODE (rhs) == BASELINK)
+ rhs = BASELINK_FUNCTIONS (rhs);
+
/* We don't overwrite rhs if it is an overloaded function.
Copying it would destroy the tree link. */
if (TREE_CODE (rhs) != OVERLOAD)
case OFFSET_REF:
rhs = TREE_OPERAND (rhs, 1);
if (BASELINK_P (rhs))
- return instantiate_type (lhstype, TREE_VALUE (rhs),
+ return instantiate_type (lhstype, BASELINK_FUNCTIONS (rhs),
flags | allow_ptrmem);
/* This can happen if we are forming a pointer-to-member for a
/* Now we should have a baselink. */
my_friendly_assert (BASELINK_P (rhs), 990412);
- return instantiate_type (lhstype, TREE_VALUE (rhs), flags);
+ return instantiate_type (lhstype, BASELINK_FUNCTIONS (rhs), flags);
case CALL_EXPR:
/* This is too hard for now. */
case ADDR_EXPR:
{
if (PTRMEM_OK_P (rhs))
- flags |= itf_ptrmem_ok;
+ flags |= tf_ptrmem_ok;
return instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags);
}
type = BINFO_TYPE (binfo);
buf = (char *) alloca (sizeof (VFIELD_NAME_FORMAT)
+ TYPE_NAME_LENGTH (type) + 2);
- sprintf (buf, VFIELD_NAME_FORMAT, TYPE_NAME_STRING (type));
+ sprintf (buf, VFIELD_NAME_FORMAT,
+ IDENTIFIER_POINTER (constructor_name (type)));
return get_identifier (buf);
}
}
/* Note that NAME was declared (as DECL) in the current class. Check
- to see that the declaration is legal. */
+ to see that the declaration is valid. */
void
note_name_declared_in_class (name, decl)
vid.primary_vtbl_p = (binfo == TYPE_BINFO (t));
vid.ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
/* The first vbase or vcall offset is at index -3 in the vtable. */
- vid.index = ssize_int (-3);
+ vid.index = ssize_int (-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);
- /* Clean up. */
- VARRAY_FREE (vid.fns);
/* Clear BINFO_VTABLE_PATH_MARKED; it's set by
build_vbase_offset_vtbl_entries. */
for (vbase = CLASSTYPE_VBASECLASSES (t);
vbase = TREE_CHAIN (vbase))
CLEAR_BINFO_VTABLE_PATH_MARKED (TREE_VALUE (vbase));
+ /* If the target requires padding between data entries, add that now. */
+ if (TARGET_VTABLE_DATA_ENTRY_DISTANCE > 1)
+ {
+ tree cur, *prev;
+
+ for (prev = &vid.inits; (cur = *prev); prev = &TREE_CHAIN (cur))
+ {
+ tree add = cur;
+ int i;
+
+ for (i = 1; i < TARGET_VTABLE_DATA_ENTRY_DISTANCE; ++i)
+ add = tree_cons (NULL_TREE, null_pointer_node, add);
+ *prev = add;
+ }
+ }
+
if (non_fn_entries_p)
*non_fn_entries_p = list_length (vid.inits);
}
/* The next vbase will come at a more negative offset. */
- vid->index = size_binop (MINUS_EXPR, vid->index, ssize_int (1));
+ vid->index = size_binop (MINUS_EXPR, vid->index,
+ ssize_int (TARGET_VTABLE_DATA_ENTRY_DISTANCE));
/* The initializer is the delta from BINFO to this virtual base.
The vbase offsets go in reverse inheritance-graph order, and