aboutsummaryrefslogtreecommitdiff
path: root/contrib/gcc/cp/class.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/cp/class.c')
-rw-r--r--contrib/gcc/cp/class.c9024
1 files changed, 5654 insertions, 3370 deletions
diff --git a/contrib/gcc/cp/class.c b/contrib/gcc/cp/class.c
index 74808c56f355..aa83b8df7bb4 100644
--- a/contrib/gcc/cp/class.c
+++ b/contrib/gcc/cp/class.c
@@ -1,5 +1,6 @@
/* Functions related to building classes and their related objects.
- Copyright (C) 1987, 92-97, 1998, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -30,18 +31,13 @@ Boston, MA 02111-1307, USA. */
#include "rtl.h"
#include "output.h"
#include "toplev.h"
-#include "splay-tree.h"
+#include "ggc.h"
+#include "lex.h"
#include "obstack.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-/* This is how we tell when two virtual member functions are really the
- same. */
-#define SAME_FN(FN1DECL, FN2DECL) (DECL_ASSEMBLER_NAME (FN1DECL) == DECL_ASSEMBLER_NAME (FN2DECL))
-
-extern void set_class_shadows PROTO ((tree));
-
/* The number of nested classes being processed. If we are not in the
scope of any class, this is zero. */
@@ -66,107 +62,164 @@ typedef struct class_stack_node {
splay_tree names_used;
}* class_stack_node_t;
+typedef struct vtbl_init_data_s
+{
+ /* The base for which we're building initializers. */
+ tree binfo;
+ /* The type of the most-derived type. */
+ tree derived;
+ /* The binfo for the dynamic type. This will be TYPE_BINFO (derived),
+ unless ctor_vtbl_p is true. */
+ 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;
+ /* The binfo for the virtual base for which we're building
+ vcall offset initializers. */
+ tree vbase;
+ /* The functions in vbase for which we have already provided vcall
+ offsets. */
+ varray_type fns;
+ /* The vtable index of the next vcall or vbase offset. */
+ tree index;
+ /* Nonzero if we are building the initializer for the primary
+ vtable. */
+ int primary_vtbl_p;
+ /* Nonzero if we are building the initializer for a construction
+ vtable. */
+ int ctor_vtbl_p;
+} vtbl_init_data;
+
+/* The type of a function passed to walk_subobject_offsets. */
+typedef int (*subobject_offset_fn) PARAMS ((tree, tree, splay_tree));
+
/* The stack itself. This is an dynamically resized array. The
number of elements allocated is CURRENT_CLASS_STACK_SIZE. */
static int current_class_stack_size;
static class_stack_node_t current_class_stack;
-/* When we're processing a member function, current_class_ptr is the
- PARM_DECL for the `this' pointer. The current_class_ref is an
- expression for `*this'. */
-tree current_class_ptr, current_class_ref;
-
-/* The following two can be derived from the previous one */
-tree current_class_name; /* IDENTIFIER_NODE: name of current class */
-tree current_class_type; /* _TYPE: the type of the current class */
-tree current_access_specifier;
-tree previous_class_type; /* _TYPE: the previous type that was a class */
-tree previous_class_values; /* TREE_LIST: copy of the class_shadowed list
- when leaving an outermost class scope. */
-
-/* The obstack on which the cached class declarations are kept. */
-static struct obstack class_cache_obstack;
-/* The first object allocated on that obstack. We can use
- obstack_free with tis value to free the entire obstack. */
-char *class_cache_firstobj;
-
-struct base_info;
-
-static tree get_vfield_name PROTO((tree));
-static void finish_struct_anon PROTO((tree));
-static tree build_vbase_pointer PROTO((tree, tree));
-static tree build_vtable_entry PROTO((tree, tree));
-static tree get_vtable_name PROTO((tree));
-static tree get_derived_offset PROTO((tree, tree));
-static tree get_basefndecls PROTO((tree, tree));
-static void set_rtti_entry PROTO((tree, tree, tree));
-static tree build_vtable PROTO((tree, tree));
-static void prepare_fresh_vtable PROTO((tree, tree));
-static tree prepare_ctor_vtable PROTO((tree, tree, tree));
-static void fixup_vtable_deltas1 PROTO((tree, tree));
-static void fixup_vtable_deltas PROTO((tree, int, tree));
-static tree finish_one_ctor_vtable PROTO((tree, tree, tree, tree));
-static tree prepend_ctor_vfields_for_vbase PROTO((tree, tree, tree, tree, int, tree));
-static tree finish_ctor_vtables_for_vbases PROTO((tree, tree, tree));
-static tree finish_ctor_vtables_1 PROTO((tree, tree));
-static tree prepend_vbase_vfields PROTO((tree, int, tree));
-static void finish_ctor_vtables PROTO((tree));
-static void finish_vtbls PROTO((tree, int, tree));
-static void modify_vtable_entry PROTO((tree, tree, tree));
-static tree get_vtable_entry_n PROTO((tree, unsigned HOST_WIDE_INT));
-static void add_virtual_function PROTO((tree *, tree *, int *, tree, tree));
-static tree delete_duplicate_fields_1 PROTO((tree, tree));
-static void delete_duplicate_fields PROTO((tree));
-static void finish_struct_bits PROTO((tree, int));
-static int alter_access PROTO((tree, tree, tree, tree));
-static void handle_using_decl PROTO((tree, tree, tree, tree));
-static int overrides PROTO((tree, tree));
-static int strictly_overrides PROTO((tree, tree));
-static void merge_overrides PROTO((tree, tree, int, tree));
-static void override_one_vtable PROTO((tree, tree, tree));
-static void mark_overriders PROTO((tree, tree));
-static void check_for_override PROTO((tree, tree));
-static tree get_class_offset_1 PROTO((tree, tree, tree, tree, tree));
-static tree get_class_offset PROTO((tree, tree, tree, tree));
-static void modify_one_vtable PROTO((tree, tree, tree, tree));
-static void modify_all_vtables PROTO((tree, tree, tree));
-static void modify_all_direct_vtables PROTO((tree, int, tree, tree,
- tree));
-static void modify_all_indirect_vtables PROTO((tree, int, int, tree,
- tree, tree));
-static int finish_base_struct PROTO((tree, struct base_info *));
-static void finish_struct_methods PROTO((tree));
-static void maybe_warn_about_overly_private_class PROTO ((tree));
-static tree make_method_vec PROTO((int));
-static void free_method_vec PROTO((tree));
-static tree add_implicitly_declared_members PROTO((tree, int, int, int));
-static tree fixed_type_or_null PROTO((tree, int *));
-static tree resolve_address_of_overloaded_function PROTO((tree, tree, int,
- int, tree));
-static void build_vtable_entry_ref PROTO((tree, tree, tree));
-
-/* Way of stacking language names. */
-tree *current_lang_base, *current_lang_stack;
-int current_lang_stacksize;
-
-/* Names of languages we recognize. */
-tree lang_name_c, lang_name_cplusplus, lang_name_java;
-tree current_lang_name;
-
-/* When layout out an aggregate type, the size of the
- basetypes (virtual and non-virtual) is passed to layout_record
- via this node. */
-static tree base_layout_decl;
-
-/* Constants used for access control. */
-tree access_default_node; /* 0 */
-tree access_public_node; /* 1 */
-tree access_protected_node; /* 2 */
-tree access_private_node; /* 3 */
-tree access_default_virtual_node; /* 4 */
-tree access_public_virtual_node; /* 5 */
-tree access_protected_virtual_node; /* 6 */
-tree access_private_virtual_node; /* 7 */
+/* An array of all local classes present in this translation unit, in
+ declaration order. */
+varray_type local_classes;
+
+static tree get_vfield_name PARAMS ((tree));
+static void finish_struct_anon PARAMS ((tree));
+static tree build_vtable_entry PARAMS ((tree, tree, tree));
+static tree get_vtable_name PARAMS ((tree));
+static tree get_basefndecls PARAMS ((tree, tree));
+static int build_primary_vtable PARAMS ((tree, tree));
+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 int alter_access PARAMS ((tree, tree, tree));
+static void handle_using_decl PARAMS ((tree, tree));
+static int strictly_overrides PARAMS ((tree, tree));
+static void check_for_override PARAMS ((tree, tree));
+static tree dfs_modify_vtables PARAMS ((tree, void *));
+static tree modify_all_vtables PARAMS ((tree, int *, tree));
+static void determine_primary_base PARAMS ((tree, int *));
+static void finish_struct_methods PARAMS ((tree));
+static void maybe_warn_about_overly_private_class PARAMS ((tree));
+static int field_decl_cmp PARAMS ((const tree *, const tree *));
+static int method_name_cmp PARAMS ((const tree *, const tree *));
+static tree add_implicitly_declared_members PARAMS ((tree, int, int, int));
+static tree fixed_type_or_null PARAMS ((tree, int *, int *));
+static tree resolve_address_of_overloaded_function PARAMS ((tree, tree, int,
+ int, int, tree));
+static tree build_vtable_entry_ref PARAMS ((tree, tree, tree));
+static tree build_vtbl_ref_1 PARAMS ((tree, tree));
+static tree build_vtbl_initializer PARAMS ((tree, tree, tree, tree, int *));
+static int count_fields PARAMS ((tree));
+static int add_fields_to_vec PARAMS ((tree, tree, int));
+static void check_bitfield_decl PARAMS ((tree));
+static void check_field_decl PARAMS ((tree, tree, int *, int *, int *, int *));
+static void check_field_decls PARAMS ((tree, tree *, int *, int *, int *,
+ int *));
+static bool build_base_field PARAMS ((record_layout_info, tree, int *,
+ splay_tree, tree));
+static bool build_base_fields PARAMS ((record_layout_info, int *,
+ splay_tree, tree));
+static void check_methods 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 void fixup_pending_inline PARAMS ((tree));
+static void fixup_inline_methods PARAMS ((tree));
+static void set_primary_base PARAMS ((tree, tree, int *));
+static void propagate_binfo_offsets PARAMS ((tree, tree, tree));
+static void layout_virtual_bases PARAMS ((tree, splay_tree));
+static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *));
+static void build_vbase_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
+static void add_vcall_offset_vtbl_entries_r PARAMS ((tree, vtbl_init_data *));
+static void add_vcall_offset_vtbl_entries_1 PARAMS ((tree, vtbl_init_data *));
+static void build_vcall_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
+static void layout_vtable_decl PARAMS ((tree, int));
+static tree dfs_find_final_overrider PARAMS ((tree, void *));
+static tree find_final_overrider PARAMS ((tree, tree, tree));
+static int make_new_vtable PARAMS ((tree, tree));
+static int maybe_indent_hierarchy PARAMS ((FILE *, int, int));
+static void dump_class_hierarchy_r PARAMS ((FILE *, int, tree, tree, int));
+static void dump_class_hierarchy PARAMS ((tree));
+static void dump_array PARAMS ((FILE *, tree));
+static void dump_vtable PARAMS ((tree, tree, tree));
+static void dump_vtt PARAMS ((tree, tree));
+static tree build_vtable PARAMS ((tree, tree, tree));
+static void initialize_vtable PARAMS ((tree, tree));
+static void initialize_array PARAMS ((tree, tree));
+static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
+ tree, tree,
+ splay_tree, tree));
+static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
+static bool layout_empty_base PARAMS ((tree, tree, splay_tree, tree));
+static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
+static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree,
+ tree));
+static void set_vindex PARAMS ((tree, int *));
+static void build_rtti_vtbl_entries PARAMS ((tree, vtbl_init_data *));
+static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree,
+ vtbl_init_data *));
+static void force_canonical_binfo_r PARAMS ((tree, tree, tree, tree));
+static void force_canonical_binfo PARAMS ((tree, tree, tree, tree));
+static tree dfs_unshared_virtual_bases PARAMS ((tree, void *));
+static void mark_primary_bases PARAMS ((tree));
+static tree mark_primary_virtual_base PARAMS ((tree, tree));
+static void clone_constructors_and_destructors PARAMS ((tree));
+static tree build_clone PARAMS ((tree, tree));
+static void update_vtable_entry_for_fn PARAMS ((tree, tree, tree, tree *));
+static tree copy_virtuals PARAMS ((tree));
+static void build_ctor_vtbl_group PARAMS ((tree, tree));
+static void build_vtt PARAMS ((tree));
+static tree binfo_ctor_vtable PARAMS ((tree));
+static tree *build_vtt_inits PARAMS ((tree, tree, tree *, tree *));
+static tree dfs_build_secondary_vptr_vtt_inits PARAMS ((tree, void *));
+static tree dfs_ctor_vtable_bases_queue_p PARAMS ((tree, void *data));
+static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *));
+static tree get_original_base PARAMS ((tree, tree));
+static tree dfs_get_primary_binfo PARAMS ((tree, void*));
+static int record_subobject_offset PARAMS ((tree, tree, splay_tree));
+static int check_subobject_offset PARAMS ((tree, tree, splay_tree));
+static int walk_subobject_offsets PARAMS ((tree, subobject_offset_fn,
+ tree, splay_tree, tree, int));
+static void record_subobject_offsets PARAMS ((tree, tree, splay_tree, int));
+static int layout_conflict_p PARAMS ((tree, tree, splay_tree, int));
+static int splay_tree_compare_integer_csts PARAMS ((splay_tree_key k1,
+ splay_tree_key k2));
+static void warn_about_ambiguous_direct_bases PARAMS ((tree));
+static bool type_requires_array_cookie PARAMS ((tree));
+
+/* Macros for dfs walking during vtt construction. See
+ dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits
+ and dfs_fixup_binfo_vtbls. */
+#define VTT_TOP_LEVEL_P(NODE) TREE_UNSIGNED (NODE)
+#define VTT_MARKED_BINFO_P(NODE) TREE_USED (NODE)
/* Variables shared between class.c and call.c. */
@@ -181,333 +234,163 @@ int n_build_method_call = 0;
int n_inner_fields_searched = 0;
#endif
-/* Virtual baseclass things. */
-
-static tree
-build_vbase_pointer (exp, type)
- tree exp, type;
-{
- char *name;
- FORMAT_VBASE_NAME (name, type);
-
- return build_component_ref (exp, get_identifier (name), NULL_TREE, 0);
-}
-
-#if 0
-/* Is the type of the EXPR, the complete type of the object?
- If we are going to be wrong, we must be conservative, and return 0. */
-
-static int
-complete_type_p (expr)
- tree expr;
-{
- tree type = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
- while (1)
- {
- switch (TREE_CODE (expr))
- {
- case SAVE_EXPR:
- case INDIRECT_REF:
- case ADDR_EXPR:
- case NOP_EXPR:
- case CONVERT_EXPR:
- expr = TREE_OPERAND (expr, 0);
- continue;
-
- case CALL_EXPR:
- if (! TREE_HAS_CONSTRUCTOR (expr))
- break;
- /* fall through... */
- case VAR_DECL:
- case FIELD_DECL:
- if (TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
- && IS_AGGR_TYPE (TREE_TYPE (TREE_TYPE (expr)))
- && TYPE_MAIN_VARIANT (TREE_TYPE (expr)) == type)
- return 1;
- /* fall through... */
- case TARGET_EXPR:
- case PARM_DECL:
- if (IS_AGGR_TYPE (TREE_TYPE (expr))
- && TYPE_MAIN_VARIANT (TREE_TYPE (expr)) == type)
- return 1;
- /* fall through... */
- case PLUS_EXPR:
- default:
- break;
- }
- break;
- }
- return 0;
-}
-#endif
-
-/* Build multi-level access to EXPR using hierarchy path PATH.
- CODE is PLUS_EXPR if we are going with the grain,
- and MINUS_EXPR if we are not (in which case, we cannot traverse
- virtual baseclass links).
-
- TYPE is the type we want this path to have on exit.
-
- NONNULL is non-zero if we know (for any reason) that EXPR is
- not, in fact, zero. */
+/* Convert to or from a base subobject. EXPR is an expression of type
+ `A' or `A*', an expression of type `B' or `B*' is returned. To
+ convert A to a base B, CODE is PLUS_EXPR and BINFO is the binfo for
+ the B base instance within A. To convert base A to derived B, CODE
+ is MINUS_EXPR and BINFO is the binfo for the A instance within B.
+ In this latter case, A must not be a morally virtual base of B.
+ NONNULL is true if EXPR is known to be non-NULL (this is only
+ needed when EXPR is of pointer type). CV qualifiers are preserved
+ from EXPR. */
tree
-build_vbase_path (code, type, expr, path, nonnull)
+build_base_path (code, expr, binfo, nonnull)
enum tree_code code;
- tree type, expr, path;
+ tree expr;
+ tree binfo;
int nonnull;
{
- register int changed = 0;
- tree last = NULL_TREE, last_virtual = NULL_TREE;
+ tree v_binfo = NULL_TREE;
+ tree d_binfo = NULL_TREE;
+ tree probe;
+ tree offset;
+ tree target_type;
+ tree null_test = NULL;
+ tree ptr_target_type;
int fixed_type_p;
- tree null_expr = 0, nonnull_expr;
- tree basetype;
- tree offset = integer_zero_node;
-
- if (BINFO_INHERITANCE_CHAIN (path) == NULL_TREE)
- return build1 (NOP_EXPR, type, expr);
+ int want_pointer = TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE;
- /* If -fthis-is-variable, we might have set nonnull incorrectly. We
- don't care enough to get this right, so just clear it. */
- if (flag_this_is_variable > 0)
- nonnull = 0;
-
- /* We could do better if we had additional logic to convert back to the
- unconverted type (the static type of the complete object), and then
- convert back to the type we want. Until that is done, we only optimize
- if the complete type is the same type as expr has. */
- fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull);
-
- if (!fixed_type_p && TREE_SIDE_EFFECTS (expr))
- expr = save_expr (expr);
- nonnull_expr = expr;
-
- if (BINFO_INHERITANCE_CHAIN (path))
- path = reverse_path (path);
-
- basetype = BINFO_TYPE (path);
+ if (expr == error_mark_node || binfo == error_mark_node || !binfo)
+ return error_mark_node;
- while (path)
+ for (probe = binfo; probe; probe = BINFO_INHERITANCE_CHAIN (probe))
{
- if (TREE_VIA_VIRTUAL (path))
- {
- last_virtual = BINFO_TYPE (path);
- if (code == PLUS_EXPR)
- {
- changed = ! fixed_type_p;
-
- if (changed)
- {
- tree ind;
-
- /* We already check for ambiguous things in the caller, just
- find a path. */
- if (last)
- {
- tree binfo = get_binfo (last, TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (nonnull_expr))), 0);
- nonnull_expr = convert_pointer_to_real (binfo, nonnull_expr);
- }
- ind = build_indirect_ref (nonnull_expr, NULL_PTR);
- nonnull_expr = build_vbase_pointer (ind, last_virtual);
- if (nonnull == 0
- && TREE_CODE (type) == POINTER_TYPE
- && null_expr == NULL_TREE)
- {
- null_expr = build1 (NOP_EXPR, build_pointer_type (last_virtual), integer_zero_node);
- expr = build (COND_EXPR, build_pointer_type (last_virtual),
- build (EQ_EXPR, boolean_type_node, expr,
- integer_zero_node),
- null_expr, nonnull_expr);
- }
- }
- /* else we'll figure out the offset below. */
-
- /* Happens in the case of parse errors. */
- if (nonnull_expr == error_mark_node)
- return error_mark_node;
- }
- else
- {
- cp_error ("cannot cast up from virtual baseclass `%T'",
- last_virtual);
- return error_mark_node;
- }
- }
- last = path;
- path = BINFO_INHERITANCE_CHAIN (path);
+ d_binfo = probe;
+ if (!v_binfo && TREE_VIA_VIRTUAL (probe))
+ v_binfo = probe;
}
- /* LAST is now the last basetype assoc on the path. */
- /* A pointer to a virtual base member of a non-null object
- is non-null. Therefore, we only need to test for zeroness once.
- Make EXPR the canonical expression to deal with here. */
- if (null_expr)
+ probe = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
+ if (want_pointer)
+ probe = TYPE_MAIN_VARIANT (TREE_TYPE (probe));
+
+ my_friendly_assert (code == MINUS_EXPR
+ ? same_type_p (BINFO_TYPE (binfo), probe)
+ : code == PLUS_EXPR
+ ? same_type_p (BINFO_TYPE (d_binfo), probe)
+ : false, 20010723);
+
+ if (code == MINUS_EXPR && v_binfo)
{
- TREE_OPERAND (expr, 2) = nonnull_expr;
- TREE_TYPE (expr) = TREE_TYPE (TREE_OPERAND (expr, 1))
- = TREE_TYPE (nonnull_expr);
+ error ("cannot convert from base `%T' to derived type `%T' via virtual base `%T'",
+ BINFO_TYPE (binfo), BINFO_TYPE (d_binfo), BINFO_TYPE (v_binfo));
+ return error_mark_node;
}
- else
- expr = nonnull_expr;
- /* If we go through any virtual base pointers, make sure that
- casts to BASETYPE from the last virtual base class use
- the right value for BASETYPE. */
- if (changed)
- {
- tree intype = TREE_TYPE (TREE_TYPE (expr));
- if (TYPE_MAIN_VARIANT (intype) != BINFO_TYPE (last))
- {
- tree binfo = get_binfo (last, TYPE_MAIN_VARIANT (intype), 0);
- offset = BINFO_OFFSET (binfo);
- }
- }
- else
+ 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))
+ expr = save_expr (expr);
+
+ if (!want_pointer)
+ expr = build_unary_op (ADDR_EXPR, expr, 0);
+ else if (!nonnull)
+ null_test = build (EQ_EXPR, boolean_type_node, expr, integer_zero_node);
+
+ offset = BINFO_OFFSET (binfo);
+
+ if (v_binfo && !fixed_type_p)
{
- if (last_virtual)
- {
- offset = BINFO_OFFSET (binfo_member (last_virtual,
- CLASSTYPE_VBASECLASSES (basetype)));
- offset = size_binop (PLUS_EXPR, offset, BINFO_OFFSET (last));
- }
+ /* Going via virtual base V_BINFO. We need the static offset
+ from V_BINFO to BINFO, and the dynamic offset from D_BINFO to
+ V_BINFO. That offset is an entry in D_BINFO's vtable. */
+ tree v_offset = build_vfield_ref (build_indirect_ref (expr, NULL),
+ TREE_TYPE (TREE_TYPE (expr)));
+
+ v_binfo = binfo_for_vbase (BINFO_TYPE (v_binfo), BINFO_TYPE (d_binfo));
+
+ v_offset = build (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);
+ v_offset = build_indirect_ref (v_offset, NULL);
+
+ 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);
else
- offset = BINFO_OFFSET (last);
+ offset = v_offset;
}
- if (TREE_INT_CST_LOW (offset))
- {
- /* Bash types to make the backend happy. */
- offset = cp_convert (type, offset);
-#if 0
- /* This shouldn't be necessary. (mrs) */
- expr = build1 (NOP_EXPR, type, expr);
-#endif
-
- /* If expr might be 0, we need to preserve that zeroness. */
- if (nonnull == 0)
- {
- if (null_expr)
- TREE_TYPE (null_expr) = type;
- else
- null_expr = build1 (NOP_EXPR, type, integer_zero_node);
- if (TREE_SIDE_EFFECTS (expr))
- expr = save_expr (expr);
-
- return build (COND_EXPR, type,
- build (EQ_EXPR, boolean_type_node, expr, integer_zero_node),
- null_expr,
- build (code, type, expr, offset));
- }
- else return build (code, type, expr, offset);
- }
+ target_type = code == PLUS_EXPR ? BINFO_TYPE (binfo) : BINFO_TYPE (d_binfo);
+
+ target_type = cp_build_qualified_type
+ (target_type, cp_type_quals (TREE_TYPE (TREE_TYPE (expr))));
+ ptr_target_type = build_pointer_type (target_type);
+ if (want_pointer)
+ target_type = ptr_target_type;
+
+ expr = build1 (NOP_EXPR, ptr_target_type, expr);
- /* Cannot change the TREE_TYPE of a NOP_EXPR here, since it may
- be used multiple times in initialization of multiple inheritance. */
- if (null_expr)
- {
- TREE_TYPE (expr) = type;
- return expr;
- }
+ if (!integer_zerop (offset))
+ expr = build (code, ptr_target_type, expr, offset);
else
- return build1 (NOP_EXPR, type, expr);
+ null_test = NULL;
+
+ if (!want_pointer)
+ expr = build_indirect_ref (expr, NULL);
+
+ if (null_test)
+ expr = build (COND_EXPR, target_type, null_test,
+ build1 (NOP_EXPR, target_type, integer_zero_node),
+ expr);
+
+ return expr;
}
+
/* Virtual function things. */
-/* Build an entry in the virtual function table.
- DELTA is the offset for the `this' pointer.
- PFN is an ADDR_EXPR containing a pointer to the virtual function.
- Note that the index (DELTA2) in the virtual function table
- is always 0. */
-
static tree
-build_vtable_entry (delta, pfn)
- tree delta, pfn;
+build_vtable_entry_ref (array_ref, instance, idx)
+ tree array_ref, instance, idx;
{
- if (flag_vtable_thunks)
- {
- HOST_WIDE_INT idelta = TREE_INT_CST_LOW (delta);
- if (idelta && ! DECL_ABSTRACT_VIRTUAL_P (TREE_OPERAND (pfn, 0)))
- {
- pfn = build1 (ADDR_EXPR, vtable_entry_type,
- make_thunk (pfn, idelta));
- TREE_READONLY (pfn) = 1;
- TREE_CONSTANT (pfn) = 1;
- }
-#ifdef GATHER_STATISTICS
- n_vtable_entries += 1;
-#endif
- return pfn;
- }
- else
- {
- extern int flag_huge_objects;
- tree elems = expr_tree_cons (NULL_TREE, delta,
- expr_tree_cons (NULL_TREE, integer_zero_node,
- build_expr_list (NULL_TREE, pfn)));
- tree entry = build (CONSTRUCTOR, vtable_entry_type, NULL_TREE, elems);
-
- /* DELTA used to be constructed by `size_int' and/or size_binop,
- which caused overflow problems when it was negative. That should
- be fixed now. */
-
- if (! int_fits_type_p (delta, delta_type_node))
- {
- if (flag_huge_objects)
- sorry ("object size exceeds built-in limit for virtual function table implementation");
- else
- sorry ("object size exceeds normal limit for virtual function table implementation, recompile all source and use -fhuge-objects");
- }
-
- TREE_CONSTANT (entry) = 1;
- TREE_STATIC (entry) = 1;
- TREE_READONLY (entry) = 1;
-
-#ifdef GATHER_STATISTICS
- n_vtable_entries += 1;
-#endif
+ tree i, i2, vtable, first_fn, basetype;
- return entry;
- }
-}
-
-/* We want to give the assembler the vtable identifier as well as
- the offset to the function pointer. So we generate
-
- __asm__ __volatile__ (".vtable_entry %c0, %c1"
- : : "s"(&class_vtable),
- "i"((long)&vtbl[idx].pfn - (long)&vtbl[0])); */
+ basetype = TREE_TYPE (instance);
+ if (TREE_CODE (basetype) == REFERENCE_TYPE)
+ basetype = TREE_TYPE (basetype);
-static void
-build_vtable_entry_ref (basetype, vtbl, idx)
- tree basetype, vtbl, idx;
-{
- static char asm_stmt[] = ".vtable_entry %c0, %c1";
- tree s, i, i2;
+ vtable = get_vtbl_decl_for_binfo (TYPE_BINFO (basetype));
+ first_fn = TYPE_BINFO_VTABLE (basetype);
- s = build_unary_op (ADDR_EXPR, TYPE_BINFO_VTABLE (basetype), 0);
- s = build_tree_list (build_string (1, "s"), s);
+ i = fold (build_array_ref (first_fn, idx));
+ i = fold (build_c_cast (ptrdiff_type_node,
+ build_unary_op (ADDR_EXPR, i, 0)));
+ i2 = fold (build_array_ref (vtable, build_int_2 (0,0)));
+ i2 = fold (build_c_cast (ptrdiff_type_node,
+ build_unary_op (ADDR_EXPR, i2, 0)));
+ i = fold (cp_build_binary_op (MINUS_EXPR, i, i2));
- i = build_array_ref (vtbl, idx);
- if (!flag_vtable_thunks)
- i = build_component_ref (i, pfn_identifier, vtable_entry_type, 0);
- i = build_c_cast (ptrdiff_type_node, build_unary_op (ADDR_EXPR, i, 0));
- i2 = build_array_ref (vtbl, build_int_2(0,0));
- i2 = build_c_cast (ptrdiff_type_node, build_unary_op (ADDR_EXPR, i2, 0));
- i = build_binary_op (MINUS_EXPR, i, i2);
- i = build_tree_list (build_string (1, "i"), i);
+ if (TREE_CODE (i) != INTEGER_CST)
+ abort ();
- expand_asm_operands (build_string (sizeof(asm_stmt)-1, asm_stmt),
- NULL_TREE, chainon (s, i), NULL_TREE, 1, NULL, 0);
+ return build (VTABLE_REF, TREE_TYPE (array_ref), array_ref, vtable, i);
}
/* Given an object INSTANCE, return an expression which yields the
- virtual function vtable element corresponding to INDEX. There are
- many special cases for INSTANCE which we take care of here, mainly
- to avoid creating extra tree nodes when we don't have to. */
+ vtable element corresponding to INDEX. There are many special
+ cases for INSTANCE which we take care of here, mainly to avoid
+ creating extra tree nodes when we don't have to. */
-tree
-build_vtbl_ref (instance, idx)
+static tree
+build_vtbl_ref_1 (instance, idx)
tree instance, idx;
{
tree vtbl, aref;
@@ -555,53 +438,65 @@ build_vtbl_ref (instance, idx)
&& (TREE_CODE (instance) == RESULT_DECL
|| TREE_CODE (instance) == PARM_DECL
|| TREE_CODE (instance) == VAR_DECL))
- vtbl = TYPE_BINFO_VTABLE (basetype);
+ {
+ 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);
}
assemble_external (vtbl);
- if (flag_vtable_gc)
- build_vtable_entry_ref (basetype, vtbl, idx);
-
aref = build_array_ref (vtbl, idx);
return aref;
}
-/* Given an object INSTANCE, return an expression which yields the
- virtual function corresponding to INDEX. There are many special
- cases for INSTANCE which we take care of here, mainly to avoid
- creating extra tree nodes when we don't have to. */
-
tree
-build_vfn_ref (ptr_to_instptr, instance, idx)
- tree *ptr_to_instptr, instance;
- tree idx;
+build_vtbl_ref (instance, idx)
+ tree instance, idx;
{
- tree aref = build_vtbl_ref (instance, idx);
+ tree aref = build_vtbl_ref_1 (instance, idx);
- /* When using thunks, there is no extra delta, and we get the pfn
- directly. */
- if (flag_vtable_thunks)
- return aref;
+ if (flag_vtable_gc)
+ aref = build_vtable_entry_ref (aref, instance, idx);
- if (ptr_to_instptr)
- {
- /* Save the intermediate result in a SAVE_EXPR so we don't have to
- compute each component of the virtual function pointer twice. */
- if (TREE_CODE (aref) == INDIRECT_REF)
- TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0));
+ return aref;
+}
- *ptr_to_instptr
- = build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr),
- *ptr_to_instptr,
- cp_convert (ptrdiff_type_node,
- build_component_ref (aref, delta_identifier, NULL_TREE, 0)));
- }
+/* Given an object INSTANCE, return an expression which yields a
+ function pointer corresponding to vtable element INDEX. */
- return build_component_ref (aref, pfn_identifier, NULL_TREE, 0);
+tree
+build_vfn_ref (instance, idx)
+ tree instance, idx;
+{
+ tree aref = build_vtbl_ref_1 (instance, idx);
+
+ /* When using function descriptors, the address of the
+ vtable entry is treated as a function pointer. */
+ if (TARGET_VTABLE_USES_DESCRIPTORS)
+ aref = build1 (NOP_EXPR, TREE_TYPE (aref),
+ build_unary_op (ADDR_EXPR, aref, /*noconvert=*/1));
+
+ if (flag_vtable_gc)
+ aref = build_vtable_entry_ref (aref, instance, idx);
+
+ return aref;
}
/* Return the name of the virtual function table (as an IDENTIFIER_NODE)
@@ -611,123 +506,137 @@ static tree
get_vtable_name (type)
tree type;
{
- tree type_id = build_typename_overload (type);
- char *buf = (char *) alloca (strlen (VTABLE_NAME_FORMAT)
- + IDENTIFIER_LENGTH (type_id) + 2);
- const char *ptr = IDENTIFIER_POINTER (type_id);
- int i;
- for (i = 0; ptr[i] == OPERATOR_TYPENAME_FORMAT[i]; i++) ;
-#if 0
- /* We don't take off the numbers; prepare_fresh_vtable uses the
- DECL_ASSEMBLER_NAME for the type, which includes the number
- in `3foo'. If we were to pull them off here, we'd end up with
- something like `_vt.foo.3bar', instead of a uniform definition. */
- while (ptr[i] >= '0' && ptr[i] <= '9')
- i += 1;
-#endif
- sprintf (buf, VTABLE_NAME_FORMAT, ptr+i);
- return get_identifier (buf);
+ return mangle_vtbl_for_type (type);
}
-/* Return the offset to the main vtable for a given base BINFO. */
+/* Return an IDENTIFIER_NODE for the name of the virtual table table
+ for TYPE. */
tree
-get_vfield_offset (binfo)
- tree binfo;
+get_vtt_name (type)
+ tree type;
{
- tree tmp
- = size_binop (FLOOR_DIV_EXPR,
- DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))),
- size_int (BITS_PER_UNIT));
- tmp = convert (sizetype, tmp);
- return size_binop (PLUS_EXPR, tmp, BINFO_OFFSET (binfo));
+ return mangle_vtt_for_type (type);
}
-/* Get the offset to the start of the original binfo that we derived
- this binfo from. If we find TYPE first, return the offset only
- that far. The shortened search is useful because the this pointer
- on method calling is expected to point to a DECL_CONTEXT (fndecl)
- object, and not a baseclass of it. */
+/* 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. */
static tree
-get_derived_offset (binfo, type)
- tree binfo, type;
+build_vtable (class_type, name, vtable_type)
+ tree class_type;
+ tree name;
+ tree vtable_type;
{
- tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
- tree offset2;
- int i;
- while (BINFO_BASETYPES (binfo)
- && (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1)
- {
- tree binfos = BINFO_BASETYPES (binfo);
- if (BINFO_TYPE (binfo) == type)
- break;
- binfo = TREE_VEC_ELT (binfos, i);
- }
- offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
- return size_binop (MINUS_EXPR, offset1, offset2);
+ tree decl;
+
+ decl = build_lang_decl (VAR_DECL, name, vtable_type);
+ /* vtable names are already mangled; give them their DECL_ASSEMBLER_NAME
+ now to avoid confusion in mangle_decl. */
+ SET_DECL_ASSEMBLER_NAME (decl, name);
+ DECL_CONTEXT (decl) = class_type;
+ DECL_ARTIFICIAL (decl) = 1;
+ TREE_STATIC (decl) = 1;
+ TREE_READONLY (decl) = 1;
+ DECL_VIRTUAL_P (decl) = 1;
+ import_export_vtable (decl, class_type, 0);
+
+ return decl;
}
-/* Update the rtti info for this class. */
+/* Get the VAR_DECL of the vtable for TYPE. TYPE need not be polymorphic,
+ or even complete. If this does not exist, create it. If COMPLETE is
+ non-zero, then complete the definition of it -- that will render it
+ impossible to actually build the vtable, but is useful to get at those
+ which are known to exist in the runtime. */
-static void
-set_rtti_entry (virtuals, offset, type)
- tree virtuals, offset, type;
+tree
+get_vtable_decl (type, complete)
+ tree type;
+ int complete;
{
- tree vfn;
+ tree name = get_vtable_name (type);
+ tree decl = IDENTIFIER_GLOBAL_VALUE (name);
+
+ if (decl)
+ {
+ my_friendly_assert (TREE_CODE (decl) == VAR_DECL
+ && DECL_VIRTUAL_P (decl), 20000118);
+ return decl;
+ }
+
+ decl = build_vtable (type, name, void_type_node);
+ decl = pushdecl_top_level (decl);
+ my_friendly_assert (IDENTIFIER_GLOBAL_VALUE (name) == decl,
+ 20000517);
+
+ /* 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));
- if (CLASSTYPE_COM_INTERFACE (type))
- return;
+ if (complete)
+ {
+ DECL_EXTERNAL (decl) = 1;
+ cp_finish_decl (decl, NULL_TREE, NULL_TREE, 0);
+ }
- if (flag_rtti)
- vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, get_tinfo_fn_unused (type));
- else
- vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, size_zero_node);
- TREE_CONSTANT (vfn) = 1;
+ return decl;
+}
- if (! flag_vtable_thunks)
- TREE_VALUE (virtuals) = build_vtable_entry (offset, vfn);
- else
- {
- tree voff = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
- TREE_CONSTANT (voff) = 1;
+/* Returns a copy of the BINFO_VIRTUALS list in BINFO. The
+ BV_VCALL_INDEX for each entry is cleared. */
- TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node, voff);
+static tree
+copy_virtuals (binfo)
+ tree binfo;
+{
+ tree copies;
+ tree t;
- /* The second slot is for the tdesc pointer when thunks are used. */
- TREE_VALUE (TREE_CHAIN (virtuals))
- = build_vtable_entry (integer_zero_node, vfn);
+ copies = copy_list (BINFO_VIRTUALS (binfo));
+ for (t = copies; t; t = TREE_CHAIN (t))
+ {
+ BV_VCALL_INDEX (t) = NULL_TREE;
+ BV_USE_VCALL_INDEX_P (t) = 0;
}
+
+ return copies;
}
-/* Build a virtual function for type TYPE.
- If BINFO is non-NULL, build the vtable starting with the initial
- approximation that it is the same as the one which is the head of
- the association list. */
+/* Build the primary virtual function table for TYPE. If BINFO is
+ non-NULL, build the vtable starting with the initial approximation
+ that it is the same as the one which is the head of the association
+ list. Returns a non-zero value if a new vtable is actually
+ created. */
-static tree
-build_vtable (binfo, type)
+static int
+build_primary_vtable (binfo, type)
tree binfo, type;
{
- tree name = get_vtable_name (type);
- tree virtuals, decl;
+ tree decl;
+ tree virtuals;
+ decl = get_vtable_decl (type, /*complete=*/0);
+
if (binfo)
{
- tree offset;
-
- virtuals = copy_list (BINFO_VIRTUALS (binfo));
- decl = build_lang_decl (VAR_DECL, name, TREE_TYPE (BINFO_VTABLE (binfo)));
-
- /* Now do rtti stuff. */
- offset = get_derived_offset (TYPE_BINFO (type), NULL_TREE);
- offset = ssize_binop (MINUS_EXPR, integer_zero_node, offset);
- set_rtti_entry (virtuals, offset, type);
+ if (BINFO_NEW_VTABLE_MARKED (binfo, type))
+ /* We have already created a vtable for this base, so there's
+ no need to do it again. */
+ return 0;
+
+ virtuals = copy_virtuals (binfo);
+ TREE_TYPE (decl) = TREE_TYPE (get_vtbl_decl_for_binfo (binfo));
+ DECL_SIZE (decl) = TYPE_SIZE (TREE_TYPE (decl));
+ DECL_SIZE_UNIT (decl) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
}
else
{
+ my_friendly_assert (TREE_CODE (TREE_TYPE (decl)) == VOID_TYPE,
+ 20000118);
virtuals = NULL_TREE;
- decl = build_lang_decl (VAR_DECL, name, void_type_node);
}
#ifdef GATHER_STATISTICS
@@ -735,625 +644,402 @@ build_vtable (binfo, type)
n_vtable_elems += list_length (virtuals);
#endif
- /* Set TREE_PUBLIC and TREE_EXTERN as appropriate. */
- import_export_vtable (decl, type, 0);
-
- decl = pushdecl_top_level (decl);
- SET_IDENTIFIER_GLOBAL_VALUE (name, decl);
/* Initialize the association list for this type, based
on our first approximation. */
TYPE_BINFO_VTABLE (type) = decl;
TYPE_BINFO_VIRTUALS (type) = virtuals;
-
- DECL_ARTIFICIAL (decl) = 1;
- TREE_STATIC (decl) = 1;
-#ifndef WRITABLE_VTABLES
- /* Make them READONLY by default. (mrs) */
- TREE_READONLY (decl) = 1;
-#endif
- /* 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));
-
- DECL_VIRTUAL_P (decl) = 1;
- DECL_CONTEXT (decl) = type;
-
- binfo = TYPE_BINFO (type);
- SET_BINFO_NEW_VTABLE_MARKED (binfo);
- return decl;
+ SET_BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (type), type);
+ return 1;
}
-extern tree signed_size_zero_node;
-
-/* Give TYPE a new virtual function table which is initialized
+/* Give BINFO a new virtual function table which is initialized
with a skeleton-copy of its original initialization. The only
entry that changes is the `delta' entry, so we can really
share a lot of structure.
- FOR_TYPE is the derived type which caused this table to
+ FOR_TYPE is the most derived type which caused this table to
be needed.
- BINFO is the type association which provided TYPE for FOR_TYPE.
+ Returns non-zero if we haven't met BINFO before.
The order in which vtables are built (by calling this function) for
an object must remain the same, otherwise a binary incompatibility
can result. */
-static void
-prepare_fresh_vtable (binfo, for_type)
+static int
+build_secondary_vtable (binfo, for_type)
tree binfo, for_type;
{
- tree basetype;
- tree orig_decl = BINFO_VTABLE (binfo);
- tree name;
- tree new_decl;
- tree offset;
- tree path = binfo;
- char *buf, *buf2;
- char joiner = '_';
- int i;
-
-#ifdef JOINER
- joiner = JOINER;
-#endif
-
- basetype = TYPE_MAIN_VARIANT (BINFO_TYPE (binfo));
-
- buf2 = TYPE_ASSEMBLER_NAME_STRING (basetype);
- i = TYPE_ASSEMBLER_NAME_LENGTH (basetype) + 1;
-
- /* We know that the vtable that we are going to create doesn't exist
- yet in the global namespace, and when we finish, it will be
- pushed into the global namespace. In complex MI hierarchies, we
- have to loop while the name we are thinking of adding is globally
- defined, adding more name components to the vtable name as we
- loop, until the name is unique. This is because in complex MI
- cases, we might have the same base more than once. This means
- that the order in which this function is called for vtables must
- remain the same, otherwise binary compatibility can be
- compromised. */
-
- while (1)
- {
- char *buf1 = (char *) alloca (TYPE_ASSEMBLER_NAME_LENGTH (for_type)
- + 1 + i);
- char *new_buf2;
+ my_friendly_assert (binfo == CANONICAL_BINFO (binfo, for_type), 20010605);
- sprintf (buf1, "%s%c%s", TYPE_ASSEMBLER_NAME_STRING (for_type), joiner,
- buf2);
- buf = (char *) alloca (strlen (VTABLE_NAME_FORMAT) + strlen (buf1) + 1);
- sprintf (buf, VTABLE_NAME_FORMAT, buf1);
- name = get_identifier (buf);
-
- /* If this name doesn't clash, then we can use it, otherwise
- we add more to the name until it is unique. */
-
- if (! IDENTIFIER_GLOBAL_VALUE (name))
- break;
-
- /* Set values for next loop through, if the name isn't unique. */
-
- path = BINFO_INHERITANCE_CHAIN (path);
-
- /* We better not run out of stuff to make it unique. */
- my_friendly_assert (path != NULL_TREE, 368);
-
- basetype = TYPE_MAIN_VARIANT (BINFO_TYPE (path));
-
- if (for_type == basetype)
- {
- /* If we run out of basetypes in the path, we have already
- found created a vtable with that name before, we now
- resort to tacking on _%d to distinguish them. */
- int j = 2;
- i = TYPE_ASSEMBLER_NAME_LENGTH (basetype) + 1 + i + 1 + 3;
- buf1 = (char *) alloca (i);
- do {
- sprintf (buf1, "%s%c%s%c%d",
- TYPE_ASSEMBLER_NAME_STRING (basetype), joiner,
- buf2, joiner, j);
- buf = (char *) alloca (strlen (VTABLE_NAME_FORMAT)
- + strlen (buf1) + 1);
- sprintf (buf, VTABLE_NAME_FORMAT, buf1);
- name = get_identifier (buf);
-
- /* If this name doesn't clash, then we can use it,
- otherwise we add something different to the name until
- it is unique. */
- } while (++j <= 999 && IDENTIFIER_GLOBAL_VALUE (name));
-
- /* Hey, they really like MI don't they? Increase the 3
- above to 6, and the 999 to 999999. :-) */
- my_friendly_assert (j <= 999, 369);
-
- break;
- }
-
- i = TYPE_ASSEMBLER_NAME_LENGTH (basetype) + 1 + i;
- new_buf2 = (char *) alloca (i);
- sprintf (new_buf2, "%s%c%s",
- TYPE_ASSEMBLER_NAME_STRING (basetype), joiner, buf2);
- buf2 = new_buf2;
- }
-
- new_decl = build_lang_decl (VAR_DECL, name, TREE_TYPE (orig_decl));
- /* Remember which class this vtable is really for. */
- DECL_CONTEXT (new_decl) = for_type;
-
- DECL_ARTIFICIAL (new_decl) = 1;
- TREE_STATIC (new_decl) = 1;
- BINFO_VTABLE (binfo) = pushdecl_top_level (new_decl);
- DECL_VIRTUAL_P (new_decl) = 1;
-#ifndef WRITABLE_VTABLES
- /* Make them READONLY by default. (mrs) */
- TREE_READONLY (new_decl) = 1;
-#endif
- DECL_ALIGN (new_decl) = DECL_ALIGN (orig_decl);
+ if (BINFO_NEW_VTABLE_MARKED (binfo, for_type))
+ /* We already created a vtable for this base. There's no need to
+ do it again. */
+ return 0;
+ /* Remember that we've created a vtable for this BINFO, so that we
+ don't try to do so again. */
+ SET_BINFO_NEW_VTABLE_MARKED (binfo, for_type);
+
/* Make fresh virtual list, so we can smash it later. */
- BINFO_VIRTUALS (binfo) = copy_list (BINFO_VIRTUALS (binfo));
-
- if (TREE_VIA_VIRTUAL (binfo))
- {
- tree binfo1 = binfo_member (BINFO_TYPE (binfo),
- CLASSTYPE_VBASECLASSES (for_type));
-
- /* XXX - This should never happen, if it does, the caller should
- ensure that the binfo is from for_type's binfos, not from any
- base type's. We can remove all this code after a while. */
- if (binfo1 != binfo)
- warning ("internal inconsistency: binfo offset error for rtti");
+ BINFO_VIRTUALS (binfo) = copy_virtuals (binfo);
- offset = BINFO_OFFSET (binfo1);
- }
- else
- offset = BINFO_OFFSET (binfo);
-
- set_rtti_entry (BINFO_VIRTUALS (binfo),
- ssize_binop (MINUS_EXPR, integer_zero_node, offset),
- for_type);
-
-#ifdef GATHER_STATISTICS
- n_vtables += 1;
- n_vtable_elems += list_length (BINFO_VIRTUALS (binfo));
-#endif
-
- /* Set TREE_PUBLIC and TREE_EXTERN as appropriate. */
- import_export_vtable (new_decl, for_type, 0);
-
- if (TREE_VIA_VIRTUAL (binfo))
- my_friendly_assert (binfo == binfo_member (BINFO_TYPE (binfo),
- CLASSTYPE_VBASECLASSES (current_class_type)),
- 170);
- SET_BINFO_NEW_VTABLE_MARKED (binfo);
+ /* Secondary vtables are laid out as part of the same structure as
+ the primary vtable. */
+ BINFO_VTABLE (binfo) = NULL_TREE;
+ return 1;
}
-/* Return a new vtable for use in initialization of the BASE subobject
- of COMPLETE_TYPE. The vtable there goes into the vfield of the
- VBASEBASE virtual subobject. */
+/* Create a new vtable for BINFO which is the hierarchy dominated by
+ T. Return non-zero if we actually created a new vtable. */
-static tree
-prepare_ctor_vtable (complete_type, base, vbasebase)
- tree complete_type, base, vbasebase;
-{
- tree orig_decl = BINFO_VTABLE (vbasebase);
- tree name = get_vlist_vtable_id (base, vbasebase);
- tree new_decl;
-
- new_decl = build_lang_decl (VAR_DECL, name, TREE_TYPE (orig_decl));
- /* Remember which class this vtable is really for. */
- DECL_CONTEXT (new_decl) = complete_type;
-
- DECL_ARTIFICIAL (new_decl) = 1;
- TREE_STATIC (new_decl) = 1;
- new_decl = pushdecl_top_level (new_decl);
- DECL_VIRTUAL_P (new_decl) = 1;
-#ifndef WRITABLE_VTABLES
- /* Make them READONLY by default. (mrs) */
- TREE_READONLY (new_decl) = 1;
-#endif
- DECL_ALIGN (new_decl) = DECL_ALIGN (orig_decl);
-
-#ifdef GATHER_STATISTICS
- n_vtables += 1;
- n_vtable_elems += list_length (BINFO_VIRTUALS (binfo));
-#endif
-
- /* Set TREE_PUBLIC and TREE_EXTERN as appropriate. */
- import_export_vtable (new_decl, complete_type, 0);
-
- return new_decl;
+static int
+make_new_vtable (t, binfo)
+ tree t;
+ tree binfo;
+{
+ if (binfo == TYPE_BINFO (t))
+ /* In this case, it is *type*'s vtable we are modifying. We start
+ with the approximation that its vtable is that of the
+ immediate base class. */
+ /* ??? This actually passes TYPE_BINFO (t), not the primary base binfo,
+ since we've updated DECL_CONTEXT (TYPE_VFIELD (t)) by now. */
+ return build_primary_vtable (TYPE_BINFO (DECL_CONTEXT (TYPE_VFIELD (t))),
+ t);
+ else
+ /* This is our very own copy of `basetype' to play with. Later,
+ we will fill in all the virtual functions that override the
+ virtual functions in these base classes which are not defined
+ by the current type. */
+ return build_secondary_vtable (binfo, t);
}
-#if 0
-/* Access the virtual function table entry that logically
- contains BASE_FNDECL. VIRTUALS is the virtual function table's
- initializer. We can run off the end, when dealing with virtual
- destructors in MI situations, return NULL_TREE in that case. */
+/* Make *VIRTUALS, an entry on the BINFO_VIRTUALS list for BINFO
+ (which is in the hierarchy dominated by T) list FNDECL as its
+ BV_FN. DELTA is the required constant adjustment from the `this'
+ pointer where the vtable entry appears to the `this' required when
+ the function is actually called. */
-static tree
-get_vtable_entry (virtuals, base_fndecl)
- tree virtuals, base_fndecl;
+static void
+modify_vtable_entry (t, binfo, fndecl, delta, virtuals)
+ tree t;
+ tree binfo;
+ tree fndecl;
+ tree delta;
+ tree *virtuals;
{
- unsigned HOST_WIDE_INT n = (HOST_BITS_PER_WIDE_INT >= BITS_PER_WORD
- ? (TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl))
- & (((unsigned HOST_WIDE_INT)1<<(BITS_PER_WORD-1))-1))
- : TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl)));
+ tree v;
-#ifdef GATHER_STATISTICS
- n_vtable_searches += n;
-#endif
+ v = *virtuals;
- while (n > 0 && virtuals)
+ if (fndecl != BV_FN (v)
+ || !tree_int_cst_equal (delta, BV_DELTA (v)))
{
- --n;
- virtuals = TREE_CHAIN (virtuals);
- }
- return virtuals;
-}
-#endif
-
-/* Put new entry ENTRY into virtual function table initializer
- VIRTUALS.
+ tree base_fndecl;
- Also update DECL_VINDEX (FNDECL). */
+ /* We need a new vtable for BINFO. */
+ if (make_new_vtable (t, binfo))
+ {
+ /* If we really did make a new vtable, we also made a copy
+ of the BINFO_VIRTUALS list. Now, we have to find the
+ corresponding entry in that list. */
+ *virtuals = BINFO_VIRTUALS (binfo);
+ while (BV_FN (*virtuals) != BV_FN (v))
+ *virtuals = TREE_CHAIN (*virtuals);
+ v = *virtuals;
+ }
-static void
-modify_vtable_entry (old_entry_in_list, new_entry, fndecl)
- tree old_entry_in_list, new_entry, fndecl;
-{
- tree base_fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (old_entry_in_list)), 0);
+ base_fndecl = BV_FN (v);
+ BV_DELTA (v) = delta;
+ BV_VCALL_INDEX (v) = NULL_TREE;
+ BV_FN (v) = fndecl;
-#ifdef NOTQUITE
- cp_warning ("replaced %D with %D", DECL_ASSEMBLER_NAME (base_fndecl),
- DECL_ASSEMBLER_NAME (fndecl));
-#endif
- TREE_VALUE (old_entry_in_list) = new_entry;
+ /* Now assign virtual dispatch information, if unset. We can
+ dispatch this through any overridden base function.
- /* Now assign virtual dispatch information, if unset. */
- /* We can dispatch this, through any overridden base function. */
- if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
- {
- DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl);
- DECL_CONTEXT (fndecl) = DECL_CONTEXT (base_fndecl);
+ FIXME this can choose a secondary vtable if the primary is not
+ also lexically first, leading to useless conversions.
+ In the V3 ABI, there's no reason for DECL_VIRTUAL_CONTEXT to
+ ever be different from DECL_CONTEXT. */
+ if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
+ {
+ DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl);
+ DECL_VIRTUAL_CONTEXT (fndecl) = DECL_VIRTUAL_CONTEXT (base_fndecl);
+ }
}
}
-/* Access the virtual function table entry N. VIRTUALS is the virtual
- function table's initializer. */
+/* Set DECL_VINDEX for DECL. VINDEX_P is the number of virtual
+ functions present in the vtable so far. */
-static tree
-get_vtable_entry_n (virtuals, n)
- tree virtuals;
- unsigned HOST_WIDE_INT n;
+static void
+set_vindex (decl, vfuns_p)
+ tree decl;
+ int *vfuns_p;
{
- while (n > 0)
- {
- --n;
- virtuals = TREE_CHAIN (virtuals);
- }
- return virtuals;
+ int vindex;
+
+ vindex = *vfuns_p;
+ *vfuns_p += (TARGET_VTABLE_USES_DESCRIPTORS
+ ? 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.
- HAS_VIRTUAL keeps track of how many virtuals there are in our main
- vtable for the type, and we build upon the PENDING_VIRTUALS list
+ 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 (pv, phv, has_virtual, fndecl, t)
- tree *pv, *phv;
- int *has_virtual;
+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 pending_virtuals = *pv;
- tree pending_hard_virtuals = *phv;
-
- /* FUNCTION_TYPEs and OFFSET_TYPEs no longer freely
- convert to void *. Make such a conversion here. */
- tree vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fndecl);
- TREE_CONSTANT (vfn) = 1;
-
-#ifndef DUMB_USER
- if (current_class_type == 0)
- cp_warning ("internal problem, current_class_type is zero when adding `%D', please report",
- fndecl);
- if (current_class_type && t != current_class_type)
- cp_warning ("internal problem, current_class_type differs when adding `%D', please report",
- fndecl);
-#endif
+ 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 the virtual function is a redefinition of a prior one,
- figure out in which base class the new definition goes,
- and if necessary, make a fresh virtual function table
- to hold that entry. */
if (DECL_VINDEX (fndecl) == error_mark_node)
{
- tree entry;
+ /* 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;
- /* If we are using thunks, use two slots at the front, one
- for the offset pointer, one for the tdesc pointer.
- For ARM-style vtables, use the same slot for both. */
- if (*has_virtual == 0 && ! CLASSTYPE_COM_INTERFACE (t))
- {
- if (flag_vtable_thunks)
- *has_virtual = 2;
- else
- *has_virtual = 1;
- }
-
- /* Build a new INT_CST for this DECL_VINDEX. */
- {
- static tree index_table[256];
- tree idx;
- /* We skip a slot for the offset/tdesc entry. */
- int i = (*has_virtual)++;
+ /* Now assign virtual dispatch information. */
+ set_vindex (fndecl, vfuns_p);
+ DECL_VIRTUAL_CONTEXT (fndecl) = t;
- if (i >= 256 || index_table[i] == 0)
- {
- idx = build_int_2 (i, 0);
- if (i < 256)
- index_table[i] = idx;
- }
- else
- idx = index_table[i];
-
- /* Now assign virtual dispatch information. */
- DECL_VINDEX (fndecl) = idx;
- DECL_CONTEXT (fndecl) = t;
- }
- entry = build_vtable_entry (integer_zero_node, vfn);
- pending_virtuals = tree_cons (DECL_VINDEX (fndecl), entry, pending_virtuals);
+ /* Save the state we've computed on the NEW_VIRTUALS list. */
+ TREE_CHAIN (new_virtual) = *new_virtuals_p;
+ *new_virtuals_p = new_virtual;
}
- /* Might already be INTEGER_CST if declared twice in class. We will
- give error later or we've already given it. */
- else if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
+ else
{
- /* Need an entry in some other virtual function table.
- Deal with this after we have laid out our virtual base classes. */
- pending_hard_virtuals = temp_tree_cons (fndecl, vfn, pending_hard_virtuals);
+ /* FNDECL overrides a function from a base class. */
+ TREE_CHAIN (new_virtual) = *overridden_virtuals_p;
+ *overridden_virtuals_p = new_virtual;
}
- *pv = pending_virtuals;
- *phv = pending_hard_virtuals;
}
-/* Obstack on which to build the vector of class methods. */
-struct obstack class_obstack;
-extern struct obstack *current_obstack;
-
-/* These are method vectors that were too small for the number of
- methods in some class, and so were abandoned. */
-static tree free_method_vecs;
-
-/* Returns a method vector with enough room for N methods. N should
- be a power of two. */
-
-static tree
-make_method_vec (n)
- int n;
-{
- tree new_vec;
- tree* t;
-
- for (t = &free_method_vecs; *t; t = &(TREE_CHAIN (*t)))
- /* Note that we don't use >= n here because we don't want to
- allocate a very large vector where it isn't needed. */
- if (TREE_VEC_LENGTH (*t) == n)
- {
- new_vec = *t;
- *t = TREE_CHAIN (new_vec);
- TREE_CHAIN (new_vec) = NULL_TREE;
- bzero ((PTR) &TREE_VEC_ELT (new_vec, 0), n * sizeof (tree));
- return new_vec;
- }
-
- new_vec = make_tree_vec (n);
- return new_vec;
-}
-
-/* Free the method vector VEC. */
-
-static void
-free_method_vec (vec)
- tree vec;
-{
- TREE_CHAIN (vec) = free_method_vecs;
- free_method_vecs = vec;
-}
-
-/* Add method METHOD to class TYPE.
-
- If non-NULL, FIELDS is the entry in the METHOD_VEC vector entry of
- the class type where the method should be added. */
+/* 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.) */
void
-add_method (type, fields, method)
- tree type, *fields, method;
+add_method (type, method, error_p)
+ tree type;
+ tree method;
+ int error_p;
{
- push_obstacks_nochange ();
- end_temporary_allocation ();
-
- /* Setting the DECL_CONTEXT and DECL_CLASS_CONTEXT here is probably
- redundant. */
- DECL_CONTEXT (method) = type;
- DECL_CLASS_CONTEXT (method) = type;
-
- if (fields && *fields)
- *fields = build_overload (method, *fields);
- else
+ int using = (DECL_CONTEXT (method) != type);
+ int len;
+ int slot;
+ tree method_vec;
+
+ 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);
+
+ /* Constructors and destructors go in special slots. */
+ if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (method))
+ slot = CLASSTYPE_CONSTRUCTOR_SLOT;
+ else if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method))
+ slot = CLASSTYPE_DESTRUCTOR_SLOT;
+ else
{
- int len;
- int slot;
- tree method_vec;
-
- 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. We keep a free list of vectors that we outgrew so
- that we don't really waste any memory. */
- CLASSTYPE_METHOD_VEC (type) = make_method_vec (8);
-
- method_vec = CLASSTYPE_METHOD_VEC (type);
- len = TREE_VEC_LENGTH (method_vec);
-
- if (DECL_NAME (method) == constructor_name (type))
- /* A new constructor or destructor. Constructors go in
- slot 0; destructors go in slot 1. */
- slot = DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (method)) ? 1 : 0;
- else
- {
- /* See if we already have an entry with this name. */
- for (slot = 2; slot < len; ++slot)
- if (!TREE_VEC_ELT (method_vec, slot)
- || (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec,
- slot)))
- == DECL_NAME (method)))
- break;
+ /* 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;
- if (slot == len)
- {
- /* We need a bigger method vector. */
- tree new_vec = make_method_vec (2 * len);
- bcopy ((PTR) &TREE_VEC_ELT (method_vec, 0),
- (PTR) &TREE_VEC_ELT (new_vec, 0),
- len * sizeof (tree));
- free_method_vec (method_vec);
- len = 2 * len;
- method_vec = CLASSTYPE_METHOD_VEC (type) = new_vec;
- }
+ 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))
+ 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. */
+ for (slot = 2; slot < len; ++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. */
- for (slot = 2; slot < len; ++slot)
- {
- tree fn = TREE_VEC_ELT (method_vec, 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 (!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))
- /* There is nothing in the Ith slot, so we can avoid
- moving anything. */
+ if (!TREE_VEC_ELT (method_vec, slot))
+ /* There is nothing in the Ith slot, so we can avoid
+ moving anything. */
;
- else
- {
- /* We know the last slot in the vector is empty
- because we know that at this point there's room
- for a new function. */
- bcopy ((PTR) &TREE_VEC_ELT (method_vec, slot),
- (PTR) &TREE_VEC_ELT (method_vec, slot + 1),
- (len - slot - 1) * sizeof (tree));
- TREE_VEC_ELT (method_vec, slot) = NULL_TREE;
- }
+ else
+ {
+ /* 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;
}
}
+ }
- if (template_class_depth (type))
- /* TYPE is a template class. Don't issue any errors now; wait
- until instantiation time to complain. */
- ;
- else
- {
- tree fns;
+ if (template_class_depth (type))
+ /* TYPE is a template class. Don't issue any errors now; wait
+ until instantiation time to complain. */
+ ;
+ else
+ {
+ 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))
- {
- tree fn = OVL_CURRENT (fns);
+ /* Check to see if we've already got this method. */
+ for (fns = TREE_VEC_ELT (method_vec, slot);
+ fns;
+ fns = OVL_NEXT (fns))
+ {
+ tree fn = OVL_CURRENT (fns);
- if (TREE_CODE (fn) != TREE_CODE (method))
- continue;
+ if (TREE_CODE (fn) != TREE_CODE (method))
+ continue;
- if (TREE_CODE (method) != TEMPLATE_DECL)
+ 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). */
+ if ((DECL_STATIC_FUNCTION_P (fn)
+ != DECL_STATIC_FUNCTION_P (method))
+ || using)
{
- /* [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. */
- if (DECL_STATIC_FUNCTION_P (fn)
- != DECL_STATIC_FUNCTION_P (method))
+ 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))
{
- tree parms1 = TYPE_ARG_TYPES (TREE_TYPE (fn));
- tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (method));
-
- if (! DECL_STATIC_FUNCTION_P (fn))
- parms1 = TREE_CHAIN (parms1);
+ if (using && DECL_CONTEXT (fn) == type)
+ /* Defer to the local function. */
+ return;
else
- parms2 = TREE_CHAIN (parms2);
-
- if (compparms (parms1, parms2))
- cp_error ("`%#D' and `%#D' cannot be overloaded",
+ error ("`%#D' and `%#D' cannot be overloaded",
fn, method);
}
-
- /* Since this is an ordinary function in a
- non-template class, it's mangled name can be used
- as a unique identifier. This technique is only
- an optimization; we would get the same results if
- we just used decls_match here. */
- if (DECL_ASSEMBLER_NAME (fn)
- != DECL_ASSEMBLER_NAME (method))
- continue;
}
- else 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);
+ if (!decls_match (fn, method))
+ continue;
- /* 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;
- }
+ /* 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;
}
+ }
- /* Actually insert the new method. */
- TREE_VEC_ELT (method_vec, slot)
- = build_overload (method, TREE_VEC_ELT (method_vec, slot));
+ /* 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));
- }
- pop_obstacks ();
+ if (!DECL_CONSTRUCTOR_P (method)
+ && !DECL_DESTRUCTOR_P (method))
+ push_class_level_binding (DECL_NAME (method),
+ TREE_VEC_ELT (method_vec, slot));
}
/* Subroutines of finish_struct. */
@@ -1380,7 +1066,7 @@ delete_duplicate_fields_1 (field, fields)
tree prev = 0;
if (DECL_NAME (field) == 0)
{
- if (TREE_CODE (TREE_TYPE (field)) != UNION_TYPE)
+ if (! ANON_AGGR_TYPE_P (TREE_TYPE (field)))
return fields;
for (x = TYPE_FIELDS (TREE_TYPE (field)); x; x = TREE_CHAIN (x))
@@ -1393,7 +1079,7 @@ delete_duplicate_fields_1 (field, fields)
{
if (DECL_NAME (x) == 0)
{
- if (TREE_CODE (TREE_TYPE (x)) != UNION_TYPE)
+ if (! ANON_AGGR_TYPE_P (TREE_TYPE (x)))
continue;
TYPE_FIELDS (TREE_TYPE (x))
= delete_duplicate_fields_1 (field, TYPE_FIELDS (TREE_TYPE (x)));
@@ -1405,43 +1091,46 @@ delete_duplicate_fields_1 (field, fields)
TREE_CHAIN (prev) = TREE_CHAIN (x);
}
}
- else
+ else if (TREE_CODE (field) == USING_DECL)
+ /* A using declaration is allowed to appear more than
+ once. We'll prune these from the field list later, and
+ handle_using_decl will complain about invalid multiple
+ uses. */
+ ;
+ else if (DECL_NAME (field) == DECL_NAME (x))
{
- if (DECL_NAME (field) == DECL_NAME (x))
+ if (TREE_CODE (field) == CONST_DECL
+ && TREE_CODE (x) == CONST_DECL)
+ cp_error_at ("duplicate enum value `%D'", x);
+ else if (TREE_CODE (field) == CONST_DECL
+ || TREE_CODE (x) == CONST_DECL)
+ cp_error_at ("duplicate field `%D' (as enum and non-enum)",
+ x);
+ else if (DECL_DECLARES_TYPE_P (field)
+ && DECL_DECLARES_TYPE_P (x))
{
- if (TREE_CODE (field) == CONST_DECL
- && TREE_CODE (x) == CONST_DECL)
- cp_error_at ("duplicate enum value `%D'", x);
- else if (TREE_CODE (field) == CONST_DECL
- || TREE_CODE (x) == CONST_DECL)
- cp_error_at ("duplicate field `%D' (as enum and non-enum)",
- x);
- else if (DECL_DECLARES_TYPE_P (field)
- && DECL_DECLARES_TYPE_P (x))
- {
- if (same_type_p (TREE_TYPE (field), TREE_TYPE (x)))
- continue;
- cp_error_at ("duplicate nested type `%D'", x);
- }
- else if (DECL_DECLARES_TYPE_P (field)
- || DECL_DECLARES_TYPE_P (x))
- {
- /* Hide tag decls. */
- if ((TREE_CODE (field) == TYPE_DECL
- && DECL_ARTIFICIAL (field))
- || (TREE_CODE (x) == TYPE_DECL
- && DECL_ARTIFICIAL (x)))
- continue;
- cp_error_at ("duplicate field `%D' (as type and non-type)",
- x);
- }
- else
- cp_error_at ("duplicate member `%D'", x);
- if (prev == 0)
- fields = TREE_CHAIN (fields);
- else
- TREE_CHAIN (prev) = TREE_CHAIN (x);
+ if (same_type_p (TREE_TYPE (field), TREE_TYPE (x)))
+ continue;
+ cp_error_at ("duplicate nested type `%D'", x);
+ }
+ else if (DECL_DECLARES_TYPE_P (field)
+ || DECL_DECLARES_TYPE_P (x))
+ {
+ /* Hide tag decls. */
+ if ((TREE_CODE (field) == TYPE_DECL
+ && DECL_ARTIFICIAL (field))
+ || (TREE_CODE (x) == TYPE_DECL
+ && DECL_ARTIFICIAL (x)))
+ continue;
+ cp_error_at ("duplicate field `%D' (as type and non-type)",
+ x);
}
+ else
+ cp_error_at ("duplicate member `%D'", x);
+ if (prev == 0)
+ fields = TREE_CHAIN (fields);
+ else
+ TREE_CHAIN (prev) = TREE_CHAIN (x);
}
}
}
@@ -1457,18 +1146,24 @@ delete_duplicate_fields (fields)
TREE_CHAIN (x) = delete_duplicate_fields_1 (x, TREE_CHAIN (x));
}
-/* Change the access of FDECL to ACCESS in T. The access to FDECL is
- along the path given by BINFO. Return 1 if change was legit,
- otherwise return 0. */
+/* Change the access of FDECL to ACCESS in T. Return 1 if change was
+ legit, otherwise return 0. */
static int
-alter_access (t, binfo, fdecl, access)
+alter_access (t, fdecl, access)
tree t;
- tree binfo;
tree fdecl;
tree access;
{
- tree elem = purpose_member (t, DECL_ACCESS (fdecl));
+ tree elem;
+
+ if (!DECL_LANG_SPECIFIC (fdecl))
+ retrofit_lang_decl (fdecl);
+
+ if (DECL_DISCRIMINATOR_P (fdecl))
+ abort ();
+
+ elem = purpose_member (t, DECL_ACCESS (fdecl));
if (elem)
{
if (TREE_VALUE (elem) != access)
@@ -1488,22 +1183,19 @@ alter_access (t, binfo, fdecl, access)
}
else
{
- enforce_access (binfo, fdecl);
+ enforce_access (t, fdecl);
DECL_ACCESS (fdecl) = tree_cons (t, access, DECL_ACCESS (fdecl));
return 1;
}
return 0;
}
-/* Process the USING_DECL, which is a member of T. The METHOD_VEC, if
- non-NULL, is the methods of T. The FIELDS are the fields of T. */
+/* Process the USING_DECL, which is a member of T. */
static void
-handle_using_decl (using_decl, t, method_vec, fields)
+handle_using_decl (using_decl, t)
tree using_decl;
tree t;
- tree method_vec;
- tree fields;
{
tree ctype = DECL_INITIAL (using_decl);
tree name = DECL_NAME (using_decl);
@@ -1513,9 +1205,7 @@ handle_using_decl (using_decl, t, method_vec, fields)
: access_public_node;
tree fdecl, binfo;
tree flist = NULL_TREE;
- tree tmp;
- int i;
- int n_methods;
+ tree old_value;
binfo = binfo_or_else (ctype, t);
if (! binfo)
@@ -1524,7 +1214,13 @@ handle_using_decl (using_decl, t, method_vec, fields)
if (name == constructor_name (ctype)
|| name == constructor_name_full (ctype))
{
- cp_error_at ("using-declaration for constructor", using_decl);
+ cp_error_at ("`%D' names constructor", using_decl);
+ return;
+ }
+ if (name == constructor_name (t)
+ || name == constructor_name_full (t))
+ {
+ cp_error_at ("`%D' invalid in `%T'", using_decl, t);
return;
}
@@ -1536,113 +1232,96 @@ handle_using_decl (using_decl, t, method_vec, fields)
return;
}
- /* Functions are represented as TREE_LIST, with the purpose
- being the type and the value the functions. Other members
- come as themselves. */
- if (TREE_CODE (fdecl) == TREE_LIST)
+ if (BASELINK_P (fdecl))
/* Ignore base type this came from. */
fdecl = TREE_VALUE (fdecl);
- if (TREE_CODE (fdecl) == OVERLOAD)
+ old_value = IDENTIFIER_CLASS_VALUE (name);
+ if (old_value)
{
- /* We later iterate over all functions. */
- flist = fdecl;
- fdecl = OVL_FUNCTION (flist);
+ if (is_overloaded_fn (old_value))
+ old_value = OVL_CURRENT (old_value);
+
+ if (DECL_P (old_value) && DECL_CONTEXT (old_value) == t)
+ /* OK */;
+ else
+ old_value = NULL_TREE;
}
-
- name = DECL_NAME (fdecl);
- n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0;
- for (i = 2; i < n_methods && TREE_VEC_ELT (method_vec, i); i++)
- if (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, i)))
- == name)
- {
- cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t);
- cp_error_at (" because of local method `%#D' with same name",
- OVL_CURRENT (TREE_VEC_ELT (method_vec, i)));
- return;
- }
- if (! DECL_LANG_SPECIFIC (fdecl))
- /* We don't currently handle DECL_ACCESS for TYPE_DECLs; just return. */
- return;
-
- for (tmp = fields; tmp; tmp = TREE_CHAIN (tmp))
- if (DECL_NAME (tmp) == name)
- {
- cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t);
- cp_error_at (" because of local field `%#D' with same name", tmp);
- return;
- }
-
- /* Make type T see field decl FDECL with access ACCESS.*/
- if (flist)
+ if (is_overloaded_fn (fdecl))
+ flist = fdecl;
+
+ if (! old_value)
+ ;
+ else if (is_overloaded_fn (old_value))
{
- while (flist)
+ if (flist)
+ /* It's OK to use functions from a base when there are functions with
+ the same name already present in the current class. */;
+ else
{
- if (alter_access (t, binfo, OVL_FUNCTION (flist),
- access) == 0)
- return;
- flist = OVL_CHAIN (flist);
+ cp_error_at ("`%D' invalid in `%#T'", using_decl, t);
+ cp_error_at (" because of local method `%#D' with same name",
+ OVL_CURRENT (old_value));
+ return;
}
}
+ else if (!DECL_ARTIFICIAL (old_value))
+ {
+ cp_error_at ("`%D' invalid in `%#T'", using_decl, t);
+ cp_error_at (" because of local member `%#D' with same name", old_value);
+ return;
+ }
+
+ /* Make type T see field decl FDECL with access ACCESS.*/
+ if (flist)
+ for (; flist; flist = OVL_NEXT (flist))
+ {
+ add_method (t, OVL_CURRENT (flist), /*error_p=*/0);
+ alter_access (t, OVL_CURRENT (flist), access);
+ }
else
- alter_access (t, binfo, fdecl, access);
+ alter_access (t, fdecl, access);
}
-struct base_info
-{
- int has_virtual;
- int max_has_virtual;
- tree vfield;
- tree vfields;
- tree rtti;
- char cant_have_default_ctor;
- char cant_have_const_ctor;
- char no_const_asn_ref;
-};
-
-/* Record information about type T derived from its base classes.
- Store most of that information in T itself, and place the
- remaining information in the struct BASE_INFO.
-
- Propagate basetype offsets throughout the lattice. Note that the
- lattice topped by T is really a pair: it's a DAG that gives the
- structure of the derivation hierarchy, and it's a list of the
- virtual baseclasses that appear anywhere in the DAG. When a vbase
- type appears in the DAG, it's offset is 0, and it's children start
- their offsets from that point. When a vbase type appears in the list,
- its offset is the offset it has in the hierarchy, and its children's
- offsets include that offset in theirs.
-
- Returns the index of the first base class to have virtual functions,
- or -1 if no such base class. */
+/* Run through the base clases of T, updating
+ CANT_HAVE_DEFAULT_CTOR_P, CANT_HAVE_CONST_CTOR_P, and
+ NO_CONST_ASN_REF_P. Also set flag bits in T based on properties of
+ the bases. */
-static int
-finish_base_struct (t, b)
+static void
+check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p,
+ no_const_asn_ref_p)
tree t;
- struct base_info *b;
+ int *cant_have_default_ctor_p;
+ int *cant_have_const_ctor_p;
+ int *no_const_asn_ref_p;
{
- tree binfos = TYPE_BINFO_BASETYPES (t);
- int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- int first_vfn_base_index = -1;
- bzero ((char *) b, sizeof (struct base_info));
+ int n_baseclasses;
+ int i;
+ int seen_non_virtual_nearly_empty_base_p;
+ tree binfos;
- for (i = 0; i < n_baseclasses; i++)
+ 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)
{
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree basetype = BINFO_TYPE (base_binfo);
+ tree base_binfo;
+ tree basetype;
- /* Effective C++ rule 14. We only need to check TYPE_VIRTUAL_P
- here because the case of virtual functions but non-virtual
- dtor is handled in finish_struct_1. */
- if (warn_ecpp && ! TYPE_VIRTUAL_P (basetype)
- && TYPE_HAS_DESTRUCTOR (basetype))
- cp_warning ("base class `%#T' has a non-virtual destructor", 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 (TYPE_SIZE (basetype) == 0)
+ /* 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
@@ -1654,177 +1333,461 @@ finish_base_struct (t, b)
n_baseclasses -= 1;
for (j = i; j+1 < n_baseclasses; j++)
TREE_VEC_ELT (binfos, j) = TREE_VEC_ELT (binfos, j+1);
+ continue;
}
- if (! TYPE_HAS_CONST_INIT_REF (basetype))
- b->cant_have_const_ctor = 1;
+ /* 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. */
+ if (warn_ecpp && ! TYPE_POLYMORPHIC_P (basetype)
+ && TYPE_HAS_DESTRUCTOR (basetype))
+ warning ("base class `%#T' has a non-virtual destructor",
+ basetype);
+ /* If the base class doesn't have copy constructors or
+ assignment operators that take const references, then the
+ derived class cannot have such a member automatically
+ generated. */
+ if (! TYPE_HAS_CONST_INIT_REF (basetype))
+ *cant_have_const_ctor_p = 1;
+ if (TYPE_HAS_ASSIGN_REF (basetype)
+ && !TYPE_HAS_CONST_ASSIGN_REF (basetype))
+ *no_const_asn_ref_p = 1;
+ /* Similarly, if the base class doesn't have a default
+ constructor, then the derived class won't have an
+ automatically generated default constructor. */
if (TYPE_HAS_CONSTRUCTOR (basetype)
&& ! TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype))
{
- b->cant_have_default_ctor = 1;
+ *cant_have_default_ctor_p = 1;
if (! TYPE_HAS_CONSTRUCTOR (t))
- {
- cp_pedwarn ("base `%T' with only non-default constructor",
- basetype);
- cp_pedwarn ("in class without a constructor");
- }
+ pedwarn ("base `%T' with only non-default constructor in class without a constructor",
+ basetype);
}
- if (TYPE_HAS_ASSIGN_REF (basetype)
- && !TYPE_HAS_CONST_ASSIGN_REF (basetype))
- b->no_const_asn_ref = 1;
+ if (TREE_VIA_VIRTUAL (base_binfo))
+ /* A virtual base does not effect nearly emptiness. */
+ ;
+ else if (CLASSTYPE_NEARLY_EMPTY_P (basetype))
+ {
+ if (seen_non_virtual_nearly_empty_base_p)
+ /* And if there is more than one nearly empty base, then the
+ derived class is not nearly empty either. */
+ CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
+ else
+ /* Remember we've seen one. */
+ seen_non_virtual_nearly_empty_base_p = 1;
+ }
+ else if (!is_empty_class (basetype))
+ /* If the base class is not empty or nearly empty, then this
+ class cannot be nearly empty. */
+ CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
+ /* A lot of properties from the bases also apply to the derived
+ class. */
TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype);
- TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (basetype);
- TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (basetype);
+ TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
+ |= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (basetype);
+ TYPE_HAS_COMPLEX_ASSIGN_REF (t)
+ |= TYPE_HAS_COMPLEX_ASSIGN_REF (basetype);
TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (basetype);
-
TYPE_OVERLOADS_CALL_EXPR (t) |= TYPE_OVERLOADS_CALL_EXPR (basetype);
TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype);
TYPE_OVERLOADS_ARROW (t) |= TYPE_OVERLOADS_ARROW (basetype);
+ TYPE_POLYMORPHIC_P (t) |= TYPE_POLYMORPHIC_P (basetype);
+ }
+}
- if (CLASSTYPE_COM_INTERFACE (basetype))
- {
- CLASSTYPE_COM_INTERFACE (t) = 1;
- if (i > 0)
- cp_error
- ("COM interface type `%T' must be the leftmost base class",
- basetype);
- }
- else if (CLASSTYPE_COM_INTERFACE (t))
- {
- cp_error ("COM interface type `%T' with non-COM base class `%T'",
- t, basetype);
- CLASSTYPE_COM_INTERFACE (t) = 0;
- }
+/* Binfo FROM is within a virtual hierarchy which is being reseated to
+ TO. Move primary information from FROM to TO, and recursively traverse
+ into FROM's bases. The hierarchy is dominated by TYPE. MAPPINGS is an
+ assoc list of binfos that have already been reseated. */
- if (TYPE_VIRTUAL_P (basetype))
- {
- /* Ensure that this is set from at least a virtual base
- class. */
- if (b->rtti == NULL_TREE)
- b->rtti = CLASSTYPE_RTTI (basetype);
+static void
+force_canonical_binfo_r (to, from, type, mappings)
+ tree to;
+ tree from;
+ tree type;
+ tree mappings;
+{
+ int i, n_baseclasses = BINFO_N_BASETYPES (from);
+
+ my_friendly_assert (to != from, 20010905);
+ BINFO_INDIRECT_PRIMARY_P (to)
+ = BINFO_INDIRECT_PRIMARY_P (from);
+ BINFO_INDIRECT_PRIMARY_P (from) = 0;
+ BINFO_UNSHARED_MARKED (to) = BINFO_UNSHARED_MARKED (from);
+ BINFO_UNSHARED_MARKED (from) = 0;
+ BINFO_LOST_PRIMARY_P (to) = BINFO_LOST_PRIMARY_P (from);
+ BINFO_LOST_PRIMARY_P (from) = 0;
+ if (BINFO_PRIMARY_P (from))
+ {
+ tree primary = BINFO_PRIMARY_BASE_OF (from);
+ tree assoc;
+
+ /* We might have just moved the primary base too, see if it's on our
+ mappings. */
+ assoc = purpose_member (primary, mappings);
+ if (assoc)
+ primary = TREE_VALUE (assoc);
+ BINFO_PRIMARY_BASE_OF (to) = primary;
+ BINFO_PRIMARY_BASE_OF (from) = NULL_TREE;
+ }
+ my_friendly_assert (same_type_p (BINFO_TYPE (to), BINFO_TYPE (from)),
+ 20010104);
+ mappings = tree_cons (from, to, mappings);
+
+ if (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (from))
+ && TREE_VIA_VIRTUAL (CLASSTYPE_PRIMARY_BINFO (BINFO_TYPE (from))))
+ {
+ tree from_primary = get_primary_binfo (from);
+
+ if (BINFO_PRIMARY_BASE_OF (from_primary) == from)
+ force_canonical_binfo (get_primary_binfo (to), from_primary,
+ type, mappings);
+ }
+
+ for (i = 0; i != n_baseclasses; i++)
+ {
+ tree from_binfo = BINFO_BASETYPE (from, i);
+ tree to_binfo = BINFO_BASETYPE (to, i);
+
+ if (TREE_VIA_VIRTUAL (from_binfo))
+ {
+ if (BINFO_PRIMARY_P (from_binfo) &&
+ purpose_member (BINFO_PRIMARY_BASE_OF (from_binfo), mappings))
+ /* This base is a primary of some binfo we have already
+ reseated. We must reseat this one too. */
+ force_canonical_binfo (to_binfo, from_binfo, type, mappings);
+ }
+ else
+ force_canonical_binfo_r (to_binfo, from_binfo, type, mappings);
+ }
+}
+
+/* FROM is the canonical binfo for a virtual base. It is being reseated to
+ make TO the canonical binfo, within the hierarchy dominated by TYPE.
+ MAPPINGS is an assoc list of binfos that have already been reseated.
+ Adjust any non-virtual bases within FROM, and also move any virtual bases
+ which are canonical. This complication arises because selecting primary
+ bases walks in inheritance graph order, but we don't share binfos for
+ virtual bases, hence we can fill in the primaries for a virtual base,
+ and then discover that a later base requires the virtual as its
+ primary. */
+
+static void
+force_canonical_binfo (to, from, type, mappings)
+ tree to;
+ tree from;
+ tree type;
+ tree mappings;
+{
+ tree assoc = purpose_member (BINFO_TYPE (to),
+ CLASSTYPE_VBASECLASSES (type));
+ if (TREE_VALUE (assoc) != to)
+ {
+ TREE_VALUE (assoc) = to;
+ force_canonical_binfo_r (to, from, type, mappings);
+ }
+}
+
+/* Make BASE_BINFO the a primary virtual base within the hierarchy
+ dominated by TYPE. Returns BASE_BINFO, if it is not already one, NULL
+ otherwise (because something else has already made it primary). */
+
+static tree
+mark_primary_virtual_base (base_binfo, type)
+ tree base_binfo;
+ tree type;
+{
+ tree shared_binfo = binfo_for_vbase (BINFO_TYPE (base_binfo), type);
+
+ if (BINFO_PRIMARY_P (shared_binfo))
+ {
+ /* It's already allocated in the hierarchy. BINFO won't have a
+ primary base in this hierarchy, even though the complete object
+ BINFO is for, would do. */
+ return NULL_TREE;
+ }
+
+ /* We need to make sure that the assoc list
+ CLASSTYPE_VBASECLASSES of TYPE, indicates this particular
+ primary BINFO for the virtual base, as this is the one
+ that'll really exist. */
+ if (base_binfo != shared_binfo)
+ force_canonical_binfo (base_binfo, shared_binfo, type, NULL);
+
+ return base_binfo;
+}
+
+/* If BINFO is an unmarked virtual binfo for a class with a primary virtual
+ base, then BINFO has no primary base in this graph. Called from
+ mark_primary_bases. DATA is the most derived type. */
- /* Don't borrow virtuals from virtual baseclasses. */
+static tree dfs_unshared_virtual_bases (binfo, data)
+ tree binfo;
+ void *data;
+{
+ tree t = (tree) data;
+
+ if (!BINFO_UNSHARED_MARKED (binfo)
+ && CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
+ {
+ /* This morally virtual base has a primary base when it
+ is a complete object. We need to locate the shared instance
+ of this binfo in the type dominated by T. We duplicate the
+ primary base information from there to here. */
+ tree vbase;
+ tree unshared_base;
+
+ for (vbase = binfo; !TREE_VIA_VIRTUAL (vbase);
+ vbase = BINFO_INHERITANCE_CHAIN (vbase))
+ continue;
+ unshared_base = get_original_base (binfo,
+ binfo_for_vbase (BINFO_TYPE (vbase),
+ t));
+ my_friendly_assert (unshared_base != binfo, 20010612);
+ BINFO_LOST_PRIMARY_P (binfo) = BINFO_LOST_PRIMARY_P (unshared_base);
+ if (!BINFO_LOST_PRIMARY_P (binfo))
+ BINFO_PRIMARY_BASE_OF (get_primary_binfo (binfo)) = binfo;
+ }
+
+ if (binfo != TYPE_BINFO (t))
+ /* The vtable fields will have been copied when duplicating the
+ base binfos. That information is bogus, make sure we don't try
+ and use it. */
+ BINFO_VTABLE (binfo) = NULL_TREE;
+
+ /* If this is a virtual primary base, make sure its offset matches
+ that which it is primary for. */
+ if (BINFO_PRIMARY_P (binfo) && TREE_VIA_VIRTUAL (binfo) &&
+ binfo_for_vbase (BINFO_TYPE (binfo), t) == binfo)
+ {
+ tree delta = size_diffop (BINFO_OFFSET (BINFO_PRIMARY_BASE_OF (binfo)),
+ BINFO_OFFSET (binfo));
+ if (!integer_zerop (delta))
+ propagate_binfo_offsets (binfo, delta, t);
+ }
+
+ BINFO_UNSHARED_MARKED (binfo) = 0;
+ return NULL;
+}
+
+/* Set BINFO_PRIMARY_BASE_OF for all binfos in the hierarchy
+ dominated by TYPE that are primary bases. */
+
+static void
+mark_primary_bases (type)
+ tree type;
+{
+ tree binfo;
+
+ /* Walk the bases in inheritance graph order. */
+ for (binfo = TYPE_BINFO (type); binfo; binfo = TREE_CHAIN (binfo))
+ {
+ tree base_binfo;
+
+ if (!CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
+ /* Not a dynamic base. */
+ continue;
+
+ base_binfo = get_primary_binfo (binfo);
+
+ if (TREE_VIA_VIRTUAL (base_binfo))
+ base_binfo = mark_primary_virtual_base (base_binfo, type);
+
+ if (base_binfo)
+ BINFO_PRIMARY_BASE_OF (base_binfo) = binfo;
+ else
+ BINFO_LOST_PRIMARY_P (binfo) = 1;
+
+ BINFO_UNSHARED_MARKED (binfo) = 1;
+ }
+ /* There could remain unshared morally virtual bases which were not
+ visited in the inheritance graph walk. These bases will have lost
+ their virtual primary base (should they have one). We must now
+ find them. Also we must fix up the BINFO_OFFSETs of primary
+ virtual bases. We could not do that as we went along, as they
+ were originally copied from the bases we inherited from by
+ unshare_base_binfos. That may have decided differently about
+ where a virtual primary base went. */
+ dfs_walk (TYPE_BINFO (type), dfs_unshared_virtual_bases, NULL, type);
+}
+
+/* Make the BINFO the primary base of T. */
+
+static void
+set_primary_base (t, binfo, vfuns_p)
+ tree t;
+ tree binfo;
+ int *vfuns_p;
+{
+ tree basetype;
+
+ CLASSTYPE_PRIMARY_BINFO (t) = binfo;
+ basetype = BINFO_TYPE (binfo);
+ TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype);
+ TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
+ TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
+ CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype);
+ *vfuns_p = CLASSTYPE_VSIZE (basetype);
+}
+
+/* Determine the primary class for T. */
+
+static void
+determine_primary_base (t, vfuns_p)
+ tree t;
+ int *vfuns_p;
+{
+ int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
+ tree vbases;
+ tree type_binfo;
+
+ /* If there are no baseclasses, there is certainly no primary base. */
+ if (n_baseclasses == 0)
+ return;
+
+ type_binfo = TYPE_BINFO (t);
+
+ for (i = 0; i < n_baseclasses; i++)
+ {
+ tree base_binfo = BINFO_BASETYPE (type_binfo, i);
+ tree basetype = BINFO_TYPE (base_binfo);
+
+ if (TYPE_CONTAINS_VPTR_P (basetype))
+ {
+ /* Even a virtual baseclass can contain our RTTI
+ information. But, we prefer a non-virtual polymorphic
+ baseclass. */
+ if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
+ CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype);
+
+ /* We prefer a non-virtual base, although a virtual one will
+ do. */
if (TREE_VIA_VIRTUAL (base_binfo))
continue;
- if (first_vfn_base_index < 0)
+ if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
{
- tree vfields;
- first_vfn_base_index = i;
-
- /* Update these two, now that we know what vtable we are
- going to extend. This is so that we can add virtual
- functions, and override them properly. */
- TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype);
- TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
- b->has_virtual = CLASSTYPE_VSIZE (basetype);
- b->vfield = CLASSTYPE_VFIELD (basetype);
- b->vfields = copy_list (CLASSTYPE_VFIELDS (basetype));
- vfields = b->vfields;
- while (vfields)
- {
- if (VF_BINFO_VALUE (vfields) == NULL_TREE
- || ! TREE_VIA_VIRTUAL (VF_BINFO_VALUE (vfields)))
- {
- tree value = VF_BASETYPE_VALUE (vfields);
- if (DECL_NAME (CLASSTYPE_VFIELD (value))
- == DECL_NAME (CLASSTYPE_VFIELD (basetype)))
- VF_NORMAL_VALUE (b->vfields) = basetype;
- else
- VF_NORMAL_VALUE (b->vfields) = VF_NORMAL_VALUE (vfields);
- }
- vfields = TREE_CHAIN (vfields);
- }
- CLASSTYPE_VFIELD (t) = b->vfield;
+ set_primary_base (t, base_binfo, vfuns_p);
+ CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype));
}
else
{
+ tree vfields;
+
/* Only add unique vfields, and flatten them out as we go. */
- tree vfields = CLASSTYPE_VFIELDS (basetype);
- while (vfields)
- {
- if (VF_BINFO_VALUE (vfields) == NULL_TREE
- || ! TREE_VIA_VIRTUAL (VF_BINFO_VALUE (vfields)))
- {
- tree value = VF_BASETYPE_VALUE (vfields);
- b->vfields = tree_cons (base_binfo, value, b->vfields);
- if (DECL_NAME (CLASSTYPE_VFIELD (value))
- == DECL_NAME (CLASSTYPE_VFIELD (basetype)))
- VF_NORMAL_VALUE (b->vfields) = basetype;
- else
- VF_NORMAL_VALUE (b->vfields) = VF_NORMAL_VALUE (vfields);
- }
- vfields = TREE_CHAIN (vfields);
- }
+ 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));
+ }
+ }
+ }
- if (b->has_virtual == 0)
+ if (!TYPE_VFIELD (t))
+ CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;
+
+ /* Find the indirect primary bases - those virtual bases which are primary
+ bases of something else in this hierarchy. */
+ for (vbases = CLASSTYPE_VBASECLASSES (t);
+ vbases;
+ vbases = TREE_CHAIN (vbases))
+ {
+ tree vbase_binfo = TREE_VALUE (vbases);
+
+ /* 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)
+ {
+ tree basetype = TYPE_BINFO_BASETYPE (t, i);
+ tree v;
+
+ for (v = CLASSTYPE_VBASECLASSES (basetype);
+ v;
+ v = TREE_CHAIN (v))
+ {
+ tree base_vbase = TREE_VALUE (v);
+
+ if (BINFO_PRIMARY_P (base_vbase)
+ && same_type_p (BINFO_TYPE (base_vbase),
+ BINFO_TYPE (vbase_binfo)))
{
- first_vfn_base_index = i;
-
- /* Update these two, now that we know what vtable we are
- going to extend. This is so that we can add virtual
- functions, and override them properly. */
- TYPE_BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (basetype);
- TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
- b->has_virtual = CLASSTYPE_VSIZE (basetype);
- b->vfield = CLASSTYPE_VFIELD (basetype);
- CLASSTYPE_VFIELD (t) = b->vfield;
- /* When we install the first one, set the VF_NORMAL_VALUE
- to be the current class, as this it is the most derived
- class. Hopefully, this is not set to something else
- later. (mrs) */
- vfields = b->vfields;
- while (vfields)
- {
- if (DECL_NAME (CLASSTYPE_VFIELD (t))
- == DECL_NAME (CLASSTYPE_VFIELD (basetype)))
- {
- VF_NORMAL_VALUE (vfields) = t;
- /* There should only be one of them! And it should
- always be found, if we get into here. (mrs) */
- break;
- }
- vfields = TREE_CHAIN (vfields);
- }
+ BINFO_INDIRECT_PRIMARY_P (vbase_binfo) = 1;
+ break;
}
}
+
+ /* If we've discovered that this virtual base is an indirect
+ primary base, then we can move on to the next virtual
+ base. */
+ if (BINFO_INDIRECT_PRIMARY_P (vbase_binfo))
+ break;
}
}
- {
- tree vfields;
- /* Find the base class with the largest number of virtual functions. */
- for (vfields = b->vfields; vfields; vfields = TREE_CHAIN (vfields))
- {
- if (CLASSTYPE_VSIZE (VF_BASETYPE_VALUE (vfields)) > b->max_has_virtual)
- b->max_has_virtual = CLASSTYPE_VSIZE (VF_BASETYPE_VALUE (vfields));
- if (VF_DERIVED_VALUE (vfields)
- && CLASSTYPE_VSIZE (VF_DERIVED_VALUE (vfields)) > b->max_has_virtual)
- b->max_has_virtual = CLASSTYPE_VSIZE (VF_DERIVED_VALUE (vfields));
- }
- }
+ /* A "nearly-empty" virtual base class can be the primary base
+ class, if no non-virtual polymorphic base can be found. */
+ if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
+ {
+ /* If not NULL, this is the best primary base candidate we have
+ found so far. */
+ tree candidate = NULL_TREE;
+ tree base_binfo;
- if (b->vfield == 0)
- /* If all virtual functions come only from virtual baseclasses. */
- return -1;
+ /* Loop over the baseclasses. */
+ for (base_binfo = TYPE_BINFO (t);
+ base_binfo;
+ base_binfo = TREE_CHAIN (base_binfo))
+ {
+ tree basetype = BINFO_TYPE (base_binfo);
- /* Update the rtti base if we have a non-virtual base class version
- of it. */
- b->rtti = CLASSTYPE_RTTI (BINFO_TYPE (TREE_VEC_ELT (binfos, first_vfn_base_index)));
+ if (TREE_VIA_VIRTUAL (base_binfo)
+ && CLASSTYPE_NEARLY_EMPTY_P (basetype))
+ {
+ /* If this is not an indirect primary base, then it's
+ definitely our primary base. */
+ if (!BINFO_INDIRECT_PRIMARY_P (base_binfo))
+ {
+ candidate = base_binfo;
+ break;
+ }
+
+ /* If this is an indirect primary base, it still could be
+ our primary base -- unless we later find there's another
+ nearly-empty virtual base that isn't an indirect
+ primary base. */
+ if (!candidate)
+ candidate = base_binfo;
+ }
+ }
+
+ /* If we've got a primary base, use it. */
+ if (candidate)
+ {
+ set_primary_base (t, candidate, vfuns_p);
+ CLASSTYPE_VFIELDS (t)
+ = copy_list (CLASSTYPE_VFIELDS (BINFO_TYPE (candidate)));
+ }
+ }
- return first_vfn_base_index;
+ /* Mark the primary base classes at this point. */
+ mark_primary_bases (t);
}
-/* Set memoizing fields and bits of T (and its variants) for later use.
- MAX_HAS_VIRTUAL is the largest size of any T's virtual function tables. */
+/* Set memoizing fields and bits of T (and its variants) for later
+ use. */
static void
-finish_struct_bits (t, max_has_virtual)
+finish_struct_bits (t)
tree t;
- int max_has_virtual;
{
int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
@@ -1837,12 +1800,13 @@ finish_struct_bits (t, max_has_virtual)
TYPE_HAS_CONSTRUCTOR (variants) = TYPE_HAS_CONSTRUCTOR (t);
TYPE_HAS_DESTRUCTOR (variants) = TYPE_HAS_DESTRUCTOR (t);
TYPE_NEEDS_CONSTRUCTING (variants) = TYPE_NEEDS_CONSTRUCTING (t);
- TYPE_NEEDS_DESTRUCTOR (variants) = TYPE_NEEDS_DESTRUCTOR (t);
+ TYPE_HAS_NONTRIVIAL_DESTRUCTOR (variants)
+ = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t);
- TYPE_USES_COMPLEX_INHERITANCE (variants) = TYPE_USES_COMPLEX_INHERITANCE (t);
- TYPE_VIRTUAL_P (variants) = TYPE_VIRTUAL_P (t);
+ 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_PVBASES (variants) = TYPE_USES_PVBASES (t);
/* Copy whatever these are holding today. */
TYPE_MIN_VALUE (variants) = TYPE_MIN_VALUE (t);
TYPE_MAX_VALUE (variants) = TYPE_MAX_VALUE (t);
@@ -1852,18 +1816,16 @@ finish_struct_bits (t, max_has_virtual)
variants = TYPE_NEXT_VARIANT (variants);
}
- if (n_baseclasses && max_has_virtual)
- {
- /* For a class w/o baseclasses, `finish_struct' has set
- CLASS_TYPE_ABSTRACT_VIRTUALS correctly (by definition). Similarly
- for a class who's 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). */
- CLASSTYPE_ABSTRACT_VIRTUALS (t) = get_abstract_virtuals (t);
- }
+ if (n_baseclasses && 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)
{
@@ -1985,7 +1947,7 @@ maybe_warn_about_overly_private_class (t)
}
if (!has_nonprivate_method)
{
- cp_warning ("all member functions in class `%T' are private", t);
+ warning ("all member functions in class `%T' are private", t);
return;
}
}
@@ -1999,7 +1961,7 @@ maybe_warn_about_overly_private_class (t)
if (TREE_PRIVATE (dtor))
{
- cp_warning ("`%#T' only defines a private destructor and has no friends",
+ warning ("`%#T' only defines a private destructor and has no friends",
t);
return;
}
@@ -2042,13 +2004,47 @@ maybe_warn_about_overly_private_class (t)
if (nonprivate_ctor == 0)
{
- cp_warning ("`%#T' only defines private constructors and has no friends",
+ warning ("`%#T' only defines private constructors and has no friends",
t);
return;
}
}
}
+/* Function to help qsort sort FIELD_DECLs by name order. */
+
+static int
+field_decl_cmp (x, y)
+ const tree *x, *y;
+{
+ if (DECL_NAME (*x) == DECL_NAME (*y))
+ /* A nontype is "greater" than a type. */
+ return DECL_DECLARES_TYPE_P (*y) - DECL_DECLARES_TYPE_P (*x);
+ if (DECL_NAME (*x) == NULL_TREE)
+ return -1;
+ if (DECL_NAME (*y) == NULL_TREE)
+ return 1;
+ if (DECL_NAME (*x) < DECL_NAME (*y))
+ return -1;
+ return 1;
+}
+
+/* Comparison function to compare two TYPE_METHOD_VEC entries by name. */
+
+static int
+method_name_cmp (m1, m2)
+ const tree *m1, *m2;
+{
+ if (*m1 == NULL_TREE && *m2 == NULL_TREE)
+ return 0;
+ if (*m1 == NULL_TREE)
+ return -1;
+ if (*m2 == NULL_TREE)
+ return 1;
+ if (DECL_NAME (OVL_CURRENT (*m1)) < DECL_NAME (OVL_CURRENT (*m2)))
+ return -1;
+ return 1;
+}
/* Warn about duplicate methods in fn_fields. Also compact method
lists so that lookup can be made faster.
@@ -2062,79 +2058,65 @@ maybe_warn_about_overly_private_class (t)
list. That allows them to be quickly deleted, and requires no
extra storage.
- If there are any constructors/destructors, they are moved to the
- front of the list. This makes pushclass more efficient.
-
- We also link each field which has shares a name with its baseclass
- to the head of the list of fields for that base class. This allows
- us to reduce search time in places like `build_method_call' to
- consider only reasonably likely functions. */
+ Sort methods that are not special (i.e., constructors, destructors,
+ and type conversion operators) so that we can find them faster in
+ search. */
static void
finish_struct_methods (t)
tree t;
{
tree fn_fields;
- tree method_vec = CLASSTYPE_METHOD_VEC (t);
- tree ctor_name = constructor_name (t);
+ 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);
/* First fill in entry 0 with the constructors, entry 1 with destructors,
and the next few with type conversion operators (if any). */
for (fn_fields = TYPE_METHODS (t); fn_fields;
fn_fields = TREE_CHAIN (fn_fields))
- {
- tree fn_name = DECL_NAME (fn_fields);
-
- /* Clear out this flag.
+ /* Clear out this flag. */
+ DECL_IN_AGGR_P (fn_fields) = 0;
- @@ Doug may figure out how to break
- @@ this with nested classes and friends. */
- DECL_IN_AGGR_P (fn_fields) = 0;
-
- /* Note here that a copy ctor is private, so we don't dare generate
- a default copy constructor for a class that has a member
- of this type without making sure they have access to it. */
- if (fn_name == ctor_name)
- {
- tree parmtypes = FUNCTION_ARG_CHAIN (fn_fields);
- tree parmtype = parmtypes ? TREE_VALUE (parmtypes) : void_type_node;
-
- if (TREE_CODE (parmtype) == REFERENCE_TYPE
- && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == t)
- {
- if (TREE_CHAIN (parmtypes) == NULL_TREE
- || TREE_CHAIN (parmtypes) == void_list_node
- || TREE_PURPOSE (TREE_CHAIN (parmtypes)))
- {
- if (TREE_PROTECTED (fn_fields))
- TYPE_HAS_NONPUBLIC_CTOR (t) = 1;
- else if (TREE_PRIVATE (fn_fields))
- TYPE_HAS_NONPUBLIC_CTOR (t) = 2;
- }
- }
- }
- else if (fn_name == ansi_opname[(int) MODIFY_EXPR])
- {
- tree parmtype = TREE_VALUE (FUNCTION_ARG_CHAIN (fn_fields));
-
- if (copy_assignment_arg_p (parmtype, DECL_VIRTUAL_P (fn_fields)))
- {
- if (TREE_PROTECTED (fn_fields))
- TYPE_HAS_NONPUBLIC_ASSIGN_REF (t) = 1;
- else if (TREE_PRIVATE (fn_fields))
- TYPE_HAS_NONPUBLIC_ASSIGN_REF (t) = 2;
- }
- }
- }
-
- if (TYPE_HAS_DESTRUCTOR (t) && !TREE_VEC_ELT (method_vec, 1))
+ if (TYPE_HAS_DESTRUCTOR (t) && !CLASSTYPE_DESTRUCTORS (t))
/* We thought there was a destructor, but there wasn't. Some
parse errors cause this anomalous situation. */
TYPE_HAS_DESTRUCTOR (t) = 0;
/* Issue warnings about private constructors and such. If there are
no methods, then some public defaults are generated. */
- maybe_warn_about_overly_private_class (t);
+ 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;
+ }
+ if (len - slot > 1)
+ qsort (&TREE_VEC_ELT (method_vec, slot), len-slot, sizeof (tree),
+ (int (*)(const void *, const void *))method_name_cmp);
}
/* Emit error when a duplicate definition of a type is seen. Patch up. */
@@ -2143,8 +2125,8 @@ void
duplicate_tag_error (t)
tree t;
{
- cp_error ("redefinition of `%#T'", t);
- cp_error_at ("previous definition here", t);
+ error ("redefinition of `%#T'", t);
+ cp_error_at ("previous definition of `%#T'", t);
/* Pretend we haven't defined this type. */
@@ -2176,14 +2158,18 @@ duplicate_tag_error (t)
tree binfo = TYPE_BINFO (t);
int interface_only = CLASSTYPE_INTERFACE_ONLY (t);
int interface_unknown = CLASSTYPE_INTERFACE_UNKNOWN (t);
+ tree template_info = CLASSTYPE_TEMPLATE_INFO (t);
+ int use_template = CLASSTYPE_USE_TEMPLATE (t);
- bzero ((char *) TYPE_LANG_SPECIFIC (t), sizeof (struct lang_type));
+ memset ((char *) TYPE_LANG_SPECIFIC (t), 0, sizeof (struct lang_type));
BINFO_BASETYPES(binfo) = NULL_TREE;
TYPE_BINFO (t) = binfo;
CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
TYPE_REDEFINED (t) = 1;
+ CLASSTYPE_TEMPLATE_INFO (t) = template_info;
+ CLASSTYPE_USE_TEMPLATE (t) = use_template;
}
TYPE_SIZE (t) = NULL_TREE;
TYPE_MODE (t) = VOIDmode;
@@ -2191,72 +2177,72 @@ duplicate_tag_error (t)
TYPE_METHODS (t) = NULL_TREE;
TYPE_VFIELD (t) = NULL_TREE;
TYPE_CONTEXT (t) = NULL_TREE;
+
+ /* Clear TYPE_LANG_FLAGS -- those in TYPE_LANG_SPECIFIC are cleared above. */
+ TYPE_LANG_FLAG_0 (t) = 0;
+ TYPE_LANG_FLAG_1 (t) = 0;
+ TYPE_LANG_FLAG_2 (t) = 0;
+ TYPE_LANG_FLAG_3 (t) = 0;
+ TYPE_LANG_FLAG_4 (t) = 0;
+ TYPE_LANG_FLAG_5 (t) = 0;
+ TYPE_LANG_FLAG_6 (t) = 0;
+ /* But not this one. */
+ SET_IS_AGGR_TYPE (t, 1);
}
-/* finish up all new vtables. */
+/* Make BINFO's vtable have N entries, including RTTI entries,
+ vbase and vcall offsets, etc. Set its type and call the backend
+ to lay it out. */
static void
-finish_vtbls (binfo, do_self, t)
+layout_vtable_decl (binfo, n)
tree binfo;
- int do_self;
- tree t;
+ int n;
{
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+ tree atype;
+ tree vtable;
- /* Should we use something besides CLASSTYPE_VFIELDS? */
- if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
- {
- if (BINFO_NEW_VTABLE_MARKED (binfo))
- {
- tree decl, context;
-
- decl = BINFO_VTABLE (binfo);
- context = DECL_CONTEXT (decl);
- DECL_CONTEXT (decl) = 0;
- if (DECL_INITIAL (decl) != BINFO_VIRTUALS (binfo))
- DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE,
- BINFO_VIRTUALS (binfo));
- cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0);
- DECL_CONTEXT (decl) = context;
- }
- CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
- }
+ atype = build_cplus_array_type (vtable_entry_type,
+ build_index_type (size_int (n - 1)));
+ layout_type (atype);
- for (i = 0; i < n_baselinks; i++)
+ /* We may have to grow the vtable. */
+ vtable = get_vtbl_decl_for_binfo (binfo);
+ if (!same_type_p (TREE_TYPE (vtable), atype))
{
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- int is_not_base_vtable
- = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
- if (TREE_VIA_VIRTUAL (base_binfo))
- {
- base_binfo = binfo_member (BINFO_TYPE (base_binfo), CLASSTYPE_VBASECLASSES (t));
- }
- finish_vtbls (base_binfo, is_not_base_vtable, t);
+ TREE_TYPE (vtable) = atype;
+ DECL_SIZE (vtable) = DECL_SIZE_UNIT (vtable) = NULL_TREE;
+ layout_decl (vtable, 0);
+
+ /* At one time the vtable info was grabbed 2 words at a time. This
+ fails on Sparc unless you have 8-byte alignment. */
+ DECL_ALIGN (vtable) = MAX (TYPE_ALIGN (double_type_node),
+ DECL_ALIGN (vtable));
}
}
-/* True if we should override the given BASE_FNDECL with the given
- FNDECL. */
+/* True iff FNDECL and BASE_FNDECL (both non-static member functions)
+ have the same signature. */
-static int
-overrides (fndecl, base_fndecl)
+int
+same_signature_p (fndecl, base_fndecl)
tree fndecl, base_fndecl;
{
- /* Destructors have special names. */
- if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (base_fndecl))
- && DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
+ /* One destructor overrides another if they are the same kind of
+ destructor. */
+ if (DECL_DESTRUCTOR_P (base_fndecl) && DECL_DESTRUCTOR_P (fndecl)
+ && special_function_p (base_fndecl) == special_function_p (fndecl))
return 1;
- if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (base_fndecl))
- || DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
+ /* But a non-destructor never overrides a destructor, nor vice
+ versa, nor do different kinds of destructors override
+ one-another. For example, a complete object destructor does not
+ override a deleting destructor. */
+ if (DECL_DESTRUCTOR_P (base_fndecl) || DECL_DESTRUCTOR_P (fndecl))
return 0;
+
if (DECL_NAME (fndecl) == DECL_NAME (base_fndecl))
{
tree types, base_types;
-#if 0
- retypes = TREE_TYPE (TREE_TYPE (fndecl));
- base_retypes = TREE_TYPE (TREE_TYPE (base_fndecl));
-#endif
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)))
@@ -2267,584 +2253,496 @@ overrides (fndecl, base_fndecl)
return 0;
}
+typedef struct find_final_overrider_data_s {
+ /* The function for which we are trying to find a final overrider. */
+ tree fn;
+ /* The base class in which the function was declared. */
+ tree declaring_base;
+ /* The most derived class in the hierarchy. */
+ tree most_derived_type;
+ /* The final overriding function. */
+ tree overriding_fn;
+ /* The functions that we thought might be final overriders, but
+ aren't. */
+ tree candidates;
+ /* The BINFO for the class in which the final overriding function
+ appears. */
+ tree overriding_base;
+} find_final_overrider_data;
+
+/* Called from find_final_overrider via dfs_walk. */
+
static tree
-get_class_offset_1 (parent, binfo, context, t, fndecl)
- tree parent, binfo, context, t, fndecl;
+dfs_find_final_overrider (binfo, data)
+ tree binfo;
+ void *data;
{
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- tree rval = NULL_TREE;
-
- if (binfo == parent)
- return error_mark_node;
-
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree nrval;
+ find_final_overrider_data *ffod = (find_final_overrider_data *) data;
+
+ if (same_type_p (BINFO_TYPE (binfo),
+ BINFO_TYPE (ffod->declaring_base))
+ && tree_int_cst_equal (BINFO_OFFSET (binfo),
+ BINFO_OFFSET (ffod->declaring_base)))
+ {
+ tree path;
+ tree method;
+
+ /* We haven't found an overrider yet. */
+ method = NULL_TREE;
+ /* We've found a path to the declaring base. Walk down the path
+ looking for an overrider for FN. */
+ for (path = reverse_path (binfo);
+ path;
+ path = TREE_CHAIN (path))
+ {
+ method = look_for_overrides_here (BINFO_TYPE (TREE_VALUE (path)),
+ ffod->fn);
+ if (method)
+ break;
+ }
- if (TREE_VIA_VIRTUAL (base_binfo))
- base_binfo = binfo_member (BINFO_TYPE (base_binfo),
- CLASSTYPE_VBASECLASSES (t));
- nrval = get_class_offset_1 (parent, base_binfo, context, t, fndecl);
- /* See if we have a new value */
- if (nrval && (nrval != error_mark_node || rval==0))
+ /* If we found an overrider, record the overriding function, and
+ the base from which it came. */
+ if (path)
{
- /* Only compare if we have two offsets */
- if (rval && rval != error_mark_node
- && ! tree_int_cst_equal (nrval, rval))
+ tree base;
+
+ /* Assume the path is non-virtual. See if there are any
+ virtual bases from (but not including) the overrider up
+ to and including the base where the function is
+ defined. */
+ for (base = TREE_CHAIN (path); base; base = TREE_CHAIN (base))
+ if (TREE_VIA_VIRTUAL (TREE_VALUE (base)))
+ {
+ base = ffod->declaring_base;
+ break;
+ }
+
+ /* If we didn't already have an overrider, or any
+ candidates, then this function is the best candidate so
+ far. */
+ if (!ffod->overriding_fn && !ffod->candidates)
{
- /* Only give error if the two offsets are different */
- error ("every virtual function must have a unique final overrider");
- cp_error (" found two (or more) `%T' class subobjects in `%T'", context, t);
- cp_error (" with virtual `%D' from virtual base class", fndecl);
- return rval;
+ ffod->overriding_fn = method;
+ ffod->overriding_base = TREE_VALUE (path);
+ }
+ else if (ffod->overriding_fn)
+ {
+ /* We had a best overrider; let's see how this compares. */
+
+ if (ffod->overriding_fn == method
+ && (tree_int_cst_equal
+ (BINFO_OFFSET (TREE_VALUE (path)),
+ BINFO_OFFSET (ffod->overriding_base))))
+ /* We found the same overrider we already have, and in the
+ same place; it's still the best. */;
+ else if (strictly_overrides (ffod->overriding_fn, method))
+ /* The old function overrides this function; it's still the
+ best. */;
+ else if (strictly_overrides (method, ffod->overriding_fn))
+ {
+ /* The new function overrides the old; it's now the
+ best. */
+ ffod->overriding_fn = method;
+ ffod->overriding_base = TREE_VALUE (path);
+ }
+ else
+ {
+ /* Ambiguous. */
+ ffod->candidates
+ = build_tree_list (NULL_TREE,
+ ffod->overriding_fn);
+ if (method != ffod->overriding_fn)
+ ffod->candidates
+ = tree_cons (NULL_TREE, method, ffod->candidates);
+ ffod->overriding_fn = NULL_TREE;
+ ffod->overriding_base = NULL_TREE;
+ }
+ }
+ else
+ {
+ /* We had a list of ambiguous overrides; let's see how this
+ new one compares. */
+
+ tree candidates;
+ bool incomparable = false;
+
+ /* If there were previous candidates, and this function
+ overrides all of them, then it is the new best
+ candidate. */
+ for (candidates = ffod->candidates;
+ candidates;
+ candidates = TREE_CHAIN (candidates))
+ {
+ /* If the candidate overrides the METHOD, then we
+ needn't worry about it any further. */
+ if (strictly_overrides (TREE_VALUE (candidates),
+ method))
+ {
+ method = NULL_TREE;
+ break;
+ }
+
+ /* If the METHOD doesn't override the candidate,
+ then it is incomporable. */
+ if (!strictly_overrides (method,
+ TREE_VALUE (candidates)))
+ incomparable = true;
+ }
+
+ /* If METHOD overrode all the candidates, then it is the
+ new best candidate. */
+ if (!candidates && !incomparable)
+ {
+ ffod->overriding_fn = method;
+ ffod->overriding_base = TREE_VALUE (path);
+ ffod->candidates = NULL_TREE;
+ }
+ /* If METHOD didn't override all the candidates, then it
+ is another candidate. */
+ else if (method && incomparable)
+ ffod->candidates
+ = tree_cons (NULL_TREE, method, ffod->candidates);
}
- rval = nrval;
- }
-
- if (rval && BINFO_TYPE (binfo) == context)
- {
- my_friendly_assert (rval == error_mark_node
- || tree_int_cst_equal (rval, BINFO_OFFSET (binfo)), 999);
- rval = BINFO_OFFSET (binfo);
}
}
- return rval;
+
+ return NULL_TREE;
}
-/* Get the offset to the CONTEXT subobject that is related to the
- given BINFO. */
+/* Returns a TREE_LIST whose TREE_PURPOSE is the final overrider for
+ FN and whose TREE_VALUE is the binfo for the base where the
+ overriding occurs. BINFO (in the hierarchy dominated by T) is the
+ base object in which FN is declared. */
static tree
-get_class_offset (context, t, binfo, fndecl)
- tree context, t, binfo, fndecl;
+find_final_overrider (t, binfo, fn)
+ tree t;
+ tree binfo;
+ tree fn;
{
- tree first_binfo = binfo;
- tree offset;
- int i;
+ find_final_overrider_data ffod;
- if (context == t)
- return integer_zero_node;
+ /* Getting this right is a little tricky. This is legal:
- if (BINFO_TYPE (binfo) == context)
- return BINFO_OFFSET (binfo);
+ struct S { virtual void f (); };
+ struct T { virtual void f (); };
+ struct U : public S, public T { };
- /* Check less derived binfos first. */
- while (BINFO_BASETYPES (binfo)
- && (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1)
- {
- tree binfos = BINFO_BASETYPES (binfo);
- binfo = TREE_VEC_ELT (binfos, i);
- if (BINFO_TYPE (binfo) == context)
- return BINFO_OFFSET (binfo);
- }
+ even though calling `f' in `U' is ambiguous. But,
- /* Ok, not found in the less derived binfos, now check the more
- derived binfos. */
- offset = get_class_offset_1 (first_binfo, TYPE_BINFO (t), context, t, fndecl);
- if (offset==0 || TREE_CODE (offset) != INTEGER_CST)
- my_friendly_abort (999); /* we have to find it. */
- return offset;
-}
+ struct R { virtual void f(); };
+ struct S : virtual public R { virtual void f (); };
+ struct T : virtual public R { virtual void f (); };
+ struct U : public S, public T { };
-/* Skip RTTI information at the front of the virtual list. */
-
-unsigned HOST_WIDE_INT
-skip_rtti_stuff (virtuals, t)
- tree *virtuals, t;
-{
- int n;
-
- if (CLASSTYPE_COM_INTERFACE (t))
- return 0;
-
- n = 0;
- if (*virtuals)
- {
- /* We always reserve a slot for the offset/tdesc entry. */
- ++n;
- *virtuals = TREE_CHAIN (*virtuals);
- }
- if (flag_vtable_thunks && *virtuals)
- {
- /* The second slot is reserved for the tdesc pointer when thunks
- are used. */
- ++n;
- *virtuals = TREE_CHAIN (*virtuals);
+ is not -- there's no way to decide whether to put `S::f' or
+ `T::f' in the vtable for `R'.
+
+ The solution is to look at all paths to BINFO. If we find
+ different overriders along any two, then there is a problem. */
+ ffod.fn = fn;
+ ffod.declaring_base = binfo;
+ ffod.most_derived_type = t;
+ ffod.overriding_fn = NULL_TREE;
+ ffod.overriding_base = NULL_TREE;
+ ffod.candidates = NULL_TREE;
+
+ dfs_walk (TYPE_BINFO (t),
+ dfs_find_final_overrider,
+ NULL,
+ &ffod);
+
+ /* If there was no winner, issue an error message. */
+ if (!ffod.overriding_fn)
+ {
+ error ("no unique final overrider for `%D' in `%T'", fn, t);
+ return error_mark_node;
}
- return n;
-}
-static void
-modify_one_vtable (binfo, t, fndecl, pfn)
- tree binfo, t, fndecl, pfn;
-{
- tree virtuals = BINFO_VIRTUALS (binfo);
- unsigned HOST_WIDE_INT n;
-
- /* update rtti entry */
- if (flag_rtti)
- {
- if (binfo == TYPE_BINFO (t))
- {
- if (! BINFO_NEW_VTABLE_MARKED (binfo))
- build_vtable (TYPE_BINFO (DECL_CONTEXT (CLASSTYPE_VFIELD (t))), t);
- }
- else
- {
- if (! BINFO_NEW_VTABLE_MARKED (binfo))
- prepare_fresh_vtable (binfo, t);
- }
- }
- if (fndecl == NULL_TREE)
- return;
+ return build_tree_list (ffod.overriding_fn, ffod.overriding_base);
+}
- n = skip_rtti_stuff (&virtuals, t);
+/* Returns the function from the BINFO_VIRTUALS entry in T which matches
+ the signature of FUNCTION_DECL FN, or NULL_TREE if none. In other words,
+ the function that the slot in T's primary vtable points to. */
- while (virtuals)
- {
- tree current_fndecl = TREE_VALUE (virtuals);
- current_fndecl = FNADDR_FROM_VTABLE_ENTRY (current_fndecl);
- current_fndecl = TREE_OPERAND (current_fndecl, 0);
- if (current_fndecl && overrides (fndecl, current_fndecl))
- {
- tree base_offset, offset;
- tree context = DECL_CLASS_CONTEXT (fndecl);
- tree vfield = CLASSTYPE_VFIELD (t);
- tree this_offset;
-
- offset = get_class_offset (context, t, binfo, fndecl);
-
- /* Find the right offset for the this pointer based on the
- base class we just found. We have to take into
- consideration the virtual base class pointers that we
- stick in before the virtual function table pointer.
-
- Also, we want just the delta between the most base class
- that we derived this vfield from and us. */
- base_offset = size_binop (PLUS_EXPR,
- get_derived_offset (binfo, DECL_CONTEXT (current_fndecl)),
- BINFO_OFFSET (binfo));
- this_offset = ssize_binop (MINUS_EXPR, offset, base_offset);
-
- if (binfo == TYPE_BINFO (t))
- {
- /* In this case, it is *type*'s vtable we are modifying.
- We start with the approximation that it's vtable is that
- of the immediate base class. */
- if (! BINFO_NEW_VTABLE_MARKED (binfo))
- build_vtable (TYPE_BINFO (DECL_CONTEXT (vfield)), t);
- }
- else
- {
- /* This is our very own copy of `basetype' to play with.
- Later, we will fill in all the virtual functions
- that override the virtual functions in these base classes
- which are not defined by the current type. */
- if (! BINFO_NEW_VTABLE_MARKED (binfo))
- prepare_fresh_vtable (binfo, t);
- }
+static tree get_matching_virtual PARAMS ((tree, tree));
+static tree
+get_matching_virtual (t, fn)
+ tree t, fn;
+{
+ tree f;
-#ifdef NOTQUITE
- cp_warning ("in %D", DECL_NAME (BINFO_VTABLE (binfo)));
-#endif
- modify_vtable_entry (get_vtable_entry_n (BINFO_VIRTUALS (binfo), n),
- build_vtable_entry (this_offset, pfn),
- fndecl);
- }
- ++n;
- virtuals = TREE_CHAIN (virtuals);
- }
+ for (f = BINFO_VIRTUALS (TYPE_BINFO (t)); f; f = TREE_CHAIN (f))
+ if (same_signature_p (BV_FN (f), fn))
+ return BV_FN (f);
+ return NULL_TREE;
}
-/* These are the ones that are not through virtual base classes. */
+/* Update an entry in the vtable for BINFO, which is in the hierarchy
+ dominated by T. FN has been overriden in BINFO; VIRTUALS points to the
+ corresponding position in the BINFO_VIRTUALS list. */
static void
-modify_all_direct_vtables (binfo, do_self, t, fndecl, pfn)
+update_vtable_entry_for_fn (t, binfo, fn, virtuals)
+ tree t;
tree binfo;
- int do_self;
- tree t, fndecl, pfn;
+ tree fn;
+ tree *virtuals;
{
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+ tree b;
+ tree overrider;
+ tree delta;
+ tree virtual_base;
+ tree first_defn;
+ bool lost = false;
+
+ /* Find the nearest primary base (possibly binfo itself) which defines
+ this function; this is the class the caller will convert to when
+ calling FN through BINFO. */
+ for (b = binfo; ; b = get_primary_binfo (b))
+ {
+ if (look_for_overrides_here (BINFO_TYPE (b), fn))
+ break;
- /* Should we use something besides CLASSTYPE_VFIELDS? */
- if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
- {
- modify_one_vtable (binfo, t, fndecl, pfn);
+ /* The nearest definition is from a lost primary. */
+ if (BINFO_LOST_PRIMARY_P (b))
+ lost = true;
}
+ first_defn = b;
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- int is_not_base_vtable
- = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
- if (! TREE_VIA_VIRTUAL (base_binfo))
- modify_all_direct_vtables (base_binfo, is_not_base_vtable, t, fndecl, pfn);
- }
-}
+ /* Find the final overrider. */
+ overrider = find_final_overrider (t, b, fn);
+ if (overrider == error_mark_node)
+ return;
-/* Fixup all the delta entries in this one vtable that need updating. */
+ /* 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;
-static void
-fixup_vtable_deltas1 (binfo, t)
- tree binfo, t;
-{
- tree virtuals = BINFO_VIRTUALS (binfo);
- unsigned HOST_WIDE_INT n;
-
- n = skip_rtti_stuff (&virtuals, t);
+ /* See if we can convert to an intermediate virtual base first, and then
+ use the vcall offset located there to finish the conversion. */
+ for (; b; b = BINFO_INHERITANCE_CHAIN (b))
+ {
+ /* If we find the final overrider, then we can stop
+ walking. */
+ if (same_type_p (BINFO_TYPE (b),
+ BINFO_TYPE (TREE_VALUE (overrider))))
+ break;
- while (virtuals)
+ /* 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 (!virtual_base && TREE_VIA_VIRTUAL (b))
+ virtual_base = b;
+ }
+
+ /* Compute the constant adjustment to the `this' pointer. The
+ `this' pointer, when this function is called, will point at BINFO
+ (or one of its primary bases, which are at the same offset). */
+
+ if (virtual_base)
+ /* The `this' pointer needs to be adjusted from the declaration to
+ the nearest virtual base. */
+ delta = size_diffop (BINFO_OFFSET (virtual_base),
+ BINFO_OFFSET (first_defn));
+ else if (lost)
+ /* If the nearest definition is in a lost primary, we don't need an
+ entry in our vtable. Except possibly in a constructor vtable,
+ if we happen to get our primary back. In that case, the offset
+ will be zero, as it will be a primary base. */
+ delta = size_zero_node;
+ else
{
- tree fndecl = TREE_VALUE (virtuals);
- tree pfn = FNADDR_FROM_VTABLE_ENTRY (fndecl);
- tree delta = DELTA_FROM_VTABLE_ENTRY (fndecl);
- fndecl = TREE_OPERAND (pfn, 0);
- if (fndecl)
+ /* The `this' pointer needs to be adjusted from pointing to
+ BINFO to pointing at the base where the final overrider
+ appears. */
+ delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)),
+ BINFO_OFFSET (binfo));
+
+ if (! integer_zerop (delta))
{
- tree base_offset, offset;
- tree context = DECL_CLASS_CONTEXT (fndecl);
- tree vfield = CLASSTYPE_VFIELD (t);
- tree this_offset;
-
- offset = get_class_offset (context, t, binfo, fndecl);
-
- /* Find the right offset for the this pointer based on the
- base class we just found. We have to take into
- consideration the virtual base class pointers that we
- stick in before the virtual function table pointer.
-
- Also, we want just the delta between the most base class
- that we derived this vfield from and us. */
- base_offset = size_binop (PLUS_EXPR,
- get_derived_offset (binfo,
- DECL_CONTEXT (fndecl)),
- BINFO_OFFSET (binfo));
- this_offset = ssize_binop (MINUS_EXPR, offset, base_offset);
-
- if (! tree_int_cst_equal (this_offset, delta))
+ /* We'll need a thunk. But if we have a (perhaps formerly)
+ primary virtual base, we have a vcall slot for this function,
+ so we can use it rather than create a non-virtual thunk. */
+
+ b = get_primary_binfo (first_defn);
+ for (; b; b = get_primary_binfo (b))
{
- /* Make sure we can modify the derived association with immunity. */
- if (binfo == TYPE_BINFO (t))
- {
- /* In this case, it is *type*'s vtable we are modifying.
- We start with the approximation that it's vtable is that
- of the immediate base class. */
- if (! BINFO_NEW_VTABLE_MARKED (binfo))
- build_vtable (TYPE_BINFO (DECL_CONTEXT (vfield)), t);
- }
- else
+ tree f = get_matching_virtual (BINFO_TYPE (b), fn);
+ if (!f)
+ /* b doesn't have this function; no suitable vbase. */
+ break;
+ if (TREE_VIA_VIRTUAL (b))
{
- /* This is our very own copy of `basetype' to play with.
- Later, we will fill in all the virtual functions
- that override the virtual functions in these base classes
- which are not defined by the current type. */
- if (! BINFO_NEW_VTABLE_MARKED (binfo))
- prepare_fresh_vtable (binfo, t);
+ /* Found one; we can treat ourselves as a virtual base. */
+ virtual_base = binfo;
+ delta = size_zero_node;
+ break;
}
-
- modify_vtable_entry (get_vtable_entry_n (BINFO_VIRTUALS (binfo), n),
- build_vtable_entry (this_offset, pfn),
- fndecl);
}
}
- ++n;
- virtuals = TREE_CHAIN (virtuals);
}
-}
-/* Fixup all the delta entries in all the direct vtables that need updating.
- This happens when we have non-overridden virtual functions from a
- virtual base class, that are at a different offset, in the new
- hierarchy, because the layout of the virtual bases has changed. */
+ modify_vtable_entry (t,
+ binfo,
+ TREE_PURPOSE (overrider),
+ delta,
+ virtuals);
-static void
-fixup_vtable_deltas (binfo, init_self, t)
- tree binfo;
- int init_self;
- tree t;
-{
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- int is_not_base_vtable
- = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
- if (! TREE_VIA_VIRTUAL (base_binfo))
- fixup_vtable_deltas (base_binfo, is_not_base_vtable, t);
- }
- /* Should we use something besides CLASSTYPE_VFIELDS? */
- if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
- {
- fixup_vtable_deltas1 (binfo, t);
- }
+ if (virtual_base)
+ BV_USE_VCALL_INDEX_P (*virtuals) = 1;
}
-/* These are the ones that are through virtual base classes. */
+/* Called from modify_all_vtables via dfs_walk. */
-static void
-modify_all_indirect_vtables (binfo, do_self, via_virtual, t, fndecl, pfn)
+static tree
+dfs_modify_vtables (binfo, data)
tree binfo;
- int do_self, via_virtual;
- tree t, fndecl, pfn;
+ void *data;
{
- tree binfos = BINFO_BASETYPES (binfo);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- /* Should we use something besides CLASSTYPE_VFIELDS? */
- if (do_self && via_virtual && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
+ 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))
+ /* Similarly, a base without a vtable needs no modification. */
+ && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
{
- modify_one_vtable (binfo, t, fndecl, pfn);
- }
+ tree t;
+ tree virtuals;
+ tree old_virtuals;
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- int is_not_base_vtable
- = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
- if (TREE_VIA_VIRTUAL (base_binfo))
- {
- via_virtual = 1;
- base_binfo = binfo_member (BINFO_TYPE (base_binfo), CLASSTYPE_VBASECLASSES (t));
- }
- modify_all_indirect_vtables (base_binfo, is_not_base_vtable, via_virtual, t, fndecl, pfn);
- }
-}
+ t = (tree) data;
-static void
-modify_all_vtables (t, fndecl, vfn)
- tree t, fndecl, vfn;
-{
- /* Do these first, so that we will make use of any non-virtual class's
- vtable, over a virtual classes vtable. */
- modify_all_direct_vtables (TYPE_BINFO (t), 1, t, fndecl, vfn);
- if (TYPE_USES_VIRTUAL_BASECLASSES (t))
- modify_all_indirect_vtables (TYPE_BINFO (t), 1, 0, t, fndecl, vfn);
+ make_new_vtable (t, binfo);
+
+ /* Now, go through each of the virtual functions in the virtual
+ function table for BINFO. Find the final overrider, and
+ update the BINFO_VIRTUALS list appropriately. */
+ for (virtuals = BINFO_VIRTUALS (binfo),
+ old_virtuals = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (binfo)));
+ virtuals;
+ virtuals = TREE_CHAIN (virtuals),
+ old_virtuals = TREE_CHAIN (old_virtuals))
+ update_vtable_entry_for_fn (t,
+ binfo,
+ BV_FN (old_virtuals),
+ &virtuals);
+ }
+
+ SET_BINFO_MARKED (binfo);
+
+ return NULL_TREE;
}
-/* Here, we already know that they match in every respect.
- All we have to check is where they had their declarations. */
+/* 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. */
-static int
-strictly_overrides (fndecl1, fndecl2)
- tree fndecl1, fndecl2;
+static tree
+modify_all_vtables (t, vfuns_p, overridden_virtuals)
+ tree t;
+ int *vfuns_p;
+ tree overridden_virtuals;
{
- int distance = get_base_distance (DECL_CLASS_CONTEXT (fndecl2),
- DECL_CLASS_CONTEXT (fndecl1),
- 0, (tree *)0);
- if (distance == -2 || distance > 0)
- return 1;
- return 0;
-}
+ tree binfo = TYPE_BINFO (t);
+ tree *fnsp;
-/* Merge overrides for one vtable.
- If we want to merge in same function, we are fine.
- else
- if one has a DECL_CLASS_CONTEXT that is a parent of the
- other, than choose the more derived one
- else
- potentially ill-formed (see 10.3 [class.virtual])
- we have to check later to see if there was an
- override in this class. If there was ok, if not
- then it is ill-formed. (mrs)
+ /* Update all of the vtables. */
+ dfs_walk (binfo,
+ dfs_modify_vtables,
+ dfs_unmarked_real_bases_queue_p,
+ t);
+ dfs_walk (binfo, dfs_unmark, dfs_marked_real_bases_queue_p, t);
- We take special care to reuse a vtable, if we can. */
+ /* Include overriding functions for secondary vtables in our primary
+ vtable. */
+ for (fnsp = &overridden_virtuals; *fnsp; )
+ {
+ tree fn = TREE_VALUE (*fnsp);
-static void
-override_one_vtable (binfo, old, t)
- tree binfo, old, t;
-{
- tree virtuals = BINFO_VIRTUALS (binfo);
- tree old_virtuals = BINFO_VIRTUALS (old);
- enum { REUSE_NEW, REUSE_OLD, UNDECIDED, NEITHER } choose = UNDECIDED;
-
- /* If we have already committed to modifying it, then don't try and
- reuse another vtable. */
- if (BINFO_NEW_VTABLE_MARKED (binfo))
- choose = NEITHER;
-
- skip_rtti_stuff (&virtuals, t);
- skip_rtti_stuff (&old_virtuals, t);
-
- while (virtuals)
- {
- tree fndecl = TREE_VALUE (virtuals);
- tree old_fndecl = TREE_VALUE (old_virtuals);
- fndecl = FNADDR_FROM_VTABLE_ENTRY (fndecl);
- old_fndecl = FNADDR_FROM_VTABLE_ENTRY (old_fndecl);
- fndecl = TREE_OPERAND (fndecl, 0);
- old_fndecl = TREE_OPERAND (old_fndecl, 0);
- /* First check to see if they are the same. */
- if (DECL_ASSEMBLER_NAME (fndecl) == DECL_ASSEMBLER_NAME (old_fndecl))
- {
- /* No need to do anything. */
- }
- else if (strictly_overrides (fndecl, old_fndecl))
+ if (!BINFO_VIRTUALS (binfo)
+ || !value_member (fn, BINFO_VIRTUALS (binfo)))
{
- if (choose == UNDECIDED)
- choose = REUSE_NEW;
- else if (choose == REUSE_OLD)
- {
- choose = NEITHER;
- if (! BINFO_NEW_VTABLE_MARKED (binfo))
- {
- prepare_fresh_vtable (binfo, t);
- override_one_vtable (binfo, old, t);
- return;
- }
- }
- }
- else if (strictly_overrides (old_fndecl, fndecl))
- {
- if (choose == UNDECIDED)
- choose = REUSE_OLD;
- else if (choose == REUSE_NEW)
- {
- choose = NEITHER;
- if (! BINFO_NEW_VTABLE_MARKED (binfo))
- {
- prepare_fresh_vtable (binfo, t);
- override_one_vtable (binfo, old, t);
- return;
- }
- TREE_VALUE (virtuals) = TREE_VALUE (old_virtuals);
- }
- else if (choose == NEITHER)
- {
- TREE_VALUE (virtuals) = TREE_VALUE (old_virtuals);
- }
+ /* Set the vtable index. */
+ set_vindex (fn, vfuns_p);
+ /* We don't need to convert to a base class when calling
+ this function. */
+ DECL_VIRTUAL_CONTEXT (fn) = t;
+
+ /* We don't need to adjust the `this' pointer when
+ calling this function. */
+ BV_DELTA (*fnsp) = integer_zero_node;
+ BV_VCALL_INDEX (*fnsp) = NULL_TREE;
+
+ /* This is an overridden function not already in our
+ vtable. Keep it. */
+ fnsp = &TREE_CHAIN (*fnsp);
}
else
- {
- choose = NEITHER;
- if (! BINFO_NEW_VTABLE_MARKED (binfo))
- {
- prepare_fresh_vtable (binfo, t);
- override_one_vtable (binfo, old, t);
- return;
- }
- {
- /* This MUST be overridden, or the class is ill-formed. */
- tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0);
- tree vfn;
-
- fndecl = copy_node (fndecl);
- copy_lang_decl (fndecl);
- DECL_NEEDS_FINAL_OVERRIDER_P (fndecl) = 1;
- /* Make sure we search for it later. */
- if (! CLASSTYPE_ABSTRACT_VIRTUALS (t))
- CLASSTYPE_ABSTRACT_VIRTUALS (t) = error_mark_node;
-
- vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fndecl);
- TREE_CONSTANT (vfn) = 1;
-
- /* We can use integer_zero_node, as we will core dump
- if this is used anyway. */
- TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node, vfn);
- }
- }
- virtuals = TREE_CHAIN (virtuals);
- old_virtuals = TREE_CHAIN (old_virtuals);
- }
-
- /* Let's reuse the old vtable. */
- if (choose == REUSE_OLD)
- {
- BINFO_VTABLE (binfo) = BINFO_VTABLE (old);
- BINFO_VIRTUALS (binfo) = BINFO_VIRTUALS (old);
+ /* We've already got an entry for this function. Skip it. */
+ *fnsp = TREE_CHAIN (*fnsp);
}
+
+ return overridden_virtuals;
}
-/* Merge in overrides for virtual bases.
- BINFO is the hierarchy we want to modify, and OLD has the potential
- overrides. */
-
-static void
-merge_overrides (binfo, old, do_self, t)
- tree binfo, old;
- int do_self;
- tree t;
-{
- tree binfos = BINFO_BASETYPES (binfo);
- tree old_binfos = BINFO_BASETYPES (old);
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+/* Here, we already know that they match in every respect.
+ All we have to check is where they had their declarations.
- /* Should we use something besides CLASSTYPE_VFIELDS? */
- if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
- {
- override_one_vtable (binfo, old, t);
- }
+ Return non-zero iff FNDECL1 is declared in a class which has a
+ proper base class containing FNDECL2. We don't care about
+ ambiguity or accessibility. */
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree old_base_binfo = TREE_VEC_ELT (old_binfos, i);
- int is_not_base_vtable
- = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
- if (! TREE_VIA_VIRTUAL (base_binfo))
- merge_overrides (base_binfo, old_base_binfo, is_not_base_vtable, t);
- }
+static int
+strictly_overrides (fndecl1, fndecl2)
+ tree fndecl1, fndecl2;
+{
+ base_kind kind;
+
+ return (lookup_base (DECL_CONTEXT (fndecl1), DECL_CONTEXT (fndecl2),
+ ba_ignore | ba_quiet, &kind)
+ && kind != bk_same_type);
}
-/* Get the base virtual function declarations in T that are either
- overridden or hidden by FNDECL as a list. We set TREE_PURPOSE with
- the overrider/hider. */
+/* Get the base virtual function declarations in T that have the
+ indicated NAME. */
static tree
-get_basefndecls (fndecl, t)
- tree fndecl, t;
+get_basefndecls (name, t)
+ tree name, t;
{
- tree methods = TYPE_METHODS (t);
+ tree methods;
tree base_fndecls = NULL_TREE;
- tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
- int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- while (methods)
- {
- if (TREE_CODE (methods) == FUNCTION_DECL
- && DECL_VINDEX (methods) != NULL_TREE
- && DECL_NAME (fndecl) == DECL_NAME (methods))
- base_fndecls = temp_tree_cons (fndecl, methods, base_fndecls);
+ int n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
+ int i;
- methods = TREE_CHAIN (methods);
- }
+ for (methods = TYPE_METHODS (t); methods; methods = TREE_CHAIN (methods))
+ if (TREE_CODE (methods) == FUNCTION_DECL
+ && DECL_VINDEX (methods) != NULL_TREE
+ && DECL_NAME (methods) == name)
+ base_fndecls = tree_cons (NULL_TREE, methods, base_fndecls);
if (base_fndecls)
return base_fndecls;
for (i = 0; i < n_baseclasses; i++)
{
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree basetype = BINFO_TYPE (base_binfo);
-
- base_fndecls = chainon (get_basefndecls (fndecl, basetype),
+ tree basetype = TYPE_BINFO_BASETYPE (t, i);
+ base_fndecls = chainon (get_basefndecls (name, basetype),
base_fndecls);
}
return base_fndecls;
}
-/* Mark the functions that have been hidden with their overriders.
- Since we start out with all functions already marked with a hider,
- no need to mark functions that are just hidden.
-
- Subroutine of warn_hidden. */
-
-static void
-mark_overriders (fndecl, base_fndecls)
- tree fndecl, base_fndecls;
-{
- for (; base_fndecls; base_fndecls = TREE_CHAIN (base_fndecls))
- {
- if (overrides (fndecl, TREE_VALUE (base_fndecls)))
- TREE_PURPOSE (base_fndecls) = fndecl;
- }
-}
-
/* If this declaration supersedes the declaration of
a method declared virtual in the base class, then
mark this field as being virtual as well. */
@@ -2853,54 +2751,24 @@ static void
check_for_override (decl, ctype)
tree decl, ctype;
{
- tree binfos = BINFO_BASETYPES (TYPE_BINFO (ctype));
- int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- int virtualp = DECL_VIRTUAL_P (decl);
- int found_overriden_fn = 0;
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ /* In [temp.mem] we have:
- for (i = 0; i < n_baselinks; i++)
+ A specialization of a member function template does not
+ override a virtual function from a base class. */
+ return;
+ if ((DECL_DESTRUCTOR_P (decl)
+ || IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)))
+ && look_for_overrides (ctype, decl)
+ && !DECL_STATIC_FUNCTION_P (decl))
{
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (TYPE_VIRTUAL_P (BINFO_TYPE (base_binfo)))
- {
- tree tmp = get_matching_virtual
- (base_binfo, decl,
- DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)));
-
- if (tmp && !found_overriden_fn)
- {
- /* If this function overrides some virtual in some base
- class, then the function itself is also necessarily
- virtual, even if the user didn't explicitly say so. */
- DECL_VIRTUAL_P (decl) = 1;
-
- /* The TMP we really want is the one from the deepest
- baseclass on this path, taking care not to
- duplicate if we have already found it (via another
- path to its virtual baseclass. */
- if (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE)
- {
- cp_error_at ("method `%D' may not be declared static",
- decl);
- cp_error_at ("(since `%D' declared virtual in base class.)",
- tmp);
- break;
- }
- virtualp = 1;
-
- DECL_VINDEX (decl)
- = tree_cons (NULL_TREE, tmp, DECL_VINDEX (decl));
-
- /* We now know that DECL overrides something,
- which is all that is important. But, we must
- continue to iterate through all the base-classes
- in order to allow get_matching_virtual to check for
- various illegal overrides. */
- found_overriden_fn = 1;
- }
- }
+ /* 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;
}
- if (virtualp)
+ if (DECL_VIRTUAL_P (decl))
{
if (DECL_VINDEX (decl) == NULL_TREE)
DECL_VINDEX (decl) = error_mark_node;
@@ -2922,365 +2790,62 @@ warn_hidden (t)
/* We go through each separately named virtual function. */
for (i = 2; i < n_methods && TREE_VEC_ELT (method_vec, i); ++i)
{
- tree fns = TREE_VEC_ELT (method_vec, i);
+ tree fns;
+ tree name;
tree fndecl;
-
- tree base_fndecls = NULL_TREE;
- tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
- int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- /* First see if we have any virtual functions in this batch. */
- for (; fns; fns = OVL_NEXT (fns))
+ tree base_fndecls;
+ 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)));
+ /* 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++)
{
- fndecl = OVL_CURRENT (fns);
- if (DECL_VINDEX (fndecl))
- break;
- }
-
- if (fns == NULL_TREE)
- continue;
-
- /* First we get a list of all possible functions that might be
- hidden from each base class. */
- for (i = 0; i < n_baseclasses; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree basetype = BINFO_TYPE (base_binfo);
-
- base_fndecls = chainon (get_basefndecls (fndecl, basetype),
+ tree basetype = TYPE_BINFO_BASETYPE (t, j);
+ base_fndecls = chainon (get_basefndecls (name, basetype),
base_fndecls);
}
- fns = OVL_NEXT (fns);
-
- /* ...then mark up all the base functions with overriders, preferring
- overriders to hiders. */
- if (base_fndecls)
- for (; fns; fns = OVL_NEXT (fns))
- {
- fndecl = OVL_CURRENT (fns);
- if (DECL_VINDEX (fndecl))
- mark_overriders (fndecl, base_fndecls);
- }
+ /* If there are no functions to hide, continue. */
+ if (!base_fndecls)
+ continue;
- /* Now give a warning for all base functions without overriders,
- as they are hidden. */
- for (; base_fndecls; base_fndecls = TREE_CHAIN (base_fndecls))
+ /* Remove any overridden functions. */
+ for (fns = TREE_VEC_ELT (method_vec, i); fns; fns = OVL_NEXT (fns))
{
- if (! overrides (TREE_PURPOSE (base_fndecls),
- TREE_VALUE (base_fndecls)))
+ fndecl = OVL_CURRENT (fns);
+ if (DECL_VINDEX (fndecl))
{
- /* 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'", TREE_PURPOSE (base_fndecls));
+ tree *prev = &base_fndecls;
+
+ while (*prev)
+ /* If the method from the base class has the same
+ signature as the method from the derived class, it
+ has been overridden. */
+ if (same_signature_p (fndecl, TREE_VALUE (*prev)))
+ *prev = TREE_CHAIN (*prev);
+ else
+ prev = &TREE_CHAIN (*prev);
}
}
- }
-}
-
-/* Generate one vtable for use in constructors or destructors of BASE
- subobjects of COMPLETE_TYPE objects. The vtable belongs to the
- vfield of the VBASEVASE subobject of the VBASE virtual base of
- COMPLETE_TYPE (and BASE). */
-static tree
-finish_one_ctor_vtable (complete_type, base, vbase, vbasebase)
- tree complete_type, base, vbase, vbasebase;
-{
- tree virtuals;
- tree newtable;
- tree newvirtuals;
- tree offset;
- tree newvbase = binfo_member (BINFO_TYPE (vbase),
- CLASSTYPE_VBASECLASSES (complete_type));
-
- newtable = prepare_ctor_vtable (complete_type, base, vbasebase);
- newvirtuals = copy_list (BINFO_VIRTUALS (vbasebase));
-
- virtuals = newvirtuals;
- /* Change the offset entry. First, delta between base an vbase. */
- offset = ssize_binop (MINUS_EXPR, BINFO_OFFSET (newvbase),
- BINFO_OFFSET (base));
- /* Add delta between vbase and vbasebase. */
- offset = ssize_binop (PLUS_EXPR, offset, BINFO_OFFSET (vbasebase));
- offset = ssize_binop (MINUS_EXPR, offset, BINFO_OFFSET (vbase));
- /* Finally, negate. */
- offset = ssize_binop (MINUS_EXPR, integer_zero_node, offset);
- offset = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
- TREE_CONSTANT (offset) = 1;
- TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node, offset);
- virtuals = TREE_CHAIN (virtuals);
-
- /* Skip the typeinfo function. */
- virtuals = TREE_CHAIN (virtuals);
-
- /* Iterate over all methods of this virtual base. */
- for (; virtuals; virtuals = TREE_CHAIN (virtuals))
- {
- tree fndecl = TREE_VALUE (virtuals);
- tree pfn = FNADDR_FROM_VTABLE_ENTRY (fndecl);
- fndecl = TREE_OPERAND (pfn, 0);
- if (fndecl)
+ /* Now give a warning for all base functions without overriders,
+ as they are hidden. */
+ while (base_fndecls)
{
- tree delta, newdelta, binfo_context;
- tree context = DECL_CLASS_CONTEXT (fndecl);
-
- /* If this method is implemented in a base of the vbase, the
- thunk we have is correct. */
- if (DERIVED_FROM_P (context, vbase))
- continue;
-
- binfo_context = binfo_value (context, base);
- if (TREE_VIA_VIRTUAL (binfo_context))
- binfo_context = binfo_member
- (context, CLASSTYPE_VBASECLASSES (complete_type));
- /* This is the delta from a complete C to a B subobject, or
- more generally to the base subobject that implements the
- virtual function for B. BASE already has the offset to
- the complete type. */
- delta = BINFO_OFFSET (binfo_context);
- /* This is the delta from the A to the complete C. */
- newdelta = BINFO_OFFSET (newvbase);
- /* This is the delta from the A to the B subobject. */
- newdelta = size_binop (MINUS_EXPR, newdelta, delta);
- newdelta = ssize_binop (MINUS_EXPR, integer_zero_node,
- newdelta);
-
- modify_vtable_entry (virtuals,
- build_vtable_entry (newdelta, pfn),
- fndecl);
+ /* 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)));
+ base_fndecls = TREE_CHAIN (base_fndecls);
}
}
- DECL_INITIAL (newtable) = build_nt (CONSTRUCTOR, NULL_TREE,
- newvirtuals);
- DECL_CONTEXT (newtable) = NULL_TREE;
- cp_finish_decl (newtable, DECL_INITIAL (newtable), NULL_TREE, 0, 0);
- DECL_CONTEXT (newtable) = complete_type;
- return newtable;
-}
-
-/* Add all vtables into LIST for the VBASEBASE subobject and its bases
- of VBASE virtual BASE of COMPLETE_TYPE for use in BASE
- constructors. DO_SELF indicates whether this is the VBASEBASE that
- has 'primary' vfield. Return the new LIST. */
-
-static tree
-prepend_ctor_vfields_for_vbase (complete_type, base, vbase, vbasebase,
- do_self, list)
- tree complete_type, base, vbase, vbasebase;
- int do_self;
- tree list;
-{
- int i;
- tree vtbl;
- tree bases = BINFO_BASETYPES (vbasebase);
- int vfp = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (vbasebase));
-
- if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (vbasebase)))
- {
- vtbl = finish_one_ctor_vtable (complete_type, base, vbase, vbasebase);
- vtbl = build1 (ADDR_EXPR, vtbl_ptr_type_node, vtbl);
- TREE_READONLY (vtbl) = 1;
- TREE_CONSTANT (vtbl) = 1;
- list = tree_cons (NULL_TREE, vtbl, list);
- }
-
- if (!bases)
- return list;
-
- for (i = 0; i < TREE_VEC_LENGTH (bases); i++)
- {
- tree vbasebase = TREE_VEC_ELT (bases, i);
- if (TREE_VIA_VIRTUAL (vbasebase))
- continue;
- list = prepend_ctor_vfields_for_vbase
- (complete_type, base, vbase, vbasebase, (i != vfp), list);
- }
-
- return list;
-}
-
-/* Iterate over all virtual bases of the BASE subobject of
- COMPLETE_TYPE. This list is given in VBASES. Return the list of
- vtables generated in the process. */
-
-static tree
-finish_ctor_vtables_for_vbases (vbases, base, complete_type)
- tree vbases, base, complete_type;
-{
- tree result = NULL_TREE;
-
- for (; vbases; vbases = TREE_CHAIN (vbases))
- result = prepend_ctor_vfields_for_vbase
- (complete_type, base, vbases, vbases, 1, result);
- return result;
-}
-
-/* Generate special vtables for virtual bases for use inside base
- class ctors and dtors. Inside this function, we assume the
- following scenario:
- class A{virtual void foo();};
- class B:virtual A{int member1;}
- class C:B{int member2;}
-
- BINFO is a base subject (e.g. B) of COMPLETE_TYPE. Returns the list
- of virtual tables. */
-
-static tree
-finish_ctor_vtables_1 (binfo, complete_type)
- tree binfo;
- tree complete_type;
-{
- int i;
- tree binfos;
- tree result = NULL_TREE;
-
- binfos = BINFO_BASETYPES (binfo);
- if (!binfos)
- return result;
-
- /* Iterate over all bases (i.e. B). */
- for (i = 0; i < TREE_VEC_LENGTH (binfos); i++)
- {
- tree base = TREE_VEC_ELT (binfos, i);
- tree vbases = CLASSTYPE_VBASECLASSES (BINFO_TYPE (base));
- if (!vbases)
- /* This base class does not have virtual bases. */
- continue;
- if (TREE_VIA_VIRTUAL (base))
- /* A virtual base class is initialized on in the most-derived
- constructor. */
- continue;
- if (!TYPE_USES_PVBASES (BINFO_TYPE (base)))
- /* Class has no polymorphic vbases. */
- continue;
- /* Prepend vtable list for base class. */
- result = chainon (finish_ctor_vtables_1 (base, complete_type),
- result);
- /* Prepend our own vtable list. */
- result = chainon
- (finish_ctor_vtables_for_vbases (vbases, base, complete_type),
- result);
- }
- return result;
-}
-
-/* Add the vtables of a virtual base BINFO in front of LIST, returning
- the new list. DO_SELF indicates whether we have to return the
- vtable of a vfield borrowed in a derived class. */
-
-static tree
-prepend_vbase_vfields (binfo, do_self, list)
- tree binfo;
- int do_self;
- tree list;
-{
- int i;
- tree vtbl;
- tree bases = BINFO_BASETYPES (binfo);
- int vfp = CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
-
- if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
- {
- vtbl = BINFO_VTABLE (binfo);
- vtbl = build1 (ADDR_EXPR, vtbl_ptr_type_node, vtbl);
- TREE_READONLY (vtbl) = 1;
- TREE_CONSTANT (vtbl) = 1;
- list = tree_cons (NULL_TREE, vtbl, list);
- }
-
- if (!bases)
- return list;
-
- for (i = 0; i < TREE_VEC_LENGTH (bases); i++)
- {
- tree base = TREE_VEC_ELT (bases, i);
- if (TREE_VIA_VIRTUAL (base))
- continue;
- list = prepend_vbase_vfields (base, (i != vfp), list);
- }
-
- return list;
}
-/* Wrapper around finish_ctor_vtables_1. Compute the vtable list for
- type T. */
-
-static void
-finish_ctor_vtables (t)
- tree t;
-{
- tree veclist = NULL_TREE;
- tree decl, type;
- char *name;
- tree vbase;
- int len;
-
- /* This is only good for vtable thunks. */
- my_friendly_assert (flag_vtable_thunks, 990307);
-
- /* Start with the list of most-derived vtables. */
-
- for (vbase = CLASSTYPE_VBASECLASSES (t); vbase;
- vbase = TREE_CHAIN (vbase))
- veclist = prepend_vbase_vfields (vbase, 1, veclist);
-
- /* Compute the list of vtables for the bases. */
- veclist = chainon (veclist, finish_ctor_vtables_1 (TYPE_BINFO (t), t));
-
- /* Finally, we initialize the virtual bases first. */
- for (vbase = CLASSTYPE_VBASECLASSES (t); vbase;
- vbase = TREE_CHAIN (vbase))
- {
- tree vbases = CLASSTYPE_VBASECLASSES (BINFO_TYPE (vbase));
- if (!vbases)
- continue;
- veclist = chainon (veclist,
- finish_ctor_vtables_for_vbases (vbases, vbase, t));
- veclist = chainon (veclist,
- finish_ctor_vtables_1 (vbase, t));
- }
-
- veclist = nreverse (veclist);
-
- /* Generate the name for the vtable list. */
- name = alloca (strlen (VLIST_NAME_FORMAT)
- + TYPE_ASSEMBLER_NAME_LENGTH (t) + 2);
- sprintf (name, VLIST_NAME_FORMAT, TYPE_ASSEMBLER_NAME_STRING (t));
-
- /* Build the type of the list. */
- len = list_length (veclist) - 1;
- if (len < 0)
- /* If this class has virtual bases without virtual methods, make a
- single zero-entry in the array. This avoids zero-sized objects. */
- len++;
- type = build_cplus_array_type (vtbl_ptr_type_node,
- build_index_type (size_int (len)));
-
-
- /* Produce a new decl holding the list. */
- decl = build_lang_decl (VAR_DECL, get_identifier (name), type);
- TREE_STATIC (decl) = 1;
- TREE_READONLY (decl) = 1;
- decl = pushdecl_top_level (decl);
- import_export_vtable (decl, t, 0);
- DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE, veclist);
-
- DECL_ARTIFICIAL (decl) = 1;
- /* This tells finish_file et.al. that this is related to virtual
- tables. There is currently no way to distinguish between vtables
- and vlists, other than the name of the decl. */
- DECL_VIRTUAL_P (decl) = 1;
-
- /* Output the array. */
- cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0);
-
- /* Set the class context after finishing, so that finish thinks this
- is an unrelated global, and then finish_vtable_vardecl knows what
- class this is related to. */
- DECL_CONTEXT (decl) = t;
-}
-
/* Check for things that are invalid. There are probably plenty of other
things we should check for also. */
@@ -3289,6 +2854,7 @@ finish_struct_anon (t)
tree t;
{
tree field;
+
for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
{
if (TREE_STATIC (field))
@@ -3297,75 +2863,82 @@ finish_struct_anon (t)
continue;
if (DECL_NAME (field) == NULL_TREE
- && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
+ && ANON_AGGR_TYPE_P (TREE_TYPE (field)))
{
- tree* uelt = &TYPE_FIELDS (TREE_TYPE (field));
- for (; *uelt; uelt = &TREE_CHAIN (*uelt))
+ tree elt = TYPE_FIELDS (TREE_TYPE (field));
+ for (; elt; elt = TREE_CHAIN (elt))
{
- if (DECL_ARTIFICIAL (*uelt))
+ /* We're generally only interested in entities the user
+ declared, but we also find nested classes by noticing
+ the TYPE_DECL that we create implicitly. You're
+ allowed to put one anonymous union inside another,
+ though, so we explicitly tolerate that. We use
+ TYPE_ANONYMOUS_P rather than ANON_AGGR_TYPE_P so that
+ we also allow unnamed types used for defining fields. */
+ if (DECL_ARTIFICIAL (elt)
+ && (!DECL_IMPLICIT_TYPEDEF_P (elt)
+ || TYPE_ANONYMOUS_P (TREE_TYPE (elt))))
continue;
- if (DECL_NAME (*uelt) == constructor_name (t))
- cp_pedwarn_at ("ANSI C++ forbids member `%D' with same name as enclosing class",
- *uelt);
+ if (DECL_NAME (elt) == constructor_name (t))
+ cp_pedwarn_at ("ISO C++ forbids member `%D' with same name as enclosing class",
+ elt);
- if (TREE_CODE (*uelt) != FIELD_DECL)
+ if (TREE_CODE (elt) != FIELD_DECL)
{
cp_pedwarn_at ("`%#D' invalid; an anonymous union can only have non-static data members",
- *uelt);
+ elt);
continue;
}
- if (TREE_PRIVATE (*uelt))
+ if (TREE_PRIVATE (elt))
cp_pedwarn_at ("private member `%#D' in anonymous union",
- *uelt);
- else if (TREE_PROTECTED (*uelt))
+ elt);
+ else if (TREE_PROTECTED (elt))
cp_pedwarn_at ("protected member `%#D' in anonymous union",
- *uelt);
+ elt);
- TREE_PRIVATE (*uelt) = TREE_PRIVATE (field);
- TREE_PROTECTED (*uelt) = TREE_PROTECTED (field);
+ TREE_PRIVATE (elt) = TREE_PRIVATE (field);
+ TREE_PROTECTED (elt) = TREE_PROTECTED (field);
}
}
}
}
-extern int interface_only, interface_unknown;
-
/* Create default constructors, assignment operators, and so forth for
the type indicated by T, if they are needed.
CANT_HAVE_DEFAULT_CTOR, CANT_HAVE_CONST_CTOR, and
- CANT_HAVE_ASSIGNMENT are nonzero if, for whatever reason, the class
- cannot have a default constructor, copy constructor taking a const
- reference argument, or an assignment operator, respectively. If a
- virtual destructor is created, its DECL is returned; otherwise the
- return value is NULL_TREE. */
+ CANT_HAVE_CONST_ASSIGNMENT are nonzero if, for whatever reason, the
+ class cannot have a default constructor, copy constructor taking a
+ const reference argument, or an assignment operator taking a const
+ reference, respectively. If a virtual destructor is created, its
+ DECL is returned; otherwise the return value is NULL_TREE. */
static tree
add_implicitly_declared_members (t, cant_have_default_ctor,
cant_have_const_cctor,
- cant_have_assignment)
+ cant_have_const_assignment)
tree t;
int cant_have_default_ctor;
int cant_have_const_cctor;
- int cant_have_assignment;
+ int cant_have_const_assignment;
{
tree default_fn;
tree implicit_fns = NULL_TREE;
- tree name = TYPE_IDENTIFIER (t);
tree virtual_dtor = NULL_TREE;
tree *f;
+ ++adding_implicit_members;
+
/* Destructor. */
- if (TYPE_NEEDS_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t)
- && !IS_SIGNATURE (t))
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t))
{
- default_fn = cons_up_default_function (t, name, 0);
+ default_fn = implicitly_declare_fn (sfk_destructor, t, /*const_p=*/0);
check_for_override (default_fn, t);
/* If we couldn't make it work, then pretend we didn't need it. */
if (default_fn == void_type_node)
- TYPE_NEEDS_DESTRUCTOR (t) = 0;
+ TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = 0;
else
{
TREE_CHAIN (default_fn) = implicit_fns;
@@ -3375,33 +2948,36 @@ add_implicitly_declared_members (t, cant_have_default_ctor,
virtual_dtor = default_fn;
}
}
- TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t);
+ else
+ /* Any non-implicit destructor is non-trivial. */
+ TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t);
/* Default constructor. */
- if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor
- && ! IS_SIGNATURE (t))
+ if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor)
{
- default_fn = cons_up_default_function (t, name, 2);
+ default_fn = implicitly_declare_fn (sfk_constructor, t, /*const_p=*/0);
TREE_CHAIN (default_fn) = implicit_fns;
implicit_fns = default_fn;
}
/* Copy constructor. */
- if (! TYPE_HAS_INIT_REF (t) && ! IS_SIGNATURE (t) && ! TYPE_FOR_JAVA (t))
+ 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 = cons_up_default_function (t, name,
- 3 + cant_have_const_cctor);
+ 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;
}
/* Assignment operator. */
- if (! TYPE_HAS_ASSIGN_REF (t) && ! IS_SIGNATURE (t) && ! TYPE_FOR_JAVA (t))
+ if (! TYPE_HAS_ASSIGN_REF (t) && ! TYPE_FOR_JAVA (t))
{
- default_fn = cons_up_default_function (t, name,
- 5 + cant_have_assignment);
+ 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;
}
@@ -3409,234 +2985,340 @@ add_implicitly_declared_members (t, cant_have_default_ctor,
/* 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, 0, *f);
+ add_method (t, *f, /*error_p=*/0);
*f = TYPE_METHODS (t);
TYPE_METHODS (t) = implicit_fns;
+ --adding_implicit_members;
+
return virtual_dtor;
}
-/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
- (or C++ class declaration).
-
- For C++, we must handle the building of derived classes.
- Also, C++ allows static class members. The way that this is
- handled is to keep the field name where it is (as the DECL_NAME
- of the field), and place the overloaded decl in the DECL_FIELD_BITPOS
- of the field. layout_record and layout_union will know about this.
-
- More C++ hair: inline functions have text in their
- DECL_PENDING_INLINE_INFO nodes which must somehow be parsed into
- meaningful tree structure. After the struct has been laid out, set
- things up so that this can happen.
-
- And still more: virtual functions. In the case of single inheritance,
- when a new virtual function is seen which redefines a virtual function
- from the base class, the new virtual function is placed into
- the virtual function table at exactly the same address that
- it had in the base class. When this is extended to multiple
- inheritance, the same thing happens, except that multiple virtual
- function tables must be maintained. The first virtual function
- table is treated in exactly the same way as in the case of single
- inheritance. Additional virtual function tables have different
- DELTAs, which tell how to adjust `this' to point to the right thing.
-
- ATTRIBUTES is the set of decl attributes to be applied, if any. */
-
-void
-finish_struct_1 (t, warn_anon)
- tree t;
- int warn_anon;
-{
- int old;
- enum tree_code code = TREE_CODE (t);
- tree fields = TYPE_FIELDS (t);
- tree x, last_x, method_vec;
- int has_virtual;
- int max_has_virtual;
- tree pending_virtuals = NULL_TREE;
- tree pending_hard_virtuals = NULL_TREE;
- tree abstract_virtuals = NULL_TREE;
- tree vfield;
- tree vfields;
- tree virtual_dtor;
- int cant_have_default_ctor;
- int cant_have_const_ctor;
- int no_const_asn_ref;
- int has_mutable = 0;
-
- /* The index of the first base class which has virtual
- functions. Only applied to non-virtual baseclasses. */
- int first_vfn_base_index;
+/* Subroutine of finish_struct_1. Recursively count the number of fields
+ in TYPE, including anonymous union members. */
- int n_baseclasses;
- int any_default_members = 0;
- int const_sans_init = 0;
- int ref_sans_init = 0;
- tree access_decls = NULL_TREE;
- int aggregate = 1;
- int empty = 1;
- int has_pointers = 0;
- tree inline_friends;
+static int
+count_fields (fields)
+ tree fields;
+{
+ tree x;
+ int n_fields = 0;
+ for (x = fields; x; x = TREE_CHAIN (x))
+ {
+ if (TREE_CODE (x) == FIELD_DECL && ANON_AGGR_TYPE_P (TREE_TYPE (x)))
+ n_fields += count_fields (TYPE_FIELDS (TREE_TYPE (x)));
+ else
+ n_fields += 1;
+ }
+ return n_fields;
+}
- if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
- pedwarn ("anonymous class type not used to declare any objects");
+/* Subroutine of finish_struct_1. Recursively add all the fields in the
+ TREE_LIST FIELDS to the TREE_VEC FIELD_VEC, starting at offset IDX. */
- if (TYPE_SIZE (t))
+static int
+add_fields_to_vec (fields, field_vec, idx)
+ tree fields, field_vec;
+ int idx;
+{
+ tree x;
+ for (x = fields; x; x = TREE_CHAIN (x))
{
- if (IS_AGGR_TYPE (t))
- cp_error ("redefinition of `%#T'", t);
+ if (TREE_CODE (x) == FIELD_DECL && ANON_AGGR_TYPE_P (TREE_TYPE (x)))
+ idx = add_fields_to_vec (TYPE_FIELDS (TREE_TYPE (x)), field_vec, idx);
else
- my_friendly_abort (172);
- popclass ();
- return;
+ TREE_VEC_ELT (field_vec, idx++) = x;
}
+ return idx;
+}
- 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. */
+/* FIELD is a bit-field. We are finishing the processing for its
+ enclosing type. Issue any appropriate messages and set appropriate
+ flags. */
- TYPE_SIZE (t) = NULL_TREE;
- CLASSTYPE_GOT_SEMICOLON (t) = 0;
+static void
+check_bitfield_decl (field)
+ tree field;
+{
+ tree type = TREE_TYPE (field);
+ tree w = NULL_TREE;
-#if 0
- /* This is in general too late to do this. I moved the main case up to
- left_curly, what else needs to move? */
- if (! IS_SIGNATURE (t))
+ /* Detect invalid bit-field type. */
+ if (DECL_INITIAL (field)
+ && ! INTEGRAL_TYPE_P (TREE_TYPE (field)))
{
- my_friendly_assert (CLASSTYPE_INTERFACE_ONLY (t) == interface_only, 999);
- my_friendly_assert (CLASSTYPE_INTERFACE_KNOWN (t) == ! interface_unknown, 999);
+ cp_error_at ("bit-field `%#D' with non-integral type", field);
+ w = error_mark_node;
}
-#endif
- old = suspend_momentary ();
+ /* Detect and ignore out of range field width. */
+ if (DECL_INITIAL (field))
+ {
+ w = DECL_INITIAL (field);
- /* Install struct as DECL_FIELD_CONTEXT of each field decl.
- Also process specified field sizes.
- Set DECL_FIELD_SIZE to the specified size, or 0 if none specified.
- The specified size is found in the DECL_INITIAL.
- Store 0 there, except for ": 0" fields (so we can find them
- and delete them, below). */
+ /* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs. */
+ STRIP_NOPS (w);
- if (TYPE_BINFO_BASETYPES (t))
- n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (t));
- else
- n_baseclasses = 0;
+ /* detect invalid field size. */
+ if (TREE_CODE (w) == CONST_DECL)
+ w = DECL_INITIAL (w);
+ else
+ w = decl_constant_value (w);
+
+ if (TREE_CODE (w) != INTEGER_CST)
+ {
+ cp_error_at ("bit-field `%D' width not an integer constant",
+ field);
+ w = error_mark_node;
+ }
+ else if (tree_int_cst_sgn (w) < 0)
+ {
+ cp_error_at ("negative width in bit-field `%D'", field);
+ w = error_mark_node;
+ }
+ else if (integer_zerop (w) && DECL_NAME (field) != 0)
+ {
+ cp_error_at ("zero width for bit-field `%D'", field);
+ w = error_mark_node;
+ }
+ else if (compare_tree_int (w, TYPE_PRECISION (type)) > 0
+ && TREE_CODE (type) != ENUMERAL_TYPE
+ && TREE_CODE (type) != BOOLEAN_TYPE)
+ cp_warning_at ("width of `%D' exceeds its type", field);
+ else if (TREE_CODE (type) == ENUMERAL_TYPE
+ && (0 > compare_tree_int (w,
+ min_precision (TYPE_MIN_VALUE (type),
+ TREE_UNSIGNED (type)))
+ || 0 > compare_tree_int (w,
+ min_precision
+ (TYPE_MAX_VALUE (type),
+ TREE_UNSIGNED (type)))))
+ cp_warning_at ("`%D' is too small to hold all values of `%#T'",
+ field, type);
+ }
+
+ /* Remove the bit-field width indicator so that the rest of the
+ compiler does not treat that value as an initializer. */
+ DECL_INITIAL (field) = NULL_TREE;
- if (n_baseclasses > 0)
+ if (w != error_mark_node)
{
- struct base_info base_info;
+ DECL_SIZE (field) = convert (bitsizetype, w);
+ DECL_BIT_FIELD (field) = 1;
- first_vfn_base_index = finish_base_struct (t, &base_info);
- /* Remember where we got our vfield from. */
- CLASSTYPE_VFIELD_PARENT (t) = first_vfn_base_index;
- has_virtual = base_info.has_virtual;
- max_has_virtual = base_info.max_has_virtual;
- vfield = base_info.vfield;
- vfields = base_info.vfields;
- CLASSTYPE_RTTI (t) = base_info.rtti;
- cant_have_default_ctor = base_info.cant_have_default_ctor;
- cant_have_const_ctor = base_info.cant_have_const_ctor;
- no_const_asn_ref = base_info.no_const_asn_ref;
- aggregate = 0;
+ if (integer_zerop (w))
+ {
+#ifdef EMPTY_FIELD_BOUNDARY
+ DECL_ALIGN (field) = MAX (DECL_ALIGN (field),
+ EMPTY_FIELD_BOUNDARY);
+#endif
+#ifdef PCC_BITFIELD_TYPE_MATTERS
+ if (PCC_BITFIELD_TYPE_MATTERS)
+ {
+ DECL_ALIGN (field) = MAX (DECL_ALIGN (field),
+ TYPE_ALIGN (type));
+ DECL_USER_ALIGN (field) |= TYPE_USER_ALIGN (type);
+ }
+#endif
+ }
}
else
{
- first_vfn_base_index = -1;
- has_virtual = 0;
- max_has_virtual = has_virtual;
- vfield = NULL_TREE;
- vfields = NULL_TREE;
- CLASSTYPE_RTTI (t) = NULL_TREE;
- cant_have_default_ctor = 0;
- cant_have_const_ctor = 0;
- no_const_asn_ref = 0;
+ /* Non-bit-fields are aligned for their type. */
+ DECL_BIT_FIELD (field) = 0;
+ CLEAR_DECL_C_BIT_FIELD (field);
+ DECL_ALIGN (field) = MAX (DECL_ALIGN (field), TYPE_ALIGN (type));
+ DECL_USER_ALIGN (field) |= TYPE_USER_ALIGN (type);
}
+}
-#if 0
- /* Both of these should be done before now. */
- if (write_virtuals == 3 && CLASSTYPE_INTERFACE_KNOWN (t)
- && ! IS_SIGNATURE (t))
+/* FIELD is a non bit-field. We are finishing the processing for its
+ enclosing type T. Issue any appropriate messages and set appropriate
+ flags. */
+
+static void
+check_field_decl (field, t, cant_have_const_ctor,
+ cant_have_default_ctor, no_const_asn_ref,
+ any_default_members)
+ tree field;
+ tree t;
+ int *cant_have_const_ctor;
+ int *cant_have_default_ctor;
+ int *no_const_asn_ref;
+ int *any_default_members;
+{
+ tree type = strip_array_types (TREE_TYPE (field));
+
+ /* An anonymous union cannot contain any fields which would change
+ the settings of CANT_HAVE_CONST_CTOR and friends. */
+ if (ANON_UNION_TYPE_P (type))
+ ;
+ /* And, we don't set TYPE_HAS_CONST_INIT_REF, etc., for anonymous
+ structs. So, we recurse through their fields here. */
+ else if (ANON_AGGR_TYPE_P (type))
{
- my_friendly_assert (CLASSTYPE_INTERFACE_ONLY (t) == interface_only, 999);
- my_friendly_assert (CLASSTYPE_VTABLE_NEEDS_WRITING (t) == ! interface_only, 999);
+ tree fields;
+
+ for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
+ if (TREE_CODE (fields) == FIELD_DECL && !DECL_C_BIT_FIELD (field))
+ check_field_decl (fields, t, cant_have_const_ctor,
+ cant_have_default_ctor, no_const_asn_ref,
+ any_default_members);
}
-#endif
+ /* Check members with class type for constructors, destructors,
+ etc. */
+ else if (CLASS_TYPE_P (type))
+ {
+ /* Never let anything with uninheritable virtuals
+ make it through without complaint. */
+ abstract_virtuals_error (field, type);
+
+ if (TREE_CODE (t) == UNION_TYPE)
+ {
+ if (TYPE_NEEDS_CONSTRUCTING (type))
+ cp_error_at ("member `%#D' with constructor not allowed in union",
+ field);
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+ cp_error_at ("member `%#D' with destructor not allowed in union",
+ field);
+ if (TYPE_HAS_COMPLEX_ASSIGN_REF (type))
+ cp_error_at ("member `%#D' with copy assignment operator not allowed in union",
+ field);
+ }
+ else
+ {
+ TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (type);
+ TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
+ |= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type);
+ TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (type);
+ TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (type);
+ }
- /* The three of these are approximations which may later be
- modified. Needed at this point to make add_virtual_function
- and modify_vtable_entries work. */
- CLASSTYPE_VFIELDS (t) = vfields;
- CLASSTYPE_VFIELD (t) = vfield;
+ if (!TYPE_HAS_CONST_INIT_REF (type))
+ *cant_have_const_ctor = 1;
- for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
+ if (!TYPE_HAS_CONST_ASSIGN_REF (type))
+ *no_const_asn_ref = 1;
+
+ if (TYPE_HAS_CONSTRUCTOR (type)
+ && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
+ *cant_have_default_ctor = 1;
+ }
+ if (DECL_INITIAL (field) != NULL_TREE)
{
- GNU_xref_member (current_class_name, x);
+ /* `build_class_init_list' does not recognize
+ non-FIELD_DECLs. */
+ if (TREE_CODE (t) == UNION_TYPE && any_default_members != 0)
+ cp_error_at ("multiple fields in union `%T' initialized");
+ *any_default_members = 1;
+ }
- /* If this was an evil function, don't keep it in class. */
- if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x)))
- continue;
+ /* Non-bit-fields are aligned for their type, except packed fields
+ which require only BITS_PER_UNIT alignment. */
+ DECL_ALIGN (field) = MAX (DECL_ALIGN (field),
+ (DECL_PACKED (field)
+ ? BITS_PER_UNIT
+ : TYPE_ALIGN (TREE_TYPE (field))));
+ if (! DECL_PACKED (field))
+ DECL_USER_ALIGN (field) |= TYPE_USER_ALIGN (TREE_TYPE (field));
+}
- /* Do both of these, even though they're in the same union;
- if the insn `r' member and the size `i' member are
- different sizes, as on the alpha, the larger of the two
- will end up with garbage in it. */
- DECL_SAVED_INSNS (x) = NULL_RTX;
- DECL_FIELD_SIZE (x) = 0;
+/* Check the data members (both static and non-static), class-scoped
+ typedefs, etc., appearing in the declaration of T. Issue
+ appropriate diagnostics. Sets ACCESS_DECLS to a list (in
+ declaration order) of access declarations; each TREE_VALUE in this
+ list is a USING_DECL.
- check_for_override (x, t);
- if (DECL_ABSTRACT_VIRTUAL_P (x) && ! DECL_VINDEX (x))
- cp_error_at ("initializer specified for non-virtual method `%D'", x);
+ In addition, set the following flags:
- /* The name of the field is the original field name
- Save this in auxiliary field for later overloading. */
- if (DECL_VINDEX (x))
- {
- add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
- &has_virtual, x, t);
- if (DECL_ABSTRACT_VIRTUAL_P (x))
- abstract_virtuals = tree_cons (NULL_TREE, x, abstract_virtuals);
-#if 0
- /* XXX Why did I comment this out? (jason) */
- else
- TREE_USED (x) = 1;
-#endif
- }
- }
+ EMPTY_P
+ The class is empty, i.e., contains no non-static data members.
- if (n_baseclasses)
- fields = chainon (build_vbase_pointer_fields (t), fields);
+ CANT_HAVE_DEFAULT_CTOR_P
+ This class cannot have an implicitly generated default
+ constructor.
- last_x = NULL_TREE;
- for (x = fields; x; x = TREE_CHAIN (x))
+ CANT_HAVE_CONST_CTOR_P
+ This class cannot have an implicitly generated copy constructor
+ taking a const reference.
+
+ CANT_HAVE_CONST_ASN_REF
+ This class cannot have an implicitly generated assignment
+ operator taking a const reference.
+
+ All of these flags should be initialized before calling this
+ function.
+
+ Returns a pointer to the end of the TYPE_FIELDs chain; additional
+ fields can be added by adding to this chain. */
+
+static void
+check_field_decls (t, access_decls, empty_p,
+ cant_have_default_ctor_p, cant_have_const_ctor_p,
+ no_const_asn_ref_p)
+ tree t;
+ tree *access_decls;
+ int *empty_p;
+ int *cant_have_default_ctor_p;
+ int *cant_have_const_ctor_p;
+ int *no_const_asn_ref_p;
+{
+ tree *field;
+ tree *next;
+ int has_pointers;
+ int any_default_members;
+
+ /* First, delete any duplicate fields. */
+ delete_duplicate_fields (TYPE_FIELDS (t));
+
+ /* Assume there are no access declarations. */
+ *access_decls = NULL_TREE;
+ /* Assume this class has no pointer members. */
+ has_pointers = 0;
+ /* Assume none of the members of this class have default
+ initializations. */
+ any_default_members = 0;
+
+ for (field = &TYPE_FIELDS (t); *field; field = next)
{
+ 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)
{
DECL_PACKED (x) |= TYPE_PACKED (t);
if (DECL_C_BIT_FIELD (x) && integer_zerop (DECL_INITIAL (x)))
- /* A zero-width bitfield doesn't do the trick. */;
+ /* We don't treat zero-width bitfields as making a class
+ non-empty. */
+ ;
else
- empty = 0;
+ {
+ /* The class is non-empty. */
+ *empty_p = 0;
+ /* The class is not even nearly empty. */
+ CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
+ }
}
if (TREE_CODE (x) == USING_DECL)
{
- /* Save access declarations for later. */
- if (last_x)
- TREE_CHAIN (last_x) = TREE_CHAIN (x);
- else
- fields = TREE_CHAIN (x);
-
- access_decls = scratch_tree_cons (NULL_TREE, x, access_decls);
+ /* Prune the access declaration from the list of fields. */
+ *field = TREE_CHAIN (x);
+
+ /* Save the access declarations for our caller. */
+ *access_decls = tree_cons (NULL_TREE, x, *access_decls);
+
+ /* Since we've reset *FIELD there's no reason to skip to the
+ next field. */
+ next = field;
continue;
}
- last_x = x;
-
if (TREE_CODE (x) == TYPE_DECL
|| TREE_CODE (x) == TEMPLATE_DECL)
continue;
@@ -3644,7 +3326,7 @@ finish_struct_1 (t, warn_anon)
/* If we've gotten this far, it's a data member, possibly static,
or an enumerator. */
- DECL_FIELD_CONTEXT (x) = t;
+ DECL_CONTEXT (x) = t;
/* ``A local class cannot have static data members.'' ARM 9.4 */
if (current_function_decl && TREE_STATIC (x))
@@ -3652,34 +3334,29 @@ finish_struct_1 (t, warn_anon)
/* Perform error checking that did not get done in
grokdeclarator. */
- if (TREE_CODE (TREE_TYPE (x)) == FUNCTION_TYPE)
+ if (TREE_CODE (type) == FUNCTION_TYPE)
{
cp_error_at ("field `%D' invalidly declared function type",
x);
- TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x));
+ type = build_pointer_type (type);
+ TREE_TYPE (x) = type;
}
- else if (TREE_CODE (TREE_TYPE (x)) == METHOD_TYPE)
+ else if (TREE_CODE (type) == METHOD_TYPE)
{
cp_error_at ("field `%D' invalidly declared method type", x);
- TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x));
+ type = build_pointer_type (type);
+ TREE_TYPE (x) = type;
}
- else if (TREE_CODE (TREE_TYPE (x)) == OFFSET_TYPE)
+ else if (TREE_CODE (type) == OFFSET_TYPE)
{
cp_error_at ("field `%D' invalidly declared offset type", x);
- TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x));
+ type = build_pointer_type (type);
+ TREE_TYPE (x) = type;
}
-#if 0
- if (DECL_NAME (x) == constructor_name (t))
- cant_have_default_ctor = 1;
-#endif
-
- if (TREE_TYPE (x) == error_mark_node)
+ if (type == error_mark_node)
continue;
- DECL_SAVED_INSNS (x) = NULL_RTX;
- DECL_FIELD_SIZE (x) = 0;
-
/* When this goes into scope, it will be a non-local reference. */
DECL_NONLOCAL (x) = 1;
@@ -3698,316 +3375,1046 @@ finish_struct_1 (t, warn_anon)
/* Now it can only be a FIELD_DECL. */
if (TREE_PRIVATE (x) || TREE_PROTECTED (x))
- aggregate = 0;
+ CLASSTYPE_NON_AGGREGATE (t) = 1;
/* If this is of reference type, check if it needs an init.
Also do a little ANSI jig if necessary. */
- if (TREE_CODE (TREE_TYPE (x)) == REFERENCE_TYPE)
+ if (TREE_CODE (type) == REFERENCE_TYPE)
{
+ CLASSTYPE_NON_POD_P (t) = 1;
if (DECL_INITIAL (x) == NULL_TREE)
- ref_sans_init = 1;
+ CLASSTYPE_REF_FIELDS_NEED_INIT (t) = 1;
/* ARM $12.6.2: [A member initializer list] (or, for an
aggregate, initialization by a brace-enclosed list) is the
only way to initialize nonstatic const and reference
members. */
- cant_have_default_ctor = 1;
+ *cant_have_default_ctor_p = 1;
TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings)
- {
- if (DECL_NAME (x))
- cp_warning_at ("non-static reference `%#D' in class without a constructor", x);
- else
- cp_warning_at ("non-static reference in class without a constructor", x);
- }
+ cp_warning_at ("non-static reference `%#D' in class without a constructor", x);
}
- if (TREE_CODE (TREE_TYPE (x)) == POINTER_TYPE)
+ type = strip_array_types (type);
+
+ if (TREE_CODE (type) == POINTER_TYPE)
has_pointers = 1;
- if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE_P (TREE_TYPE (x)))
- has_mutable = 1;
+ if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE_P (type))
+ CLASSTYPE_HAS_MUTABLE (t) = 1;
+
+ if (! pod_type_p (type))
+ /* DR 148 now allows pointers to members (which are POD themselves),
+ to be allowed in POD structs. */
+ CLASSTYPE_NON_POD_P (t) = 1;
/* If any field is const, the structure type is pseudo-const. */
- if (CP_TYPE_CONST_P (TREE_TYPE (x)))
+ if (CP_TYPE_CONST_P (type))
{
C_TYPE_FIELDS_READONLY (t) = 1;
if (DECL_INITIAL (x) == NULL_TREE)
- const_sans_init = 1;
+ CLASSTYPE_READONLY_FIELDS_NEED_INIT (t) = 1;
/* ARM $12.6.2: [A member initializer list] (or, for an
aggregate, initialization by a brace-enclosed list) is the
only way to initialize nonstatic const and reference
members. */
- cant_have_default_ctor = 1;
+ *cant_have_default_ctor_p = 1;
TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
- if (! TYPE_HAS_CONSTRUCTOR (t) && !IS_SIGNATURE (t)
- && extra_warnings)
- {
- if (DECL_NAME (x))
- cp_warning_at ("non-static const member `%#D' in class without a constructor", x);
- else
- cp_warning_at ("non-static const member in class without a constructor", x);
- }
+ if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings)
+ cp_warning_at ("non-static const member `%#D' in class without a constructor", x);
}
- else
+ /* A field that is pseudo-const makes the structure likewise. */
+ else if (IS_AGGR_TYPE (type))
{
- /* A field that is pseudo-const makes the structure
- likewise. */
- tree t1 = TREE_TYPE (x);
- while (TREE_CODE (t1) == ARRAY_TYPE)
- t1 = TREE_TYPE (t1);
- if (IS_AGGR_TYPE (t1))
- {
- if (C_TYPE_FIELDS_READONLY (t1))
- C_TYPE_FIELDS_READONLY (t) = 1;
- if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (t1))
- const_sans_init = 1;
- }
+ C_TYPE_FIELDS_READONLY (t) |= C_TYPE_FIELDS_READONLY (type);
+ CLASSTYPE_READONLY_FIELDS_NEED_INIT (t)
+ |= CLASSTYPE_READONLY_FIELDS_NEED_INIT (type);
}
+ /* Core issue 80: A nonstatic data member is required to have a
+ different name from the class iff the class has a
+ user-defined constructor. */
+ if (DECL_NAME (x) == constructor_name (t)
+ && TYPE_HAS_CONSTRUCTOR (t))
+ cp_pedwarn_at ("field `%#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);
+ else
+ check_field_decl (x, t,
+ cant_have_const_ctor_p,
+ cant_have_default_ctor_p,
+ no_const_asn_ref_p,
+ &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)))
+ {
+ warning ("`%#T' has pointer data members", t);
+
+ if (! TYPE_HAS_INIT_REF (t))
{
- /* Invalid bit-field size done by grokfield. */
- /* Detect invalid bit-field type. */
- if (DECL_INITIAL (x)
- && ! INTEGRAL_TYPE_P (TREE_TYPE (x)))
- {
- cp_error_at ("bit-field `%#D' with non-integral type", x);
- DECL_INITIAL (x) = NULL;
- }
+ warning (" but does not override `%T(const %T&)'", t, t);
+ if (! TYPE_HAS_ASSIGN_REF (t))
+ warning (" or `operator=(const %T&)'", t);
+ }
+ else if (! TYPE_HAS_ASSIGN_REF (t))
+ warning (" but does not override `operator=(const %T&)'", t);
+ }
- /* Detect and ignore out of range field width. */
- if (DECL_INITIAL (x))
- {
- tree w = DECL_INITIAL (x);
- register int width = 0;
- /* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs. */
- STRIP_NOPS (w);
+ /* Check anonymous struct/anonymous union fields. */
+ finish_struct_anon (t);
- /* detect invalid field size. */
- if (TREE_CODE (w) == CONST_DECL)
- w = DECL_INITIAL (w);
- else if (TREE_READONLY_DECL_P (w))
- w = decl_constant_value (w);
+ /* We've built up the list of access declarations in reverse order.
+ Fix that now. */
+ *access_decls = nreverse (*access_decls);
+}
- if (TREE_CODE (w) != INTEGER_CST)
- {
- cp_error_at ("bit-field `%D' width not an integer constant",
- x);
- DECL_INITIAL (x) = NULL_TREE;
- }
- else if (width = TREE_INT_CST_LOW (w),
- width < 0)
- {
- DECL_INITIAL (x) = NULL;
- cp_error_at ("negative width in bit-field `%D'", x);
- }
- else if (width == 0 && DECL_NAME (x) != 0)
- {
- DECL_INITIAL (x) = NULL;
- cp_error_at ("zero width for bit-field `%D'", x);
- }
- else if (width
- > TYPE_PRECISION (long_long_unsigned_type_node))
- {
- /* The backend will dump if you try to use something
- too big; avoid that. */
- DECL_INITIAL (x) = NULL;
- sorry ("bit-fields larger than %d bits",
- TYPE_PRECISION (long_long_unsigned_type_node));
- cp_error_at (" in declaration of `%D'", x);
- }
- else if (width > TYPE_PRECISION (TREE_TYPE (x))
- && TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE
- && TREE_CODE (TREE_TYPE (x)) != BOOLEAN_TYPE)
- {
- cp_warning_at ("width of `%D' exceeds its type", x);
- }
- else if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
- && ((min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)),
- TREE_UNSIGNED (TREE_TYPE (x))) > width)
- || (min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)),
- TREE_UNSIGNED (TREE_TYPE (x))) > width)))
- {
- cp_warning_at ("`%D' is too small to hold all values of `%#T'",
- x, TREE_TYPE (x));
- }
+/* If TYPE is an empty class type, records its OFFSET in the table of
+ OFFSETS. */
- if (DECL_INITIAL (x))
- {
- DECL_INITIAL (x) = NULL_TREE;
- DECL_FIELD_SIZE (x) = width;
- DECL_BIT_FIELD (x) = 1;
+static int
+record_subobject_offset (type, offset, offsets)
+ tree type;
+ tree offset;
+ splay_tree offsets;
+{
+ splay_tree_node n;
- if (width == 0)
- {
-#ifdef EMPTY_FIELD_BOUNDARY
- DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
- EMPTY_FIELD_BOUNDARY);
-#endif
-#ifdef PCC_BITFIELD_TYPE_MATTERS
- if (PCC_BITFIELD_TYPE_MATTERS)
- DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
- TYPE_ALIGN (TREE_TYPE (x)));
-#endif
- }
- }
- }
- else
- /* Non-bit-fields are aligned for their type. */
- DECL_ALIGN (x) = MAX (DECL_ALIGN (x), TYPE_ALIGN (TREE_TYPE (x)));
+ if (!is_empty_class (type))
+ return 0;
+
+ /* Record the location of this empty object in OFFSETS. */
+ n = splay_tree_lookup (offsets, (splay_tree_key) offset);
+ if (!n)
+ n = splay_tree_insert (offsets,
+ (splay_tree_key) offset,
+ (splay_tree_value) NULL_TREE);
+ n->value = ((splay_tree_value)
+ tree_cons (NULL_TREE,
+ type,
+ (tree) n->value));
+
+ return 0;
+}
+
+/* Returns non-zero if TYPE is an empty class type and there is
+ already an entry in OFFSETS for the same TYPE as the same OFFSET. */
+
+static int
+check_subobject_offset (type, offset, offsets)
+ tree type;
+ tree offset;
+ splay_tree offsets;
+{
+ splay_tree_node n;
+ tree t;
+
+ if (!is_empty_class (type))
+ return 0;
+
+ /* Record the location of this empty object in OFFSETS. */
+ n = splay_tree_lookup (offsets, (splay_tree_key) offset);
+ if (!n)
+ return 0;
+
+ for (t = (tree) n->value; t; t = TREE_CHAIN (t))
+ if (same_type_p (TREE_VALUE (t), type))
+ return 1;
+
+ return 0;
+}
+
+/* Walk through all the subobjects of TYPE (located at OFFSET). Call
+ F for every subobject, passing it the type, offset, and table of
+ OFFSETS. If VBASES_P is non-zero, then even virtual non-primary
+ bases should be traversed; otherwise, they are ignored.
+
+ If MAX_OFFSET is non-NULL, then subobjects with an offset greater
+ than MAX_OFFSET will not be walked.
+
+ If F returns a non-zero value, the traversal ceases, and that value
+ is returned. Otherwise, returns zero. */
+
+static int
+walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
+ tree type;
+ subobject_offset_fn f;
+ tree offset;
+ splay_tree offsets;
+ tree max_offset;
+ int vbases_p;
+{
+ int r = 0;
+
+ /* If this OFFSET is bigger than the MAX_OFFSET, then we should
+ stop. */
+ if (max_offset && INT_CST_LT (max_offset, offset))
+ return 0;
+
+ if (CLASS_TYPE_P (type))
+ {
+ tree field;
+ int i;
+
+ /* Record the location of TYPE. */
+ r = (*f) (type, offset, offsets);
+ if (r)
+ return r;
+
+ /* Iterate through the direct base classes of TYPE. */
+ for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i)
+ {
+ tree binfo = BINFO_BASETYPE (TYPE_BINFO (type), i);
+
+ if (!vbases_p
+ && TREE_VIA_VIRTUAL (binfo)
+ && !BINFO_PRIMARY_P (binfo))
+ continue;
+
+ r = walk_subobject_offsets (BINFO_TYPE (binfo),
+ f,
+ size_binop (PLUS_EXPR,
+ offset,
+ BINFO_OFFSET (binfo)),
+ offsets,
+ max_offset,
+ vbases_p);
+ if (r)
+ return r;
+ }
+
+ /* Iterate through the fields of TYPE. */
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL)
+ {
+ r = walk_subobject_offsets (TREE_TYPE (field),
+ f,
+ size_binop (PLUS_EXPR,
+ offset,
+ DECL_FIELD_OFFSET (field)),
+ offsets,
+ max_offset,
+ /*vbases_p=*/1);
+ if (r)
+ return r;
+ }
+ }
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ tree domain = TYPE_DOMAIN (type);
+ tree index;
+
+ /* Step through each of the elements in the array. */
+ for (index = size_zero_node;
+ INT_CST_LT (index, TYPE_MAX_VALUE (domain));
+ index = size_binop (PLUS_EXPR, index, size_one_node))
+ {
+ r = walk_subobject_offsets (TREE_TYPE (type),
+ f,
+ offset,
+ offsets,
+ max_offset,
+ /*vbases_p=*/1);
+ if (r)
+ return r;
+ offset = size_binop (PLUS_EXPR, offset,
+ TYPE_SIZE_UNIT (TREE_TYPE (type)));
+ /* If this new OFFSET is bigger than the MAX_OFFSET, then
+ there's no point in iterating through the remaining
+ elements of the array. */
+ if (max_offset && INT_CST_LT (max_offset, offset))
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/* Record all of the empty subobjects of TYPE (located at OFFSET) in
+ OFFSETS. If VBASES_P is non-zero, virtual bases of TYPE are
+ examined. */
+
+static void
+record_subobject_offsets (type, offset, offsets, vbases_p)
+ tree type;
+ tree offset;
+ splay_tree offsets;
+ int vbases_p;
+{
+ walk_subobject_offsets (type, record_subobject_offset, offset,
+ offsets, /*max_offset=*/NULL_TREE, vbases_p);
+}
+
+/* Returns non-zero if any of the empty subobjects of TYPE (located at
+ OFFSET) conflict with entries in OFFSETS. If VBASES_P is non-zero,
+ virtual bases of TYPE are examined. */
+
+static int
+layout_conflict_p (type, offset, offsets, vbases_p)
+ tree type;
+ tree offset;
+ splay_tree offsets;
+ int vbases_p;
+{
+ splay_tree_node max_node;
+
+ /* Get the node in OFFSETS that indicates the maximum offset where
+ an empty subobject is located. */
+ max_node = splay_tree_max (offsets);
+ /* If there aren't any empty subobjects, then there's no point in
+ performing this check. */
+ if (!max_node)
+ return 0;
+
+ return walk_subobject_offsets (type, check_subobject_offset, offset,
+ offsets, (tree) (max_node->key),
+ vbases_p);
+}
+
+/* DECL is a FIELD_DECL corresponding either to a base subobject of a
+ non-static data member of the type indicated by RLI. BINFO is the
+ binfo corresponding to the base subobject, OFFSETS maps offsets to
+ types already located at those offsets. T is the most derived
+ type. This function determines the position of the DECL. */
+
+static void
+layout_nonempty_base_or_field (rli, decl, binfo, offsets, t)
+ record_layout_info rli;
+ tree decl;
+ tree binfo;
+ splay_tree offsets;
+ tree t;
+{
+ tree offset = NULL_TREE;
+ tree type = TREE_TYPE (decl);
+ /* If we are laying out a base class, rather than a field, then
+ DECL_ARTIFICIAL will be set on the FIELD_DECL. */
+ int field_p = !DECL_ARTIFICIAL (decl);
+
+ /* Try to place the field. It may take more than one try if we have
+ a hard time placing the field without putting two objects of the
+ same type at the same address. */
+ while (1)
+ {
+ struct record_layout_info_s old_rli = *rli;
+
+ /* Place this field. */
+ place_field (rli, decl);
+ offset = byte_position (decl);
+
+ /* We have to check to see whether or not there is already
+ something of the same type at the offset we're about to use.
+ For example:
+
+ struct S {};
+ struct T : public S { int i; };
+ struct U : public S, public T {};
+
+ Here, we put S at offset zero in U. Then, we can't put T at
+ offset zero -- its S component would be at the same address
+ as the S we already allocated. So, we have to skip ahead.
+ Since all data members, including those whose type is an
+ empty class, have non-zero size, any overlap can happen only
+ with a direct or indirect base-class -- it can't happen with
+ a data member. */
+ if (layout_conflict_p (TREE_TYPE (decl),
+ offset,
+ offsets,
+ field_p))
+ {
+ /* Strip off the size allocated to this field. That puts us
+ at the first place we could have put the field with
+ proper alignment. */
+ *rli = old_rli;
+
+ /* Bump up by the alignment required for the type. */
+ rli->bitpos
+ = size_binop (PLUS_EXPR, rli->bitpos,
+ bitsize_int (binfo
+ ? CLASSTYPE_ALIGN (type)
+ : TYPE_ALIGN (type)));
+ normalize_rli (rli);
}
else
+ /* There was no conflict. We're done laying out this field. */
+ break;
+ }
+
+ /* Now that we know where it will be placed, update its
+ BINFO_OFFSET. */
+ if (binfo && CLASS_TYPE_P (BINFO_TYPE (binfo)))
+ propagate_binfo_offsets (binfo,
+ convert (ssizetype, offset), t);
+}
+
+/* Layout the empty base BINFO. EOC indicates the byte currently just
+ past the end of the class, and should be correctly aligned for a
+ class of the type indicated by BINFO; OFFSETS gives the offsets of
+ the empty bases allocated so far. T is the most derived
+ type. Return non-zero iff we added it at the end. */
+
+static bool
+layout_empty_base (binfo, eoc, offsets, t)
+ tree binfo;
+ tree eoc;
+ splay_tree offsets;
+ tree t;
+{
+ tree alignment;
+ tree basetype = BINFO_TYPE (binfo);
+ bool atend = false;
+
+ /* This routine should only be used for empty classes. */
+ my_friendly_assert (is_empty_class (basetype), 20000321);
+ alignment = ssize_int (CLASSTYPE_ALIGN_UNIT (basetype));
+
+ /* This is an empty base class. We first try to put it at offset
+ zero. */
+ if (layout_conflict_p (BINFO_TYPE (binfo),
+ BINFO_OFFSET (binfo),
+ offsets,
+ /*vbases_p=*/0))
+ {
+ /* That didn't work. Now, we move forward from the next
+ available spot in the class. */
+ atend = true;
+ propagate_binfo_offsets (binfo, convert (ssizetype, eoc), t);
+ while (1)
{
- tree type = TREE_TYPE (x);
+ if (!layout_conflict_p (BINFO_TYPE (binfo),
+ BINFO_OFFSET (binfo),
+ offsets,
+ /*vbases_p=*/0))
+ /* We finally found a spot where there's no overlap. */
+ break;
- while (TREE_CODE (type) == ARRAY_TYPE)
- type = TREE_TYPE (type);
+ /* There's overlap here, too. Bump along to the next spot. */
+ propagate_binfo_offsets (binfo, alignment, t);
+ }
+ }
+ return atend;
+}
- if (TYPE_LANG_SPECIFIC (type) && ! ANON_UNION_P (x)
- && ! TYPE_PTRMEMFUNC_P (type))
- {
- /* Never let anything with uninheritable virtuals
- make it through without complaint. */
- if (CLASSTYPE_ABSTRACT_VIRTUALS (type))
- abstract_virtuals_error (x, type);
-
- /* Don't let signatures make it through either. */
- if (IS_SIGNATURE (type))
- signature_error (x, type);
-
- if (code == UNION_TYPE)
- {
- const char *fie = NULL;
- if (TYPE_NEEDS_CONSTRUCTING (type))
- fie = "constructor";
- else if (TYPE_NEEDS_DESTRUCTOR (type))
- fie = "destructor";
- else if (TYPE_HAS_COMPLEX_ASSIGN_REF (type))
- fie = "copy assignment operator";
- if (fie)
- cp_error_at ("member `%#D' with %s not allowed in union", x,
- fie);
- }
- else
- {
- TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (type);
- TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (type);
- TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (type);
- TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (type);
- }
+/* Build a FIELD_DECL for the base given by BINFO in the class
+ indicated by RLI. If the new object is non-empty, clear *EMPTY_P.
+ *BASE_ALIGN is a running maximum of the alignments of any base
+ class. OFFSETS gives the location of empty base subobjects. T is
+ the most derived type. Return non-zero if the new object cannot be
+ nearly-empty. */
- if (!TYPE_HAS_CONST_INIT_REF (type))
- cant_have_const_ctor = 1;
+static bool
+build_base_field (rli, binfo, empty_p, offsets, t)
+ record_layout_info rli;
+ tree binfo;
+ int *empty_p;
+ splay_tree offsets;
+ tree t;
+{
+ tree basetype = BINFO_TYPE (binfo);
+ tree decl;
+ bool atend = false;
+
+ if (!COMPLETE_TYPE_P (basetype))
+ /* This error is now reported in xref_tag, thus giving better
+ location information. */
+ return atend;
+
+ decl = build_decl (FIELD_DECL, NULL_TREE, basetype);
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_FIELD_CONTEXT (decl) = rli->t;
+ DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
+ DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
+ DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
+ DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
+
+ if (!integer_zerop (DECL_SIZE (decl)))
+ {
+ /* The containing class is non-empty because it has a non-empty
+ base class. */
+ *empty_p = 0;
- if (!TYPE_HAS_CONST_ASSIGN_REF (type))
- no_const_asn_ref = 1;
+ /* Try to place the field. It may take more than one try if we
+ have a hard time placing the field without putting two
+ objects of the same type at the same address. */
+ layout_nonempty_base_or_field (rli, decl, binfo, offsets, t);
+ }
+ else
+ {
+ unsigned HOST_WIDE_INT eoc;
- if (TYPE_HAS_CONSTRUCTOR (type)
- && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
- {
- cant_have_default_ctor = 1;
-#if 0
- /* This is wrong for aggregates. */
- if (! TYPE_HAS_CONSTRUCTOR (t))
- {
- if (DECL_NAME (x))
- cp_pedwarn_at ("member `%#D' with only non-default constructor", x);
- else
- cp_pedwarn_at ("member with only non-default constructor", x);
- cp_pedwarn_at ("in class without a constructor",
- x);
- }
-#endif
- }
- }
- if (DECL_INITIAL (x) != NULL_TREE)
+ /* On some platforms (ARM), even empty classes will not be
+ byte-aligned. */
+ eoc = tree_low_cst (rli_size_unit_so_far (rli), 0);
+ eoc = CEIL (eoc, DECL_ALIGN_UNIT (decl)) * DECL_ALIGN_UNIT (decl);
+ atend |= layout_empty_base (binfo, size_int (eoc), offsets, t);
+ }
+
+ /* Record the offsets of BINFO and its base subobjects. */
+ record_subobject_offsets (BINFO_TYPE (binfo),
+ BINFO_OFFSET (binfo),
+ offsets,
+ /*vbases_p=*/0);
+ return atend;
+}
+
+/* Layout all of the non-virtual base classes. Record empty
+ subobjects in OFFSETS. T is the most derived type. Return
+ non-zero if the type cannot be nearly empty. */
+
+static bool
+build_base_fields (rli, empty_p, offsets, t)
+ record_layout_info rli;
+ int *empty_p;
+ splay_tree offsets;
+ tree t;
+{
+ /* Chain to hold all the new FIELD_DECLs which stand in for base class
+ subobjects. */
+ tree rec = rli->t;
+ int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
+ int i;
+ bool atend = 0;
+
+ /* The primary base class is always allocated first. */
+ if (CLASSTYPE_HAS_PRIMARY_BASE_P (rec))
+ build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (rec),
+ empty_p, offsets, t);
+
+ /* Now allocate the rest of the bases. */
+ for (i = 0; i < n_baseclasses; ++i)
+ {
+ tree base_binfo;
+
+ base_binfo = BINFO_BASETYPE (TYPE_BINFO (rec), i);
+
+ /* The primary base was already allocated above, so we don't
+ need to allocate it again here. */
+ if (base_binfo == CLASSTYPE_PRIMARY_BINFO (rec))
+ continue;
+
+ /* A primary virtual base class is allocated just like any other
+ base class, but a non-primary virtual base is allocated
+ later, in layout_virtual_bases. */
+ if (TREE_VIA_VIRTUAL (base_binfo)
+ && !BINFO_PRIMARY_P (base_binfo))
+ continue;
+
+ atend |= build_base_field (rli, base_binfo, empty_p, offsets, t);
+ }
+ return atend;
+}
+
+/* Go through the TYPE_METHODS of T issuing any appropriate
+ diagnostics, figuring out which methods override which other
+ methods, and so forth. */
+
+static void
+check_methods (t)
+ tree t;
+{
+ tree x;
+
+ 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)))
+ continue;
+
+ 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))
+ {
+ TYPE_POLYMORPHIC_P (t) = 1;
+ if (DECL_PURE_VIRTUAL_P (x))
+ CLASSTYPE_PURE_VIRTUALS (t)
+ = tree_cons (NULL_TREE, x, CLASSTYPE_PURE_VIRTUALS (t));
+ }
+ }
+}
+
+/* FN is a constructor or destructor. Clone the declaration to create
+ a specialized in-charge or not-in-charge version, as indicated by
+ NAME. */
+
+static tree
+build_clone (fn, name)
+ tree fn;
+ tree name;
+{
+ tree parms;
+ tree clone;
+
+ /* Copy the function. */
+ clone = copy_decl (fn);
+ /* Remember where this function came from. */
+ DECL_CLONED_FUNCTION (clone) = fn;
+ DECL_ABSTRACT_ORIGIN (clone) = fn;
+ /* Reset the function name. */
+ DECL_NAME (clone) = name;
+ SET_DECL_ASSEMBLER_NAME (clone, NULL_TREE);
+ /* There's no pending inline data for this function. */
+ DECL_PENDING_INLINE_INFO (clone) = NULL;
+ DECL_PENDING_INLINE_P (clone) = 0;
+ /* And it hasn't yet been deferred. */
+ DECL_DEFERRED_FN (clone) = 0;
+
+ /* The base-class destructor is not virtual. */
+ if (name == base_dtor_identifier)
+ {
+ DECL_VIRTUAL_P (clone) = 0;
+ if (TREE_CODE (clone) != TEMPLATE_DECL)
+ DECL_VINDEX (clone) = NULL_TREE;
+ }
+
+ /* If there was an in-charge parameter, drop it from the function
+ type. */
+ if (DECL_HAS_IN_CHARGE_PARM_P (clone))
+ {
+ tree basetype;
+ tree parmtypes;
+ tree exceptions;
+
+ exceptions = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (clone));
+ basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (clone));
+ parmtypes = TYPE_ARG_TYPES (TREE_TYPE (clone));
+ /* Skip the `this' parameter. */
+ parmtypes = TREE_CHAIN (parmtypes);
+ /* Skip the in-charge parameter. */
+ parmtypes = TREE_CHAIN (parmtypes);
+ /* And the VTT parm, in a complete [cd]tor. */
+ if (DECL_HAS_VTT_PARM_P (fn)
+ && ! DECL_NEEDS_VTT_PARM_P (clone))
+ parmtypes = TREE_CHAIN (parmtypes);
+ /* If this is subobject constructor or destructor, add the vtt
+ parameter. */
+ TREE_TYPE (clone)
+ = build_cplus_method_type (basetype,
+ TREE_TYPE (TREE_TYPE (clone)),
+ parmtypes);
+ if (exceptions)
+ TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone),
+ exceptions);
+ }
+
+ /* Copy the function parameters. But, DECL_ARGUMENTS on a TEMPLATE_DECL
+ aren't function parameters; those are the template parameters. */
+ if (TREE_CODE (clone) != TEMPLATE_DECL)
+ {
+ DECL_ARGUMENTS (clone) = copy_list (DECL_ARGUMENTS (clone));
+ /* Remove the in-charge parameter. */
+ if (DECL_HAS_IN_CHARGE_PARM_P (clone))
+ {
+ TREE_CHAIN (DECL_ARGUMENTS (clone))
+ = TREE_CHAIN (TREE_CHAIN (DECL_ARGUMENTS (clone)));
+ DECL_HAS_IN_CHARGE_PARM_P (clone) = 0;
+ }
+ /* And the VTT parm, in a complete [cd]tor. */
+ if (DECL_HAS_VTT_PARM_P (fn))
+ {
+ if (DECL_NEEDS_VTT_PARM_P (clone))
+ DECL_HAS_VTT_PARM_P (clone) = 1;
+ else
{
- /* `build_class_init_list' does not recognize
- non-FIELD_DECLs. */
- if (code == UNION_TYPE && any_default_members != 0)
- cp_error_at ("multiple fields in union `%T' initialized");
- any_default_members = 1;
+ TREE_CHAIN (DECL_ARGUMENTS (clone))
+ = TREE_CHAIN (TREE_CHAIN (DECL_ARGUMENTS (clone)));
+ DECL_HAS_VTT_PARM_P (clone) = 0;
}
}
+
+ for (parms = DECL_ARGUMENTS (clone); parms; parms = TREE_CHAIN (parms))
+ {
+ DECL_CONTEXT (parms) = clone;
+ copy_lang_decl (parms);
+ }
}
- /* If this type has any constant members which did not come
- with their own initialization, mark that fact here. It is
- not an error here, since such types can be saved either by their
- constructors, or by fortuitous initialization. */
- CLASSTYPE_READONLY_FIELDS_NEED_INIT (t) = const_sans_init;
- CLASSTYPE_REF_FIELDS_NEED_INIT (t) = ref_sans_init;
- CLASSTYPE_ABSTRACT_VIRTUALS (t) = abstract_virtuals;
- CLASSTYPE_HAS_MUTABLE (t) = has_mutable;
+ /* Create the RTL for this function. */
+ SET_DECL_RTL (clone, NULL_RTX);
+ rest_of_decl_compilation (clone, NULL, /*top_level=*/1, at_eof);
+
+ /* Make it easy to find the CLONE given the FN. */
+ TREE_CHAIN (clone) = TREE_CHAIN (fn);
+ TREE_CHAIN (fn) = clone;
- /* Effective C++ rule 11. */
- if (has_pointers && warn_ecpp && TYPE_HAS_CONSTRUCTOR (t)
- && ! (TYPE_HAS_INIT_REF (t) && TYPE_HAS_ASSIGN_REF (t)))
+ /* If this is a template, handle the DECL_TEMPLATE_RESULT as well. */
+ if (TREE_CODE (clone) == TEMPLATE_DECL)
{
- cp_warning ("`%#T' has pointer data members", t);
-
- if (! TYPE_HAS_INIT_REF (t))
+ tree result;
+
+ DECL_TEMPLATE_RESULT (clone)
+ = build_clone (DECL_TEMPLATE_RESULT (clone), name);
+ result = DECL_TEMPLATE_RESULT (clone);
+ DECL_TEMPLATE_INFO (result) = copy_node (DECL_TEMPLATE_INFO (result));
+ DECL_TI_TEMPLATE (result) = clone;
+ }
+ else if (DECL_DEFERRED_FN (fn))
+ defer_fn (clone);
+
+ return clone;
+}
+
+/* Produce declarations for all appropriate clones of FN. If
+ UPDATE_METHOD_VEC_P is non-zero, the clones are added to the
+ CLASTYPE_METHOD_VEC as well. */
+
+void
+clone_function_decl (fn, update_method_vec_p)
+ tree fn;
+ int update_method_vec_p;
+{
+ tree clone;
+
+ /* Avoid inappropriate cloning. */
+ if (TREE_CHAIN (fn)
+ && DECL_CLONED_FUNCTION (TREE_CHAIN (fn)))
+ return;
+
+ if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn))
+ {
+ /* For each constructor, we need two variants: an in-charge version
+ 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);
+ clone = build_clone (fn, base_ctor_identifier);
+ if (update_method_vec_p)
+ add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
+ }
+ else
+ {
+ my_friendly_assert (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fn), 20000411);
+
+ /* For each destructor, we need three variants: an in-charge
+ version, a not-in-charge version, and an in-charge deleting
+ version. We clone the deleting version first because that
+ means it will go second on the TYPE_METHODS list -- and that
+ corresponds to the correct layout order in the virtual
+ function table.
+
+ For a non-virtual destructor, we do not build a deleting
+ destructor. */
+ if (DECL_VIRTUAL_P (fn))
{
- cp_warning (" but does not override `%T(const %T&)'", t, t);
- if (! TYPE_HAS_ASSIGN_REF (t))
- cp_warning (" or `operator=(const %T&)'", t);
+ clone = build_clone (fn, deleting_dtor_identifier);
+ if (update_method_vec_p)
+ add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
}
- else if (! TYPE_HAS_ASSIGN_REF (t))
- cp_warning (" but does not override `operator=(const %T&)'", t);
+ clone = build_clone (fn, complete_dtor_identifier);
+ if (update_method_vec_p)
+ add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
+ clone = build_clone (fn, base_dtor_identifier);
+ if (update_method_vec_p)
+ add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
}
+
+ /* Note that this is an abstract function that is never emitted. */
+ DECL_ABSTRACT (fn) = 1;
+}
+
+/* DECL is an in charge constructor, which is being defined. This will
+ have had an in class declaration, from whence clones were
+ declared. An out-of-class definition can specify additional default
+ arguments. As it is the clones that are involved in overload
+ resolution, we must propagate the information from the DECL to its
+ clones. */
+
+void
+adjust_clone_args (decl)
+ tree decl;
+{
+ tree clone;
+ for (clone = TREE_CHAIN (decl); clone && DECL_CLONED_FUNCTION (clone);
+ clone = TREE_CHAIN (clone))
+ {
+ tree orig_clone_parms = TYPE_ARG_TYPES (TREE_TYPE (clone));
+ tree orig_decl_parms = TYPE_ARG_TYPES (TREE_TYPE (decl));
+ tree decl_parms, clone_parms;
+
+ clone_parms = orig_clone_parms;
+
+ /* Skip the 'this' parameter. */
+ orig_clone_parms = TREE_CHAIN (orig_clone_parms);
+ orig_decl_parms = TREE_CHAIN (orig_decl_parms);
+
+ if (DECL_HAS_IN_CHARGE_PARM_P (decl))
+ orig_decl_parms = TREE_CHAIN (orig_decl_parms);
+ if (DECL_HAS_VTT_PARM_P (decl))
+ orig_decl_parms = TREE_CHAIN (orig_decl_parms);
+
+ clone_parms = orig_clone_parms;
+ if (DECL_HAS_VTT_PARM_P (clone))
+ clone_parms = TREE_CHAIN (clone_parms);
+
+ for (decl_parms = orig_decl_parms; decl_parms;
+ decl_parms = TREE_CHAIN (decl_parms),
+ clone_parms = TREE_CHAIN (clone_parms))
+ {
+ my_friendly_assert (same_type_p (TREE_TYPE (decl_parms),
+ TREE_TYPE (clone_parms)), 20010424);
+
+ if (TREE_PURPOSE (decl_parms) && !TREE_PURPOSE (clone_parms))
+ {
+ /* A default parameter has been added. Adjust the
+ clone's parameters. */
+ tree exceptions = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (clone));
+ tree basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (clone));
+ tree type;
+
+ clone_parms = orig_decl_parms;
+
+ if (DECL_HAS_VTT_PARM_P (clone))
+ {
+ clone_parms = tree_cons (TREE_PURPOSE (orig_clone_parms),
+ TREE_VALUE (orig_clone_parms),
+ clone_parms);
+ TREE_TYPE (clone_parms) = TREE_TYPE (orig_clone_parms);
+ }
+ type = build_cplus_method_type (basetype,
+ TREE_TYPE (TREE_TYPE (clone)),
+ clone_parms);
+ if (exceptions)
+ type = build_exception_variant (type, exceptions);
+ TREE_TYPE (clone) = type;
+
+ clone_parms = NULL_TREE;
+ break;
+ }
+ }
+ my_friendly_assert (!clone_parms, 20010424);
+ }
+}
+
+/* For each of the constructors and destructors in T, create an
+ in-charge and not-in-charge variant. */
+
+static void
+clone_constructors_and_destructors (t)
+ tree t;
+{
+ tree fns;
+
+ /* If for some reason we don't have a CLASSTYPE_METHOD_VEC, we bail
+ out now. */
+ if (!CLASSTYPE_METHOD_VEC (t))
+ return;
+
+ for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns))
+ clone_function_decl (OVL_CURRENT (fns), /*update_method_vec_p=*/1);
+ for (fns = CLASSTYPE_DESTRUCTORS (t); fns; fns = OVL_NEXT (fns))
+ clone_function_decl (OVL_CURRENT (fns), /*update_method_vec_p=*/1);
+}
+
+/* Remove all zero-width bit-fields from T. */
+
+static void
+remove_zero_width_bit_fields (t)
+ tree t;
+{
+ tree *fieldsp;
+
+ fieldsp = &TYPE_FIELDS (t);
+ while (*fieldsp)
+ {
+ if (TREE_CODE (*fieldsp) == FIELD_DECL
+ && DECL_C_BIT_FIELD (*fieldsp)
+ && DECL_INITIAL (*fieldsp))
+ *fieldsp = TREE_CHAIN (*fieldsp);
+ else
+ fieldsp = &TREE_CHAIN (*fieldsp);
+ }
+}
+
+/* Returns TRUE iff we need a cookie when dynamically allocating an
+ array whose elements have the indicated class TYPE. */
+
+static bool
+type_requires_array_cookie (type)
+ tree type;
+{
+ tree fns;
+ bool has_two_argument_delete_p = false;
+
+ my_friendly_assert (CLASS_TYPE_P (type), 20010712);
+
+ /* If there's a non-trivial destructor, we need a cookie. In order
+ to iterate through the array calling the destructor for each
+ element, we'll have to know how many elements there are. */
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+ return true;
+
+ /* If the usual deallocation function is a two-argument whose second
+ argument is of type `size_t', then we have to pass the size of
+ the array to the deallocation function, so we will need to store
+ a cookie. */
+ fns = lookup_fnfields (TYPE_BINFO (type),
+ ansi_opname (VEC_DELETE_EXPR),
+ /*protect=*/0);
+ /* If there are no `operator []' members, or the lookup is
+ ambiguous, then we don't need a cookie. */
+ if (!fns || fns == error_mark_node)
+ return false;
+ /* Loop through all of the functions. */
+ for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns))
+ {
+ tree fn;
+ tree second_parm;
+
+ /* Select the current function. */
+ fn = OVL_CURRENT (fns);
+ /* See if this function is a one-argument delete function. If
+ it is, then it will be the usual deallocation function. */
+ second_parm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
+ if (second_parm == void_list_node)
+ return false;
+ /* Otherwise, if we have a two-argument function and the second
+ argument is `size_t', it will be the usual deallocation
+ function -- unless there is one-argument function, too. */
+ if (TREE_CHAIN (second_parm) == void_list_node
+ && same_type_p (TREE_VALUE (second_parm), sizetype))
+ has_two_argument_delete_p = true;
+ }
+
+ return has_two_argument_delete_p;
+}
+
+/* Check the validity of the bases and members declared in T. Add any
+ implicitly-generated functions (like copy-constructors and
+ assignment operators). Compute various flag bits (like
+ CLASSTYPE_NON_POD_T) for T. This routine works purely at the C++
+ level: i.e., independently of the ABI in use. */
+
+static void
+check_bases_and_members (t, empty_p)
+ tree t;
+ int *empty_p;
+{
+ /* Nonzero if we are not allowed to generate a default constructor
+ for this case. */
+ int cant_have_default_ctor;
+ /* Nonzero if the implicitly generated copy constructor should take
+ a non-const reference argument. */
+ int cant_have_const_ctor;
+ /* Nonzero if the the implicitly generated assignment operator
+ should take a non-const reference argument. */
+ int no_const_asn_ref;
+ tree access_decls;
+
+ /* By default, we use const reference arguments and generate default
+ constructors. */
+ cant_have_default_ctor = 0;
+ cant_have_const_ctor = 0;
+ no_const_asn_ref = 0;
+
+ /* Assume that the class is nearly empty; we'll clear this flag if
+ it turns out not to be nearly empty. */
+ CLASSTYPE_NEARLY_EMPTY_P (t) = 1;
+
+ /* Check all the base-classes. */
+ check_bases (t, &cant_have_default_ctor, &cant_have_const_ctor,
+ &no_const_asn_ref);
+
+ /* Check all the data member declarations. */
+ check_field_decls (t, &access_decls, empty_p,
+ &cant_have_default_ctor,
+ &cant_have_const_ctor,
+ &no_const_asn_ref);
+
+ /* Check all the method declarations. */
+ check_methods (t);
+
+ /* A nearly-empty class has to be vptr-containing; a nearly empty
+ class contains just a vptr. */
+ if (!TYPE_CONTAINS_VPTR_P (t))
+ CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
+
/* Do some bookkeeping that will guide the generation of implicitly
declared member functions. */
TYPE_HAS_COMPLEX_INIT_REF (t)
- |= (TYPE_HAS_INIT_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t)
- || has_virtual || any_default_members);
+ |= (TYPE_HAS_INIT_REF (t)
+ || TYPE_USES_VIRTUAL_BASECLASSES (t)
+ || TYPE_POLYMORPHIC_P (t));
TYPE_NEEDS_CONSTRUCTING (t)
- |= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_USES_VIRTUAL_BASECLASSES (t)
- || has_virtual || any_default_members);
- if (! IS_SIGNATURE (t))
- CLASSTYPE_NON_AGGREGATE (t)
- = ! aggregate || has_virtual || TYPE_HAS_CONSTRUCTOR (t);
+ |= (TYPE_HAS_CONSTRUCTOR (t)
+ || TYPE_USES_VIRTUAL_BASECLASSES (t)
+ || TYPE_POLYMORPHIC_P (t));
+ CLASSTYPE_NON_AGGREGATE (t) |= (TYPE_HAS_CONSTRUCTOR (t)
+ || TYPE_POLYMORPHIC_P (t));
+ 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_USES_VIRTUAL_BASECLASSES (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. */
- virtual_dtor
- = add_implicitly_declared_members (t, cant_have_default_ctor,
- cant_have_const_ctor,
- no_const_asn_ref);
- if (virtual_dtor)
- add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
- &has_virtual, virtual_dtor, t);
+ add_implicitly_declared_members (t, cant_have_default_ctor,
+ cant_have_const_ctor,
+ no_const_asn_ref);
- if (TYPE_METHODS (t))
- {
- finish_struct_methods (t);
- method_vec = CLASSTYPE_METHOD_VEC (t);
- }
- else
- {
- method_vec = 0;
+ /* Create the in-charge and not-in-charge variants of constructors
+ and destructors. */
+ clone_constructors_and_destructors (t);
- /* Just in case these got accidentally
- filled in by syntax errors. */
- TYPE_HAS_CONSTRUCTOR (t) = 0;
- TYPE_HAS_DESTRUCTOR (t) = 0;
- }
+ /* Process the using-declarations. */
+ for (; access_decls; access_decls = TREE_CHAIN (access_decls))
+ handle_using_decl (TREE_VALUE (access_decls), t);
+
+ /* Build and sort the CLASSTYPE_METHOD_VEC. */
+ finish_struct_methods (t);
+
+ /* 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_requires_array_cookie (t);
+}
+
+/* If T needs a pointer to its virtual function table, set TYPE_VFIELD
+ 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. */
- for (access_decls = nreverse (access_decls); access_decls;
- access_decls = TREE_CHAIN (access_decls))
- handle_using_decl (TREE_VALUE (access_decls), t, method_vec, fields);
+static tree
+create_vtable_ptr (t, empty_p, vfuns_p,
+ new_virtuals_p, overridden_virtuals_p)
+ tree t;
+ int *empty_p;
+ int *vfuns_p;
+ tree *new_virtuals_p;
+ tree *overridden_virtuals_p;
+{
+ tree fn;
- if (vfield == NULL_TREE && has_virtual)
+ /* Loop over the virtual functions, adding them to our various
+ vtables. */
+ 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 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)))
{
/* We build this decl with vtbl_ptr_type_node, which is a
`vtable_entry_type*'. It might seem more precise to use
@@ -4028,255 +4435,682 @@ finish_struct_1 (t, warn_anon)
bounds. That's better than using `void*' or some such; it's
cleaner, and it let's the alias analysis code know that these
stores cannot alias stores to void*! */
- vfield = build_lang_field_decl (FIELD_DECL, get_vfield_name (t),
- vtbl_ptr_type_node);
- /* If you change any of the below, take a look at all the
- other VFIELD_BASEs and VTABLE_BASEs in the code, and change
- them too. */
- DECL_ASSEMBLER_NAME (vfield) = get_identifier (VFIELD_BASE);
- CLASSTYPE_VFIELD (t) = vfield;
- DECL_VIRTUAL_P (vfield) = 1;
- DECL_ARTIFICIAL (vfield) = 1;
- DECL_FIELD_CONTEXT (vfield) = t;
- DECL_CLASS_CONTEXT (vfield) = t;
- DECL_FCONTEXT (vfield) = t;
- DECL_SAVED_INSNS (vfield) = NULL_RTX;
- DECL_FIELD_SIZE (vfield) = 0;
- DECL_ALIGN (vfield) = TYPE_ALIGN (ptr_type_node);
-#if 0
- /* This is more efficient, but breaks binary compatibility, turn
- it on sometime when we don't care. If we turn it on, we also
- have to enable the code in dfs_init_vbase_pointers. */
- /* vfield is always first entry in structure. */
- TREE_CHAIN (vfield) = fields;
- fields = vfield;
-#else
- if (last_x)
+ tree field;
+
+ field = build_decl (FIELD_DECL, get_vfield_name (t), vtbl_ptr_type_node);
+ SET_DECL_ASSEMBLER_NAME (field, get_identifier (VFIELD_BASE));
+ DECL_VIRTUAL_P (field) = 1;
+ DECL_ARTIFICIAL (field) = 1;
+ DECL_FIELD_CONTEXT (field) = t;
+ DECL_FCONTEXT (field) = t;
+ DECL_ALIGN (field) = TYPE_ALIGN (vtbl_ptr_type_node);
+ DECL_USER_ALIGN (field) = TYPE_USER_ALIGN (vtbl_ptr_type_node);
+
+ TYPE_VFIELD (t) = field;
+
+ /* This class is non-empty. */
+ *empty_p = 0;
+
+ if (CLASSTYPE_N_BASECLASSES (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
+ take work. */
+ TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (t) = 1;
+
+ return field;
+ }
+
+ return NULL_TREE;
+}
+
+/* Fixup the inline function given by INFO now that the class is
+ complete. */
+
+static void
+fixup_pending_inline (fn)
+ tree fn;
+{
+ if (DECL_PENDING_INLINE_INFO (fn))
+ {
+ tree args = DECL_ARGUMENTS (fn);
+ while (args)
{
- my_friendly_assert (TREE_CHAIN (last_x) == NULL_TREE, 175);
- TREE_CHAIN (last_x) = vfield;
- last_x = vfield;
+ DECL_CONTEXT (args) = fn;
+ args = TREE_CHAIN (args);
}
+ }
+}
+
+/* Fixup the inline methods and friends in TYPE now that TYPE is
+ complete. */
+
+static void
+fixup_inline_methods (type)
+ tree type;
+{
+ tree method = TYPE_METHODS (type);
+
+ if (method && TREE_CODE (method) == TREE_VEC)
+ {
+ if (TREE_VEC_ELT (method, 1))
+ method = TREE_VEC_ELT (method, 1);
+ else if (TREE_VEC_ELT (method, 0))
+ method = TREE_VEC_ELT (method, 0);
else
- fields = vfield;
-#endif
- empty = 0;
- vfields = chainon (vfields, build_tree_list (NULL_TREE, t));
+ method = TREE_VEC_ELT (method, 2);
}
- /* Now DECL_INITIAL is null on all members except for zero-width bit-fields.
+ /* Do inline member functions. */
+ for (; method; method = TREE_CHAIN (method))
+ fixup_pending_inline (method);
+
+ /* Do friends. */
+ for (method = CLASSTYPE_INLINE_FRIENDS (type);
+ method;
+ method = TREE_CHAIN (method))
+ fixup_pending_inline (TREE_VALUE (method));
+ CLASSTYPE_INLINE_FRIENDS (type) = NULL_TREE;
+}
+
+/* Add OFFSET to all base types of BINFO which is a base in the
+ hierarchy dominated by T.
- C++: maybe we will support default field initialization some day... */
+ OFFSET, which is a type offset, is number of bytes. */
- /* Delete all duplicate fields from the fields */
- delete_duplicate_fields (fields);
+static void
+propagate_binfo_offsets (binfo, offset, t)
+ tree binfo;
+ tree offset;
+ tree t;
+{
+ int i;
+ tree primary_binfo;
- /* Now we have the nearly final fieldlist for the data fields. Record it,
- then lay out the structure or union (including the fields). */
+ /* Update BINFO's offset. */
+ BINFO_OFFSET (binfo)
+ = convert (sizetype,
+ size_binop (PLUS_EXPR,
+ convert (ssizetype, BINFO_OFFSET (binfo)),
+ offset));
- TYPE_FIELDS (t) = fields;
+ /* Find the primary base class. */
+ primary_binfo = get_primary_binfo (binfo);
- if (n_baseclasses)
+ /* Scan all of the bases, pushing the BINFO_OFFSET adjust
+ downwards. */
+ for (i = -1; i < BINFO_N_BASETYPES (binfo); ++i)
{
- last_x = build_base_fields (t);
+ 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;
- /* If all our bases are empty, we can be empty too. */
- for (x = last_x; empty && x; x = TREE_CHAIN (x))
- if (DECL_SIZE (x) != integer_zero_node)
- empty = 0;
+ base_binfo = primary_binfo;
+ }
+ else
+ {
+ base_binfo = BINFO_BASETYPE (binfo, i);
+ /* 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
+ || base_binfo != binfo_for_vbase (BINFO_TYPE (base_binfo), t)))
+ continue;
+
+ propagate_binfo_offsets (base_binfo, offset, t);
}
+}
- /* CLASSTYPE_INLINE_FRIENDS is really TYPE_NONCOPIED_PARTS. Thus,
- we have to save this before we start modifying
- TYPE_NONCOPIED_PARTS. */
- inline_friends = CLASSTYPE_INLINE_FRIENDS (t);
- CLASSTYPE_INLINE_FRIENDS (t) = NULL_TREE;
+/* Called via dfs_walk from layout_virtual bases. */
- if (empty)
+static tree
+dfs_set_offset_for_unshared_vbases (binfo, data)
+ tree binfo;
+ void *data;
+{
+ /* If this is a virtual base, make sure it has the same offset as
+ the shared copy. If it's a primary base, then we know it's
+ correct. */
+ if (TREE_VIA_VIRTUAL (binfo))
{
- /* C++: do not let empty structures exist. */
- tree decl = build_lang_field_decl
- (FIELD_DECL, NULL_TREE, char_type_node);
- TREE_CHAIN (decl) = fields;
- TYPE_FIELDS (t) = decl;
- TYPE_NONCOPIED_PARTS (t)
- = tree_cons (NULL_TREE, decl, TYPE_NONCOPIED_PARTS (t));
- TREE_STATIC (TYPE_NONCOPIED_PARTS (t)) = 1;
+ tree t = (tree) data;
+ tree vbase;
+ tree offset;
+
+ vbase = binfo_for_vbase (BINFO_TYPE (binfo), t);
+ if (vbase != binfo)
+ {
+ offset = size_diffop (BINFO_OFFSET (vbase), BINFO_OFFSET (binfo));
+ propagate_binfo_offsets (binfo, offset, t);
+ }
}
- if (n_baseclasses)
- TYPE_FIELDS (t) = chainon (last_x, TYPE_FIELDS (t));
-
- layout_type (t);
+ return NULL_TREE;
+}
- /* Remember the size and alignment of the class before adding
- the virtual bases. */
- if (empty && flag_new_abi)
- CLASSTYPE_SIZE (t) = integer_zero_node;
- else if (flag_new_abi && TYPE_HAS_COMPLEX_INIT_REF (t)
- && TYPE_HAS_COMPLEX_ASSIGN_REF (t))
- CLASSTYPE_SIZE (t) = TYPE_BINFO_SIZE (t);
- else
- CLASSTYPE_SIZE (t) = TYPE_SIZE (t);
- CLASSTYPE_ALIGN (t) = TYPE_ALIGN (t);
+/* Set BINFO_OFFSET for all of the virtual bases for T. Update
+ TYPE_ALIGN and TYPE_SIZE for T. OFFSETS gives the location of
+ empty subobjects of T. */
- finish_struct_anon (t);
+static void
+layout_virtual_bases (t, offsets)
+ tree t;
+ splay_tree offsets;
+{
+ tree vbases;
+ unsigned HOST_WIDE_INT dsize;
+ unsigned HOST_WIDE_INT eoc;
- /* Set the TYPE_DECL for this type to contain the right
- value for DECL_OFFSET, so that we can use it as part
- of a COMPONENT_REF for multiple inheritance. */
+ if (CLASSTYPE_N_BASECLASSES (t) == 0)
+ return;
- layout_decl (TYPE_MAIN_DECL (t), 0);
+#ifdef STRUCTURE_SIZE_BOUNDARY
+ /* Packed structures don't need to have minimum size. */
+ if (! TYPE_PACKED (t))
+ TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), STRUCTURE_SIZE_BOUNDARY);
+#endif
- /* Now fix up any virtual base class types that we left lying
- around. We must get these done before we try to lay out the
- virtual function table. */
- pending_hard_virtuals = nreverse (pending_hard_virtuals);
+ /* DSIZE is the size of the class without the virtual bases. */
+ dsize = tree_low_cst (TYPE_SIZE (t), 1);
- if (n_baseclasses)
- /* layout_basetypes will remove the base subobject fields. */
- max_has_virtual = layout_basetypes (t, max_has_virtual);
- if (empty)
- TYPE_FIELDS (t) = fields;
-
- my_friendly_assert (TYPE_FIELDS (t) == fields, 981117);
-
- /* Delete all zero-width bit-fields from the front of the fieldlist */
- while (fields && DECL_C_BIT_FIELD (fields)
- && DECL_INITIAL (fields))
- fields = TREE_CHAIN (fields);
- /* Delete all such fields from the rest of the fields. */
- for (x = fields; x;)
- {
- if (TREE_CHAIN (x) && DECL_C_BIT_FIELD (TREE_CHAIN (x))
- && DECL_INITIAL (TREE_CHAIN (x)))
- TREE_CHAIN (x) = TREE_CHAIN (TREE_CHAIN (x));
- else
- x = TREE_CHAIN (x);
- }
- TYPE_FIELDS (t) = fields;
+ /* Make every class have alignment of at least one. */
+ TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), BITS_PER_UNIT);
- if (TYPE_USES_VIRTUAL_BASECLASSES (t))
+ /* Go through the virtual bases, allocating space for each virtual
+ base that is not already a primary base class. These are
+ allocated in inheritance graph order. */
+ for (vbases = TYPE_BINFO (t);
+ vbases;
+ vbases = TREE_CHAIN (vbases))
{
- tree vbases;
+ tree vbase;
- vbases = CLASSTYPE_VBASECLASSES (t);
-
- {
- /* Now fixup overrides of all functions in vtables from all
- direct or indirect virtual base classes. */
- tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
- int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+ if (!TREE_VIA_VIRTUAL (vbases))
+ continue;
+ vbase = binfo_for_vbase (BINFO_TYPE (vbases), t);
- for (i = 0; i < n_baseclasses; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree basetype = BINFO_TYPE (base_binfo);
- tree vbases;
+ if (!BINFO_PRIMARY_P (vbase))
+ {
+ /* This virtual base is not a primary base of any class in the
+ hierarchy, so we have to add space for it. */
+ tree basetype;
+ unsigned int desired_align;
+
+ basetype = BINFO_TYPE (vbase);
+
+ desired_align = CLASSTYPE_ALIGN (basetype);
+ TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), desired_align);
+
+ /* Add padding so that we can put the virtual base class at an
+ appropriately aligned offset. */
+ dsize = CEIL (dsize, desired_align) * desired_align;
+
+ /* 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)),
+ offsets, t);
+ else
+ {
+ tree offset;
+
+ offset = ssize_int (CEIL (dsize, BITS_PER_UNIT));
+ offset = size_diffop (offset,
+ convert (ssizetype,
+ BINFO_OFFSET (vbase)));
+
+ /* And compute the offset of the virtual base. */
+ propagate_binfo_offsets (vbase, offset, t);
+ /* 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));
+ }
- vbases = CLASSTYPE_VBASECLASSES (basetype);
- while (vbases)
- {
- merge_overrides (binfo_member (BINFO_TYPE (vbases),
- CLASSTYPE_VBASECLASSES (t)),
- vbases, 1, t);
- vbases = TREE_CHAIN (vbases);
- }
- }
+ /* Keep track of the offsets assigned to this virtual base. */
+ record_subobject_offsets (BINFO_TYPE (vbase),
+ BINFO_OFFSET (vbase),
+ offsets,
+ /*vbases_p=*/0);
}
}
- /* Set up the DECL_FIELD_BITPOS of the vfield if we need to, as we
- might need to know it for setting up the offsets in the vtable
- (or in thunks) below. */
- if (vfield != NULL_TREE
- && DECL_FIELD_CONTEXT (vfield) != t)
+ /* Now, go through the TYPE_BINFO hierarchy, setting the
+ BINFO_OFFSETs correctly for all non-primary copies of the virtual
+ bases and their direct and indirect bases. The ambiguity checks
+ in lookup_base depend on the BINFO_OFFSETs being set
+ correctly. */
+ dfs_walk (TYPE_BINFO (t), dfs_set_offset_for_unshared_vbases, NULL, t);
+
+ /* If we had empty base classes that protruded beyond the end of the
+ 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;
+
+ /* 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);
+ TYPE_SIZE_UNIT (t) = convert (sizetype,
+ size_binop (CEIL_DIV_EXPR, TYPE_SIZE (t),
+ bitsize_unit_node));
+
+ /* Check for ambiguous virtual bases. */
+ if (extra_warnings)
+ for (vbases = CLASSTYPE_VBASECLASSES (t);
+ vbases;
+ vbases = TREE_CHAIN (vbases))
+ {
+ tree basetype = BINFO_TYPE (TREE_VALUE (vbases));
+
+ if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
+ warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
+ basetype, t);
+ }
+}
+
+/* Returns the offset of the byte just past the end of the base class
+ with the highest offset in T. If INCLUDE_VIRTUALS_P is zero, then
+ only non-virtual bases are included. */
+
+static unsigned HOST_WIDE_INT
+end_of_class (t, include_virtuals_p)
+ tree t;
+ int include_virtuals_p;
+{
+ unsigned HOST_WIDE_INT result = 0;
+ int i;
+
+ for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
{
- tree binfo = get_binfo (DECL_FIELD_CONTEXT (vfield), t, 0);
- tree offset = BINFO_OFFSET (binfo);
+ tree base_binfo;
+ tree offset;
+ tree size;
+ unsigned HOST_WIDE_INT end_of_base;
- vfield = copy_node (vfield);
- copy_lang_decl (vfield);
+ base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
- if (! integer_zerop (offset))
- offset = size_binop (MULT_EXPR, offset, size_int (BITS_PER_UNIT));
- DECL_FIELD_CONTEXT (vfield) = t;
- DECL_CLASS_CONTEXT (vfield) = t;
- DECL_FIELD_BITPOS (vfield)
- = size_binop (PLUS_EXPR, offset, DECL_FIELD_BITPOS (vfield));
- CLASSTYPE_VFIELD (t) = vfield;
+ if (!include_virtuals_p
+ && TREE_VIA_VIRTUAL (base_binfo)
+ && !BINFO_PRIMARY_P (base_binfo))
+ continue;
+
+ if (is_empty_class (BINFO_TYPE (base_binfo)))
+ /* An empty class has zero CLASSTYPE_SIZE_UNIT, but we need to
+ allocate some space for it. It cannot have virtual bases,
+ so TYPE_SIZE_UNIT is fine. */
+ size = TYPE_SIZE_UNIT (BINFO_TYPE (base_binfo));
+ else
+ size = CLASSTYPE_SIZE_UNIT (BINFO_TYPE (base_binfo));
+ offset = size_binop (PLUS_EXPR,
+ BINFO_OFFSET (base_binfo),
+ size);
+ end_of_base = tree_low_cst (offset, /*pos=*/1);
+ if (end_of_base > result)
+ result = end_of_base;
}
-
-#ifdef NOTQUITE
- cp_warning ("Doing hard virtuals for %T...", t);
-#endif
- if (has_virtual > max_has_virtual)
- max_has_virtual = has_virtual;
- if (max_has_virtual > 0)
- TYPE_VIRTUAL_P (t) = 1;
+ return result;
+}
+
+/* Warn about direct bases of T that are inaccessible because they are
+ ambiguous. For example:
+
+ struct S {};
+ struct T : public S {};
+ struct U : public S, public T {};
- if (flag_rtti && TYPE_VIRTUAL_P (t) && !pending_hard_virtuals)
- modify_all_vtables (t, NULL_TREE, NULL_TREE);
+ Here, `(S*) new U' is not allowed because there are two `S'
+ subobjects of U. */
- while (pending_hard_virtuals)
+static void
+warn_about_ambiguous_direct_bases (t)
+ tree t;
+{
+ int i;
+
+ for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
{
- modify_all_vtables (t,
- TREE_PURPOSE (pending_hard_virtuals),
- TREE_VALUE (pending_hard_virtuals));
- pending_hard_virtuals = TREE_CHAIN (pending_hard_virtuals);
+ tree basetype = TYPE_BINFO_BASETYPE (t, i);
+
+ if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
+ warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
+ basetype, t);
}
-
- if (TYPE_USES_VIRTUAL_BASECLASSES (t))
- {
- tree vbases;
- /* Now fixup any virtual function entries from virtual bases
- that have different deltas. This has to come after we do the
- pending hard virtuals, as we might have a function that comes
- from multiple virtual base instances that is only overridden
- by a hard virtual above. */
- vbases = CLASSTYPE_VBASECLASSES (t);
- while (vbases)
- {
- /* We might be able to shorten the amount of work we do by
- only doing this for vtables that come from virtual bases
- that have differing offsets, but don't want to miss any
- entries. */
- fixup_vtable_deltas (vbases, 1, t);
- vbases = TREE_CHAIN (vbases);
- }
+}
+
+/* Compare two INTEGER_CSTs K1 and K2. */
+
+static int
+splay_tree_compare_integer_csts (k1, k2)
+ splay_tree_key k1;
+ splay_tree_key k2;
+{
+ return tree_int_cst_compare ((tree) k1, (tree) k2);
+}
+
+/* Calculate the TYPE_SIZE, TYPE_ALIGN, etc for T. Calculate
+ BINFO_OFFSETs for all of the base-classes. Position the vtable
+ pointer. */
+
+static void
+layout_class_type (t, empty_p, vfuns_p,
+ new_virtuals_p, overridden_virtuals_p)
+ tree t;
+ int *empty_p;
+ int *vfuns_p;
+ tree *new_virtuals_p;
+ tree *overridden_virtuals_p;
+{
+ tree non_static_data_members;
+ tree field;
+ tree vptr;
+ record_layout_info rli;
+ unsigned HOST_WIDE_INT eoc;
+ /* Maps offsets (represented as INTEGER_CSTs) to a TREE_LIST of
+ types that appear at that offset. */
+ splay_tree empty_base_offsets;
+
+ /* Keep track of the first non-static data member. */
+ non_static_data_members = TYPE_FIELDS (t);
+
+ /* Start laying out the record. */
+ rli = start_record_layout (t);
+
+ /* If possible, we reuse the virtual function table pointer from one
+ of our base classes. */
+ determine_primary_base (t, 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);
+
+ /* The vptr is always the first thing in the class. */
+ if (vptr)
+ {
+ TYPE_FIELDS (t) = chainon (vptr, TYPE_FIELDS (t));
+ place_field (rli, vptr);
}
- /* Under our model of GC, every C++ class gets its own virtual
- function table, at least virtually. */
- if (pending_virtuals)
+ /* Build FIELD_DECLs for all of the non-virtual base-types. */
+ empty_base_offsets = splay_tree_new (splay_tree_compare_integer_csts,
+ NULL, NULL);
+ if (build_base_fields (rli, empty_p, empty_base_offsets, t))
+ CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
+
+ /* Layout the non-static data members. */
+ for (field = non_static_data_members; field; field = TREE_CHAIN (field))
{
- pending_virtuals = nreverse (pending_virtuals);
- /* We must enter these virtuals into the table. */
- if (first_vfn_base_index < 0)
+ tree type;
+ tree padding;
+
+ /* We still pass things that aren't non-static data members to
+ the back-end, in case it wants to do something with them. */
+ if (TREE_CODE (field) != FIELD_DECL)
{
- if (! CLASSTYPE_COM_INTERFACE (t))
- {
- /* The second slot is for the tdesc pointer when thunks are used. */
- if (flag_vtable_thunks)
- pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals);
+ place_field (rli, field);
+ continue;
+ }
- /* The first slot is for the rtti offset. */
- pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals);
+ type = TREE_TYPE (field);
- set_rtti_entry (pending_virtuals,
- convert (ssizetype, integer_zero_node), t);
- }
- build_vtable (NULL_TREE, t);
+ /* If this field is a bit-field whose width is greater than its
+ type, then there are some special rules for allocating
+ it. */
+ if (DECL_C_BIT_FIELD (field)
+ && INT_CST_LT (TYPE_SIZE (type), DECL_SIZE (field)))
+ {
+ integer_type_kind itk;
+ tree integer_type;
+
+ /* We must allocate the bits as if suitably aligned for the
+ longest integer type that fits in this many bits. type
+ 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])))
+ 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];
+ padding = size_binop (MINUS_EXPR, DECL_SIZE (field),
+ TYPE_SIZE (integer_type));
+ DECL_SIZE (field) = TYPE_SIZE (integer_type);
+ DECL_ALIGN (field) = TYPE_ALIGN (integer_type);
+ DECL_USER_ALIGN (field) = TYPE_USER_ALIGN (integer_type);
}
else
- {
- /* Here we know enough to change the type of our virtual
- function table, but we will wait until later this function. */
+ padding = NULL_TREE;
- if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t)))
- build_vtable (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), first_vfn_base_index), t);
+ layout_nonempty_base_or_field (rli, field, NULL_TREE,
+ empty_base_offsets, t);
+
+ /* If we needed additional padding after this field, add it
+ now. */
+ if (padding)
+ {
+ tree padding_field;
+
+ padding_field = build_decl (FIELD_DECL,
+ NULL_TREE,
+ char_type_node);
+ DECL_BIT_FIELD (padding_field) = 1;
+ DECL_SIZE (padding_field) = padding;
+ DECL_ALIGN (padding_field) = 1;
+ DECL_USER_ALIGN (padding_field) = 0;
+ layout_nonempty_base_or_field (rli, padding_field,
+ NULL_TREE,
+ empty_base_offsets, t);
}
+ }
+
+ /* It might be the case that we grew the class to allocate a
+ zero-sized base class. That won't be reflected in RLI, yet,
+ because we are willing to overlay multiple bases at the same
+ offset. However, now we need to make sure that RLI is big enough
+ to reflect the entire class. */
+ eoc = end_of_class (t, /*include_virtuals_p=*/0);
+ if (TREE_CODE (rli_size_unit_so_far (rli)) == INTEGER_CST
+ && compare_tree_int (rli_size_unit_so_far (rli), eoc) < 0)
+ {
+ rli->offset = size_binop (MAX_EXPR, rli->offset, size_int (eoc));
+ rli->bitpos = bitsize_zero_node;
+ }
+
+ /* We make all structures have at least one element, so that they
+ have non-zero size. The class may be empty even if it has
+ basetypes. Therefore, we add the fake field after all the other
+ fields; if there are already FIELD_DECLs on the list, their
+ offsets will not be disturbed. */
+ if (!eoc && *empty_p)
+ {
+ tree padding;
+
+ padding = build_decl (FIELD_DECL, NULL_TREE, char_type_node);
+ place_field (rli, padding);
+ }
+
+ /* Let the back-end lay out the type. Note that at this point we
+ have only included non-virtual base-classes; we will lay out the
+ virtual base classes later. So, the TYPE_SIZE/TYPE_ALIGN after
+ this call are not necessarily correct; they are just the size and
+ alignment when no virtual base clases are used. */
+ finish_record_layout (rli);
+
+ /* Delete all zero-width bit-fields from the list of fields. Now
+ that the type is laid out they are no longer important. */
+ remove_zero_width_bit_fields (t);
+
+ /* Remember the size and alignment of the class before adding
+ the virtual bases. */
+ if (*empty_p)
+ {
+ CLASSTYPE_SIZE (t) = bitsize_zero_node;
+ CLASSTYPE_SIZE_UNIT (t) = size_zero_node;
+ }
+ else
+ {
+ CLASSTYPE_SIZE (t) = TYPE_BINFO_SIZE (t);
+ CLASSTYPE_SIZE_UNIT (t) = TYPE_BINFO_SIZE_UNIT (t);
+ }
+
+ CLASSTYPE_ALIGN (t) = TYPE_ALIGN (t);
+ CLASSTYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (t);
+
+ /* Set the TYPE_DECL for this type to contain the right
+ value for DECL_OFFSET, so that we can use it as part
+ of a COMPONENT_REF for multiple inheritance. */
+ layout_decl (TYPE_MAIN_DECL (t), 0);
+
+ /* Now fix up any virtual base class types that we left lying
+ around. We must get these done before we try to lay out the
+ virtual function table. As a side-effect, this will remove the
+ base subobject fields. */
+ layout_virtual_bases (t, empty_base_offsets);
+
+ /* Warn about direct bases that can't be talked about due to
+ ambiguity. */
+ warn_about_ambiguous_direct_bases (t);
+
+ /* Clean up. */
+ splay_tree_delete (empty_base_offsets);
+}
+
+/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
+ (or C++ class declaration).
+
+ For C++, we must handle the building of derived classes.
+ Also, C++ allows static class members. The way that this is
+ handled is to keep the field name where it is (as the DECL_NAME
+ of the field), and place the overloaded decl in the bit position
+ of the field. layout_record and layout_union will know about this.
+
+ More C++ hair: inline functions have text in their
+ DECL_PENDING_INLINE_INFO nodes which must somehow be parsed into
+ meaningful tree structure. After the struct has been laid out, set
+ things up so that this can happen.
+
+ And still more: virtual functions. In the case of single inheritance,
+ when a new virtual function is seen which redefines a virtual function
+ from the base class, the new virtual function is placed into
+ the virtual function table at exactly the same address that
+ it had in the base class. When this is extended to multiple
+ inheritance, the same thing happens, except that multiple virtual
+ function tables must be maintained. The first virtual function
+ table is treated in exactly the same way as in the case of single
+ inheritance. Additional virtual function tables have different
+ DELTAs, which tell how to adjust `this' to point to the right thing.
+
+ ATTRIBUTES is the set of decl attributes to be applied, if any. */
+
+void
+finish_struct_1 (t)
+ tree 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;
+ int n_fields = 0;
+ tree vfield;
+ int empty = 1;
+
+ if (COMPLETE_TYPE_P (t))
+ {
+ if (IS_AGGR_TYPE (t))
+ error ("redefinition of `%#T'", t);
+ else
+ abort ();
+ popclass ();
+ 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;
+ CLASSTYPE_GOT_SEMICOLON (t) = 0;
+ CLASSTYPE_PRIMARY_BINFO (t) = NULL_TREE;
+ vfuns = 0;
+ CLASSTYPE_RTTI (t) = NULL_TREE;
+
+ fixup_inline_methods (t);
+
+ /* Do end-of-class semantic processing: checking the validity of the
+ bases and members and add implicitly generated methods. */
+ check_bases_and_members (t, &empty);
+
+ /* Layout the class itself. */
+ layout_class_type (t, &empty, &vfuns,
+ &new_virtuals, &overridden_virtuals);
+
+ /* Make sure that we get our own copy of the vfield FIELD_DECL. */
+ vfield = TYPE_VFIELD (t);
+ if (vfield && CLASSTYPE_HAS_PRIMARY_BASE_P (t))
+ {
+ tree primary = CLASSTYPE_PRIMARY_BINFO (t);
+
+ my_friendly_assert (same_type_p (DECL_FIELD_CONTEXT (vfield),
+ BINFO_TYPE (primary)),
+ 20010726);
+ /* The vtable better be at the start. */
+ my_friendly_assert (integer_zerop (DECL_FIELD_OFFSET (vfield)),
+ 20010726);
+ my_friendly_assert (integer_zerop (BINFO_OFFSET (primary)),
+ 20010726);
+
+ vfield = copy_decl (vfield);
+ DECL_FIELD_CONTEXT (vfield) = t;
+ TYPE_VFIELD (t) = vfield;
+ }
+ else
+ my_friendly_assert (!vfield || DECL_FIELD_CONTEXT (vfield) == t, 20010726);
+
+ overridden_virtuals
+ = modify_all_vtables (t, &vfuns, nreverse (overridden_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 (new_virtuals || overridden_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);
+ else if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t), t))
+ /* Here we know enough to change the type of our virtual
+ function table, but we will wait until later this function. */
+ build_primary_vtable (CLASSTYPE_PRIMARY_BINFO (t), t);
/* If this type has basetypes with constructors, then those
constructors might clobber the virtual function table. But
@@ -4285,80 +5119,66 @@ finish_struct_1 (t, warn_anon)
CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
}
- else if (first_vfn_base_index >= 0)
+ /* If we didn't need a new vtable, see if we should copy one from
+ the base. */
+ else if (CLASSTYPE_HAS_PRIMARY_BASE_P (t))
{
- tree binfo = TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), first_vfn_base_index);
- /* This class contributes nothing new to the virtual function
- table. However, it may have declared functions which
- went into the virtual function table "inherited" from the
- base class. If so, we grab a copy of those updated functions,
- and pretend they are ours. */
+ tree binfo = CLASSTYPE_PRIMARY_BINFO (t);
- /* See if we should steal the virtual info from base class. */
- if (TYPE_BINFO_VTABLE (t) == NULL_TREE)
- TYPE_BINFO_VTABLE (t) = BINFO_VTABLE (binfo);
- if (TYPE_BINFO_VIRTUALS (t) == NULL_TREE)
- TYPE_BINFO_VIRTUALS (t) = BINFO_VIRTUALS (binfo);
+ /* If this class uses a different vtable than its primary base
+ then when we will need to initialize our vptr after the base
+ class constructor runs. */
if (TYPE_BINFO_VTABLE (t) != BINFO_VTABLE (binfo))
CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
}
- if (max_has_virtual || first_vfn_base_index >= 0)
- {
- CLASSTYPE_VSIZE (t) = has_virtual;
- if (first_vfn_base_index >= 0)
- {
- if (pending_virtuals)
- TYPE_BINFO_VIRTUALS (t) = chainon (TYPE_BINFO_VIRTUALS (t),
- pending_virtuals);
- }
- else if (has_virtual)
- {
- TYPE_BINFO_VIRTUALS (t) = pending_virtuals;
- DECL_VIRTUAL_P (TYPE_BINFO_VTABLE (t)) = 1;
- }
- }
-
- /* Now lay out the virtual function table. */
- if (has_virtual)
+ if (TYPE_CONTAINS_VPTR_P (t))
{
- /* Use size_int so values are memoized in common cases. */
- tree itype = build_index_type (size_int (has_virtual));
- tree atype = build_cplus_array_type (vtable_entry_type, itype);
-
- layout_type (atype);
+ if (TYPE_BINFO_VTABLE (t))
+ my_friendly_assert (DECL_VIRTUAL_P (TYPE_BINFO_VTABLE (t)),
+ 20000116);
+ if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
+ my_friendly_assert (TYPE_BINFO_VIRTUALS (t) == NULL_TREE,
+ 20000116);
- CLASSTYPE_VFIELD (t) = vfield;
-
- /* We may have to grow the vtable. */
- if (TREE_TYPE (TYPE_BINFO_VTABLE (t)) != atype)
- {
- TREE_TYPE (TYPE_BINFO_VTABLE (t)) = atype;
- DECL_SIZE (TYPE_BINFO_VTABLE (t)) = 0;
- layout_decl (TYPE_BINFO_VTABLE (t), 0);
- /* 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 (TYPE_BINFO_VTABLE (t))
- = MAX (TYPE_ALIGN (double_type_node),
- DECL_ALIGN (TYPE_BINFO_VTABLE (t)));
- }
+ 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);
}
- else if (first_vfn_base_index >= 0)
- CLASSTYPE_VFIELD (t) = vfield;
- CLASSTYPE_VFIELDS (t) = vfields;
- finish_struct_bits (t, max_has_virtual);
+ finish_struct_bits (t);
/* Complete the rtl for any static member objects of the type we're
working on. */
- for (x = fields; x; x = TREE_CHAIN (x))
+ for (x = TYPE_FIELDS (t); x; x = TREE_CHAIN (x))
+ if (TREE_CODE (x) == VAR_DECL && TREE_STATIC (x)
+ && TREE_TYPE (x) == t)
+ DECL_MODE (x) = TYPE_MODE (t);
+
+ /* Done with FIELDS...now decide whether to sort these for
+ faster lookups later.
+
+ The C front-end only does this when n_fields > 15. We use
+ a smaller number because most searches fail (succeeding
+ ultimately as the search bores through the inheritance
+ hierarchy), and we want this failure to occur quickly. */
+
+ n_fields = count_fields (TYPE_FIELDS (t));
+ if (n_fields > 7)
{
- if (TREE_CODE (x) == VAR_DECL && TREE_STATIC (x)
- && TREE_TYPE (x) == t)
- {
- DECL_MODE (x) = TYPE_MODE (t);
- make_decl_rtl (x, NULL, 0);
- }
+ tree field_vec = make_tree_vec (n_fields);
+ add_fields_to_vec (TYPE_FIELDS (t), field_vec, 0);
+ qsort (&TREE_VEC_ELT (field_vec, 0), n_fields, sizeof (tree),
+ (int (*)(const void *, const void *))field_decl_cmp);
+ if (! DECL_LANG_SPECIFIC (TYPE_MAIN_DECL (t)))
+ retrofit_lang_decl (TYPE_MAIN_DECL (t));
+ DECL_SORTED_FIELDS (TYPE_MAIN_DECL (t)) = field_vec;
}
if (TYPE_HAS_CONSTRUCTOR (t))
@@ -4376,108 +5196,28 @@ finish_struct_1 (t, warn_anon)
}
}
- /* Write out inline function definitions. */
- do_inline_function_hair (t, inline_friends);
-
- if (CLASSTYPE_VSIZE (t) != 0)
- {
-#if 0
- /* This is now done above. */
- if (DECL_FIELD_CONTEXT (vfield) != t)
- {
- tree binfo = get_binfo (DECL_FIELD_CONTEXT (vfield), t, 0);
- tree offset = BINFO_OFFSET (binfo);
-
- vfield = copy_node (vfield);
- copy_lang_decl (vfield);
-
- if (! integer_zerop (offset))
- offset = size_binop (MULT_EXPR, offset, size_int (BITS_PER_UNIT));
- DECL_FIELD_CONTEXT (vfield) = t;
- DECL_CLASS_CONTEXT (vfield) = t;
- DECL_FIELD_BITPOS (vfield)
- = size_binop (PLUS_EXPR, offset, DECL_FIELD_BITPOS (vfield));
- CLASSTYPE_VFIELD (t) = vfield;
- }
-#endif
-
- /* In addition to this one, all the other vfields should be listed. */
- /* Before that can be done, we have to have FIELD_DECLs for them, and
- a place to find them. */
- TYPE_NONCOPIED_PARTS (t)
- = tree_cons (default_conversion (TYPE_BINFO_VTABLE (t)),
- vfield, TYPE_NONCOPIED_PARTS (t));
-
- if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (t)
- && DECL_VINDEX (TREE_VEC_ELT (method_vec, 1)) == NULL_TREE)
- cp_warning ("`%#T' has virtual functions but non-virtual destructor",
- t);
- }
-
/* Make the rtl for any new vtables we have created, and unmark
the base types we marked. */
- finish_vtbls (TYPE_BINFO (t), 1, t);
- /* If we use thunks, and have virtual bases, we might need to emit
- additional vtables. */
- if (flag_vtable_thunks && TYPE_USES_PVBASES (t))
- finish_ctor_vtables (t);
- hack_incomplete_structures (t);
+ finish_vtbls (t);
+
+ /* Build the VTT for T. */
+ build_vtt (t);
-#if 0
- if (TYPE_NAME (t) && TYPE_IDENTIFIER (t))
- undo_template_name_overload (TYPE_IDENTIFIER (t), 1);
-#endif
+ if (warn_nonvdtor && TYPE_POLYMORPHIC_P (t) && TYPE_HAS_DESTRUCTOR (t)
+ && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1)) == NULL_TREE)
+ warning ("`%#T' has virtual functions but non-virtual destructor", t);
- resume_momentary (old);
+ hack_incomplete_structures (t);
if (warn_overloaded_virtual)
warn_hidden (t);
-#if 0
- /* This has to be done after we have sorted out what to do with
- the enclosing type. */
- if (write_symbols != DWARF_DEBUG)
- {
- /* Be smarter about nested classes here. If a type is nested,
- only output it if we would output the enclosing type. */
- if (DECL_CLASS_SCOPE_P (TYPE_MAIN_DECL (t)))
- DECL_IGNORED_P (TYPE_MAIN_DECL (t)) = TREE_ASM_WRITTEN (TYPE_MAIN_DECL (t));
- }
-#endif
-
- if (write_symbols != DWARF_DEBUG && write_symbols != DWARF2_DEBUG)
- {
- /* If the type has methods, we want to think about cutting down
- the amount of symbol table stuff we output. The value stored in
- the TYPE_DECL's DECL_IGNORED_P slot is a first approximation.
- For example, if a member function is seen and we decide to
- write out that member function, then we can change the value
- of the DECL_IGNORED_P slot, and the type will be output when
- that member function's debug info is written out.
-
- We can't do this with DWARF, which does not support name
- references between translation units. */
- if (CLASSTYPE_METHOD_VEC (t))
- {
- /* Don't output full info about any type
- which does not have its implementation defined here. */
- if (CLASSTYPE_INTERFACE_ONLY (t))
- TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
-#if 0
- /* XXX do something about this. */
- else if (CLASSTYPE_INTERFACE_UNKNOWN (t))
- /* Only a first approximation! */
- TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
-#endif
- }
- else if (CLASSTYPE_INTERFACE_ONLY (t))
- TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
- }
+ maybe_suppress_debug_info (t);
+ dump_class_hierarchy (t);
+
/* Finish debugging output for this type. */
- rest_of_type_compilation (t, toplevel_bindings_p ());
-
- return;
+ rest_of_type_compilation (t, ! LOCAL_CLASS_P (t));
}
/* When T was built up, the member declarations were added in reverse
@@ -4516,69 +5256,47 @@ unreverse_member_declarations (t)
}
tree
-finish_struct (t, attributes, warn_anon)
+finish_struct (t, attributes)
tree t, attributes;
- int warn_anon;
{
- tree name = TYPE_NAME (t);
-
- if (TREE_CODE (name) == TYPE_DECL)
- {
- extern int lineno;
-
- DECL_SOURCE_FILE (name) = input_filename;
- /* For TYPE_DECL that are not typedefs (those marked with a line
- number of zero, we don't want to mark them as real typedefs.
- If this fails one needs to make sure real typedefs have a
- previous line number, even if it is wrong, that way the below
- will fill in the right line number. (mrs) */
- if (DECL_SOURCE_LINE (name))
- DECL_SOURCE_LINE (name) = lineno;
- name = DECL_NAME (name);
- }
-
- /* Append the fields we need for constructing signature tables. */
- if (IS_SIGNATURE (t))
- append_signature_fields (t);
+ const char *saved_filename = input_filename;
+ int saved_lineno = lineno;
/* Now that we've got all the field declarations, reverse everything
as necessary. */
unreverse_member_declarations (t);
- cplus_decl_attributes (t, attributes, NULL_TREE);
+ cplus_decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
+
+ /* Nadger the current location so that diagnostics point to the start of
+ the struct, not the end. */
+ input_filename = DECL_SOURCE_FILE (TYPE_NAME (t));
+ lineno = DECL_SOURCE_LINE (TYPE_NAME (t));
if (processing_template_decl)
{
- tree d = getdecls ();
- for (; d; d = TREE_CHAIN (d))
- {
- /* If this is the decl for the class or one of the template
- parms, we've seen all the injected decls. */
- if ((TREE_CODE (d) == TYPE_DECL
- && (TREE_TYPE (d) == t
- || TREE_CODE (TREE_TYPE (d)) == TEMPLATE_TYPE_PARM
- || TREE_CODE (TREE_TYPE (d)) == TEMPLATE_TEMPLATE_PARM))
- || TREE_CODE (d) == CONST_DECL)
- break;
- /* Don't inject cache decls. */
- else if (IDENTIFIER_TEMPLATE (DECL_NAME (d)))
- continue;
- DECL_TEMPLATE_INJECT (CLASSTYPE_TI_TEMPLATE (t))
- = tree_cons (NULL_TREE, d,
- DECL_TEMPLATE_INJECT (CLASSTYPE_TI_TEMPLATE (t)));
- }
finish_struct_methods (t);
- TYPE_SIZE (t) = integer_zero_node;
- }
+ TYPE_SIZE (t) = bitsize_zero_node;
+ }
else
- finish_struct_1 (t, warn_anon);
+ finish_struct_1 (t);
+
+ input_filename = saved_filename;
+ lineno = saved_lineno;
TYPE_BEING_DEFINED (t) = 0;
if (current_class_type)
popclass ();
else
- error ("trying to finish struct, but kicked out due to previous parse errors.");
+ 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));
+ }
return t;
}
@@ -4588,21 +5306,24 @@ finish_struct (t, attributes, warn_anon)
or not.
*NONNULL is set iff INSTANCE can be known to be nonnull, regardless
- of our knowledge of its type. */
+ of our knowledge of its type. *NONNULL should be initialized
+ before this function is called. */
static tree
-fixed_type_or_null (instance, nonnull)
+fixed_type_or_null (instance, nonnull, cdtorp)
tree instance;
int *nonnull;
+ int *cdtorp;
{
switch (TREE_CODE (instance))
{
case INDIRECT_REF:
- /* Check that we are not going through a cast of some sort. */
- if (TREE_TYPE (instance)
- == TREE_TYPE (TREE_TYPE (TREE_OPERAND (instance, 0))))
- instance = TREE_OPERAND (instance, 0);
- /* fall through... */
+ if (POINTER_TYPE_P (TREE_TYPE (instance)))
+ return NULL_TREE;
+ else
+ return fixed_type_or_null (TREE_OPERAND (instance, 0),
+ nonnull, cdtorp);
+
case CALL_EXPR:
/* This is a call to a constructor, hence it's never zero. */
if (TREE_HAS_CONSTRUCTOR (instance))
@@ -4621,31 +5342,31 @@ fixed_type_or_null (instance, nonnull)
*nonnull = 1;
return TREE_TYPE (instance);
}
- return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull);
+ return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
case RTL_EXPR:
return NULL_TREE;
case PLUS_EXPR:
case MINUS_EXPR:
+ if (TREE_CODE (TREE_OPERAND (instance, 0)) == ADDR_EXPR)
+ return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
if (TREE_CODE (TREE_OPERAND (instance, 1)) == INTEGER_CST)
/* Propagate nonnull. */
- fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull);
- if (TREE_CODE (TREE_OPERAND (instance, 0)) == ADDR_EXPR)
- return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull);
+ fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
return NULL_TREE;
case NOP_EXPR:
case CONVERT_EXPR:
- return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull);
+ return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
case ADDR_EXPR:
if (nonnull)
*nonnull = 1;
- return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull);
+ return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
case COMPONENT_REF:
- return fixed_type_or_null (TREE_OPERAND (instance, 1), nonnull);
+ return fixed_type_or_null (TREE_OPERAND (instance, 1), nonnull, cdtorp);
case VAR_DECL:
case FIELD_DECL:
@@ -4665,21 +5386,25 @@ fixed_type_or_null (instance, nonnull)
*nonnull = 1;
return TREE_TYPE (instance);
}
- else if (nonnull)
- {
- if (instance == current_class_ptr
- && flag_this_is_variable <= 0)
- {
- /* Normally, 'this' must be non-null. */
- if (flag_this_is_variable == 0)
- *nonnull = 1;
-
- /* <0 means we're in a constructor and we know our type. */
- if (flag_this_is_variable < 0)
- return TREE_TYPE (TREE_TYPE (instance));
- }
- else if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
- /* Reference variables should be references to objects. */
+ else if (instance == current_class_ptr)
+ {
+ if (nonnull)
+ *nonnull = 1;
+
+ /* if we're in a ctor or dtor, we know our type. */
+ if (DECL_LANG_SPECIFIC (current_function_decl)
+ && (DECL_CONSTRUCTOR_P (current_function_decl)
+ || DECL_DESTRUCTOR_P (current_function_decl)))
+ {
+ if (cdtorp)
+ *cdtorp = 1;
+ return TREE_TYPE (TREE_TYPE (instance));
+ }
+ }
+ else if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
+ {
+ /* Reference variables should be references to objects. */
+ if (nonnull)
*nonnull = 1;
}
return NULL_TREE;
@@ -4689,15 +5414,19 @@ fixed_type_or_null (instance, nonnull)
}
}
-/* Return non-zero if the dynamic type of INSTANCE is known, and equivalent
- to the static type. We also handle the case where INSTANCE is really
- a pointer.
+/* Return non-zero if the dynamic type of INSTANCE is known, and
+ equivalent to the static type. We also handle the case where
+ INSTANCE is really a pointer. Return negative if this is a
+ ctor/dtor. There the dynamic type is known, but this might not be
+ the most derived base of the original object, and hence virtual
+ bases may not be layed out according to this type.
Used to determine whether the virtual function table is needed
or not.
*NONNULL is set iff INSTANCE can be known to be nonnull, regardless
- of our knowledge of its type. */
+ of our knowledge of its type. *NONNULL should be initialized
+ before this function is called. */
int
resolves_to_fixed_type_p (instance, nonnull)
@@ -4705,12 +5434,16 @@ resolves_to_fixed_type_p (instance, nonnull)
int *nonnull;
{
tree t = TREE_TYPE (instance);
- tree fixed = fixed_type_or_null (instance, nonnull);
+ int cdtorp = 0;
+
+ tree fixed = fixed_type_or_null (instance, nonnull, &cdtorp);
if (fixed == NULL_TREE)
return 0;
if (POINTER_TYPE_P (t))
t = TREE_TYPE (t);
- return same_type_p (TYPE_MAIN_VARIANT (t), TYPE_MAIN_VARIANT (fixed));
+ if (!same_type_ignoring_top_level_qualifiers_p (t, fixed))
+ return 0;
+ return cdtorp ? -1 : 1;
}
@@ -4722,25 +5455,21 @@ init_class_processing ()
current_class_stack
= (class_stack_node_t) xmalloc (current_class_stack_size
* sizeof (struct class_stack_node));
-
- current_lang_stacksize = 10;
- current_lang_base = (tree *)xmalloc(current_lang_stacksize * sizeof (tree));
- current_lang_stack = current_lang_base;
+ 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 (1, 0);
- access_protected_node = build_int_2 (2, 0);
- access_private_node = build_int_2 (3, 0);
+ access_public_node = build_int_2 (ak_public, 0);
+ access_protected_node = build_int_2 (ak_protected, 0);
+ access_private_node = build_int_2 (ak_private, 0);
access_default_virtual_node = build_int_2 (4, 0);
- access_public_virtual_node = build_int_2 (5, 0);
- access_protected_virtual_node = build_int_2 (6, 0);
- access_private_virtual_node = build_int_2 (7, 0);
+ access_public_virtual_node = build_int_2 (4 | ak_public, 0);
+ access_protected_virtual_node = build_int_2 (4 | ak_protected, 0);
+ access_private_virtual_node = build_int_2 (4 | ak_private, 0);
- /* Keep these values lying around. */
- base_layout_decl = build_lang_field_decl (FIELD_DECL, NULL_TREE, error_mark_node);
- TREE_TYPE (base_layout_decl) = make_node (RECORD_TYPE);
-
- gcc_obstack_init (&class_obstack);
+ ridpointers[(int) RID_PUBLIC] = access_public_node;
+ ridpointers[(int) RID_PRIVATE] = access_private_node;
+ ridpointers[(int) RID_PROTECTED] = access_protected_node;
}
/* Set current scope to NAME. CODE tells us if this is a
@@ -4815,17 +5544,11 @@ pushclass (type, modify)
if (previous_class_type != NULL_TREE
&& (type != previous_class_type
- || TYPE_SIZE (previous_class_type) == NULL_TREE)
+ || !COMPLETE_TYPE_P (previous_class_type))
&& current_class_depth == 1)
{
/* Forcibly remove any old class remnants. */
invalidate_class_lookup_cache ();
-
- /* Now, free the obstack on which we cached all the values. */
- if (class_cache_firstobj)
- obstack_free (&class_cache_obstack, class_cache_firstobj);
- class_cache_firstobj
- = (char*) obstack_finish (&class_cache_obstack);
}
/* If we're about to enter a nested class, clear
@@ -4835,11 +5558,6 @@ pushclass (type, modify)
pushlevel_class ();
-#if 0
- if (CLASSTYPE_TEMPLATE_INFO (type))
- overload_template_name (type);
-#endif
-
if (modify)
{
if (type != previous_class_type || current_class_depth > 1)
@@ -4880,12 +5598,11 @@ invalidate_class_lookup_cache ()
{
tree t;
- /* This code can be seen as a cache miss. When we've cached a
- class' scope's bindings and we can't use them, we need to reset
- them. This is it! */
+ /* 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;
}
@@ -4895,7 +5612,7 @@ invalidate_class_lookup_cache ()
void
popclass ()
{
- poplevel (1, 0, 0);
+ 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 ();
@@ -4908,7 +5625,9 @@ popclass ()
splay_tree_delete (current_class_stack[current_class_depth].names_used);
}
-/* Returns 1 if current_class_type is either T or a nested type of T. */
+/* Returns 1 if current_class_type is either T or a nested type of T.
+ We start looking from 1 because entry 0 is from global scope, and has
+ no type. */
int
currently_open_class (t)
@@ -4917,12 +5636,32 @@ currently_open_class (t)
int i;
if (t == current_class_type)
return 1;
- for (i = 0; i < current_class_depth; ++i)
+ for (i = 1; i < current_class_depth; ++i)
if (current_class_stack [i].type == t)
return 1;
return 0;
}
+/* If either current_class_type or one of its enclosing classes are derived
+ from T, return the appropriate type. Used to determine how we found
+ something via unqualified lookup. */
+
+tree
+currently_open_derived_class (t)
+ tree t;
+{
+ int i;
+
+ if (DERIVED_FROM_P (t, current_class_type))
+ return current_class_type;
+
+ for (i = current_class_depth - 1; i > 0; --i)
+ if (DERIVED_FROM_P (t, current_class_stack[i].type))
+ return current_class_stack[i].type;
+
+ 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 pushclass for all
@@ -4938,10 +5677,12 @@ push_nested_class (type, modify)
tree context;
/* A namespace might be passed in error cases, like A::B:C. */
- if (type == NULL_TREE || type == error_mark_node || ! IS_AGGR_TYPE (type)
+ if (type == NULL_TREE
+ || type == error_mark_node
|| TREE_CODE (type) == NAMESPACE_DECL
+ || ! IS_AGGR_TYPE (type)
|| TREE_CODE (type) == TEMPLATE_TYPE_PARM
- || TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
+ || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
return;
context = DECL_CONTEXT (TYPE_MAIN_DECL (type));
@@ -4963,6 +5704,14 @@ pop_nested_class ()
pop_nested_class ();
}
+/* Returns the number of extern "LANG" blocks we are nested within. */
+
+int
+current_lang_depth ()
+{
+ return VARRAY_ACTIVE_SIZE (current_lang_base);
+}
+
/* Set global variables CURRENT_LANG_NAME to appropriate value
so that behavior of name-mangling machinery is correct. */
@@ -4970,41 +5719,30 @@ void
push_lang_context (name)
tree name;
{
- *current_lang_stack++ = current_lang_name;
- if (current_lang_stack >= current_lang_base + current_lang_stacksize)
- {
- current_lang_base
- = (tree *)xrealloc (current_lang_base,
- sizeof (tree) * (current_lang_stacksize + 10));
- current_lang_stack = current_lang_base + current_lang_stacksize;
- current_lang_stacksize += 10;
- }
+ VARRAY_PUSH_TREE (current_lang_base, current_lang_name);
if (name == lang_name_cplusplus)
{
- strict_prototype = strict_prototypes_lang_cplusplus;
current_lang_name = name;
}
else if (name == lang_name_java)
{
- strict_prototype = strict_prototypes_lang_cplusplus;
current_lang_name = name;
/* DECL_IGNORED_P is initially set for these types, to avoid clutter.
(See record_builtin_java_type in decl.c.) However, that causes
incorrect debug entries if these types are actually used.
So we re-enable debug output after extern "Java". */
- DECL_IGNORED_P (java_byte_type_node) = 0;
- DECL_IGNORED_P (java_short_type_node) = 0;
- DECL_IGNORED_P (java_int_type_node) = 0;
- DECL_IGNORED_P (java_long_type_node) = 0;
- DECL_IGNORED_P (java_float_type_node) = 0;
- DECL_IGNORED_P (java_double_type_node) = 0;
- DECL_IGNORED_P (java_char_type_node) = 0;
- DECL_IGNORED_P (java_boolean_type_node) = 0;
+ DECL_IGNORED_P (TYPE_NAME (java_byte_type_node)) = 0;
+ DECL_IGNORED_P (TYPE_NAME (java_short_type_node)) = 0;
+ DECL_IGNORED_P (TYPE_NAME (java_int_type_node)) = 0;
+ DECL_IGNORED_P (TYPE_NAME (java_long_type_node)) = 0;
+ DECL_IGNORED_P (TYPE_NAME (java_float_type_node)) = 0;
+ DECL_IGNORED_P (TYPE_NAME (java_double_type_node)) = 0;
+ DECL_IGNORED_P (TYPE_NAME (java_char_type_node)) = 0;
+ DECL_IGNORED_P (TYPE_NAME (java_boolean_type_node)) = 0;
}
else if (name == lang_name_c)
{
- strict_prototype = strict_prototypes_lang_c;
current_lang_name = name;
}
else
@@ -5016,12 +5754,8 @@ push_lang_context (name)
void
pop_lang_context ()
{
- current_lang_name = *--current_lang_stack;
- if (current_lang_name == lang_name_cplusplus
- || current_lang_name == lang_name_java)
- strict_prototype = strict_prototypes_lang_cplusplus;
- else if (current_lang_name == lang_name_c)
- strict_prototype = strict_prototypes_lang_c;
+ current_lang_name = VARRAY_TOP_TREE (current_lang_base);
+ VARRAY_POP (current_lang_base);
}
/* Type instantiation routines. */
@@ -5029,19 +5763,22 @@ pop_lang_context ()
/* Given an OVERLOAD and a TARGET_TYPE, return the function that
matches the TARGET_TYPE. If there is no satisfactory match, return
error_mark_node, and issue an error message if COMPLAIN is
- non-zero. If TEMPLATE_ONLY, the name of the overloaded function
+ non-zero. Permit pointers to member function if PTRMEM is non-zero.
+ If TEMPLATE_ONLY, the name of the overloaded function
was a template-id, and EXPLICIT_TARGS are the explicitly provided
template arguments. */
static tree
resolve_address_of_overloaded_function (target_type,
overload,
- complain,
+ complain,
+ ptrmem,
template_only,
explicit_targs)
tree target_type;
tree overload;
int complain;
+ int ptrmem;
int template_only;
tree explicit_targs;
{
@@ -5086,10 +5823,12 @@ resolve_address_of_overloaded_function (target_type,
&& (TREE_CODE (TREE_TYPE (target_type))
== METHOD_TYPE)), 0);
+ if (TREE_CODE (overload) == COMPONENT_REF)
+ overload = TREE_OPERAND (overload, 1);
+
/* Check that the TARGET_TYPE is reasonable. */
if (TYPE_PTRFN_P (target_type))
- /* This is OK. */
- ;
+ /* This is OK. */;
else if (TYPE_PTRMEMFUNC_P (target_type))
/* This is OK, too. */
is_ptrmem = 1;
@@ -5103,8 +5842,9 @@ resolve_address_of_overloaded_function (target_type,
else
{
if (complain)
- cp_error("cannot resolve overloaded function `%D' based on conversion to type `%T'",
- DECL_NAME (OVL_FUNCTION (overload)), target_type);
+ error ("\
+cannot resolve overloaded function `%D' based on conversion to type `%T'",
+ DECL_NAME (OVL_FUNCTION (overload)), target_type);
return error_mark_node;
}
@@ -5139,7 +5879,7 @@ resolve_address_of_overloaded_function (target_type,
fntype = build_pointer_type (fntype);
if (can_convert_arg (target_type, fntype, fn))
- matches = scratch_tree_cons (fn, NULL_TREE, matches);
+ matches = tree_cons (fn, NULL_TREE, matches);
}
}
@@ -5150,6 +5890,7 @@ resolve_address_of_overloaded_function (target_type,
{
tree target_fn_type;
tree target_arg_types;
+ tree target_ret_type;
tree fns;
if (is_ptrmem)
@@ -5158,6 +5899,11 @@ resolve_address_of_overloaded_function (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);
for (fns = overload; fns; fns = OVL_CHAIN (fns))
{
@@ -5177,10 +5923,10 @@ resolve_address_of_overloaded_function (target_type,
continue;
/* Try to do argument deduction. */
- targs = make_scratch_vec (DECL_NTPARMS (fn));
+ targs = make_tree_vec (DECL_NTPARMS (fn));
if (fn_type_unification (fn, explicit_targs, targs,
- target_arg_types, NULL_TREE,
- DEDUCE_EXACT) != 0)
+ target_arg_types, target_ret_type,
+ DEDUCE_EXACT, -1) != 0)
/* Argument deduction failed. */
continue;
@@ -5198,17 +5944,16 @@ resolve_address_of_overloaded_function (target_type,
else if (!is_reference)
instantiation_type = build_pointer_type (instantiation_type);
if (can_convert_arg (target_type, instantiation_type, instantiation))
- matches = scratch_tree_cons (instantiation, fn, matches);
+ matches = tree_cons (instantiation, fn, matches);
}
/* Now, remove all but the most specialized of the matches. */
if (matches)
{
- tree match = most_specialized_instantiation (matches,
- explicit_targs);
+ tree match = most_specialized_instantiation (matches);
if (match != error_mark_node)
- matches = scratch_tree_cons (match, NULL_TREE, NULL_TREE);
+ matches = tree_cons (match, NULL_TREE, NULL_TREE);
}
}
@@ -5218,7 +5963,7 @@ resolve_address_of_overloaded_function (target_type,
/* There were *no* matches. */
if (complain)
{
- cp_error ("no matches converting function `%D' to type `%#T'",
+ error ("no matches converting function `%D' to type `%#T'",
DECL_NAME (OVL_FUNCTION (overload)),
target_type);
@@ -5226,8 +5971,8 @@ resolve_address_of_overloaded_function (target_type,
TREE_VALUE slots, so we cons one up here (we're losing anyway,
so why be clever?). */
for (; overload; overload = OVL_NEXT (overload))
- matches = scratch_tree_cons (NULL_TREE, OVL_CURRENT (overload),
- matches);
+ matches = tree_cons (NULL_TREE, OVL_CURRENT (overload),
+ matches);
print_candidates (matches);
}
@@ -5241,7 +5986,7 @@ resolve_address_of_overloaded_function (target_type,
{
tree match;
- cp_error ("converting overloaded function `%D' to type `%#T' is ambiguous",
+ error ("converting overloaded function `%D' to type `%#T' is ambiguous",
DECL_NAME (OVL_FUNCTION (overload)),
target_type);
@@ -5259,6 +6004,21 @@ resolve_address_of_overloaded_function (target_type,
/* Good, exactly one match. Now, convert it to the correct type. */
fn = TREE_PURPOSE (matches);
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+ && !ptrmem && !flag_ms_extensions)
+ {
+ static int explained;
+
+ if (!complain)
+ return error_mark_node;
+
+ pedwarn ("assuming pointer to member `%D'", fn);
+ if (!explained)
+ {
+ pedwarn ("(a pointer to member can only be formed with `&%E')", fn);
+ explained = 1;
+ }
+ }
mark_used (fn);
if (TYPE_PTRFN_P (target_type) || TYPE_PTRMEMFUNC_P (target_type))
@@ -5276,24 +6036,26 @@ resolve_address_of_overloaded_function (target_type,
/* This function will instantiate the type of the expression given in
RHS to match the type of LHSTYPE. If errors exist, then return
- error_mark_node. We only complain is COMPLAIN is set. If we are
- not complaining, never modify rhs, as overload resolution wants to
- try many possible instantiations, in hopes that at least one will
- work.
-
- FLAGS is a bitmask, as we see at the top of the function.
-
+ error_mark_node. FLAGS is a bit mask. If ITF_COMPLAIN is set, then
+ we complain on errors. If we are not complaining, never modify rhs,
+ as overload resolution wants to try many possible instantiations, in
+ the hope that at least one will work.
+
For non-recursive calls, LHSTYPE should be a function, pointer to
function, or a pointer to member function. */
tree
instantiate_type (lhstype, rhs, flags)
tree lhstype, rhs;
- int flags;
+ enum instantiate_type_flags flags;
{
- int complain = (flags & 1);
- int strict = (flags & 2) ? COMPARE_NO_ATTRIBUTES : COMPARE_STRICT;
-
+ int complain = (flags & itf_complain);
+ int strict = (flags & itf_no_attributes)
+ ? COMPARE_NO_ATTRIBUTES : COMPARE_STRICT;
+ int allow_ptrmem = flags & itf_ptrmem_ok;
+
+ flags &= ~itf_ptrmem_ok;
+
if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
{
if (complain)
@@ -5306,7 +6068,7 @@ instantiate_type (lhstype, rhs, flags)
if (comptypes (lhstype, TREE_TYPE (rhs), strict))
return rhs;
if (complain)
- cp_error ("argument of type `%T' does not match `%T'",
+ error ("argument of type `%T' does not match `%T'",
TREE_TYPE (rhs), lhstype);
return error_mark_node;
}
@@ -5328,7 +6090,7 @@ instantiate_type (lhstype, rhs, flags)
case SAVE_EXPR:
case CONSTRUCTOR:
case BUFFER_REF:
- my_friendly_abort (177);
+ abort ();
return error_mark_node;
case INDIRECT_REF:
@@ -5352,40 +6114,13 @@ instantiate_type (lhstype, rhs, flags)
return instantiate_type (lhstype, rhs, flags);
case COMPONENT_REF:
- {
- tree field = TREE_OPERAND (rhs, 1);
- tree r;
-
- r = instantiate_type (lhstype, field, flags);
-
- if (r != error_mark_node && TYPE_PTRMEMFUNC_P (lhstype))
- {
- if (complain)
- {
- tree t = TYPE_PTRMEMFUNC_OBJECT_TYPE (lhstype);
-
- if (TREE_CODE (field) == OVERLOAD)
- field = OVL_FUNCTION (field);
- if (TREE_CODE (field) == FUNCTION_DECL)
- {
- cp_pedwarn ("object-dependent reference `%E' can only be used in a call",
- DECL_NAME (field));
- cp_pedwarn (" to form a pointer to member function, say `&%T::%E'",
- t, DECL_NAME (field));
- }
- else
- cp_pedwarn ("object-dependent reference can only be used in a call");
- }
- return r;
- }
-
- return r;
- }
+ return instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
case OFFSET_REF:
rhs = TREE_OPERAND (rhs, 1);
if (BASELINK_P (rhs))
- return instantiate_type (lhstype, TREE_VALUE (rhs), flags);
+ return instantiate_type (lhstype, TREE_VALUE (rhs),
+ flags | allow_ptrmem);
/* This can happen if we are forming a pointer-to-member for a
member template. */
@@ -5394,18 +6129,25 @@ instantiate_type (lhstype, rhs, flags)
/* Fall through. */
case TEMPLATE_ID_EXPR:
- return
- resolve_address_of_overloaded_function (lhstype,
- TREE_OPERAND (rhs, 0),
- complain,
- /*template_only=*/1,
- TREE_OPERAND (rhs, 1));
+ {
+ tree fns = TREE_OPERAND (rhs, 0);
+ tree args = TREE_OPERAND (rhs, 1);
+
+ return
+ resolve_address_of_overloaded_function (lhstype,
+ fns,
+ complain,
+ allow_ptrmem,
+ /*template_only=*/1,
+ args);
+ }
case OVERLOAD:
return
resolve_address_of_overloaded_function (lhstype,
rhs,
complain,
+ allow_ptrmem,
/*template_only=*/0,
/*explicit_targs=*/NULL_TREE);
@@ -5417,7 +6159,7 @@ instantiate_type (lhstype, rhs, flags)
case CALL_EXPR:
/* This is too hard for now. */
- my_friendly_abort (183);
+ abort ();
return error_mark_node;
case PLUS_EXPR:
@@ -5517,17 +6259,21 @@ instantiate_type (lhstype, rhs, flags)
return rhs;
case ADDR_EXPR:
+ {
+ if (PTRMEM_OK_P (rhs))
+ flags |= itf_ptrmem_ok;
+
return instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags);
-
+ }
case ENTRY_VALUE_EXPR:
- my_friendly_abort (184);
+ abort ();
return error_mark_node;
case ERROR_MARK:
return error_mark_node;
default:
- my_friendly_abort (185);
+ abort ();
return error_mark_node;
}
}
@@ -5546,7 +6292,7 @@ get_vfield_name (type)
char *buf;
while (BINFO_BASETYPES (binfo)
- && TYPE_VIRTUAL_P (BINFO_TYPE (BINFO_BASETYPE (binfo, 0)))
+ && TYPE_CONTAINS_VPTR_P (BINFO_TYPE (BINFO_BASETYPE (binfo, 0)))
&& ! TREE_VIA_VIRTUAL (BINFO_BASETYPE (binfo, 0)))
binfo = BINFO_BASETYPE (binfo, 0);
@@ -5575,27 +6321,6 @@ print_class_statistics ()
#endif
}
-/* Push an obstack which is sufficiently long-lived to hold such class
- decls that may be cached in the previous_class_values list. The
- effect is undone by pop_obstacks. */
-
-void
-push_cache_obstack ()
-{
- static int cache_obstack_initialized;
-
- if (!cache_obstack_initialized)
- {
- gcc_obstack_init (&class_cache_obstack);
- class_cache_firstobj
- = (char*) obstack_finish (&class_cache_obstack);
- cache_obstack_initialized = 1;
- }
-
- push_obstacks_nochange ();
- current_obstack = &class_cache_obstack;
-}
-
/* Build a dummy reference to ourselves so Derived::Base (and A::A) works,
according to [class]:
The class-name is also inserted
@@ -5611,9 +6336,11 @@ build_self_reference ()
DECL_NONLOCAL (value) = 1;
DECL_CONTEXT (value) = current_class_type;
- DECL_CLASS_CONTEXT (value) = current_class_type;
DECL_ARTIFICIAL (value) = 1;
+ if (processing_template_decl)
+ value = push_template_decl (value);
+
saved_cas = current_access_specifier;
current_access_specifier = access_public_node;
finish_member_declaration (value);
@@ -5626,23 +6353,13 @@ int
is_empty_class (type)
tree type;
{
- tree t;
-
if (type == error_mark_node)
return 0;
if (! IS_AGGR_TYPE (type))
return 0;
- if (flag_new_abi)
- return CLASSTYPE_SIZE (type) == integer_zero_node;
-
- if (TYPE_BINFO_BASETYPES (type))
- return 0;
- t = TYPE_FIELDS (type);
- while (t && TREE_CODE (t) != FIELD_DECL)
- t = TREE_CHAIN (t);
- return (t == NULL_TREE);
+ return integer_zerop (CLASSTYPE_SIZE (type));
}
/* Find the enclosing class of the given NODE. NODE can be a *_DECL or
@@ -5669,7 +6386,7 @@ get_enclosing_class (type)
break;
default:
- my_friendly_abort (0);
+ abort ();
}
}
return NULL_TREE;
@@ -5683,7 +6400,7 @@ is_base_of_enclosing_class (base, type)
{
while (type)
{
- if (get_binfo (base, type, 0))
+ if (lookup_base (type, base, ba_any, NULL))
return 1;
type = get_enclosing_class (type);
@@ -5745,9 +6462,1576 @@ note_name_declared_in_class (name, decl)
A name N used in a class S shall refer to the same declaration
in its context and when re-evaluated in the completed scope of
S. */
- cp_error ("declaration of `%#D'", decl);
- cp_error_at ("changes meaning of `%s' from `%+#D'",
- IDENTIFIER_POINTER (DECL_NAME (decl)),
+ error ("declaration of `%#D'", decl);
+ cp_error_at ("changes meaning of `%D' from `%+#D'",
+ DECL_NAME (OVL_CURRENT (decl)),
(tree) n->value);
}
}
+
+/* Returns the VAR_DECL for the complete vtable associated with BINFO.
+ Secondary vtables are merged with primary vtables; this function
+ will return the VAR_DECL for the primary vtable. */
+
+tree
+get_vtbl_decl_for_binfo (binfo)
+ tree binfo;
+{
+ tree decl;
+
+ decl = BINFO_VTABLE (binfo);
+ if (decl && TREE_CODE (decl) == PLUS_EXPR)
+ {
+ my_friendly_assert (TREE_CODE (TREE_OPERAND (decl, 0)) == ADDR_EXPR,
+ 2000403);
+ decl = TREE_OPERAND (TREE_OPERAND (decl, 0), 0);
+ }
+ if (decl)
+ my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 20000403);
+ return decl;
+}
+
+/* Called from get_primary_binfo via dfs_walk. DATA is a TREE_LIST
+ who's TREE_PURPOSE is the TYPE of the required primary base and
+ who's TREE_VALUE is a list of candidate binfos that we fill in. */
+
+static tree
+dfs_get_primary_binfo (binfo, data)
+ tree binfo;
+ void *data;
+{
+ tree cons = (tree) data;
+ tree primary_base = TREE_PURPOSE (cons);
+
+ if (TREE_VIA_VIRTUAL (binfo)
+ && same_type_p (BINFO_TYPE (binfo), primary_base))
+ /* This is the right type of binfo, but it might be an unshared
+ instance, and the shared instance is later in the dfs walk. We
+ must keep looking. */
+ TREE_VALUE (cons) = tree_cons (NULL, binfo, TREE_VALUE (cons));
+
+ return NULL_TREE;
+}
+
+/* Returns the unshared binfo for the primary base of BINFO. Note
+ that in a complex hierarchy the resulting BINFO may not actually
+ *be* primary. In particular if the resulting BINFO is a virtual
+ base, and it occurs elsewhere in the hierarchy, then this
+ occurrence may not actually be a primary base in the complete
+ object. Check BINFO_PRIMARY_P to be sure. */
+
+tree
+get_primary_binfo (binfo)
+ tree binfo;
+{
+ tree primary_base;
+ tree result = NULL_TREE;
+ tree virtuals;
+
+ primary_base = CLASSTYPE_PRIMARY_BINFO (BINFO_TYPE (binfo));
+ if (!primary_base)
+ return NULL_TREE;
+
+ /* A non-virtual primary base is always a direct base, and easy to
+ find. */
+ if (!TREE_VIA_VIRTUAL (primary_base))
+ {
+ int i;
+
+ /* Scan the direct basetypes until we find a base with the same
+ type as the primary base. */
+ for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
+ {
+ tree base_binfo = BINFO_BASETYPE (binfo, i);
+
+ if (same_type_p (BINFO_TYPE (base_binfo),
+ BINFO_TYPE (primary_base)))
+ return base_binfo;
+ }
+
+ /* We should always find the primary base. */
+ abort ();
+ }
+
+ /* For a primary virtual base, we have to scan the entire hierarchy
+ rooted at BINFO; the virtual base could be an indirect virtual
+ base. There could be more than one instance of the primary base
+ in the hierarchy, and if one is the canonical binfo we want that
+ one. If it exists, it should be the first one we find, but as a
+ consistency check we find them all and make sure. */
+ virtuals = build_tree_list (BINFO_TYPE (primary_base), NULL_TREE);
+ dfs_walk (binfo, dfs_get_primary_binfo, NULL, virtuals);
+ virtuals = TREE_VALUE (virtuals);
+
+ /* We must have found at least one instance. */
+ my_friendly_assert (virtuals, 20010612);
+
+ if (TREE_CHAIN (virtuals))
+ {
+ /* We found more than one instance of the base. We must make
+ sure that, if one is the canonical one, it is the first one
+ we found. As the chain is in reverse dfs order, that means
+ the last on the list. */
+ tree complete_binfo;
+ tree canonical;
+
+ for (complete_binfo = binfo;
+ BINFO_INHERITANCE_CHAIN (complete_binfo);
+ complete_binfo = BINFO_INHERITANCE_CHAIN (complete_binfo))
+ continue;
+ canonical = binfo_for_vbase (BINFO_TYPE (primary_base),
+ BINFO_TYPE (complete_binfo));
+
+ for (; virtuals; virtuals = TREE_CHAIN (virtuals))
+ {
+ result = TREE_VALUE (virtuals);
+
+ if (canonical == result)
+ {
+ /* This is the unshared instance. Make sure it was the
+ first one found. */
+ my_friendly_assert (!TREE_CHAIN (virtuals), 20010612);
+ break;
+ }
+ }
+ }
+ else
+ result = TREE_VALUE (virtuals);
+ return result;
+}
+
+/* If INDENTED_P is zero, indent to INDENT. Return non-zero. */
+
+static int
+maybe_indent_hierarchy (stream, indent, indented_p)
+ FILE *stream;
+ int indent;
+ int indented_p;
+{
+ if (!indented_p)
+ fprintf (stream, "%*s", indent, "");
+ return 1;
+}
+
+/* Dump the offsets of all the bases rooted at BINFO (in the hierarchy
+ dominated by T) to stderr. INDENT should be zero when called from
+ the top level; it is incremented recursively. */
+
+static void
+dump_class_hierarchy_r (stream, flags, t, binfo, indent)
+ FILE *stream;
+ int flags;
+ tree t;
+ tree binfo;
+ int indent;
+{
+ int i;
+ int indented = 0;
+
+ indented = maybe_indent_hierarchy (stream, indent, 0);
+ fprintf (stream, "%s (0x%lx) ",
+ type_as_string (binfo, TFF_PLAIN_IDENTIFIER),
+ (unsigned long) binfo);
+ fprintf (stream, HOST_WIDE_INT_PRINT_DEC,
+ tree_low_cst (BINFO_OFFSET (binfo), 0));
+ if (is_empty_class (BINFO_TYPE (binfo)))
+ fprintf (stream, " empty");
+ else if (CLASSTYPE_NEARLY_EMPTY_P (BINFO_TYPE (binfo)))
+ fprintf (stream, " nearly-empty");
+ if (TREE_VIA_VIRTUAL (binfo))
+ {
+ tree canonical = binfo_for_vbase (BINFO_TYPE (binfo), t);
+
+ fprintf (stream, " virtual");
+ if (canonical == binfo)
+ fprintf (stream, " canonical");
+ else
+ fprintf (stream, " non-canonical");
+ }
+ fprintf (stream, "\n");
+
+ indented = 0;
+ if (BINFO_PRIMARY_BASE_OF (binfo))
+ {
+ indented = maybe_indent_hierarchy (stream, indent + 3, indented);
+ fprintf (stream, " primary-for %s (0x%lx)",
+ type_as_string (BINFO_PRIMARY_BASE_OF (binfo),
+ TFF_PLAIN_IDENTIFIER),
+ (unsigned long)BINFO_PRIMARY_BASE_OF (binfo));
+ }
+ if (BINFO_LOST_PRIMARY_P (binfo))
+ {
+ indented = maybe_indent_hierarchy (stream, indent + 3, indented);
+ fprintf (stream, " lost-primary");
+ }
+ if (indented)
+ fprintf (stream, "\n");
+
+ if (!(flags & TDF_SLIM))
+ {
+ int indented = 0;
+
+ if (BINFO_SUBVTT_INDEX (binfo))
+ {
+ indented = maybe_indent_hierarchy (stream, indent + 3, indented);
+ fprintf (stream, " subvttidx=%s",
+ expr_as_string (BINFO_SUBVTT_INDEX (binfo),
+ TFF_PLAIN_IDENTIFIER));
+ }
+ if (BINFO_VPTR_INDEX (binfo))
+ {
+ indented = maybe_indent_hierarchy (stream, indent + 3, indented);
+ fprintf (stream, " vptridx=%s",
+ expr_as_string (BINFO_VPTR_INDEX (binfo),
+ TFF_PLAIN_IDENTIFIER));
+ }
+ if (BINFO_VPTR_FIELD (binfo))
+ {
+ indented = maybe_indent_hierarchy (stream, indent + 3, indented);
+ fprintf (stream, " vbaseoffset=%s",
+ expr_as_string (BINFO_VPTR_FIELD (binfo),
+ TFF_PLAIN_IDENTIFIER));
+ }
+ if (BINFO_VTABLE (binfo))
+ {
+ indented = maybe_indent_hierarchy (stream, indent + 3, indented);
+ fprintf (stream, " vptr=%s",
+ expr_as_string (BINFO_VTABLE (binfo),
+ TFF_PLAIN_IDENTIFIER));
+ }
+
+ if (indented)
+ fprintf (stream, "\n");
+ }
+
+
+ for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
+ dump_class_hierarchy_r (stream, flags,
+ t, BINFO_BASETYPE (binfo, i),
+ indent + 2);
+}
+
+/* Dump the BINFO hierarchy for T. */
+
+static void
+dump_class_hierarchy (t)
+ tree t;
+{
+ int flags;
+ FILE *stream = dump_begin (TDI_class, &flags);
+
+ if (!stream)
+ return;
+
+ fprintf (stream, "Class %s\n", type_as_string (t, TFF_PLAIN_IDENTIFIER));
+ fprintf (stream, " size=%lu align=%lu\n",
+ (unsigned long)(tree_low_cst (TYPE_SIZE (t), 0) / BITS_PER_UNIT),
+ (unsigned long)(TYPE_ALIGN (t) / BITS_PER_UNIT));
+ dump_class_hierarchy_r (stream, flags, t, TYPE_BINFO (t), 0);
+ fprintf (stream, "\n");
+ dump_end (TDI_class, stream);
+}
+
+static void
+dump_array (stream, decl)
+ FILE *stream;
+ tree decl;
+{
+ tree inits;
+ int ix;
+ HOST_WIDE_INT elt;
+ tree size = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (decl)));
+
+ elt = (tree_low_cst (TYPE_SIZE (TREE_TYPE (TREE_TYPE (decl))), 0)
+ / BITS_PER_UNIT);
+ fprintf (stream, "%s:", decl_as_string (decl, TFF_PLAIN_IDENTIFIER));
+ fprintf (stream, " %s entries",
+ expr_as_string (size_binop (PLUS_EXPR, size, size_one_node),
+ TFF_PLAIN_IDENTIFIER));
+ fprintf (stream, "\n");
+
+ for (ix = 0, inits = TREE_OPERAND (DECL_INITIAL (decl), 1);
+ inits; ix++, inits = TREE_CHAIN (inits))
+ fprintf (stream, "%-4ld %s\n", (long)(ix * elt),
+ expr_as_string (TREE_VALUE (inits), TFF_PLAIN_IDENTIFIER));
+}
+
+static void
+dump_vtable (t, binfo, vtable)
+ tree t;
+ tree binfo;
+ tree vtable;
+{
+ int flags;
+ FILE *stream = dump_begin (TDI_class, &flags);
+
+ if (!stream)
+ return;
+
+ if (!(flags & TDF_SLIM))
+ {
+ int ctor_vtbl_p = TYPE_BINFO (t) != binfo;
+
+ fprintf (stream, "%s for %s",
+ ctor_vtbl_p ? "Construction vtable" : "Vtable",
+ type_as_string (binfo, TFF_PLAIN_IDENTIFIER));
+ if (ctor_vtbl_p)
+ {
+ if (!TREE_VIA_VIRTUAL (binfo))
+ fprintf (stream, " (0x%lx instance)", (unsigned long)binfo);
+ fprintf (stream, " in %s", type_as_string (t, TFF_PLAIN_IDENTIFIER));
+ }
+ fprintf (stream, "\n");
+ dump_array (stream, vtable);
+ fprintf (stream, "\n");
+ }
+
+ dump_end (TDI_class, stream);
+}
+
+static void
+dump_vtt (t, vtt)
+ tree t;
+ tree vtt;
+{
+ int flags;
+ FILE *stream = dump_begin (TDI_class, &flags);
+
+ if (!stream)
+ return;
+
+ if (!(flags & TDF_SLIM))
+ {
+ fprintf (stream, "VTT for %s\n",
+ type_as_string (t, TFF_PLAIN_IDENTIFIER));
+ dump_array (stream, vtt);
+ fprintf (stream, "\n");
+ }
+
+ dump_end (TDI_class, stream);
+}
+
+/* Virtual function table initialization. */
+
+/* Create all the necessary vtables for T and its base classes. */
+
+static void
+finish_vtbls (t)
+ tree t;
+{
+ tree list;
+ tree vbase;
+ int i;
+
+ /* 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);
+ 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))
+ {
+ tree real_base;
+
+ if (!TREE_VIA_VIRTUAL (vbase))
+ continue;
+
+ /* Although we walk in inheritance order, that might not get the
+ canonical base. */
+ real_base = binfo_for_vbase (BINFO_TYPE (vbase), t);
+
+ accumulate_vtbl_inits (real_base, real_base,
+ TYPE_BINFO (t), t, list);
+ }
+
+ /* Fill in BINFO_VPTR_FIELD in the immediate binfos for our virtual
+ base classes, for the benefit of the debugging backends. */
+ for (i = 0; i < BINFO_N_BASETYPES (TYPE_BINFO (t)); ++i)
+ {
+ tree base = BINFO_BASETYPE (TYPE_BINFO (t), i);
+ if (TREE_VIA_VIRTUAL (base))
+ {
+ vbase = binfo_for_vbase (BINFO_TYPE (base), t);
+ BINFO_VPTR_FIELD (base) = BINFO_VPTR_FIELD (vbase);
+ }
+ }
+
+ if (TYPE_BINFO_VTABLE (t))
+ initialize_vtable (TYPE_BINFO (t), TREE_VALUE (list));
+}
+
+/* Initialize the vtable for BINFO with the INITS. */
+
+static void
+initialize_vtable (binfo, inits)
+ tree binfo;
+ tree inits;
+{
+ tree decl;
+
+ layout_vtable_decl (binfo, list_length (inits));
+ decl = get_vtbl_decl_for_binfo (binfo);
+ initialize_array (decl, inits);
+ dump_vtable (BINFO_TYPE (binfo), binfo, decl);
+}
+
+/* Initialize DECL (a declaration for a namespace-scope array) with
+ the INITS. */
+
+static void
+initialize_array (decl, inits)
+ tree decl;
+ tree inits;
+{
+ tree context;
+
+ context = DECL_CONTEXT (decl);
+ DECL_CONTEXT (decl) = NULL_TREE;
+ DECL_INITIAL (decl) = build_nt (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.
+ A class requires a VTT if it has virtual bases.
+
+ This holds
+ 1 - primary virtual pointer for complete object T
+ 2 - secondary VTTs for each direct non-virtual base of T which requires a
+ VTT
+ 3 - secondary virtual pointers for each direct or indirect base of T which
+ has virtual bases or is reachable via a virtual path from T.
+ 4 - secondary VTTs for each direct or indirect virtual base of T.
+
+ Secondary VTTs look like complete object VTTs without part 4. */
+
+static void
+build_vtt (t)
+ tree t;
+{
+ tree inits;
+ tree type;
+ tree vtt;
+ tree index;
+
+ /* Build up the initializers for the VTT. */
+ inits = NULL_TREE;
+ index = size_zero_node;
+ build_vtt_inits (TYPE_BINFO (t), t, &inits, &index);
+
+ /* If we didn't need a VTT, we're done. */
+ if (!inits)
+ return;
+
+ /* Figure out the type of the VTT. */
+ type = build_index_type (size_int (list_length (inits) - 1));
+ type = build_cplus_array_type (const_ptr_type_node, type);
+
+ /* Now, build the VTT object itself. */
+ vtt = build_vtable (t, get_vtt_name (t), type);
+ pushdecl_top_level (vtt);
+ initialize_array (vtt, inits);
+
+ dump_vtt (t, vtt);
+}
+
+/* The type corresponding to BASE_BINFO is a base of the type of BINFO, but
+ from within some hierarchy which is inherited from the type of BINFO.
+ Return BASE_BINFO's equivalent binfo from the hierarchy dominated by
+ BINFO. */
+
+static tree
+get_original_base (base_binfo, binfo)
+ tree base_binfo;
+ tree binfo;
+{
+ tree derived;
+ int ix;
+
+ if (same_type_p (BINFO_TYPE (base_binfo), BINFO_TYPE (binfo)))
+ return binfo;
+ if (TREE_VIA_VIRTUAL (base_binfo))
+ return binfo_for_vbase (BINFO_TYPE (base_binfo), BINFO_TYPE (binfo));
+ derived = get_original_base (BINFO_INHERITANCE_CHAIN (base_binfo), binfo);
+
+ for (ix = 0; ix != BINFO_N_BASETYPES (derived); ix++)
+ if (same_type_p (BINFO_TYPE (base_binfo),
+ BINFO_TYPE (BINFO_BASETYPE (derived, ix))))
+ return BINFO_BASETYPE (derived, ix);
+ abort ();
+ return NULL;
+}
+
+/* When building a secondary VTT, BINFO_VTABLE is set to a TREE_LIST with
+ PURPOSE the RTTI_BINFO, VALUE the real vtable pointer for this binfo,
+ and CHAIN the vtable pointer for this binfo after construction is
+ complete. VALUE can also be another BINFO, in which case we recurse. */
+
+static tree
+binfo_ctor_vtable (binfo)
+ tree binfo;
+{
+ tree vt;
+
+ while (1)
+ {
+ vt = BINFO_VTABLE (binfo);
+ if (TREE_CODE (vt) == TREE_LIST)
+ vt = TREE_VALUE (vt);
+ if (TREE_CODE (vt) == TREE_VEC)
+ binfo = vt;
+ else
+ break;
+ }
+
+ return vt;
+}
+
+/* Recursively build the VTT-initializer for BINFO (which is in the
+ hierarchy dominated by T). INITS points to the end of the initializer
+ list to date. INDEX is the VTT index where the next element will be
+ replaced. Iff BINFO is the binfo for T, this is the top level VTT (i.e.
+ not a subvtt for some base of T). When that is so, we emit the sub-VTTs
+ 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 (binfo, t, inits, index)
+ tree binfo;
+ tree t;
+ tree *inits;
+ tree *index;
+{
+ int i;
+ tree b;
+ tree init;
+ tree secondary_vptrs;
+ int top_level_p = same_type_p (TREE_TYPE (binfo), t);
+
+ /* We only need VTTs for subobjects with virtual bases. */
+ if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
+ return inits;
+
+ /* We need to use a construction vtable if this is not the primary
+ VTT. */
+ if (!top_level_p)
+ {
+ build_ctor_vtbl_group (binfo, t);
+
+ /* Record the offset in the VTT where this sub-VTT can be found. */
+ BINFO_SUBVTT_INDEX (binfo) = *index;
+ }
+
+ /* 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);
+ if (top_level_p)
+ {
+ my_friendly_assert (!BINFO_VPTR_INDEX (binfo), 20010129);
+ BINFO_VPTR_INDEX (binfo) = *index;
+ }
+ *index = size_binop (PLUS_EXPR, *index, TYPE_SIZE_UNIT (ptr_type_node));
+
+ /* Recursively add the secondary VTTs for non-virtual bases. */
+ for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
+ {
+ b = BINFO_BASETYPE (binfo, i);
+ if (!TREE_VIA_VIRTUAL (b))
+ inits = build_vtt_inits (BINFO_BASETYPE (binfo, i), t,
+ inits, index);
+ }
+
+ /* 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. */
+ secondary_vptrs = tree_cons (t, NULL_TREE, BINFO_TYPE (binfo));
+ TREE_TYPE (secondary_vptrs) = *index;
+ VTT_TOP_LEVEL_P (secondary_vptrs) = top_level_p;
+ VTT_MARKED_BINFO_P (secondary_vptrs) = 0;
+
+ dfs_walk_real (binfo,
+ dfs_build_secondary_vptr_vtt_inits,
+ NULL,
+ dfs_ctor_vtable_bases_queue_p,
+ secondary_vptrs);
+ VTT_MARKED_BINFO_P (secondary_vptrs) = 1;
+ dfs_walk (binfo, dfs_unmark, dfs_ctor_vtable_bases_queue_p,
+ secondary_vptrs);
+
+ *index = TREE_TYPE (secondary_vptrs);
+
+ /* 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 = TREE_VALUE (secondary_vptrs);
+ if (secondary_vptrs)
+ {
+ *inits = nreverse (secondary_vptrs);
+ inits = &TREE_CHAIN (secondary_vptrs);
+ my_friendly_assert (*inits == NULL_TREE, 20000517);
+ }
+
+ /* Add the secondary VTTs for virtual bases. */
+ if (top_level_p)
+ for (b = TYPE_BINFO (BINFO_TYPE (binfo)); b; b = TREE_CHAIN (b))
+ {
+ tree vbase;
+
+ if (!TREE_VIA_VIRTUAL (b))
+ continue;
+
+ vbase = binfo_for_vbase (BINFO_TYPE (b), t);
+ inits = build_vtt_inits (vbase, t, inits, index);
+ }
+
+ if (!top_level_p)
+ {
+ tree data = tree_cons (t, binfo, NULL_TREE);
+ VTT_TOP_LEVEL_P (data) = 0;
+ VTT_MARKED_BINFO_P (data) = 0;
+
+ dfs_walk (binfo, dfs_fixup_binfo_vtbls,
+ dfs_ctor_vtable_bases_queue_p,
+ data);
+ }
+
+ return inits;
+}
+
+/* Called from build_vtt_inits via dfs_walk. BINFO is the binfo
+ for the base in most derived. DATA is a TREE_LIST who's
+ TREE_CHAIN is the type of the base being
+ constructed whilst this secondary vptr is live. The TREE_UNSIGNED
+ flag of DATA indicates that this is a constructor vtable. The
+ TREE_TOP_LEVEL flag indicates that this is the primary VTT. */
+
+static tree
+dfs_build_secondary_vptr_vtt_inits (binfo, data)
+ tree binfo;
+ void *data;
+{
+ tree l;
+ tree t;
+ tree init;
+ tree index;
+ int top_level_p;
+
+ l = (tree) data;
+ t = TREE_CHAIN (l);
+ top_level_p = VTT_TOP_LEVEL_P (l);
+
+ SET_BINFO_MARKED (binfo);
+
+ /* We don't care about bases that don't have vtables. */
+ if (!TYPE_VFIELD (BINFO_TYPE (binfo)))
+ return NULL_TREE;
+
+ /* We're only interested in proper subobjects of T. */
+ if (same_type_p (BINFO_TYPE (binfo), t))
+ return NULL_TREE;
+
+ /* We're not interested in non-virtual primary bases. */
+ if (!TREE_VIA_VIRTUAL (binfo) && BINFO_PRIMARY_P (binfo))
+ return NULL_TREE;
+
+ /* If BINFO has virtual bases or is reachable via a virtual path
+ from T, it'll have a secondary vptr. */
+ if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo))
+ && !binfo_via_virtual (binfo, t))
+ return NULL_TREE;
+
+ /* Record the index where this secondary vptr can be found. */
+ index = TREE_TYPE (l);
+ if (top_level_p)
+ {
+ my_friendly_assert (!BINFO_VPTR_INDEX (binfo), 20010129);
+ BINFO_VPTR_INDEX (binfo) = index;
+ }
+ TREE_TYPE (l) = size_binop (PLUS_EXPR, index,
+ TYPE_SIZE_UNIT (ptr_type_node));
+
+ /* Add the initializer for the secondary vptr itself. */
+ if (top_level_p && TREE_VIA_VIRTUAL (binfo))
+ {
+ /* It's a primary virtual base, and this is not the construction
+ vtable. Find the base this is primary of in the inheritance graph,
+ and use that base's vtable now. */
+ while (BINFO_PRIMARY_BASE_OF (binfo))
+ binfo = BINFO_PRIMARY_BASE_OF (binfo);
+ }
+ init = binfo_ctor_vtable (binfo);
+ TREE_VALUE (l) = tree_cons (NULL_TREE, init, TREE_VALUE (l));
+
+ return NULL_TREE;
+}
+
+/* dfs_walk_real predicate for building vtables. DATA is a TREE_LIST,
+ VTT_MARKED_BINFO_P indicates whether marked or unmarked bases
+ should be walked. TREE_PURPOSE is the TREE_TYPE that dominates the
+ hierarchy. */
+
+static tree
+dfs_ctor_vtable_bases_queue_p (binfo, data)
+ tree binfo;
+ void *data;
+{
+ if (TREE_VIA_VIRTUAL (binfo))
+ /* Get the shared version. */
+ binfo = binfo_for_vbase (BINFO_TYPE (binfo), TREE_PURPOSE ((tree) data));
+
+ if (!BINFO_MARKED (binfo) == VTT_MARKED_BINFO_P ((tree) data))
+ return NULL_TREE;
+ return binfo;
+}
+
+/* Called from build_vtt_inits via dfs_walk. After building constructor
+ vtables and generating the sub-vtt from them, we need to restore the
+ BINFO_VTABLES that were scribbled on. DATA is a TREE_LIST whose
+ TREE_VALUE is the TREE_TYPE of the base whose sub vtt was generated. */
+
+static tree
+dfs_fixup_binfo_vtbls (binfo, data)
+ tree binfo;
+ void *data;
+{
+ CLEAR_BINFO_MARKED (binfo);
+
+ /* We don't care about bases that don't have vtables. */
+ if (!TYPE_VFIELD (BINFO_TYPE (binfo)))
+ return NULL_TREE;
+
+ /* If we scribbled the construction vtable vptr into BINFO, clear it
+ out now. */
+ if (BINFO_VTABLE (binfo)
+ && TREE_CODE (BINFO_VTABLE (binfo)) == TREE_LIST
+ && (TREE_PURPOSE (BINFO_VTABLE (binfo))
+ == TREE_VALUE ((tree) data)))
+ BINFO_VTABLE (binfo) = TREE_CHAIN (BINFO_VTABLE (binfo));
+
+ return NULL_TREE;
+}
+
+/* Build the construction vtable group for BINFO which is in the
+ hierarchy dominated by T. */
+
+static void
+build_ctor_vtbl_group (binfo, t)
+ tree binfo;
+ tree t;
+{
+ tree list;
+ tree type;
+ tree vtbl;
+ tree inits;
+ tree id;
+ tree vbase;
+
+ /* See if we've already created this construction vtable group. */
+ id = mangle_ctor_vtbl_for_type (t, binfo);
+ if (IDENTIFIER_GLOBAL_VALUE (id))
+ return;
+
+ my_friendly_assert (!same_type_p (BINFO_TYPE (binfo), t), 20010124);
+ /* Build a version of VTBL (with the wrong type) for use in
+ constructing the addresses of secondary vtables in the
+ construction vtable group. */
+ vtbl = build_vtable (t, id, ptr_type_node);
+ list = build_tree_list (vtbl, NULL_TREE);
+ accumulate_vtbl_inits (binfo, TYPE_BINFO (TREE_TYPE (binfo)),
+ binfo, t, list);
+
+ /* Add the vtables for each of our virtual bases using the vbase in T
+ binfo. */
+ for (vbase = TYPE_BINFO (BINFO_TYPE (binfo));
+ vbase;
+ vbase = TREE_CHAIN (vbase))
+ {
+ tree b;
+ tree orig_base;
+
+ if (!TREE_VIA_VIRTUAL (vbase))
+ continue;
+ b = binfo_for_vbase (BINFO_TYPE (vbase), t);
+ orig_base = binfo_for_vbase (BINFO_TYPE (vbase), BINFO_TYPE (binfo));
+
+ accumulate_vtbl_inits (b, orig_base, binfo, t, list);
+ }
+ inits = TREE_VALUE (list);
+
+ /* Figure out the type of the construction vtable. */
+ type = build_index_type (size_int (list_length (inits) - 1));
+ type = build_cplus_array_type (vtable_entry_type, type);
+ TREE_TYPE (vtbl) = type;
+
+ /* Initialize the construction vtable. */
+ pushdecl_top_level (vtbl);
+ initialize_array (vtbl, inits);
+ dump_vtable (t, binfo, vtbl);
+}
+
+/* Add the vtbl initializers for BINFO (and its bases other than
+ non-virtual primaries) to the list of INITS. BINFO is in the
+ hierarchy dominated by T. RTTI_BINFO is the binfo within T of
+ the constructor the vtbl inits should be accumulated for. (If this
+ is the complete object vtbl then RTTI_BINFO will be TYPE_BINFO (T).)
+ ORIG_BINFO is the binfo for this object within BINFO_TYPE (RTTI_BINFO).
+ BINFO is the active base equivalent of ORIG_BINFO in the inheritance
+ graph of T. Both BINFO and ORIG_BINFO will have the same BINFO_TYPE,
+ but are not necessarily the same in terms of layout. */
+
+static void
+accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, inits)
+ tree binfo;
+ tree orig_binfo;
+ tree rtti_binfo;
+ tree t;
+ tree inits;
+{
+ int i;
+ int ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
+
+ my_friendly_assert (same_type_p (BINFO_TYPE (binfo),
+ BINFO_TYPE (orig_binfo)),
+ 20000517);
+
+ /* If it doesn't have a vptr, we don't do anything. */
+ if (!TYPE_CONTAINS_VPTR_P (BINFO_TYPE (binfo)))
+ return;
+
+ /* If we're building a construction vtable, we're not interested in
+ subobjects that don't require construction vtables. */
+ if (ctor_vtbl_p
+ && !TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo))
+ && !binfo_via_virtual (orig_binfo, BINFO_TYPE (rtti_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));
+
+ /* 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
+ 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)
+ {
+ tree base_binfo = BINFO_BASETYPE (binfo, i);
+
+ /* Skip virtual bases. */
+ if (TREE_VIA_VIRTUAL (base_binfo))
+ continue;
+ accumulate_vtbl_inits (base_binfo,
+ BINFO_BASETYPE (orig_binfo, i),
+ rtti_binfo, t,
+ inits);
+ }
+}
+
+/* Called from accumulate_vtbl_inits. Returns the initializers for
+ the BINFO vtable. */
+
+static tree
+dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
+ tree binfo;
+ tree orig_binfo;
+ tree rtti_binfo;
+ tree t;
+ tree l;
+{
+ tree inits = NULL_TREE;
+ tree vtbl = NULL_TREE;
+ 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))
+ {
+ /* In the hierarchy of BINFO_TYPE (RTTI_BINFO), this is a
+ primary virtual base. If it is not the same primary in
+ the hierarchy of T, we'll need to generate a ctor vtable
+ for it, to place at its location in T. If it is the same
+ primary, we still need a VTT entry for the vtable, but it
+ should point to the ctor vtable for the base it is a
+ primary for within the sub-hierarchy of RTTI_BINFO.
+
+ There are three possible cases:
+
+ 1) We are in the same place.
+ 2) We are a primary base within a lost primary virtual base of
+ RTTI_BINFO.
+ 3) We are primary to something not a base of RTTI_BINFO. */
+
+ tree b = BINFO_PRIMARY_BASE_OF (binfo);
+ tree last = NULL_TREE;
+
+ /* First, look through the bases we are primary to for RTTI_BINFO
+ or a virtual base. */
+ for (; b; b = BINFO_PRIMARY_BASE_OF (b))
+ {
+ last = b;
+ if (TREE_VIA_VIRTUAL (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)
+ break;
+
+ /* If we found RTTI_BINFO, this is case 1. If we found a virtual
+ base B and it is a base of RTTI_BINFO, this is case 2. In
+ either case, we share our vtable with LAST, i.e. the
+ derived-most base within B of which we are a primary. */
+ if (b == 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. */
+ vtbl = last;
+
+ /* Otherwise, this is case 3 and we get our own. */
+ }
+ else if (!BINFO_NEW_VTABLE_MARKED (orig_binfo, BINFO_TYPE (rtti_binfo)))
+ return inits;
+
+ 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);
+
+ /* Figure out the position to which the VPTR should point. */
+ vtbl = TREE_PURPOSE (l);
+ vtbl = build1 (ADDR_EXPR,
+ vtbl_ptr_type_node,
+ vtbl);
+ TREE_CONSTANT (vtbl) = 1;
+ index = size_binop (PLUS_EXPR,
+ size_int (non_fn_entries),
+ size_int (list_length (TREE_VALUE (l))));
+ index = size_binop (MULT_EXPR,
+ TYPE_SIZE_UNIT (vtable_entry_type),
+ index);
+ vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);
+ TREE_CONSTANT (vtbl) = 1;
+ }
+
+ if (ctor_vtbl_p)
+ /* For a construction vtable, we can't overwrite BINFO_VTABLE.
+ 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))
+ inits = NULL_TREE;
+ else
+ /* For an ordinary vtable, set BINFO_VTABLE. */
+ BINFO_VTABLE (binfo) = vtbl;
+
+ return inits;
+}
+
+/* Construct the initializer for BINFO's virtual function table. BINFO
+ is part of the hierarchy dominated by T. If we're building a
+ construction vtable, the ORIG_BINFO is the binfo we should use to
+ find the actual function pointers to put in the vtable - but they
+ can be overridden on the path to most-derived in the graph that
+ ORIG_BINFO belongs. Otherwise,
+ ORIG_BINFO should be the same as BINFO. The RTTI_BINFO is the
+ BINFO that should be indicated by the RTTI information in the
+ vtable; it will be a base class of T, rather than T itself, if we
+ are building a construction vtable.
+
+ The value returned is a TREE_LIST suitable for wrapping in a
+ CONSTRUCTOR to use as the DECL_INITIAL for a vtable. If
+ NON_FN_ENTRIES_P is not NULL, *NON_FN_ENTRIES_P is set to the
+ number of non-function entries in the vtable.
+
+ It might seem that this function should never be called with a
+ BINFO for which BINFO_PRIMARY_P holds, the vtable for such a
+ base is always subsumed by a derived class vtable. However, when
+ we are building construction vtables, we do build vtables for
+ primary bases; we need these while the primary base is being
+ constructed. */
+
+static tree
+build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
+ tree binfo;
+ tree orig_binfo;
+ tree t;
+ tree rtti_binfo;
+ int *non_fn_entries_p;
+{
+ tree v, b;
+ tree vfun_inits;
+ tree vbase;
+ vtbl_init_data vid;
+
+ /* 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 = (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);
+
+ /* Add entries to the vtable for RTTI. */
+ build_rtti_vtbl_entries (binfo, &vid);
+
+ /* Create an array for keeping track of the functions we've
+ processed. When we see multiple functions with the same
+ signature, we share the vcall offsets. */
+ 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;
+ vbase = TREE_CHAIN (vbase))
+ CLEAR_BINFO_VTABLE_PATH_MARKED (TREE_VALUE (vbase));
+
+ if (non_fn_entries_p)
+ *non_fn_entries_p = list_length (vid.inits);
+
+ /* 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;
+ tree vcall_index;
+ tree fn;
+ tree pfn;
+ tree init = NULL_TREE;
+
+ fn = BV_FN (v);
+
+ /* If the only definition of this function signature along our
+ primary base chain is from a lost primary, this vtable slot will
+ never be used, so just zero it out. This is important to avoid
+ requiring extra thunks which cannot be generated with the function.
+
+ We first check this in update_vtable_entry_for_fn, so we handle
+ restored primary bases properly; we also need to do it here so we
+ zero out unused slots in ctor vtables, rather than filling themff
+ with erroneous values (though harmless, apart from relocation
+ costs). */
+ for (b = binfo; ; b = get_primary_binfo (b))
+ {
+ /* We found a defn before a lost primary; go ahead as normal. */
+ if (look_for_overrides_here (BINFO_TYPE (b), fn))
+ break;
+
+ /* The nearest definition is from a lost primary; clear the
+ slot. */
+ if (BINFO_LOST_PRIMARY_P (b))
+ {
+ init = size_zero_node;
+ break;
+ }
+ }
+
+ if (! init)
+ {
+ /* Pull the offset for `this', and the function to call, out of
+ the list. */
+ delta = BV_DELTA (v);
+
+ if (BV_USE_VCALL_INDEX_P (v))
+ {
+ vcall_index = BV_VCALL_INDEX (v);
+ my_friendly_assert (vcall_index != NULL_TREE, 20000621);
+ }
+ else
+ vcall_index = NULL_TREE;
+
+ my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727);
+ my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 19990727);
+
+ /* You can't call an abstract virtual function; it's abstract.
+ So, we replace these functions with __pure_virtual. */
+ if (DECL_PURE_VIRTUAL_P (fn))
+ fn = abort_fndecl;
+
+ /* Take the address of the function, considering it to be of an
+ appropriate generic type. */
+ pfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn);
+ /* The address of a function can't change. */
+ TREE_CONSTANT (pfn) = 1;
+
+ /* Enter it in the vtable. */
+ init = build_vtable_entry (delta, vcall_index, pfn);
+ }
+
+ /* And add it to the chain of initializers. */
+ if (TARGET_VTABLE_USES_DESCRIPTORS)
+ {
+ 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);
+ 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_CONSTANT (fdesc) = 1;
+
+ vfun_inits = tree_cons (NULL_TREE, fdesc, vfun_inits);
+ }
+ }
+ else
+ vfun_inits = tree_cons (NULL_TREE, init, vfun_inits);
+ }
+
+ /* 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
+ offsets in BINFO, which is in the hierarchy dominated by T. */
+
+static void
+build_vcall_and_vbase_vtbl_entries (binfo, vid)
+ tree binfo;
+ vtbl_init_data *vid;
+{
+ tree b;
+
+ /* If this is a derived class, we must first create entries
+ corresponding to the primary base class. */
+ b = get_primary_binfo (binfo);
+ if (b)
+ build_vcall_and_vbase_vtbl_entries (b, vid);
+
+ /* Add the vbase entries for this base. */
+ build_vbase_offset_vtbl_entries (binfo, vid);
+ /* Add the vcall entries for this base. */
+ build_vcall_offset_vtbl_entries (binfo, vid);
+}
+
+/* Returns the initializers for the vbase offset entries in the vtable
+ for BINFO (which is part of the class hierarchy dominated by T), in
+ reverse order. VBASE_OFFSET_INDEX gives the vtable index
+ where the next vbase offset will go. */
+
+static void
+build_vbase_offset_vtbl_entries (binfo, vid)
+ tree binfo;
+ vtbl_init_data *vid;
+{
+ tree vbase;
+ tree t;
+ tree non_primary_binfo;
+
+ /* If there are no virtual baseclasses, then there is nothing to
+ do. */
+ if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
+ return;
+
+ t = vid->derived;
+
+ /* We might be a primary base class. Go up the inheritance hierarchy
+ until we find the most derived class of which we are a primary base:
+ it is the offset of that which we need to use. */
+ non_primary_binfo = binfo;
+ while (BINFO_INHERITANCE_CHAIN (non_primary_binfo))
+ {
+ tree b;
+
+ /* If we have reached a virtual base, then it must be a primary
+ 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))
+ {
+ non_primary_binfo = vid->binfo;
+ break;
+ }
+
+ b = BINFO_INHERITANCE_CHAIN (non_primary_binfo);
+ if (get_primary_binfo (b) != non_primary_binfo)
+ break;
+ non_primary_binfo = b;
+ }
+
+ /* Go through the virtual bases, adding the offsets. */
+ for (vbase = TYPE_BINFO (BINFO_TYPE (binfo));
+ vbase;
+ vbase = TREE_CHAIN (vbase))
+ {
+ tree b;
+ tree delta;
+
+ if (!TREE_VIA_VIRTUAL (vbase))
+ continue;
+
+ /* Find the instance of this virtual base in the complete
+ object. */
+ b = binfo_for_vbase (BINFO_TYPE (vbase), t);
+
+ /* If we've already got an offset for this virtual base, we
+ don't need another one. */
+ if (BINFO_VTABLE_PATH_MARKED (b))
+ continue;
+ SET_BINFO_VTABLE_PATH_MARKED (b);
+
+ /* Figure out where we can find this vbase offset. */
+ delta = size_binop (MULT_EXPR,
+ vid->index,
+ convert (ssizetype,
+ TYPE_SIZE_UNIT (vtable_entry_type)));
+ if (vid->primary_vtbl_p)
+ BINFO_VPTR_FIELD (b) = delta;
+
+ if (binfo != TYPE_BINFO (t))
+ {
+ tree orig_vbase;
+
+ /* Find the instance of this virtual base in the type of BINFO. */
+ orig_vbase = binfo_for_vbase (BINFO_TYPE (vbase),
+ BINFO_TYPE (binfo));
+
+ /* The vbase offset had better be the same. */
+ if (!tree_int_cst_equal (delta,
+ BINFO_VPTR_FIELD (orig_vbase)))
+ abort ();
+ }
+
+ /* The next vbase will come at a more negative offset. */
+ vid->index = size_binop (MINUS_EXPR, vid->index, ssize_int (1));
+
+ /* The initializer is the delta from BINFO to this virtual base.
+ The vbase offsets go in reverse inheritance-graph order, and
+ we are walking in inheritance graph order so these end up in
+ the right order. */
+ delta = size_diffop (BINFO_OFFSET (b), BINFO_OFFSET (non_primary_binfo));
+
+ *vid->last_init
+ = build_tree_list (NULL_TREE,
+ fold (build1 (NOP_EXPR,
+ vtable_entry_type,
+ delta)));
+ vid->last_init = &TREE_CHAIN (*vid->last_init);
+ }
+}
+
+/* Adds the initializers for the vcall offset entries in the vtable
+ for BINFO (which is part of the class hierarchy dominated by VID->DERIVED)
+ to VID->INITS. */
+
+static void
+build_vcall_offset_vtbl_entries (binfo, vid)
+ tree binfo;
+ vtbl_init_data *vid;
+{
+ /* We only need these entries if this base is a virtual base. */
+ if (!TREE_VIA_VIRTUAL (binfo))
+ return;
+
+ /* We need a vcall offset for each of the virtual functions in this
+ vtable. For example:
+
+ class A { virtual void f (); };
+ class B1 : virtual public A { virtual void f (); };
+ class B2 : virtual public A { virtual void f (); };
+ class C: public B1, public B2 { virtual void f (); };
+
+ A C object has a primary base of B1, which has a primary base of A. A
+ C also has a secondary base of B2, which no longer has a primary base
+ of A. So the B2-in-C construction vtable needs a secondary vtable for
+ A, which will adjust the A* to a B2* to call f. We have no way of
+ knowing what (or even whether) this offset will be when we define B2,
+ so we store this "vcall offset" in the A sub-vtable and look it up in
+ a "virtual thunk" for B2::f.
+
+ We need entries for all the functions in our primary vtable and
+ in our non-virtual bases' secondary vtables. */
+ vid->vbase = binfo;
+ /* Now, walk through the non-virtual bases, adding vcall offsets. */
+ add_vcall_offset_vtbl_entries_r (binfo, vid);
+}
+
+/* Build vcall offsets, starting with those for BINFO. */
+
+static void
+add_vcall_offset_vtbl_entries_r (binfo, vid)
+ tree binfo;
+ vtbl_init_data *vid;
+{
+ int i;
+ tree primary_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)
+ return;
+
+ /* If BINFO has a primary base, process it first. */
+ primary_binfo = get_primary_binfo (binfo);
+ if (primary_binfo)
+ add_vcall_offset_vtbl_entries_r (primary_binfo, vid);
+
+ /* Add BINFO itself to the list. */
+ 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);
+ }
+}
+
+/* Called from build_vcall_offset_vtbl_entries_r. */
+
+static void
+add_vcall_offset_vtbl_entries_1 (binfo, vid)
+ tree binfo;
+ vtbl_init_data* vid;
+{
+ tree derived_virtuals;
+ tree base_virtuals;
+ tree orig_virtuals;
+ tree binfo_inits;
+ /* If BINFO is a primary base, the most derived class which has BINFO as
+ a primary base; otherwise, just BINFO. */
+ tree non_primary_binfo;
+
+ binfo_inits = NULL_TREE;
+
+ /* We might be a primary base class. Go up the inheritance hierarchy
+ until we find the most derived class of which we are a primary base:
+ it is the BINFO_VIRTUALS there that we need to consider. */
+ non_primary_binfo = binfo;
+ while (BINFO_INHERITANCE_CHAIN (non_primary_binfo))
+ {
+ tree b;
+
+ /* If we have reached a virtual base, then it must be vid->vbase,
+ because we ignore other virtual bases in
+ add_vcall_offset_vtbl_entries_r. In turn, it must be a primary
+ 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 (non_primary_binfo != vid->vbase)
+ abort ();
+ non_primary_binfo = vid->binfo;
+ break;
+ }
+
+ b = BINFO_INHERITANCE_CHAIN (non_primary_binfo);
+ if (get_primary_binfo (b) != non_primary_binfo)
+ break;
+ non_primary_binfo = b;
+ }
+
+ if (vid->ctor_vtbl_p)
+ /* For a ctor vtable we need the equivalent binfo within the hierarchy
+ where rtti_binfo is the most derived type. */
+ non_primary_binfo = get_original_base
+ (non_primary_binfo, TYPE_BINFO (BINFO_TYPE (vid->rtti_binfo)));
+
+ /* Make entries for the rest of the virtuals. */
+ for (base_virtuals = BINFO_VIRTUALS (binfo),
+ derived_virtuals = BINFO_VIRTUALS (non_primary_binfo),
+ orig_virtuals = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (binfo)));
+ base_virtuals;
+ base_virtuals = TREE_CHAIN (base_virtuals),
+ derived_virtuals = TREE_CHAIN (derived_virtuals),
+ orig_virtuals = TREE_CHAIN (orig_virtuals))
+ {
+ tree orig_fn;
+ tree fn;
+ tree base;
+ tree base_binfo;
+ size_t i;
+ tree vcall_offset;
+
+ /* Find the declaration that originally caused this function to
+ be present in BINFO_TYPE (binfo). */
+ orig_fn = BV_FN (orig_virtuals);
+
+ /* When processing BINFO, we only want to generate vcall slots for
+ function slots introduced in BINFO. So don't try to generate
+ one if the function isn't even defined in BINFO. */
+ if (!same_type_p (DECL_CONTEXT (orig_fn), BINFO_TYPE (binfo)))
+ continue;
+
+ /* Find the overriding function. */
+ fn = BV_FN (derived_virtuals);
+
+ /* If there is already an entry for a function with the same
+ signature as FN, then we do not need a second vcall offset.
+ Check the list of functions already present in the derived
+ class vtable. */
+ for (i = 0; i < VARRAY_ACTIVE_SIZE (vid->fns); ++i)
+ {
+ tree derived_entry;
+
+ derived_entry = VARRAY_TREE (vid->fns, i);
+ if (same_signature_p (BV_FN (derived_entry), fn)
+ /* We only use one vcall offset for virtual destructors,
+ even though there are two virtual table entries. */
+ || (DECL_DESTRUCTOR_P (BV_FN (derived_entry))
+ && DECL_DESTRUCTOR_P (fn)))
+ {
+ if (!vid->ctor_vtbl_p)
+ BV_VCALL_INDEX (derived_virtuals)
+ = BV_VCALL_INDEX (derived_entry);
+ break;
+ }
+ }
+ if (i != VARRAY_ACTIVE_SIZE (vid->fns))
+ continue;
+
+ /* The FN comes from BASE. So, we must calculate the adjustment from
+ vid->vbase to BASE. We can just look for BASE in the complete
+ object because we are converting from a virtual base, so if there
+ were multiple copies, there would not be a unique final overrider
+ and vid->derived would be ill-formed. */
+ base = DECL_CONTEXT (fn);
+ base_binfo = lookup_base (vid->derived, base, ba_any, NULL);
+
+ /* Compute the vcall offset. */
+ /* As mentioned above, the vbase we're working on is a primary base of
+ vid->binfo. But it might be a lost primary, so its BINFO_OFFSET
+ might be wrong, so we just use the BINFO_OFFSET from vid->binfo. */
+ vcall_offset = BINFO_OFFSET (vid->binfo);
+ vcall_offset = size_diffop (BINFO_OFFSET (base_binfo),
+ vcall_offset);
+ vcall_offset = fold (build1 (NOP_EXPR, vtable_entry_type,
+ vcall_offset));
+
+ *vid->last_init = build_tree_list (NULL_TREE, vcall_offset);
+ vid->last_init = &TREE_CHAIN (*vid->last_init);
+
+ /* Keep track of the vtable index where this vcall offset can be
+ found. For a construction vtable, we already made this
+ annotation when we built the original vtable. */
+ if (!vid->ctor_vtbl_p)
+ BV_VCALL_INDEX (derived_virtuals) = vid->index;
+
+ /* The next vcall offset will be found at a more negative
+ offset. */
+ vid->index = size_binop (MINUS_EXPR, vid->index, ssize_int (1));
+
+ /* Keep track of this function. */
+ VARRAY_PUSH_TREE (vid->fns, derived_virtuals);
+ }
+}
+
+/* Return vtbl initializers for the RTTI entries coresponding to the
+ BINFO's vtable. The RTTI entries should indicate the object given
+ by VID->rtti_binfo. */
+
+static void
+build_rtti_vtbl_entries (binfo, vid)
+ tree binfo;
+ vtbl_init_data *vid;
+{
+ 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
+ primary base, and then add the offset in the vtbl to that value. */
+ b = binfo;
+ while (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (b))
+ && !BINFO_LOST_PRIMARY_P (b))
+ {
+ tree primary_base;
+
+ primary_base = get_primary_binfo (b);
+ my_friendly_assert (BINFO_PRIMARY_BASE_OF (primary_base) == b, 20010127);
+ b = primary_base;
+ }
+ offset = size_diffop (BINFO_OFFSET (vid->rtti_binfo), BINFO_OFFSET (b));
+
+ /* The second entry is the address of the typeinfo object. */
+ if (flag_rtti)
+ decl = build_unary_op (ADDR_EXPR, get_tinfo_decl (t), 0);
+ else
+ decl = integer_zero_node;
+
+ /* Convert the declaration to a type that can be stored in the
+ vtable. */
+ init = build1 (NOP_EXPR, vfunc_ptr_type_node, decl);
+ TREE_CONSTANT (init) = 1;
+ *vid->last_init = build_tree_list (NULL_TREE, init);
+ vid->last_init = &TREE_CHAIN (*vid->last_init);
+
+ /* Add the offset-to-top entry. It comes earlier in the vtable that
+ the the typeinfo entry. Convert the offset to look like a
+ function pointer, so that we can put it in the vtable. */
+ init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
+ TREE_CONSTANT (init) = 1;
+ *vid->last_init = build_tree_list (NULL_TREE, init);
+ vid->last_init = &TREE_CHAIN (*vid->last_init);
+}
+
+/* Build an entry in the virtual function table. DELTA is the offset
+ for the `this' pointer. VCALL_INDEX is the vtable index containing
+ the vcall offset; NULL_TREE if none. ENTRY is the virtual function
+ table entry itself. It's TREE_TYPE must be VFUNC_PTR_TYPE_NODE,
+ but it may not actually be a virtual function table pointer. (For
+ example, it might be the address of the RTTI object, under the new
+ ABI.) */
+
+static tree
+build_vtable_entry (delta, vcall_index, entry)
+ tree delta;
+ tree vcall_index;
+ tree entry;
+{
+ tree fn = TREE_OPERAND (entry, 0);
+
+ if ((!integer_zerop (delta) || vcall_index != NULL_TREE)
+ && fn != abort_fndecl)
+ {
+ entry = make_thunk (entry, delta, vcall_index);
+ entry = build1 (ADDR_EXPR, vtable_entry_type, entry);
+ TREE_READONLY (entry) = 1;
+ TREE_CONSTANT (entry) = 1;
+ }
+#ifdef GATHER_STATISTICS
+ n_vtable_entries += 1;
+#endif
+ return entry;
+}