diff options
Diffstat (limited to 'gcc/cp/class.c')
-rwxr-xr-x | gcc/cp/class.c | 5669 |
1 files changed, 0 insertions, 5669 deletions
diff --git a/gcc/cp/class.c b/gcc/cp/class.c deleted file mode 100755 index a219b7d..0000000 --- a/gcc/cp/class.c +++ /dev/null @@ -1,5669 +0,0 @@ -/* Functions related to building classes and their related objects. - Copyright (C) 1987, 92-97, 1998, 1999 Free Software Foundation, Inc. - Contributed by Michael Tiemann (tiemann@cygnus.com) - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - - -/* High-level class interface. */ - -#include "config.h" -#include "system.h" -#include "tree.h" -#include "cp-tree.h" -#include "flags.h" -#include "rtl.h" -#include "output.h" -#include "toplev.h" - -#include "obstack.h" -#define obstack_chunk_alloc xmalloc -#define obstack_chunk_free free - -extern struct obstack permanent_obstack; - -/* 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. */ - -int current_class_depth; - -/* In order to deal with nested classes, we keep a stack of classes. - The topmost entry is the innermost class, and is the entry at index - CURRENT_CLASS_DEPTH */ - -typedef struct class_stack_node { - /* The name of the class. */ - tree name; - - /* The _TYPE node for the class. */ - tree type; - - /* The access specifier pending for new declarations in the scope of - this class. */ - tree access; -}* class_stack_node_t; - -/* 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. */ -static 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 void fixup_vtable_deltas1 PROTO((tree, tree)); -static void fixup_vtable_deltas PROTO((tree, int, 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 maybe_fixup_vptrs PROTO((tree, 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 void build_class_init_list PROTO((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 void check_member_decl_is_same_in_complete_scope PROTO((tree, 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)); - -/* 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 */ - -/* Variables shared between class.c and call.c. */ - -#ifdef GATHER_STATISTICS -int n_vtables = 0; -int n_vtable_entries = 0; -int n_vtable_searches = 0; -int n_vtable_elems = 0; -int n_convert_harshness = 0; -int n_compute_conversion_costs = 0; -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. */ - -tree -build_vbase_path (code, type, expr, path, nonnull) - enum tree_code code; - tree type, expr, path; - int nonnull; -{ - register int changed = 0; - tree last = NULL_TREE, last_virtual = NULL_TREE; - 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); - - /* 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); - - while (path) - { - 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); - } - /* 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) - { - TREE_OPERAND (expr, 2) = nonnull_expr; - TREE_TYPE (expr) = TREE_TYPE (TREE_OPERAND (expr, 1)) - = TREE_TYPE (nonnull_expr); - } - 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 - { - if (last_virtual) - { - offset = BINFO_OFFSET (binfo_member (last_virtual, - CLASSTYPE_VBASECLASSES (basetype))); - offset = size_binop (PLUS_EXPR, offset, BINFO_OFFSET (last)); - } - else - offset = BINFO_OFFSET (last); - } - - 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); - } - - /* 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; - } - else - return build1 (NOP_EXPR, type, 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; -{ - 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 - - 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])); */ - -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; - - s = build_unary_op (ADDR_EXPR, TYPE_BINFO_VTABLE (basetype), 0); - s = build_tree_list (build_string (1, "s"), s); - - 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, 0); - i = build_tree_list (build_string (1, "i"), i); - - expand_asm_operands (build_string (sizeof(asm_stmt)-1, asm_stmt), - NULL_TREE, chainon (s, i), NULL_TREE, 1, NULL, 0); -} - -/* 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. */ - -tree -build_vtbl_ref (instance, idx) - tree instance, idx; -{ - tree vtbl, aref; - tree basetype = TREE_TYPE (instance); - - if (TREE_CODE (basetype) == REFERENCE_TYPE) - basetype = TREE_TYPE (basetype); - - if (instance == current_class_ref) - vtbl = build_vfield_ref (instance, basetype); - else - { - if (optimize) - { - /* Try to figure out what a reference refers to, and - access its virtual function table directly. */ - tree ref = NULL_TREE; - - if (TREE_CODE (instance) == INDIRECT_REF - && TREE_CODE (TREE_TYPE (TREE_OPERAND (instance, 0))) == REFERENCE_TYPE) - ref = TREE_OPERAND (instance, 0); - else if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE) - ref = instance; - - if (ref && TREE_CODE (ref) == VAR_DECL - && DECL_INITIAL (ref)) - { - tree init = DECL_INITIAL (ref); - - while (TREE_CODE (init) == NOP_EXPR - || TREE_CODE (init) == NON_LVALUE_EXPR) - init = TREE_OPERAND (init, 0); - if (TREE_CODE (init) == ADDR_EXPR) - { - init = TREE_OPERAND (init, 0); - if (IS_AGGR_TYPE (TREE_TYPE (init)) - && (TREE_CODE (init) == PARM_DECL - || TREE_CODE (init) == VAR_DECL)) - instance = init; - } - } - } - - if (IS_AGGR_TYPE (TREE_TYPE (instance)) - && (TREE_CODE (instance) == RESULT_DECL - || TREE_CODE (instance) == PARM_DECL - || TREE_CODE (instance) == VAR_DECL)) - vtbl = TYPE_BINFO_VTABLE (basetype); - 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; -{ - tree aref = build_vtbl_ref (instance, idx); - - /* When using thunks, there is no extra delta, and we get the pfn - directly. */ - if (flag_vtable_thunks) - return aref; - - 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)); - - *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))); - } - - return build_component_ref (aref, pfn_identifier, NULL_TREE, 0); -} - -/* Return the name of the virtual function table (as an IDENTIFIER_NODE) - for the given TYPE. */ - -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); - 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 the offset to the main vtable for a given base BINFO. */ - -tree -get_vfield_offset (binfo) - tree binfo; -{ - 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)); -} - -/* 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. */ - -static tree -get_derived_offset (binfo, type) - tree binfo, 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); -} - -/* Update the rtti info for this class. */ - -static void -set_rtti_entry (virtuals, offset, type) - tree virtuals, offset, type; -{ - tree vfn; - - if (flag_rtti) - vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, get_tinfo_fn (type)); - else - vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, size_zero_node); - TREE_CONSTANT (vfn) = 1; - - 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; - - TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node, voff); - - /* The second slot is for the tdesc pointer when thunks are used. */ - TREE_VALUE (TREE_CHAIN (virtuals)) - = build_vtable_entry (integer_zero_node, vfn); - } -} - -/* 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. */ - -static tree -build_vtable (binfo, type) - tree binfo, type; -{ - tree name = get_vtable_name (type); - tree virtuals, decl; - - if (binfo) - { - tree offset; - - virtuals = copy_list (BINFO_VIRTUALS (binfo)); - decl = build_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); - } - else - { - virtuals = NULL_TREE; - decl = build_decl (VAR_DECL, name, void_type_node); - } - -#ifdef GATHER_STATISTICS - n_vtables += 1; - 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; -} - -extern tree signed_size_zero_node; - -/* Give TYPE 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 - be needed. - - BINFO is the type association which provided TYPE for FOR_TYPE. - - 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) - 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; - - 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_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); - - /* 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"); - - 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); -} - -#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. */ - -static tree -get_vtable_entry (virtuals, base_fndecl) - tree virtuals, base_fndecl; -{ - 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))); - -#ifdef GATHER_STATISTICS - n_vtable_searches += n; -#endif - - while (n > 0 && virtuals) - { - --n; - virtuals = TREE_CHAIN (virtuals); - } - return virtuals; -} -#endif - -/* Put new entry ENTRY into virtual function table initializer - VIRTUALS. - - Also update DECL_VINDEX (FNDECL). */ - -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); - -#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. */ - if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST) - { - DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl); - DECL_CONTEXT (fndecl) = DECL_CONTEXT (base_fndecl); - } -} - -/* Access the virtual function table entry N. VIRTUALS is the virtual - function table's initializer. */ - -static tree -get_vtable_entry_n (virtuals, n) - tree virtuals; - unsigned HOST_WIDE_INT n; -{ - while (n > 0) - { - --n; - virtuals = TREE_CHAIN (virtuals); - } - return virtuals; -} - -/* 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 - and return it. */ - -static void -add_virtual_function (pv, phv, has_virtual, fndecl, t) - tree *pv, *phv; - int *has_virtual; - 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 - - /* 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; - - /* 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. */ - if (*has_virtual == 0 && flag_vtable_thunks) - { - *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); - - 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); - } - /* 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) - { - /* 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); - } - *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. */ - -void -add_method (type, fields, method) - tree type, *fields, method; -{ - push_obstacks (&permanent_obstack, &permanent_obstack); - - /* 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 len; - 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. */ - int slot - = DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (method)) ? 1 : 0; - - TREE_VEC_ELT (method_vec, slot) - = build_overload (method, TREE_VEC_ELT (method_vec, slot)); - } - else - { - int i; - - /* See if we already have an entry with this name. */ - for (i = 2; i < len; ++i) - if (!TREE_VEC_ELT (method_vec, i) - || (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, i))) - == DECL_NAME (method))) - break; - - if (i == 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; - } - else 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, i); - fns; - fns = OVL_NEXT (fns)) - { - tree fn = OVL_CURRENT (fns); - - if (TREE_CODE (fn) != TREE_CODE (method)) - continue; - - if (TREE_CODE (method) != TEMPLATE_DECL) - { - /* [over.load] Member function declarations with the - same name and the same parameter types cannot be - overloaded if any of them is a static member - function declaration. */ - 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)); - - if (! DECL_STATIC_FUNCTION_P (fn)) - parms1 = TREE_CHAIN (parms1); - else - parms2 = TREE_CHAIN (parms2); - - if (compparms (parms1, parms2)) - cp_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); - - /* We don't call duplicate_decls here to merege the - declarations because that will confuse things if - the methods have inline definitions In - particular, we will crash while processing the - definitions. */ - return; - } - } - - if (TREE_VEC_ELT (method_vec, i)) - /* We found a match. */; - else if (DECL_CONV_FN_P (method)) - { - /* 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 (i = 2; i < len; ++i) - { - tree fn = TREE_VEC_ELT (method_vec, i); - - 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 Ith - position. */ - break; - } - - if (!TREE_VEC_ELT (method_vec, i)) - /* 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, i), - (PTR) &TREE_VEC_ELT (method_vec, i + 1), - (len - i - 1) * sizeof (tree)); - TREE_VEC_ELT (method_vec, i) = NULL_TREE; - } - } - - /* Actually insert the new method. */ - TREE_VEC_ELT (method_vec, i) - = build_overload (method, TREE_VEC_ELT (method_vec, i)); - } - - if (TYPE_BINFO_BASETYPES (type) && CLASSTYPE_BASELINK_VEC (type)) - { - /* ??? May be better to know whether these can be extended? */ - tree baselink_vec = CLASSTYPE_BASELINK_VEC (type); - - TREE_VEC_LENGTH (baselink_vec) += 1; - CLASSTYPE_BASELINK_VEC (type) = copy_node (baselink_vec); - TREE_VEC_LENGTH (baselink_vec) -= 1; - - TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), len) = 0; - } - } - pop_obstacks (); -} - -/* Subroutines of finish_struct. */ - -/* Look through the list of fields for this struct, deleting - duplicates as we go. This must be recursive to handle - anonymous unions. - - FIELD is the field which may not appear anywhere in FIELDS. - FIELD_PTR, if non-null, is the starting point at which - chained deletions may take place. - The value returned is the first acceptable entry found - in FIELDS. - - Note that anonymous fields which are not of UNION_TYPE are - not duplicates, they are just anonymous fields. This happens - when we have unnamed bitfields, for example. */ - -static tree -delete_duplicate_fields_1 (field, fields) - tree field, fields; -{ - tree x; - tree prev = 0; - if (DECL_NAME (field) == 0) - { - if (TREE_CODE (TREE_TYPE (field)) != UNION_TYPE) - return fields; - - for (x = TYPE_FIELDS (TREE_TYPE (field)); x; x = TREE_CHAIN (x)) - fields = delete_duplicate_fields_1 (x, fields); - return fields; - } - else - { - for (x = fields; x; prev = x, x = TREE_CHAIN (x)) - { - if (DECL_NAME (x) == 0) - { - if (TREE_CODE (TREE_TYPE (x)) != UNION_TYPE) - continue; - TYPE_FIELDS (TREE_TYPE (x)) - = delete_duplicate_fields_1 (field, TYPE_FIELDS (TREE_TYPE (x))); - if (TYPE_FIELDS (TREE_TYPE (x)) == 0) - { - if (prev == 0) - fields = TREE_CHAIN (fields); - else - TREE_CHAIN (prev) = TREE_CHAIN (x); - } - } - else - { - 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 (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); - } - } - } - } - return fields; -} - -static void -delete_duplicate_fields (fields) - tree fields; -{ - tree x; - for (x = fields; x && TREE_CHAIN (x); x = TREE_CHAIN (x)) - 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. */ - -static int -alter_access (t, binfo, fdecl, access) - tree t; - tree binfo; - tree fdecl; - tree access; -{ - tree elem = purpose_member (t, DECL_ACCESS (fdecl)); - if (elem) - { - if (TREE_VALUE (elem) != access) - { - if (TREE_CODE (TREE_TYPE (fdecl)) == FUNCTION_DECL) - cp_error_at ("conflicting access specifications for method `%D', ignored", TREE_TYPE (fdecl)); - else - error ("conflicting access specifications for field `%s', ignored", - IDENTIFIER_POINTER (DECL_NAME (fdecl))); - } - else - { - /* They're changing the access to the same thing they changed - it to before. That's OK. */ - ; - } - } - else - { - enforce_access (binfo, 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. */ - -static void -handle_using_decl (using_decl, t, method_vec, fields) - tree using_decl; - tree t; - tree method_vec; - tree fields; -{ - tree ctype = DECL_INITIAL (using_decl); - tree name = DECL_NAME (using_decl); - tree access - = TREE_PRIVATE (using_decl) ? access_private_node - : TREE_PROTECTED (using_decl) ? access_protected_node - : access_public_node; - tree fdecl, binfo; - tree flist = NULL_TREE; - tree tmp; - int i; - int n_methods; - - binfo = binfo_or_else (ctype, t); - if (! binfo) - return; - - if (name == constructor_name (ctype) - || name == constructor_name_full (ctype)) - { - cp_error_at ("using-declaration for constructor", using_decl); - return; - } - - fdecl = lookup_member (binfo, name, 0, 0); - - if (!fdecl) - { - cp_error_at ("no members matching `%D' in `%#T'", using_decl, ctype); - 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) - /* Ignore base type this came from. */ - fdecl = TREE_VALUE (fdecl); - - if (TREE_CODE (fdecl) == OVERLOAD) - { - /* We later iterate over all functions. */ - flist = fdecl; - fdecl = OVL_FUNCTION (flist); - } - - 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) - { - while (flist) - { - if (alter_access (t, binfo, OVL_FUNCTION (flist), - access) == 0) - return; - flist = OVL_CHAIN (flist); - } - } - else - alter_access (t, binfo, fdecl, access); -} - -/* If FOR_TYPE needs to reinitialize virtual function table pointers - for TYPE's sub-objects, add such reinitializations to BASE_INIT_LIST. - Returns BASE_INIT_LIST appropriately modified. */ - -static tree -maybe_fixup_vptrs (for_type, binfo, base_init_list) - tree for_type, binfo, base_init_list; -{ - /* Now reinitialize any slots that don't fall under our virtual - function table pointer. */ - tree vfields = CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)); - while (vfields) - { - tree basetype = VF_NORMAL_VALUE (vfields) - ? TYPE_MAIN_VARIANT (VF_NORMAL_VALUE (vfields)) - : VF_BASETYPE_VALUE (vfields); - - tree base_binfo = get_binfo (basetype, for_type, 0); - /* Punt until this is implemented. */ - if (1 /* BINFO_MODIFIED (base_binfo) */) - { - tree base_offset = get_vfield_offset (base_binfo); - if (! tree_int_cst_equal (base_offset, get_vfield_offset (TYPE_BINFO (for_type))) - && ! tree_int_cst_equal (base_offset, get_vfield_offset (binfo))) - base_init_list = tree_cons (error_mark_node, base_binfo, - base_init_list); - } - vfields = TREE_CHAIN (vfields); - } - return base_init_list; -} - -/* If TYPE does not have a constructor, then the compiler must - manually deal with all of the initialization this type requires. - - If a base initializer exists only to fill in the virtual function - table pointer, then we mark that fact with the TREE_VIRTUAL bit. - This way, we avoid multiple initializations of the same field by - each virtual function table up the class hierarchy. - - Virtual base class pointers are not initialized here. They are - initialized only at the "top level" of object creation. If we - initialized them here, we would have to skip a lot of work. */ - -static void -build_class_init_list (type) - tree type; -{ - tree base_init_list = NULL_TREE; - tree member_init_list = NULL_TREE; - - /* Since we build member_init_list and base_init_list using - tree_cons, backwards fields the all through work. */ - tree x; - tree binfos = BINFO_BASETYPES (TYPE_BINFO (type)); - int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; - - for (x = TYPE_FIELDS (type); x; x = TREE_CHAIN (x)) - { - if (TREE_CODE (x) != FIELD_DECL) - continue; - - if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (x)) - || DECL_INITIAL (x) != NULL_TREE) - member_init_list = tree_cons (x, type, member_init_list); - } - member_init_list = nreverse (member_init_list); - - /* We will end up doing this last. Need special marker - to avoid infinite regress. */ - if (TYPE_VIRTUAL_P (type)) - { - base_init_list = build_tree_list (error_mark_node, TYPE_BINFO (type)); - if (CLASSTYPE_NEEDS_VIRTUAL_REINIT (type) == 0) - TREE_VALUE (base_init_list) = NULL_TREE; - TREE_ADDRESSABLE (base_init_list) = 1; - } - - /* Each base class which needs to have initialization - of some kind gets to make such requests known here. */ - for (i = n_baseclasses-1; i >= 0; i--) - { - tree base_binfo = TREE_VEC_ELT (binfos, i); - tree blist; - - /* Don't initialize virtual baseclasses this way. */ - if (TREE_VIA_VIRTUAL (base_binfo)) - continue; - - if (TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (base_binfo))) - { - /* ...and the last shall come first... */ - base_init_list = maybe_fixup_vptrs (type, base_binfo, base_init_list); - base_init_list = tree_cons (NULL_TREE, base_binfo, base_init_list); - continue; - } - - if ((blist = CLASSTYPE_BASE_INIT_LIST (BINFO_TYPE (base_binfo))) == NULL_TREE) - /* Nothing to initialize. */ - continue; - - /* ...ditto... */ - base_init_list = maybe_fixup_vptrs (type, base_binfo, base_init_list); - - /* This is normally true for single inheritance. - The win is we can shrink the chain of initializations - to be done by only converting to the actual type - we are interested in. */ - if (TREE_VALUE (blist) - && TREE_CODE (TREE_VALUE (blist)) == TREE_VEC - && tree_int_cst_equal (BINFO_OFFSET (base_binfo), - BINFO_OFFSET (TREE_VALUE (blist)))) - { - if (base_init_list) - { - /* Does it do more than just fill in a - virtual function table pointer? */ - if (! TREE_ADDRESSABLE (blist)) - base_init_list = build_tree_list (blist, base_init_list); - /* Can we get by just with the virtual function table - pointer that it fills in? */ - else if (TREE_ADDRESSABLE (base_init_list) - && TREE_VALUE (base_init_list) == 0) - base_init_list = blist; - /* Maybe, but it is not obvious as the previous case. */ - else if (! CLASSTYPE_NEEDS_VIRTUAL_REINIT (type)) - { - tree last = tree_last (base_init_list); - while (TREE_VALUE (last) - && TREE_CODE (TREE_VALUE (last)) == TREE_LIST) - last = tree_last (TREE_VALUE (last)); - if (TREE_VALUE (last) == 0) - base_init_list = build_tree_list (blist, base_init_list); - } - } - else - base_init_list = blist; - } - else - { - /* The function expand_aggr_init knows how to do the - initialization of `basetype' without getting - an explicit `blist'. */ - if (base_init_list) - base_init_list = tree_cons (NULL_TREE, base_binfo, base_init_list); - else - base_init_list = CLASSTYPE_BINFO_AS_LIST (BINFO_TYPE (base_binfo)); - } - } - - if (base_init_list) - { - if (member_init_list) - CLASSTYPE_BASE_INIT_LIST (type) = - build_tree_list (base_init_list, member_init_list); - else - CLASSTYPE_BASE_INIT_LIST (type) = base_init_list; - } - else if (member_init_list) - CLASSTYPE_BASE_INIT_LIST (type) = member_init_list; -} - -struct base_info -{ - int has_virtual; - int max_has_virtual; - int n_ancestors; - 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. */ - -static int -finish_base_struct (t, b) - tree t; - struct base_info *b; -{ - 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)); - - for (i = 0; i < n_baseclasses; i++) - { - tree base_binfo = TREE_VEC_ELT (binfos, i); - tree basetype = BINFO_TYPE (base_binfo); - - /* 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); - - /* 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) - { - int j; - /* The base type is of incomplete type. It is - probably best to pretend that it does not - exist. */ - if (i == n_baseclasses-1) - TREE_VEC_ELT (binfos, i) = NULL_TREE; - TREE_VEC_LENGTH (binfos) -= 1; - n_baseclasses -= 1; - for (j = i; j+1 < n_baseclasses; j++) - TREE_VEC_ELT (binfos, j) = TREE_VEC_ELT (binfos, j+1); - } - - if (! TYPE_HAS_CONST_INIT_REF (basetype)) - b->cant_have_const_ctor = 1; - - if (TYPE_HAS_CONSTRUCTOR (basetype) - && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype)) - { - b->cant_have_default_ctor = 1; - if (! TYPE_HAS_CONSTRUCTOR (t)) - { - cp_pedwarn ("base `%T' with only non-default constructor", - basetype); - cp_pedwarn ("in class without a constructor"); - } - } - - if (TYPE_HAS_ASSIGN_REF (basetype) - && !TYPE_HAS_CONST_ASSIGN_REF (basetype)) - b->no_const_asn_ref = 1; - - b->n_ancestors += CLASSTYPE_N_SUPERCLASSES (basetype); - 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_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); - - if (! TREE_VIA_VIRTUAL (base_binfo)) - CLASSTYPE_N_SUPERCLASSES (t) += 1; - - 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); - - /* Don't borrow virtuals from virtual baseclasses. */ - if (TREE_VIA_VIRTUAL (base_binfo)) - continue; - - if (first_vfn_base_index < 0) - { - 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; - } - else - { - /* 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); - } - - if (b->has_virtual == 0) - { - 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); - } - } - } - } - } - - { - 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)); - } - } - - if (b->vfield == 0) - /* If all virtual functions come only from virtual baseclasses. */ - return -1; - - /* 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))); - - return first_vfn_base_index; -} - -/* 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. */ - -static void -finish_struct_bits (t, max_has_virtual) - tree t; - int max_has_virtual; -{ - int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t); - - /* Fix up variants (if any). */ - tree variants = TYPE_NEXT_VARIANT (t); - while (variants) - { - /* These fields are in the _TYPE part of the node, not in - the TYPE_LANG_SPECIFIC component, so they are not shared. */ - 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_USES_COMPLEX_INHERITANCE (variants) = TYPE_USES_COMPLEX_INHERITANCE (t); - TYPE_VIRTUAL_P (variants) = TYPE_VIRTUAL_P (t); - TYPE_USES_VIRTUAL_BASECLASSES (variants) = TYPE_USES_VIRTUAL_BASECLASSES (t); - /* Copy whatever these are holding today. */ - TYPE_MIN_VALUE (variants) = TYPE_MIN_VALUE (t); - TYPE_MAX_VALUE (variants) = TYPE_MAX_VALUE (t); - TYPE_FIELDS (variants) = TYPE_FIELDS (t); - TYPE_SIZE (variants) = TYPE_SIZE (t); - TYPE_SIZE_UNIT (variants) = TYPE_SIZE_UNIT (t); - variants = TYPE_NEXT_VARIANT (variants); - } - - if (n_baseclasses && 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) - { - /* Notice whether this class has type conversion functions defined. */ - tree binfo = TYPE_BINFO (t); - tree binfos = BINFO_BASETYPES (binfo); - tree basetype; - - for (i = n_baseclasses-1; i >= 0; i--) - { - basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i)); - - TYPE_HAS_CONVERSION (t) |= TYPE_HAS_CONVERSION (basetype); - if (CLASSTYPE_MAX_DEPTH (basetype) >= CLASSTYPE_MAX_DEPTH (t)) - CLASSTYPE_MAX_DEPTH (t) = CLASSTYPE_MAX_DEPTH (basetype) + 1; - } - } - - /* If this type has a copy constructor, force its mode to be BLKmode, and - force its TREE_ADDRESSABLE bit to be nonzero. This will cause it to - be passed by invisible reference and prevent it from being returned in - a register. - - Also do this if the class has BLKmode but can still be returned in - registers, since function_cannot_inline_p won't let us inline - functions returning such a type. This affects the HP-PA. */ - if (! TYPE_HAS_TRIVIAL_INIT_REF (t) - || (TYPE_MODE (t) == BLKmode && ! aggregate_value_p (t) - && CLASSTYPE_NON_AGGREGATE (t))) - { - tree variants; - DECL_MODE (TYPE_MAIN_DECL (t)) = BLKmode; - for (variants = t; variants; variants = TYPE_NEXT_VARIANT (variants)) - { - TYPE_MODE (variants) = BLKmode; - TREE_ADDRESSABLE (variants) = 1; - } - } -} - -/* Issue warnings about T having private constructors, but no friends, - and so forth. - - HAS_NONPRIVATE_METHOD is nonzero if T has any non-private methods or - static members. HAS_NONPRIVATE_STATIC_FN is nonzero if T has any - non-private static member functions. */ - -static void -maybe_warn_about_overly_private_class (t) - tree t; -{ - int has_member_fn = 0; - int has_nonprivate_method = 0; - tree fn; - - if (!warn_ctor_dtor_privacy - /* If the class has friends, those entities might create and - access instances, so we should not warn. */ - || (CLASSTYPE_FRIEND_CLASSES (t) - || DECL_FRIENDLIST (TYPE_MAIN_DECL (t))) - /* We will have warned when the template was declared; there's - no need to warn on every instantiation. */ - || CLASSTYPE_TEMPLATE_INSTANTIATION (t)) - /* There's no reason to even consider warning about this - class. */ - return; - - /* We only issue one warning, if more than one applies, because - otherwise, on code like: - - class A { - // Oops - forgot `public:' - A(); - A(const A&); - ~A(); - }; - - we warn several times about essentially the same problem. */ - - /* Check to see if all (non-constructor, non-destructor) member - functions are private. (Since there are no friends or - non-private statics, we can't ever call any of the private member - functions.) */ - for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn)) - /* We're not interested in compiler-generated methods; they don't - provide any way to call private members. */ - if (!DECL_ARTIFICIAL (fn)) - { - if (!TREE_PRIVATE (fn)) - { - if (DECL_STATIC_FUNCTION_P (fn)) - /* A non-private static member function is just like a - friend; it can create and invoke private member - functions, and be accessed without a class - instance. */ - return; - - has_nonprivate_method = 1; - break; - } - else if (!DECL_CONSTRUCTOR_P (fn) && !DECL_DESTRUCTOR_P (fn)) - has_member_fn = 1; - } - - if (!has_nonprivate_method && has_member_fn) - { - /* There are no non-private methods, and there's at least one - private member function that isn't a constructor or - destructor. (If all the private members are - constructors/destructors we want to use the code below that - issues error messages specifically referring to - constructors/destructors.) */ - int i; - tree binfos = BINFO_BASETYPES (TYPE_BINFO (t)); - for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); i++) - if (TREE_VIA_PUBLIC (TREE_VEC_ELT (binfos, i)) - || TREE_VIA_PROTECTED (TREE_VEC_ELT (binfos, i))) - { - has_nonprivate_method = 1; - break; - } - if (!has_nonprivate_method) - { - cp_warning ("all member functions in class `%T' are private", t); - return; - } - } - - /* Even if some of the member functions are non-private, the class - won't be useful for much if all the constructors or destructors - are private: such an object can never be created or destroyed. */ - if (TYPE_HAS_DESTRUCTOR (t)) - { - tree dtor = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1); - - if (TREE_PRIVATE (dtor)) - { - cp_warning ("`%#T' only defines a private destructor and has no friends", - t); - return; - } - } - - if (TYPE_HAS_CONSTRUCTOR (t)) - { - int nonprivate_ctor = 0; - - /* If a non-template class does not define a copy - constructor, one is defined for it, enabling it to avoid - this warning. For a template class, this does not - happen, and so we would normally get a warning on: - - template <class T> class C { private: C(); }; - - To avoid this asymmetry, we check TYPE_HAS_INIT_REF. All - complete non-template or fully instantiated classes have this - flag set. */ - if (!TYPE_HAS_INIT_REF (t)) - nonprivate_ctor = 1; - else - for (fn = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0); - fn; - fn = OVL_NEXT (fn)) - { - tree ctor = OVL_CURRENT (fn); - /* Ideally, we wouldn't count copy constructors (or, in - fact, any constructor that takes an argument of the - class type as a parameter) because such things cannot - be used to construct an instance of the class unless - you already have one. But, for now at least, we're - more generous. */ - if (! TREE_PRIVATE (ctor)) - { - nonprivate_ctor = 1; - break; - } - } - - if (nonprivate_ctor == 0) - { - cp_warning ("`%#T' only defines private constructors and has no friends", - t); - return; - } - } -} - - -/* Warn about duplicate methods in fn_fields. Also compact method - lists so that lookup can be made faster. - - Data Structure: List of method lists. The outer list is a - TREE_LIST, whose TREE_PURPOSE field is the field name and the - TREE_VALUE is the DECL_CHAIN of the FUNCTION_DECLs. TREE_CHAIN - links the entire list of methods for TYPE_METHODS. Friends are - chained in the same way as member functions (? TREE_CHAIN or - DECL_CHAIN), but they live in the TREE_TYPE field of the outer - 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. */ - -static void -finish_struct_methods (t) - tree t; -{ - tree fn_fields; - tree method_vec = CLASSTYPE_METHOD_VEC (t); - tree ctor_name = constructor_name (t); - int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t); - - /* 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. - - @@ 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)) - /* 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); - - /* Now for each member function (except for constructors and - destructors), compute where member functions of the same - name reside in base classes. */ - if (n_baseclasses != 0 - && method_vec - && TREE_VEC_LENGTH (method_vec) > 2) - { - int len = TREE_VEC_LENGTH (method_vec); - tree baselink_vec = make_tree_vec (len); - int any_links = 0; - tree baselink_binfo = build_tree_list (NULL_TREE, TYPE_BINFO (t)); - - for (i = 2; i < len && TREE_VEC_ELT (method_vec, i); i++) - { - tree ovl = TREE_VEC_ELT (method_vec, i); - - TREE_VEC_ELT (baselink_vec, i) - = get_baselinks (baselink_binfo, t, - DECL_NAME (OVL_CURRENT (ovl))); - if (TREE_VEC_ELT (baselink_vec, i) != 0) - any_links = 1; - } - if (any_links != 0) - CLASSTYPE_BASELINK_VEC (t) = baselink_vec; - else - obstack_free (current_obstack, baselink_vec); - } -} - -/* Emit error when a duplicate definition of a type is seen. Patch up. */ - -void -duplicate_tag_error (t) - tree t; -{ - cp_error ("redefinition of `%#T'", t); - cp_error_at ("previous definition here", t); - - /* Pretend we haven't defined this type. */ - - /* All of the component_decl's were TREE_CHAINed together in the parser. - finish_struct_methods walks these chains and assembles all methods with - the same base name into DECL_CHAINs. Now we don't need the parser chains - anymore, so we unravel them. */ - - /* This used to be in finish_struct, but it turns out that the - TREE_CHAIN is used by dbxout_type_methods and perhaps some other - things... */ - if (CLASSTYPE_METHOD_VEC (t)) - { - tree method_vec = CLASSTYPE_METHOD_VEC (t); - int i, len = TREE_VEC_LENGTH (method_vec); - for (i = 0; i < len; i++) - { - tree unchain = TREE_VEC_ELT (method_vec, i); - while (unchain != NULL_TREE) - { - TREE_CHAIN (OVL_CURRENT (unchain)) = NULL_TREE; - unchain = OVL_NEXT (unchain); - } - } - } - - if (TYPE_LANG_SPECIFIC (t)) - { - tree as_list = CLASSTYPE_AS_LIST (t); - tree binfo = TYPE_BINFO (t); - tree binfo_as_list = CLASSTYPE_BINFO_AS_LIST (t); - int interface_only = CLASSTYPE_INTERFACE_ONLY (t); - int interface_unknown = CLASSTYPE_INTERFACE_UNKNOWN (t); - - bzero ((char *) TYPE_LANG_SPECIFIC (t), sizeof (struct lang_type)); - BINFO_BASETYPES(binfo) = NULL_TREE; - - CLASSTYPE_AS_LIST (t) = as_list; - TYPE_BINFO (t) = binfo; - CLASSTYPE_BINFO_AS_LIST (t) = binfo_as_list; - CLASSTYPE_INTERFACE_ONLY (t) = interface_only; - SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown); - TYPE_REDEFINED (t) = 1; - } - TYPE_SIZE (t) = NULL_TREE; - TYPE_MODE (t) = VOIDmode; - TYPE_FIELDS (t) = NULL_TREE; - TYPE_METHODS (t) = NULL_TREE; - TYPE_VFIELD (t) = NULL_TREE; - TYPE_CONTEXT (t) = NULL_TREE; -} - -/* finish up all new vtables. */ - -static void -finish_vtbls (binfo, do_self, t) - tree binfo; - int do_self; - tree t; -{ - 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 && 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); - } - - 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)) - { - base_binfo = binfo_member (BINFO_TYPE (base_binfo), CLASSTYPE_VBASECLASSES (t)); - } - finish_vtbls (base_binfo, is_not_base_vtable, t); - } -} - -/* True if we should override the given BASE_FNDECL with the given - FNDECL. */ - -static int -overrides (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))) - return 1; - if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (base_fndecl)) - || DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (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))) - == TYPE_QUALS (TREE_TYPE (TREE_VALUE (types)))) - && compparms (TREE_CHAIN (base_types), TREE_CHAIN (types))) - return 1; - } - return 0; -} - -static tree -get_class_offset_1 (parent, binfo, context, t, fndecl) - tree parent, binfo, context, t, fndecl; -{ - 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; - - 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)) - { - /* Only compare if we have two offsets */ - if (rval && rval != error_mark_node - && ! tree_int_cst_equal (nrval, rval)) - { - /* 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; - } - 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; -} - -/* Get the offset to the CONTEXT subobject that is related to the - given BINFO. */ - -static tree -get_class_offset (context, t, binfo, fndecl) - tree context, t, binfo, fndecl; -{ - tree first_binfo = binfo; - tree offset; - int i; - - if (context == t) - return integer_zero_node; - - if (BINFO_TYPE (binfo) == context) - return BINFO_OFFSET (binfo); - - /* 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); - } - - /* 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; -} - -/* Skip RTTI information at the front of the virtual list. */ - -unsigned HOST_WIDE_INT -skip_rtti_stuff (virtuals) - tree *virtuals; -{ - int n; - - 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); - } - 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; - - n = skip_rtti_stuff (&virtuals); - - 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); - } - -#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); - } -} - -/* These are the ones that are not through virtual base classes. */ - -static void -modify_all_direct_vtables (binfo, do_self, t, fndecl, pfn) - tree binfo; - int do_self; - tree t, fndecl, pfn; -{ - 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 && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))) - { - modify_one_vtable (binfo, t, fndecl, pfn); - } - - 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); - } -} - -/* Fixup all the delta entries in this one vtable that need updating. */ - -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); - - while (virtuals) - { - 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) - { - 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)) - { - /* 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 - { - /* 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); - } - - 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. */ - -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); - } -} - -/* These are the ones that are through virtual base classes. */ - -static void -modify_all_indirect_vtables (binfo, do_self, via_virtual, t, fndecl, pfn) - tree binfo; - int do_self, via_virtual; - tree t, fndecl, pfn; -{ - 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))) - { - modify_one_vtable (binfo, t, fndecl, pfn); - } - - 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); - } -} - -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); -} - -/* Here, we already know that they match in every respect. - All we have to check is where they had their declarations. */ - -static int -strictly_overrides (fndecl1, fndecl2) - tree fndecl1, fndecl2; -{ - 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; -} - -/* 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) - - We take special care to reuse a vtable, if we can. */ - -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); - skip_rtti_stuff (&old_virtuals); - - 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 (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); - } - } - 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); - } -} - -/* 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; - - /* Should we use something besides CLASSTYPE_VFIELDS? */ - if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))) - { - override_one_vtable (binfo, old, t); - } - - 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); - } -} - -/* 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. */ - -static tree -get_basefndecls (fndecl, t) - tree fndecl, t; -{ - tree methods = TYPE_METHODS (t); - 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); - - methods = TREE_CHAIN (methods); - } - - 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), - 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. */ - -static void -mark_overriders (fndecl, base_fndecls) - tree fndecl, base_fndecls; -{ - while (base_fndecls) - { - if (overrides (TREE_VALUE (base_fndecls), fndecl)) - TREE_PURPOSE (base_fndecls) = fndecl; - - base_fndecls = TREE_CHAIN (base_fndecls); - } -} - -/* If this declaration supersedes the declaration of - a method declared virtual in the base class, then - mark this field as being virtual as well. */ - -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); - - for (i = 0; i < n_baselinks; i++) - { - 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) - { - /* 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; - -#if 0 /* The signature of an overriding function is not changed. */ - { - /* The argument types may have changed... */ - tree type = TREE_TYPE (decl); - tree argtypes = TYPE_ARG_TYPES (type); - tree base_variant = TREE_TYPE (TREE_VALUE (argtypes)); - tree raises = TYPE_RAISES_EXCEPTIONS (type); - - argtypes = commonparms (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (tmp))), - TREE_CHAIN (argtypes)); - /* But the return type has not. */ - type = build_cplus_method_type (base_variant, TREE_TYPE (type), argtypes); - if (raises) - type = build_exception_variant (type, raises); - TREE_TYPE (decl) = type; - } -#endif - DECL_VINDEX (decl) - = tree_cons (NULL_TREE, tmp, DECL_VINDEX (decl)); - break; - } - } - } - if (virtualp) - { - if (DECL_VINDEX (decl) == NULL_TREE) - DECL_VINDEX (decl) = error_mark_node; - IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1; - } -} - -/* Warn about hidden virtual functions that are not overridden in t. - We know that constructors and destructors don't apply. */ - -void -warn_hidden (t) - tree t; -{ - tree method_vec = CLASSTYPE_METHOD_VEC (t); - int n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0; - int i; - - /* 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 fndecl; - - tree base_fndecls = NULL_TREE; - tree binfos = BINFO_BASETYPES (TYPE_BINFO (t)); - int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; - - fndecl = OVL_CURRENT (fns); - if (DECL_VINDEX (fndecl) == 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), - base_fndecls); - } - - fns = OVL_NEXT (fns); - if (fns) - fndecl = OVL_CURRENT (fns); - else - fndecl = NULL_TREE; - - /* ...then mark up all the base functions with overriders, preferring - overriders to hiders. */ - if (base_fndecls) - while (fndecl) - { - mark_overriders (fndecl, base_fndecls); - - fns = OVL_NEXT (fns); - if (fns) - fndecl = OVL_CURRENT (fns); - else - fndecl = NULL_TREE; - } - - /* Now give a warning for all base functions without overriders, - as they are hidden. */ - while (base_fndecls) - { - if (! overrides (TREE_VALUE (base_fndecls), - TREE_PURPOSE (base_fndecls))) - { - /* Here we know it is a hider, and no overrider exists. */ - cp_warning_at ("`%D' was hidden", TREE_VALUE (base_fndecls)); - cp_warning_at (" by `%D'", TREE_PURPOSE (base_fndecls)); - } - - base_fndecls = TREE_CHAIN (base_fndecls); - } - } -} - -/* Check for things that are invalid. There are probably plenty of other - things we should check for also. */ - -static void -finish_struct_anon (t) - tree t; -{ - tree field; - for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field)) - { - if (TREE_STATIC (field)) - continue; - if (TREE_CODE (field) != FIELD_DECL) - continue; - - if (DECL_NAME (field) == NULL_TREE - && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) - { - tree* uelt = &TYPE_FIELDS (TREE_TYPE (field)); - for (; *uelt; uelt = &TREE_CHAIN (*uelt)) - { - if (DECL_ARTIFICIAL (*uelt)) - continue; - - if (DECL_NAME (*uelt) == constructor_name (t)) - cp_pedwarn_at ("ANSI C++ forbids member `%D' with same name as enclosing class", - *uelt); - - if (TREE_CODE (*uelt) != FIELD_DECL) - { - cp_pedwarn_at ("`%#D' invalid; an anonymous union can only have non-static data members", - *uelt); - continue; - } - - if (TREE_PRIVATE (*uelt)) - cp_pedwarn_at ("private member `%#D' in anonymous union", - *uelt); - else if (TREE_PROTECTED (*uelt)) - cp_pedwarn_at ("protected member `%#D' in anonymous union", - *uelt); - - TREE_PRIVATE (*uelt) = TREE_PRIVATE (field); - TREE_PROTECTED (*uelt) = 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. */ - -static tree -add_implicitly_declared_members (t, cant_have_default_ctor, - cant_have_const_cctor, - cant_have_assignment) - tree t; - int cant_have_default_ctor; - int cant_have_const_cctor; - int cant_have_assignment; -{ - tree default_fn; - tree implicit_fns = NULL_TREE; - tree name = TYPE_IDENTIFIER (t); - tree virtual_dtor = NULL_TREE; - tree *f; - - /* Destructor. */ - if (TYPE_NEEDS_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t) - && !IS_SIGNATURE (t)) - { - default_fn = cons_up_default_function (t, name, 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; - else - { - TREE_CHAIN (default_fn) = implicit_fns; - implicit_fns = default_fn; - - if (DECL_VINDEX (default_fn)) - virtual_dtor = default_fn; - } - } - TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t); - - /* Default constructor. */ - if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor - && ! IS_SIGNATURE (t)) - { - default_fn = cons_up_default_function (t, name, 2); - 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)) - { - /* 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); - 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)) - { - default_fn = cons_up_default_function (t, name, - 5 + cant_have_assignment); - TREE_CHAIN (default_fn) = implicit_fns; - implicit_fns = default_fn; - } - - /* 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); - *f = TYPE_METHODS (t); - TYPE_METHODS (t) = implicit_fns; - - 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. */ - -tree -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; - - 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; - - if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))) - pedwarn ("anonymous class type not used to declare any objects"); - - if (TYPE_SIZE (t)) - { - if (IS_AGGR_TYPE (t)) - cp_error ("redefinition of `%#T'", t); - else - my_friendly_abort (172); - popclass (0); - return t; - } - - 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; - -#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)) - { - my_friendly_assert (CLASSTYPE_INTERFACE_ONLY (t) == interface_only, 999); - my_friendly_assert (CLASSTYPE_INTERFACE_KNOWN (t) == ! interface_unknown, 999); - } -#endif - - old = suspend_momentary (); - - /* 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). */ - - if (TYPE_BINFO_BASETYPES (t)) - n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (t)); - else - n_baseclasses = 0; - - if (n_baseclasses > 0) - { - struct base_info base_info; - - 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; - CLASSTYPE_N_SUPERCLASSES (t) += base_info.n_ancestors; - 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; - } - 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; - } - -#if 0 - /* Both of these should be done before now. */ - if (write_virtuals == 3 && CLASSTYPE_INTERFACE_KNOWN (t) - && ! IS_SIGNATURE (t)) - { - my_friendly_assert (CLASSTYPE_INTERFACE_ONLY (t) == interface_only, 999); - my_friendly_assert (CLASSTYPE_VTABLE_NEEDS_WRITING (t) == ! interface_only, 999); - } -#endif - - /* 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; - - 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 (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x))) - continue; - - /* 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_for_override (x, t); - if (DECL_ABSTRACT_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)) - { - 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 - } - } - - if (n_baseclasses) - fields = chainon (build_vbase_pointer_fields (t), fields); - - last_x = NULL_TREE; - for (x = fields; x; x = TREE_CHAIN (x)) - { - GNU_xref_member (current_class_name, 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. */; - else - empty = 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); - continue; - } - - last_x = x; - - if (TREE_CODE (x) == TYPE_DECL - || TREE_CODE (x) == TEMPLATE_DECL) - continue; - - /* If we've gotten this far, it's a data member, possibly static, - or an enumerator. */ - - DECL_FIELD_CONTEXT (x) = t; - - /* ``A local class cannot have static data members.'' ARM 9.4 */ - if (current_function_decl && TREE_STATIC (x)) - cp_error_at ("field `%D' in local class cannot be static", x); - - /* Perform error checking that did not get done in - grokdeclarator. */ - if (TREE_CODE (TREE_TYPE (x)) == FUNCTION_TYPE) - { - cp_error_at ("field `%D' invalidly declared function type", - x); - TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); - } - else if (TREE_CODE (TREE_TYPE (x)) == METHOD_TYPE) - { - cp_error_at ("field `%D' invalidly declared method type", x); - TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); - } - else if (TREE_CODE (TREE_TYPE (x)) == OFFSET_TYPE) - { - cp_error_at ("field `%D' invalidly declared offset type", x); - TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x)); - } - -#if 0 - if (DECL_NAME (x) == constructor_name (t)) - cant_have_default_ctor = 1; -#endif - - if (TREE_TYPE (x) == 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; - - if (TREE_CODE (x) == CONST_DECL) - continue; - - if (TREE_CODE (x) == VAR_DECL) - { - if (TREE_CODE (t) == UNION_TYPE) - /* Unions cannot have static members. */ - cp_error_at ("field `%D' declared static in union", x); - - continue; - } - - /* Now it can only be a FIELD_DECL. */ - - if (TREE_PRIVATE (x) || TREE_PROTECTED (x)) - aggregate = 0; - - /* 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 (DECL_INITIAL (x) == NULL_TREE) - ref_sans_init = 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; - 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); - } - } - - if (TREE_CODE (TREE_TYPE (x)) == POINTER_TYPE) - has_pointers = 1; - - if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE_P (TREE_TYPE (x))) - has_mutable = 1; - - /* If any field is const, the structure type is pseudo-const. */ - if (TREE_READONLY (x)) - { - C_TYPE_FIELDS_READONLY (t) = 1; - if (DECL_INITIAL (x) == NULL_TREE) - const_sans_init = 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; - 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); - } - } - else - { - /* 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; - } - } - - /* 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)) - { - /* 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; - } - - /* 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); - - /* 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); - - 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 (DECL_INITIAL (x)) - { - DECL_INITIAL (x) = NULL_TREE; - DECL_FIELD_SIZE (x) = width; - DECL_BIT_FIELD (x) = 1; - - 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))); - } - else - { - tree type = TREE_TYPE (x); - - while (TREE_CODE (type) == ARRAY_TYPE) - type = TREE_TYPE (type); - - 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) - { - 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); - } - - if (!TYPE_HAS_CONST_INIT_REF (type)) - cant_have_const_ctor = 1; - - 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 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) - { - /* `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; - } - } - } - - /* 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; - - /* Effective C++ rule 11. */ - if (has_pointers && warn_ecpp && TYPE_HAS_CONSTRUCTOR (t) - && ! (TYPE_HAS_INIT_REF (t) && TYPE_HAS_ASSIGN_REF (t))) - { - cp_warning ("`%#T' has pointer data members", t); - - if (! TYPE_HAS_INIT_REF (t)) - { - cp_warning (" but does not override `%T(const %T&)'", t, t); - if (! TYPE_HAS_ASSIGN_REF (t)) - cp_warning (" or `operator=(const %T&)'", t); - } - else if (! TYPE_HAS_ASSIGN_REF (t)) - cp_warning (" but does not override `operator=(const %T&)'", t); - } - - /* 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_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_REAL_ASSIGNMENT (t) |= TYPE_HAS_ASSIGNMENT (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); - - /* 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); - - if (TYPE_METHODS (t)) - { - finish_struct_methods (t); - method_vec = CLASSTYPE_METHOD_VEC (t); - } - else - { - method_vec = 0; - - /* Just in case these got accidentally - filled in by syntax errors. */ - TYPE_HAS_CONSTRUCTOR (t) = 0; - TYPE_HAS_DESTRUCTOR (t) = 0; - } - - 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); - - if (vfield == NULL_TREE && has_virtual) - { - /* We build this decl with vtbl_ptr_type_node, which is a - `vtable_entry_type*'. It might seem more precise to use - `vtable_entry_type (*)[N]' where N is the number of firtual - functions. However, that would require the vtable pointer in - base classes to have a different type than the vtable pointer - in derived classes. We could make that happen, but that - still wouldn't solve all the problems. In particular, the - type-based alias analysis code would decide that assignments - to the base class vtable pointer can't alias assignments to - the derived class vtable pointer, since they have different - types. Thus, in an derived class destructor, where the base - class constructor was inlined, we could generate bad code for - setting up the vtable pointer. - - Therefore, we use one type for all vtable pointers. We still - use a type-correct type; it's just doesn't indicate the array - 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) - { - my_friendly_assert (TREE_CHAIN (last_x) == NULL_TREE, 175); - TREE_CHAIN (last_x) = vfield; - last_x = vfield; - } - else - fields = vfield; -#endif - empty = 0; - vfields = chainon (vfields, CLASSTYPE_AS_LIST (t)); - } - - /* Now DECL_INITIAL is null on all members except for zero-width bit-fields. - - C++: maybe we will support default field initialization some day... */ - - /* Delete all duplicate fields from the fields */ - delete_duplicate_fields (fields); - - /* Catch function/field name conflict. We don't need to do this for a - signature, since it can only contain the fields constructed in - append_signature_fields. */ - if (! IS_SIGNATURE (t)) - { - int n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0; - for (x = fields; x; x = TREE_CHAIN (x)) - { - tree name = DECL_NAME (x); - int i; - - if (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)) - continue; - - 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_at ("data member `%#D' conflicts with", x); - cp_error_at ("function member `%#D'", - OVL_CURRENT (TREE_VEC_ELT (method_vec, i))); - break; - } - } - } - - /* Now we have the nearly final fieldlist for the data fields. Record it, - then lay out the structure or union (including the fields). */ - - TYPE_FIELDS (t) = fields; - - if (n_baseclasses) - { - last_x = build_base_fields (t); - - /* 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; - } - if (empty) - { - /* 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; - } - if (n_baseclasses) - TYPE_FIELDS (t) = chainon (last_x, TYPE_FIELDS (t)); - - layout_type (t); - - /* 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); - - finish_struct_anon (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. */ - pending_hard_virtuals = nreverse (pending_hard_virtuals); - - if (n_baseclasses) - /* layout_basetypes will remove the base subobject fields. */ - max_has_virtual = layout_basetypes (t, max_has_virtual); - else 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; - - if (TYPE_USES_VIRTUAL_BASECLASSES (t)) - { - tree vbases; - - vbases = CLASSTYPE_VBASECLASSES (t); - CLASSTYPE_N_VBASECLASSES (t) = list_length (vbases); - - { - /* 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; - - for (i = 0; i < n_baseclasses; i++) - { - tree base_binfo = TREE_VEC_ELT (binfos, i); - tree basetype = BINFO_TYPE (base_binfo); - tree vbases; - - vbases = CLASSTYPE_VBASECLASSES (basetype); - while (vbases) - { - merge_overrides (binfo_member (BINFO_TYPE (vbases), - CLASSTYPE_VBASECLASSES (t)), - vbases, 1, t); - vbases = TREE_CHAIN (vbases); - } - } - } - } - - /* 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) - { - 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; - } - -#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; - - if (flag_rtti && TYPE_VIRTUAL_P (t) && !pending_hard_virtuals) - modify_all_vtables (t, NULL_TREE, NULL_TREE); - - while (pending_hard_virtuals) - { - modify_all_vtables (t, - TREE_PURPOSE (pending_hard_virtuals), - TREE_VALUE (pending_hard_virtuals)); - pending_hard_virtuals = TREE_CHAIN (pending_hard_virtuals); - } - - 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); - } - } - - /* Under our model of GC, every C++ class gets its own virtual - function table, at least virtually. */ - if (pending_virtuals) - { - pending_virtuals = nreverse (pending_virtuals); - /* We must enter these virtuals into the table. */ - if (first_vfn_base_index < 0) - { - /* 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); - - /* The first slot is for the rtti offset. */ - pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals); - - set_rtti_entry (pending_virtuals, - convert (ssizetype, integer_zero_node), t); - build_vtable (NULL_TREE, t); - } - else - { - /* Here we know enough to change the type of our virtual - function table, but we will wait until later this function. */ - - if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t))) - build_vtable (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), first_vfn_base_index), t); - } - - /* If this type has basetypes with constructors, then those - constructors might clobber the virtual function table. But - they don't if the derived class shares the exact vtable of the base - class. */ - - CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1; - } - else if (first_vfn_base_index >= 0) - { - 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. */ - - /* 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 (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) - { - /* 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); - - 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))); - } - } - else if (first_vfn_base_index >= 0) - CLASSTYPE_VFIELD (t) = vfield; - CLASSTYPE_VFIELDS (t) = vfields; - - finish_struct_bits (t, max_has_virtual); - - /* Complete the rtl for any static member objects of the type we're - working on. */ - for (x = fields; x; x = TREE_CHAIN (x)) - { - 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); - } - } - - if (TYPE_HAS_CONSTRUCTOR (t)) - { - tree vfields = CLASSTYPE_VFIELDS (t); - - while (vfields) - { - /* Mark the fact that constructor for T - could affect anybody inheriting from T - who wants to initialize vtables for VFIELDS's type. */ - if (VF_DERIVED_VALUE (vfields)) - TREE_ADDRESSABLE (vfields) = 1; - vfields = TREE_CHAIN (vfields); - } - if (any_default_members != 0) - build_class_init_list (t); - } - else if (TYPE_NEEDS_CONSTRUCTING (t)) - build_class_init_list (t); - - /* Write out inline function definitions. */ - do_inline_function_hair (t, CLASSTYPE_INLINE_FRIENDS (t)); - CLASSTYPE_INLINE_FRIENDS (t) = 0; - - 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) = build_tree_list (default_conversion (TYPE_BINFO_VTABLE (t)), vfield); - - 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); - hack_incomplete_structures (t); - -#if 0 - if (TYPE_NAME (t) && TYPE_IDENTIFIER (t)) - undo_template_name_overload (TYPE_IDENTIFIER (t), 1); -#endif - - resume_momentary (old); - - 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; - } - - /* Finish debugging output for this type. */ - rest_of_type_compilation (t, toplevel_bindings_p ()); - - return t; -} - -/* In [basic.scope.class] we have: - - 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. - - This function checks this condition for X, which is a member of - T. */ - -static void -check_member_decl_is_same_in_complete_scope (t, x) - tree t; - tree x; -{ - /* 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. - - Enums, types and static vars have already been checked. */ - if (TREE_CODE (x) != USING_DECL - && TREE_CODE (x) != TYPE_DECL && !DECL_CLASS_TEMPLATE_P (x) - && TREE_CODE (x) != CONST_DECL && TREE_CODE (x) != VAR_DECL) - { - tree name = DECL_NAME (x); - tree icv; - - /* Don't get confused by access decls. */ - if (name && TREE_CODE (name) == IDENTIFIER_NODE) - icv = IDENTIFIER_CLASS_VALUE (name); - else - icv = NULL_TREE; - - /* This should match pushdecl_class_level. */ - if (icv && icv != x - && flag_optional_diags - /* Don't complain about constructors. */ - && name != constructor_name (current_class_type) - /* Or inherited names. */ - && id_in_current_class (name) - /* Or shadowed tags. */ - && !(TREE_CODE (icv) == TYPE_DECL && DECL_CONTEXT (icv) == t)) - { - cp_pedwarn_at ("declaration of identifier `%D' as `%+#D'", - name, x); - cp_pedwarn_at ("conflicts with other use in class as `%#D'", - icv); - } - } -} - -/* When T was built up, the member declarations were added in reverse - order. Rearrange them to declaration order. */ - -void -unreverse_member_declarations (t) - tree t; -{ - tree next; - tree prev; - tree x; - - /* The TYPE_FIELDS, TYPE_METHODS, and CLASSTYPE_TAGS are all in - reverse order. Put them in declaration order now. */ - TYPE_METHODS (t) = nreverse (TYPE_METHODS (t)); - CLASSTYPE_TAGS (t) = nreverse (CLASSTYPE_TAGS (t)); - - /* Actually, for the TYPE_FIELDS, only the non TYPE_DECLs are in - reverse order, so we can't just use nreverse. */ - prev = NULL_TREE; - for (x = TYPE_FIELDS (t); - x && TREE_CODE (x) != TYPE_DECL; - x = next) - { - next = TREE_CHAIN (x); - TREE_CHAIN (x) = prev; - prev = x; - } - if (prev) - { - TREE_CHAIN (TYPE_FIELDS (t)) = x; - if (prev) - TYPE_FIELDS (t) = prev; - } -} - -tree -finish_struct (t, attributes, warn_anon) - tree t, attributes; - int warn_anon; -{ - tree name = TYPE_NAME (t); - tree x; - - 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); - - /* Now that we've got all the field declarations, reverse everything - as necessary. */ - unreverse_member_declarations (t); - - if (flag_optional_diags) - { - for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x)) - check_member_decl_is_same_in_complete_scope (t, x); - for (x = TYPE_FIELDS (t); x; x = TREE_CHAIN (x)) - check_member_decl_is_same_in_complete_scope (t, x); - } - - /* Mark all the tags in the class as class-local. */ - for (x = CLASSTYPE_TAGS (t); x; x = TREE_CHAIN (x)) - TREE_NONLOCAL_FLAG (TREE_VALUE (x)) = 0; - - cplus_decl_attributes (t, attributes, NULL_TREE); - - 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; - } - else - t = finish_struct_1 (t, warn_anon); - - TYPE_BEING_DEFINED (t) = 0; - if (current_class_type) - popclass (0); - else - error ("trying to finish struct, but kicked out due to previous parse errors."); - - return t; -} - -/* Return the dynamic type of INSTANCE, if known. - 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. */ - -tree -fixed_type_or_null (instance, nonnull) - tree instance; - int *nonnull; -{ - 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... */ - case CALL_EXPR: - /* This is a call to a constructor, hence it's never zero. */ - if (TREE_HAS_CONSTRUCTOR (instance)) - { - if (nonnull) - *nonnull = 1; - return TREE_TYPE (instance); - } - return NULL_TREE; - - case SAVE_EXPR: - /* This is a call to a constructor, hence it's never zero. */ - if (TREE_HAS_CONSTRUCTOR (instance)) - { - if (nonnull) - *nonnull = 1; - return TREE_TYPE (instance); - } - return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull); - - case RTL_EXPR: - return NULL_TREE; - - case PLUS_EXPR: - case MINUS_EXPR: - 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); - return NULL_TREE; - - case NOP_EXPR: - case CONVERT_EXPR: - return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull); - - case ADDR_EXPR: - if (nonnull) - *nonnull = 1; - return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull); - - case COMPONENT_REF: - return fixed_type_or_null (TREE_OPERAND (instance, 1), nonnull); - - case VAR_DECL: - case FIELD_DECL: - if (TREE_CODE (TREE_TYPE (instance)) == ARRAY_TYPE - && IS_AGGR_TYPE (TREE_TYPE (TREE_TYPE (instance)))) - { - if (nonnull) - *nonnull = 1; - return TREE_TYPE (TREE_TYPE (instance)); - } - /* fall through... */ - case TARGET_EXPR: - case PARM_DECL: - if (IS_AGGR_TYPE (TREE_TYPE (instance))) - { - if (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. */ - *nonnull = 1; - } - return NULL_TREE; - - default: - return NULL_TREE; - } -} - -/* 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. - - 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. */ - -int -resolves_to_fixed_type_p (instance, nonnull) - tree instance; - int *nonnull; -{ - tree t = TREE_TYPE (instance); - tree fixed = fixed_type_or_null (instance, nonnull); - 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)); -} - - -void -init_class_processing () -{ - current_class_depth = 0; - current_class_stack_size = 10; - 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; - - 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_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); - - /* 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); -} - -/* Set current scope to NAME. CODE tells us if this is a - STRUCT, UNION, or ENUM environment. - - NAME may end up being NULL_TREE if this is an anonymous or - late-bound struct (as in "struct { ... } foo;") */ - -/* Set global variables CURRENT_CLASS_NAME and CURRENT_CLASS_TYPE to - appropriate values, found by looking up the type definition of - NAME (as a CODE). - - If MODIFY is 1, we set IDENTIFIER_CLASS_VALUE's of names - which can be seen locally to the class. They are shadowed by - any subsequent local declaration (including parameter names). - - If MODIFY is 2, we set IDENTIFIER_CLASS_VALUE's of names - which have static meaning (i.e., static members, static - member functions, enum declarations, etc). - - If MODIFY is 3, we set IDENTIFIER_CLASS_VALUE of names - which can be seen locally to the class (as in 1), but - know that we are doing this for declaration purposes - (i.e. friend foo::bar (int)). - - So that we may avoid calls to lookup_name, we cache the _TYPE - nodes of local TYPE_DECLs in the TREE_TYPE field of the name. - - For multiple inheritance, we perform a two-pass depth-first search - of the type lattice. The first pass performs a pre-order search, - marking types after the type has had its fields installed in - the appropriate IDENTIFIER_CLASS_VALUE slot. The second pass merely - unmarks the marked types. If a field or member function name - appears in an ambiguous way, the IDENTIFIER_CLASS_VALUE of - that name becomes `error_mark_node'. */ - -void -pushclass (type, modify) - tree type; - int modify; -{ - type = TYPE_MAIN_VARIANT (type); - - /* Make sure there is enough room for the new entry on the stack. */ - if (current_class_depth + 1 >= current_class_stack_size) - { - current_class_stack_size *= 2; - current_class_stack - = (class_stack_node_t) xrealloc (current_class_stack, - current_class_stack_size - * sizeof (struct class_stack_node)); - } - - /* Insert a new entry on the class stack. */ - current_class_stack[current_class_depth].name = current_class_name; - current_class_stack[current_class_depth].type = current_class_type; - current_class_stack[current_class_depth].access = current_access_specifier; - current_class_depth++; - - /* Now set up the new type. */ - current_class_name = TYPE_NAME (type); - if (TREE_CODE (current_class_name) == TYPE_DECL) - current_class_name = DECL_NAME (current_class_name); - current_class_type = type; - - /* By default, things in classes are private, while things in - structures or unions are public. */ - current_access_specifier = (CLASSTYPE_DECLARED_CLASS (type) - ? access_private_node - : access_public_node); - - if (previous_class_type != NULL_TREE - && (type != previous_class_type || TYPE_SIZE (previous_class_type) == NULL_TREE) - && current_class_depth == 1) - { - /* Forcibly remove any old class remnants. */ - popclass (-1); - previous_class_type = NULL_TREE; - - /* Now, free the obstack on which we cached all the values. */ - obstack_free (&class_cache_obstack, class_cache_firstobj); - class_cache_firstobj - = (char*) obstack_finish (&class_cache_obstack); - } - - pushlevel_class (); - -#if 0 - if (CLASSTYPE_TEMPLATE_INFO (type)) - overload_template_name (type); -#endif - - if (modify) - { - tree tags; - tree this_fndecl = current_function_decl; - - if (current_function_decl - && DECL_CONTEXT (current_function_decl) - && TREE_CODE (DECL_CONTEXT (current_function_decl)) == FUNCTION_DECL) - current_function_decl = DECL_CONTEXT (current_function_decl); - else - current_function_decl = NULL_TREE; - - if (type != previous_class_type || current_class_depth > 1) - { -#ifdef MI_MATRIX - build_mi_matrix (type); - push_class_decls (type); - free_mi_matrix (); -#else - push_class_decls (type); -#endif - } - else - { - tree item; - - /* We are re-entering the same class we just left, so we - don't have to search the whole inheritance matrix to find - all the decls to bind again. Instead, we install the - cached class_shadowed list, and walk through it binding - names and setting up IDENTIFIER_TYPE_VALUEs. */ - set_class_shadows (previous_class_values); - for (item = previous_class_values; item; item = TREE_CHAIN (item)) - { - tree id = TREE_PURPOSE (item); - tree decl = TREE_TYPE (item); - - push_class_binding (id, decl); - if (TREE_CODE (decl) == TYPE_DECL) - set_identifier_type_value (id, TREE_TYPE (decl)); - } - unuse_fields (type); - } - - for (tags = CLASSTYPE_TAGS (type); tags; tags = TREE_CHAIN (tags)) - { - tree tag_type = TREE_VALUE (tags); - - TREE_NONLOCAL_FLAG (tag_type) = 1; - if (! TREE_PURPOSE (tags)) - continue; - if (! (IS_AGGR_TYPE_CODE (TREE_CODE (tag_type)) - && CLASSTYPE_IS_TEMPLATE (tag_type))) - pushtag (TREE_PURPOSE (tags), tag_type, 0); - } - - current_function_decl = this_fndecl; - } -} - -/* Get out of the current class scope. If we were in a class scope - previously, that is the one popped to. The flag MODIFY tells whether - the current scope declarations needs to be modified as a result of - popping to the previous scope. 0 is used for class definitions. */ - -void -popclass (modify) - int modify; -{ - if (modify < 0) - { - /* Back this old class out completely. */ - tree tags = CLASSTYPE_TAGS (previous_class_type); - 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! */ - for (t = previous_class_values; t; t = TREE_CHAIN (t)) - IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE; - while (tags) - { - TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 0; - tags = TREE_CHAIN (tags); - } - - return; - } - - if (modify) - { - /* Just remove from this class what didn't make - it into IDENTIFIER_CLASS_VALUE. */ - tree tags = CLASSTYPE_TAGS (current_class_type); - - while (tags) - { - TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 0; - tags = TREE_CHAIN (tags); - } - } - - /* Force clearing of IDENTIFIER_CLASS_VALUEs after a class definition, - since not all class decls make it there currently. */ - poplevel_class (! modify); - - /* Since poplevel_class does the popping of class decls nowadays, - this really only frees the obstack used for these decls. - That's why it had to be moved down here. */ - if (modify) - pop_class_decls (); - - current_class_depth--; - current_class_name = current_class_stack[current_class_depth].name; - current_class_type = current_class_stack[current_class_depth].type; - current_access_specifier = current_class_stack[current_class_depth].access; -} - -/* Returns 1 if current_class_type is either T or a nested type of T. */ - -int -currently_open_class (t) - tree t; -{ - int i; - if (t == current_class_type) - return 1; - for (i = 0; i < current_class_depth; ++i) - if (current_class_stack [i].type == t) - return 1; - return 0; -} - -/* 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 - enclosing class contexts until global or a local scope is reached. - TYPE is the enclosed class and MODIFY is equivalent with the pushclass - formal of the same name. */ - -void -push_nested_class (type, modify) - tree type; - int modify; -{ - tree context; - - my_friendly_assert (!type || TREE_CODE (type) != NAMESPACE_DECL, 980711); - - if (type == NULL_TREE || type == error_mark_node || ! IS_AGGR_TYPE (type) - || TREE_CODE (type) == TEMPLATE_TYPE_PARM - || TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM) - return; - - context = DECL_CONTEXT (TYPE_MAIN_DECL (type)); - - if (context && TREE_CODE (context) == RECORD_TYPE) - push_nested_class (context, 2); - pushclass (type, modify); -} - -/* Undoes a push_nested_class call. MODIFY is passed on to popclass. */ - -void -pop_nested_class (modify) - int modify; -{ - tree context = DECL_CONTEXT (TYPE_MAIN_DECL (current_class_type)); - - popclass (modify); - if (context && TREE_CODE (context) == RECORD_TYPE) - pop_nested_class (modify); -} - -/* Set global variables CURRENT_LANG_NAME to appropriate value - so that behavior of name-mangling machinery is correct. */ - -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; - } - - if (name == lang_name_cplusplus || name == lang_name_java) - { - strict_prototype = strict_prototypes_lang_cplusplus; - current_lang_name = name; - } - else if (name == lang_name_c) - { - strict_prototype = strict_prototypes_lang_c; - current_lang_name = name; - } - else - error ("language string `\"%s\"' not recognized", IDENTIFIER_POINTER (name)); -} - -/* Get out of the current language scope. */ - -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; -} - -/* Type instantiation routines. */ - -/* 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 - was a template-id, and EXPLICIT_TARGS are the explicitly provided - template arguments. */ - -static tree -resolve_address_of_overloaded_function (target_type, - overload, - complain, - template_only, - explicit_targs) - tree target_type; - tree overload; - int complain; - int template_only; - tree explicit_targs; -{ - /* Here's what the standard says: - - [over.over] - - If the name is a function template, template argument deduction - is done, and if the argument deduction succeeds, the deduced - arguments are used to generate a single template function, which - is added to the set of overloaded functions considered. - - Non-member functions and static member functions match targets of - type "pointer-to-function" or "reference-to-function." Nonstatic - member functions match targets of type "pointer-to-member - function;" the function type of the pointer to member is used to - select the member function from the set of overloaded member - functions. If a nonstatic member function is selected, the - reference to the overloaded function name is required to have the - form of a pointer to member as described in 5.3.1. - - If more than one function is selected, any template functions in - the set are eliminated if the set also contains a non-template - function, and any given template function is eliminated if the - set contains a second template function that is more specialized - than the first according to the partial ordering rules 14.5.5.2. - After such eliminations, if any, there shall remain exactly one - selected function. */ - - int is_ptrmem = 0; - int is_reference = 0; - /* We store the matches in a TREE_LIST rooted here. The functions - are the TREE_PURPOSE, not the TREE_VALUE, in this list, for easy - interoperability with most_specialized_instantiation. */ - tree matches = NULL_TREE; - tree fn; - - /* By the time we get here, we should be seeing only real - pointer-to-member types, not the internal POINTER_TYPE to - METHOD_TYPE representation. */ - my_friendly_assert (!(TREE_CODE (target_type) == POINTER_TYPE - && (TREE_CODE (TREE_TYPE (target_type)) - == METHOD_TYPE)), 0); - - /* Check that the TARGET_TYPE is reasonable. */ - if (TYPE_PTRFN_P (target_type)) - /* This is OK. */ - ; - else if (TYPE_PTRMEMFUNC_P (target_type)) - /* This is OK, too. */ - is_ptrmem = 1; - else if (TREE_CODE (target_type) == FUNCTION_TYPE) - { - /* This is OK, too. This comes from a conversion to reference - type. */ - target_type = build_reference_type (target_type); - is_reference = 1; - } - else - { - if (complain) - cp_error("cannot resolve overloaded function `%D' based on conversion to type `%T'", - DECL_NAME (OVL_FUNCTION (overload)), target_type); - return error_mark_node; - } - - /* If we can find a non-template function that matches, we can just - use it. There's no point in generating template instantiations - if we're just going to throw them out anyhow. But, of course, we - can only do this when we don't *need* a template function. */ - if (!template_only) - { - tree fns; - - for (fns = overload; fns; fns = OVL_CHAIN (fns)) - { - tree fn = OVL_FUNCTION (fns); - tree fntype; - - if (TREE_CODE (fn) == TEMPLATE_DECL) - /* We're not looking for templates just yet. */ - continue; - - if ((TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE) - != is_ptrmem) - /* We're looking for a non-static member, and this isn't - one, or vice versa. */ - continue; - - /* See if there's a match. */ - fntype = TREE_TYPE (fn); - if (is_ptrmem) - fntype = build_ptrmemfunc_type (build_pointer_type (fntype)); - else if (!is_reference) - fntype = build_pointer_type (fntype); - - if (can_convert_arg (target_type, fntype, fn)) - matches = scratch_tree_cons (fn, NULL_TREE, matches); - } - } - - /* Now, if we've already got a match (or matches), there's no need - to proceed to the template functions. But, if we don't have a - match we need to look at them, too. */ - if (!matches) - { - tree target_fn_type; - tree target_arg_types; - tree fns; - - if (is_ptrmem) - { - target_fn_type - = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (target_type)); - target_arg_types = TREE_CHAIN (TYPE_ARG_TYPES (target_fn_type)); - } - else - { - target_fn_type = TREE_TYPE (target_type); - target_arg_types = TYPE_ARG_TYPES (target_fn_type); - } - - for (fns = overload; fns; fns = OVL_CHAIN (fns)) - { - tree fn = OVL_FUNCTION (fns); - tree fn_arg_types; - tree instantiation; - tree instantiation_type; - tree targs; - - if (TREE_CODE (fn) != TEMPLATE_DECL) - /* We're only looking for templates. */ - continue; - - if ((TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE) - != is_ptrmem) - /* We're looking for a non-static member, and this isn't - one, or vice versa. */ - continue; - - /* We don't use the `this' argument to do argument deduction - since that would prevent us from converting a base class - pointer-to-member to a derived class pointer-to-member. */ - fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn)); - if (is_ptrmem) - fn_arg_types = TREE_CHAIN (fn_arg_types); - - /* Try to do argument deduction. */ - targs = make_scratch_vec (DECL_NTPARMS (fn)); - if (type_unification (DECL_INNERMOST_TEMPLATE_PARMS (fn), - targs, - fn_arg_types, - target_arg_types, - explicit_targs, - DEDUCE_EXACT, - /*allow_incomplete=*/1) != 0) - /* Argument deduction failed. */ - continue; - - /* Instantiate the template. */ - instantiation = instantiate_template (fn, targs); - if (instantiation == error_mark_node) - /* Instantiation failed. */ - continue; - - /* See if there's a match. */ - instantiation_type = TREE_TYPE (instantiation); - if (is_ptrmem) - instantiation_type = - build_ptrmemfunc_type (build_pointer_type (instantiation_type)); - else if (!is_reference) - instantiation_type = build_pointer_type (instantiation_type); - if (can_convert_arg (target_type, instantiation_type, instantiation)) - matches = scratch_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); - - if (match != error_mark_node) - matches = scratch_tree_cons (match, NULL_TREE, NULL_TREE); - } - } - - /* Now we should have exactly one function in MATCHES. */ - if (matches == NULL_TREE) - { - /* There were *no* matches. */ - if (complain) - { - cp_error ("no matches converting function `%D' to type `%#T'", - DECL_NAME (OVL_FUNCTION (overload)), - target_type); - - /* print_candidates expects a chain with the functions in - 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); - - print_candidates (matches); - } - return error_mark_node; - } - else if (TREE_CHAIN (matches)) - { - /* There were too many matches. */ - - if (complain) - { - tree match; - - cp_error ("converting overloaded function `%D' to type `%#T' is ambiguous", - DECL_NAME (OVL_FUNCTION (overload)), - target_type); - - /* Since print_candidates expects the functions in the - TREE_VALUE slot, we flip them here. */ - for (match = matches; match; match = TREE_CHAIN (match)) - TREE_VALUE (match) = TREE_PURPOSE (match); - - print_candidates (matches); - } - - return error_mark_node; - } - - /* Good, exactly one match. Now, convert it to the correct type. */ - fn = TREE_PURPOSE (matches); - - mark_used (fn); - - if (TYPE_PTRFN_P (target_type) || TYPE_PTRMEMFUNC_P (target_type)) - return build_unary_op (ADDR_EXPR, fn, 0); - else - { - /* The target must be a REFERENCE_TYPE. Above, build_unary_op - will mark the function as addressed, but here we must do it - explicitly. */ - mark_addressable (fn); - - return fn; - } -} - -/* 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. - - For non-recursive calls, LHSTYPE should be a function, pointer to - function, or a pointer to member function. */ - -tree -instantiate_type (lhstype, rhs, complain) - tree lhstype, rhs; - int complain; -{ - if (TREE_CODE (lhstype) == UNKNOWN_TYPE) - { - if (complain) - error ("not enough type information"); - return error_mark_node; - } - - if (TREE_TYPE (rhs) != NULL_TREE && ! (type_unknown_p (rhs))) - { - if (same_type_p (lhstype, TREE_TYPE (rhs))) - return rhs; - if (complain) - cp_error ("argument of type `%T' does not match `%T'", - TREE_TYPE (rhs), lhstype); - return error_mark_node; - } - - /* We don't overwrite rhs if it is an overloaded function. - Copying it would destroy the tree link. */ - if (TREE_CODE (rhs) != OVERLOAD) - rhs = copy_node (rhs); - - /* This should really only be used when attempting to distinguish - what sort of a pointer to function we have. For now, any - arithmetic operation which is not supported on pointers - is rejected as an error. */ - - switch (TREE_CODE (rhs)) - { - case TYPE_EXPR: - case CONVERT_EXPR: - case SAVE_EXPR: - case CONSTRUCTOR: - case BUFFER_REF: - my_friendly_abort (177); - return error_mark_node; - - case INDIRECT_REF: - case ARRAY_REF: - { - tree new_rhs; - - new_rhs = instantiate_type (build_pointer_type (lhstype), - TREE_OPERAND (rhs, 0), complain); - if (new_rhs == error_mark_node) - return error_mark_node; - - TREE_TYPE (rhs) = lhstype; - TREE_OPERAND (rhs, 0) = new_rhs; - return rhs; - } - - case NOP_EXPR: - rhs = copy_node (TREE_OPERAND (rhs, 0)); - TREE_TYPE (rhs) = unknown_type_node; - return instantiate_type (lhstype, rhs, complain); - - case COMPONENT_REF: - { - tree field = TREE_OPERAND (rhs, 1); - tree r; - - my_friendly_assert (TREE_CODE (field) == TREE_LIST, 0); - - r = instantiate_type (lhstype, field, complain); - - if (r != error_mark_node && TYPE_PTRMEMFUNC_P (lhstype)) - { - if (complain) - { - tree t = TYPE_PTRMEMFUNC_OBJECT_TYPE (lhstype); - tree fn = TREE_VALUE (field); - if (TREE_CODE (fn) == OVERLOAD) - fn = OVL_FUNCTION (fn); - if (TREE_CODE (fn) == FUNCTION_DECL) - { - cp_error ("object-dependent reference `%E' can only be used in a call", - DECL_NAME (fn)); - cp_error (" to form a pointer to member function, say `&%T::%E'", - t, DECL_NAME (fn)); - } - else - cp_error ("object-dependent reference can only be used in a call"); - } - return error_mark_node; - } - - return r; - } - - case OFFSET_REF: - /* This can happen if we are forming a pointer-to-member for a - member template. */ - rhs = TREE_OPERAND (rhs, 1); - my_friendly_assert (TREE_CODE (rhs) == TEMPLATE_ID_EXPR, 0); - - /* 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)); - - case OVERLOAD: - return - resolve_address_of_overloaded_function (lhstype, - rhs, - complain, - /*template_only=*/0, - /*explicit_targs=*/NULL_TREE); - - case TREE_LIST: - { - if (TREE_PURPOSE (rhs) == error_mark_node) - { - /* Make sure we don't drop the non-local flag, as the old code - would rely on it. */ - int nl = TREE_NONLOCAL_FLAG (rhs); - /* We don't need the type of this node. */ - rhs = TREE_VALUE (rhs); - my_friendly_assert (TREE_NONLOCAL_FLAG (rhs) == nl, 980331); - } - - /* Now we should have a baselink. */ - my_friendly_assert (TREE_CODE (TREE_PURPOSE (rhs)) == TREE_VEC, - 980331); - my_friendly_assert (TREE_CHAIN (rhs) == NULL_TREE, 181); - my_friendly_assert (TREE_CODE (TREE_VALUE (rhs)) == FUNCTION_DECL - || TREE_CODE (TREE_VALUE (rhs)) == OVERLOAD, - 182); - - return instantiate_type (lhstype, TREE_VALUE (rhs), complain); - } - - case CALL_EXPR: - /* This is too hard for now. */ - my_friendly_abort (183); - return error_mark_node; - - case PLUS_EXPR: - case MINUS_EXPR: - case COMPOUND_EXPR: - TREE_OPERAND (rhs, 0) - = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain); - if (TREE_OPERAND (rhs, 0) == error_mark_node) - return error_mark_node; - TREE_OPERAND (rhs, 1) - = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain); - if (TREE_OPERAND (rhs, 1) == error_mark_node) - return error_mark_node; - - TREE_TYPE (rhs) = lhstype; - return rhs; - - case MULT_EXPR: - case TRUNC_DIV_EXPR: - case FLOOR_DIV_EXPR: - case CEIL_DIV_EXPR: - case ROUND_DIV_EXPR: - case RDIV_EXPR: - case TRUNC_MOD_EXPR: - case FLOOR_MOD_EXPR: - case CEIL_MOD_EXPR: - case ROUND_MOD_EXPR: - case FIX_ROUND_EXPR: - case FIX_FLOOR_EXPR: - case FIX_CEIL_EXPR: - case FIX_TRUNC_EXPR: - case FLOAT_EXPR: - case NEGATE_EXPR: - case ABS_EXPR: - case MAX_EXPR: - case MIN_EXPR: - case FFS_EXPR: - - case BIT_AND_EXPR: - case BIT_IOR_EXPR: - case BIT_XOR_EXPR: - case LSHIFT_EXPR: - case RSHIFT_EXPR: - case LROTATE_EXPR: - case RROTATE_EXPR: - - case PREINCREMENT_EXPR: - case PREDECREMENT_EXPR: - case POSTINCREMENT_EXPR: - case POSTDECREMENT_EXPR: - if (complain) - error ("invalid operation on uninstantiated type"); - return error_mark_node; - - case TRUTH_AND_EXPR: - case TRUTH_OR_EXPR: - case TRUTH_XOR_EXPR: - case LT_EXPR: - case LE_EXPR: - case GT_EXPR: - case GE_EXPR: - case EQ_EXPR: - case NE_EXPR: - case TRUTH_ANDIF_EXPR: - case TRUTH_ORIF_EXPR: - case TRUTH_NOT_EXPR: - if (complain) - error ("not enough type information"); - return error_mark_node; - - case COND_EXPR: - if (type_unknown_p (TREE_OPERAND (rhs, 0))) - { - if (complain) - error ("not enough type information"); - return error_mark_node; - } - TREE_OPERAND (rhs, 1) - = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain); - if (TREE_OPERAND (rhs, 1) == error_mark_node) - return error_mark_node; - TREE_OPERAND (rhs, 2) - = instantiate_type (lhstype, TREE_OPERAND (rhs, 2), complain); - if (TREE_OPERAND (rhs, 2) == error_mark_node) - return error_mark_node; - - TREE_TYPE (rhs) = lhstype; - return rhs; - - case MODIFY_EXPR: - TREE_OPERAND (rhs, 1) - = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), complain); - if (TREE_OPERAND (rhs, 1) == error_mark_node) - return error_mark_node; - - TREE_TYPE (rhs) = lhstype; - return rhs; - - case ADDR_EXPR: - return instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain); - - case ENTRY_VALUE_EXPR: - my_friendly_abort (184); - return error_mark_node; - - case ERROR_MARK: - return error_mark_node; - - default: - my_friendly_abort (185); - return error_mark_node; - } -} - -/* Return the name of the virtual function pointer field - (as an IDENTIFIER_NODE) for the given TYPE. Note that - this may have to look back through base types to find the - ultimate field name. (For single inheritance, these could - all be the same name. Who knows for multiple inheritance). */ - -static tree -get_vfield_name (type) - tree type; -{ - tree binfo = TYPE_BINFO (type); - char *buf; - - while (BINFO_BASETYPES (binfo) - && TYPE_VIRTUAL_P (BINFO_TYPE (BINFO_BASETYPE (binfo, 0))) - && ! TREE_VIA_VIRTUAL (BINFO_BASETYPE (binfo, 0))) - binfo = BINFO_BASETYPE (binfo, 0); - - type = BINFO_TYPE (binfo); - buf = (char *) alloca (sizeof (VFIELD_NAME_FORMAT) - + TYPE_NAME_LENGTH (type) + 2); - sprintf (buf, VFIELD_NAME_FORMAT, TYPE_NAME_STRING (type)); - return get_identifier (buf); -} - -void -print_class_statistics () -{ -#ifdef GATHER_STATISTICS - fprintf (stderr, "convert_harshness = %d\n", n_convert_harshness); - fprintf (stderr, "compute_conversion_costs = %d\n", n_compute_conversion_costs); - fprintf (stderr, "build_method_call = %d (inner = %d)\n", - n_build_method_call, n_inner_fields_searched); - if (n_vtables) - { - fprintf (stderr, "vtables = %d; vtable searches = %d\n", - n_vtables, n_vtable_searches); - fprintf (stderr, "vtable entries = %d; vtable elems = %d\n", - n_vtable_entries, n_vtable_elems); - } -#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 -maybe_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 - into the scope of the class itself. For purposes of access checking, - the inserted class name is treated as if it were a public member name. */ - -tree -build_self_reference () -{ - tree name = constructor_name (current_class_type); - tree value = build_lang_decl (TYPE_DECL, name, current_class_type); - DECL_NONLOCAL (value) = 1; - DECL_CONTEXT (value) = current_class_type; - DECL_CLASS_CONTEXT (value) = current_class_type; - DECL_ARTIFICIAL (value) = 1; - - pushdecl_class_level (value); - return value; -} - -/* Returns 1 if TYPE contains only padding bytes. */ - -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); -} - -/* Find the enclosing class of the given NODE. NODE can be a *_DECL or - a *_TYPE node. NODE can also be a local class. */ - -tree -get_enclosing_class (type) - tree type; -{ - tree node = type; - - while (node && TREE_CODE (node) != NAMESPACE_DECL) - { - switch (TREE_CODE_CLASS (TREE_CODE (node))) - { - case 'd': - node = DECL_CONTEXT (node); - break; - - case 't': - if (node != type) - return node; - node = TYPE_CONTEXT (node); - break; - - default: - my_friendly_abort (0); - } - } - return NULL_TREE; -} - -/* Return 1 if TYPE or one of its enclosing classes is derived from BASE. */ - -int -is_base_of_enclosing_class (base, type) - tree base, type; -{ - while (type) - { - if (get_binfo (base, type, 0)) - return 1; - - type = get_enclosing_class (type); - } - return 0; -} |