diff options
Diffstat (limited to 'gnu/usr.bin/cc/cc1plus/class.c')
-rw-r--r-- | gnu/usr.bin/cc/cc1plus/class.c | 5052 |
1 files changed, 0 insertions, 5052 deletions
diff --git a/gnu/usr.bin/cc/cc1plus/class.c b/gnu/usr.bin/cc/cc1plus/class.c deleted file mode 100644 index b0d815b..0000000 --- a/gnu/usr.bin/cc/cc1plus/class.c +++ /dev/null @@ -1,5052 +0,0 @@ -/* Functions related to building classes and their related objects. - Copyright (C) 1987, 1992, 1993, 1994 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ - - -/* High-level class interface. */ - -#include "config.h" -#include "tree.h" -#include <stdio.h> -#include "cp-tree.h" -#include "flags.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)); - -/* Way of stacking class types. */ -static tree *current_class_base, *current_class_stack; -static int current_class_stacksize; -int current_class_depth; - -struct class_level -{ - /* The previous class level. */ - struct class_level *level_chain; - - /* The class instance variable, as a PARM_DECL. */ - tree decl; - /* The class instance variable, as an object. */ - tree object; - /* The virtual function table pointer - for the class instance variable. */ - tree vtable_decl; - - /* Name of the current class. */ - tree name; - /* Type of the current class. */ - tree type; - - /* Flags for this class level. */ - int this_is_variable; - int memoized_lookups; - int save_memoized; - int unused; -}; - -tree current_class_decl, C_C_D; /* PARM_DECL: the class instance variable */ -tree current_vtable_decl; - -/* 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 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. */ -static tree get_vfield_name PROTO((tree)); -tree the_null_vtable_entry; - -/* 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; -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; - -/* Variables shared between class.c and call.c. */ - -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; - -/* Virtual baseclass things. */ -tree -build_vbase_pointer (exp, type) - tree exp, type; -{ - char *name; - - name = (char *) alloca (TYPE_NAME_LENGTH (type) + sizeof (VBASE_NAME) + 1); - sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (type)); - return build_component_ref (exp, get_identifier (name), 0, 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. */ -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; -} - -/* 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. - - ALIAS_THIS is non-zero if EXPR in an expression involving `this'. */ -tree -build_vbase_path (code, type, expr, path, alias_this) - enum tree_code code; - tree type, expr, path; - int alias_this; -{ - register int changed = 0; - tree last = NULL_TREE, last_virtual = NULL_TREE; - int nonnull = 0; - int fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull); - tree null_expr = 0, nonnull_expr; - tree basetype; - tree offset = integer_zero_node; - - /* We need 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, or until we can - recognize when that is, we cannot do the short cut logic. (mrs) */ - /* Do this, until we can undo any previous convertions. See net35.C - for a testcase. */ - fixed_type_p = complete_type_p (expr); - - if (!fixed_type_p && TREE_SIDE_EFFECTS (expr)) - expr = save_expr (expr); - nonnull_expr = expr; - - if (BINFO_INHERITANCE_CHAIN (path)) - { - tree reverse_path = NULL_TREE; - - while (path) - { - tree r = copy_node (path); - BINFO_INHERITANCE_CHAIN (r) = reverse_path; - reverse_path = r; - path = BINFO_INHERITANCE_CHAIN (path); - } - path = reverse_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) - { - extern int flag_assume_nonnull_objects; - 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 && !flag_assume_nonnull_objects - && null_expr == NULL_TREE) - { - null_expr = build1 (NOP_EXPR, TYPE_POINTER_TO (last_virtual), integer_zero_node); - expr = build (COND_EXPR, TYPE_POINTER_TO (last_virtual), - build (EQ_EXPR, integer_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 (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)) - basetype = intype; - else - { - tree binfo = get_binfo (last, TYPE_MAIN_VARIANT (intype), 0); - basetype = last; - 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)) - { - /* For multiple inheritance: if `this' can be set by any - function, then it could be 0 on entry to any function. - Preserve such zeroness here. Otherwise, only in the - case of constructors need we worry, and in those cases, - it will be zero, or initialized to some legal value to - which we may add. */ - if (nonnull == 0 && (alias_this == 0 || flag_this_is_variable > 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, integer_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. */ - -/* Virtual functions to be dealt with after laying out our base - classes. We do all overrides after we layout virtual base classes. - */ -static tree pending_hard_virtuals; -static int doing_hard_virtuals; - -/* 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. */ -tree -build_vtable_entry (delta, pfn) - tree delta, pfn; -{ - - if (flag_vtable_thunks) - { - HOST_WIDE_INT idelta = TREE_INT_CST_LOW (delta); - extern tree make_thunk (); - if (idelta) - { - 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 = tree_cons (NULL_TREE, delta, - tree_cons (NULL_TREE, integer_zero_node, - build_tree_list (NULL_TREE, pfn))); - tree entry = build (CONSTRUCTOR, vtable_entry_type, NULL_TREE, elems); - - /* DELTA is constructed by `size_int', which means it may be an - unsigned quantity on some platforms. Therefore, we cannot use - `int_fits_type_p', because when DELTA is really negative, - `force_fit_type' will make it look like a very large number. */ - - if ((TREE_INT_CST_LOW (TYPE_MAX_VALUE (delta_type_node)) - < TREE_INT_CST_LOW (delta)) - || (TREE_INT_CST_LOW (delta) - < TREE_INT_CST_LOW (TYPE_MIN_VALUE (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; - } -} - -/* 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; -{ - extern int building_cleanup; - tree vtbl, aref; - tree basetype = TREE_TYPE (instance); - - if (TREE_CODE (basetype) == REFERENCE_TYPE) - basetype = TREE_TYPE (basetype); - - if (instance == C_C_D) - { - if (current_vtable_decl == NULL_TREE - || current_vtable_decl == error_mark_node - || !UNIQUELY_DERIVED_FROM_P (DECL_FCONTEXT (CLASSTYPE_VFIELD (current_class_type)), basetype)) - vtbl = build_indirect_ref (build_vfield_ref (instance, basetype), NULL_PTR); - else - vtbl = current_vtable_decl; - } - 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)) - && !IS_SIGNATURE_POINTER (TREE_TYPE (instance)) - && !IS_SIGNATURE_REFERENCE (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_indirect_ref (build_vfield_ref (instance, basetype), - NULL_PTR); - } - if (!flag_vtable_thunks) - assemble_external (vtbl); - aref = build_array_ref (vtbl, idx); - - /* Save the intermediate result in a SAVE_EXPR so we don't have to - compute each component of the virtual function pointer twice. */ - if (!building_cleanup && TREE_CODE (aref) == INDIRECT_REF) - TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0)); - - if (flag_vtable_thunks) - return aref; - else - { - *ptr_to_instptr - = build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr), - *ptr_to_instptr, - convert (ptrdiff_type_node, - build_component_ref (aref, delta_identifier, 0, 0))); - return build_component_ref (aref, pfn_identifier, 0, 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); -} - -/* 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) - { - virtuals = copy_list (BINFO_VIRTUALS (binfo)); - decl = build_decl (VAR_DECL, name, TREE_TYPE (BINFO_VTABLE (binfo))); - } - 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. */ - if (! flag_vtable_thunks) - import_export_vtable (decl, type); - - IDENTIFIER_GLOBAL_VALUE (name) = decl = pushdecl_top_level (decl); - /* Initialize the association list for this type, based - on our first approximation. */ - TYPE_BINFO_VTABLE (type) = decl; - TYPE_BINFO_VIRTUALS (type) = virtuals; - - 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)); - - /* Why is this conditional? (mrs) */ - if (binfo && write_virtuals >= 0) - DECL_VIRTUAL_P (decl) = 1; - DECL_CONTEXT (decl) = type; - - binfo = TYPE_BINFO (type); - SET_BINFO_NEW_VTABLE_MARKED (binfo); - return decl; -} - -/* Given a base type PARENT, and a derived type TYPE, build - a name which distinguishes exactly the PARENT member of TYPE's type. - - FORMAT is a string which controls how sprintf formats the name - we have generated. - - For example, given - - class A; class B; class C : A, B; - - it is possible to distinguish "A" from "C's A". And given - - class L; - class A : L; class B : L; class C : A, B; - - it is possible to distinguish "L" from "A's L", and also from - "C's L from A". - - Make sure to use the DECL_ASSEMBLER_NAME of the TYPE_NAME of the - type, as template have DECL_NAMEs like: X<int>, whereas the - DECL_ASSEMBLER_NAME is set to be something the assembler can handle. - */ -static tree -build_type_pathname (format, parent, type) - char *format; - tree parent, type; -{ - extern struct obstack temporary_obstack; - char *first, *base, *name; - int i; - tree id; - - parent = TYPE_MAIN_VARIANT (parent); - - /* Remember where to cut the obstack to. */ - first = obstack_base (&temporary_obstack); - - /* Put on TYPE+PARENT. */ - obstack_grow (&temporary_obstack, - TYPE_ASSEMBLER_NAME_STRING (type), - TYPE_ASSEMBLER_NAME_LENGTH (type)); -#ifdef JOINER - obstack_1grow (&temporary_obstack, JOINER); -#else - obstack_1grow (&temporary_obstack, '_'); -#endif - obstack_grow0 (&temporary_obstack, - TYPE_ASSEMBLER_NAME_STRING (parent), - TYPE_ASSEMBLER_NAME_LENGTH (parent)); - i = obstack_object_size (&temporary_obstack); - base = obstack_base (&temporary_obstack); - obstack_finish (&temporary_obstack); - - /* Put on FORMAT+TYPE+PARENT. */ - obstack_blank (&temporary_obstack, strlen (format) + i + 1); - name = obstack_base (&temporary_obstack); - sprintf (name, format, base); - id = get_identifier (name); - obstack_free (&temporary_obstack, first); - - return id; -} - -/* 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. */ -static void -prepare_fresh_vtable (binfo, for_type) - tree binfo, for_type; -{ - tree basetype = BINFO_TYPE (binfo); - tree orig_decl = BINFO_VTABLE (binfo); - /* This name is too simplistic. We can have multiple basetypes for - for_type, and we really want different names. (mrs) */ - tree name = build_type_pathname (VTABLE_NAME_FORMAT, basetype, for_type); - tree new_decl = build_decl (VAR_DECL, name, TREE_TYPE (orig_decl)); - tree path; - int result; - - /* Remember which class this vtable is really for. */ - DECL_CONTEXT (new_decl) = for_type; - - 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)); - /* Install the value for `headof' if that's what we're doing. */ - if (flag_dossier) - TREE_VALUE (TREE_CHAIN (BINFO_VIRTUALS (binfo))) - = build_vtable_entry (size_binop (MINUS_EXPR, integer_zero_node, BINFO_OFFSET (binfo)), - FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (TREE_CHAIN (BINFO_VIRTUALS (binfo))))); - -#ifdef GATHER_STATISTICS - n_vtables += 1; - n_vtable_elems += list_length (BINFO_VIRTUALS (binfo)); -#endif - - /* Set TREE_PUBLIC and TREE_EXTERN as appropriate. */ - if (! flag_vtable_thunks) - import_export_vtable (new_decl, for_type); - - 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); -} - -/* 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 i = (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 += i; -#endif - - while (i > 0 && virtuals) - { - virtuals = TREE_CHAIN (virtuals); - i -= 1; - } - return virtuals; -} - -/* 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 i. VIRTUALS is the virtual - function table's initializer. */ -static tree -get_vtable_entry_n (virtuals, i) - tree virtuals; - unsigned HOST_WIDE_INT i; -{ - while (i > 0) - { - virtuals = TREE_CHAIN (virtuals); - i -= 1; - } - 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 tree -add_virtual_function (pending_virtuals, has_virtual, fndecl, t) - tree pending_virtuals; - int *has_virtual; - tree fndecl; - tree t; /* Structure type. */ -{ - /* 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 (!flag_vtable_thunks) - TREE_ADDRESSABLE (fndecl) = CLASSTYPE_VTABLE_NEEDS_WRITING (t); - - /* 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; - - if (flag_dossier && *has_virtual == 0) - { - /* CLASSTYPE_DOSSIER is only used as a Boolean (NULL or not). */ - CLASSTYPE_DOSSIER (t) = integer_one_node; - *has_virtual = 1; - } - - /* Build a new INT_CST for this DECL_VINDEX. */ - { - static tree index_table[256]; - tree index; - int i = ++(*has_virtual); - - if (i >= 256 || index_table[i] == 0) - { - index = build_int_2 (i, 0); - if (i < 256) - index_table[i] = index; - } - else - index = index_table[i]; - - /* Now assign virtual dispatch information. */ - DECL_VINDEX (fndecl) = index; - 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); - } - return pending_virtuals; -} - -/* Obstack on which to build the vector of class methods. */ -struct obstack class_obstack; -extern struct obstack *current_obstack; - -/* Add method METHOD to class TYPE. This is used when a method - has been defined which did not initially appear in the class definition, - and helps cut down on spurious error messages. - - 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; -{ - /* We must make a copy of METHOD here, since we must be sure that - we have exclusive title to this method's DECL_CHAIN. */ - tree decl; - - push_obstacks (&permanent_obstack, &permanent_obstack); - { - decl = copy_node (method); - if (DECL_RTL (decl) == 0 - && (!processing_template_decl - || !uses_template_parms (decl))) - { - make_function_rtl (decl); - DECL_RTL (method) = DECL_RTL (decl); - } - } - - if (fields && *fields) - { - /* Take care not to hide destructor. */ - DECL_CHAIN (decl) = DECL_CHAIN (*fields); - DECL_CHAIN (*fields) = decl; - } - else if (CLASSTYPE_METHOD_VEC (type) == 0) - { - tree method_vec = make_node (TREE_VEC); - if (TYPE_IDENTIFIER (type) == DECL_NAME (decl)) - { - TREE_VEC_ELT (method_vec, 0) = decl; - TREE_VEC_LENGTH (method_vec) = 1; - } - else - { - /* ??? Is it possible for there to have been enough room in the - current chunk for the tree_vec structure but not a tree_vec - plus a tree*? Will this work in that case? */ - obstack_free (current_obstack, method_vec); - obstack_blank (current_obstack, sizeof (struct tree_vec) + sizeof (tree *)); - TREE_VEC_ELT (method_vec, 1) = decl; - TREE_VEC_LENGTH (method_vec) = 2; - obstack_finish (current_obstack); - } - CLASSTYPE_METHOD_VEC (type) = method_vec; - } - else - { - tree method_vec = CLASSTYPE_METHOD_VEC (type); - int len = TREE_VEC_LENGTH (method_vec); - - /* Adding a new ctor or dtor. This is easy because our - METHOD_VEC always has a slot for such entries. */ - if (TYPE_IDENTIFIER (type) == DECL_NAME (decl)) - { - /* TREE_VEC_ELT (method_vec, 0) = decl; */ - if (decl != TREE_VEC_ELT (method_vec, 0)) - { - DECL_CHAIN (decl) = TREE_VEC_ELT (method_vec, 0); - TREE_VEC_ELT (method_vec, 0) = decl; - } - } - else - { - /* This is trickier. We try to extend the TREE_VEC in-place, - but if that does not work, we copy all its data to a new - TREE_VEC that's large enough. */ - struct obstack *ob = &class_obstack; - tree *end = (tree *)obstack_next_free (ob); - - if (end != TREE_VEC_END (method_vec)) - { - ob = current_obstack; - TREE_VEC_LENGTH (method_vec) += 1; - TREE_VEC_ELT (method_vec, len) = NULL_TREE; - method_vec = copy_node (method_vec); - TREE_VEC_LENGTH (method_vec) -= 1; - } - else - { - tree tmp_vec = (tree) obstack_base (ob); - if (obstack_room (ob) < sizeof (tree)) - { - obstack_blank (ob, sizeof (struct tree_common) - + tree_code_length[(int) TREE_VEC] - * sizeof (char *) - + len * sizeof (tree)); - tmp_vec = (tree) obstack_base (ob); - bcopy ((char *) method_vec, (char *) tmp_vec, - (sizeof (struct tree_common) - + tree_code_length[(int) TREE_VEC] * sizeof (char *) - + (len-1) * sizeof (tree))); - method_vec = tmp_vec; - } - else - obstack_blank (ob, sizeof (tree)); - } - - obstack_finish (ob); - TREE_VEC_ELT (method_vec, len) = decl; - TREE_VEC_LENGTH (method_vec) = len + 1; - CLASSTYPE_METHOD_VEC (type) = method_vec; - - 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; - } - } - } - DECL_CONTEXT (decl) = type; - DECL_CLASS_CONTEXT (decl) = type; - - 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 (TREE_CODE (field) == TYPE_DECL - && TREE_CODE (x) == TYPE_DECL) - cp_error_at ("duplicate nested type `%D'", x); - else if (TREE_CODE (field) == TYPE_DECL - || TREE_CODE (x) == TYPE_DECL) - 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. - Return 1 if change was legit, otherwise return 0. */ -static int -alter_access (t, fdecl, access) - tree t; - tree fdecl; - enum access_type access; -{ - tree elem = purpose_member (t, DECL_ACCESS (fdecl)); - if (elem && TREE_VALUE (elem) != (tree)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 if (TREE_PRIVATE (fdecl) && access != access_private) - cp_error_at ("cannot make private `%D' non-private", fdecl); - else if (TREE_PROTECTED (fdecl)) - { - if (access == access_public) - cp_error_at ("cannot make protected `%D' public", fdecl); - goto alter; - } - /* ARM 11.3: an access declaration may not be used to restrict access - to a member that is accessible in the base class. */ - else if (TREE_PUBLIC (fdecl) - && (access == access_private - || access == access_protected)) - cp_error_at ("cannot reduce access of public member `%D'", fdecl); - else if (elem == NULL_TREE) - { - alter: - DECL_ACCESS (fdecl) = tree_cons (t, (tree)access, - DECL_ACCESS (fdecl)); - return 1; - } - return 0; -} - -/* Return the offset to the main vtable for a given base BINFO. */ -tree -get_vfield_offset (binfo) - tree binfo; -{ - return size_binop (PLUS_EXPR, - size_binop (FLOOR_DIV_EXPR, - DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))), - size_int (BITS_PER_UNIT)), - 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); -} - -/* 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; - char cant_have_default_ctor; - char cant_have_const_ctor; - char cant_synth_copy_ctor; - char cant_synth_asn_ref; - char no_const_asn_ref; - char needs_virtual_dtor; -}; - -/* 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. - - Note that at this point TYPE_BINFO (t) != t_binfo. */ - -static int -finish_base_struct (t, b, t_binfo) - tree t; - struct base_info *b; - tree t_binfo; -{ - tree binfos = BINFO_BASETYPES (t_binfo); - 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); - - /* 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_INIT_REF (basetype) - && !TYPE_HAS_CONST_INIT_REF (basetype)) - b->cant_have_const_ctor = 1; - if (! TYPE_HAS_INIT_REF (basetype) - || (TYPE_HAS_NONPUBLIC_CTOR (basetype) == 2 - && ! is_friend_type (t, basetype))) - b->cant_synth_copy_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; - if (! TYPE_HAS_ASSIGN_REF (basetype) - || TYPE_HAS_ABSTRACT_ASSIGN_REF (basetype) - || (TYPE_HAS_NONPUBLIC_ASSIGN_REF (basetype) == 2 - && ! is_friend_type (t, basetype))) - b->cant_synth_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_NEEDS_CONSTRUCTING (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) -#if 0 - /* This cannot be done, as prepare_fresh_vtable wants to modify - binfos associated with vfields anywhere in the hierarchy, not - just immediate base classes. Due to unsharing, the compiler - might consume 3% more memory on a real program. - */ - && ! BINFO_OFFSET_ZEROP (base_binfo) -#endif - && BINFO_BASETYPES (base_binfo)) - { - tree base_binfos = BINFO_BASETYPES (base_binfo); - tree chain = NULL_TREE; - int j; - - /* Now unshare the structure beneath BASE_BINFO. */ - for (j = TREE_VEC_LENGTH (base_binfos)-1; - j >= 0; j--) - { - tree base_base_binfo = TREE_VEC_ELT (base_binfos, j); - if (! TREE_VIA_VIRTUAL (base_base_binfo)) - TREE_VEC_ELT (base_binfos, j) - = make_binfo (BINFO_OFFSET (base_base_binfo), - base_base_binfo, - BINFO_VTABLE (base_base_binfo), - BINFO_VIRTUALS (base_base_binfo), - chain); - chain = TREE_VEC_ELT (base_binfos, j); - TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo); - TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo); - } - - /* Completely unshare potentially shared data, and - update what is ours. */ - propagate_binfo_offsets (base_binfo, BINFO_OFFSET (base_binfo)); - } - - if (! TREE_VIA_VIRTUAL (base_binfo)) - CLASSTYPE_N_SUPERCLASSES (t) += 1; - - if (TYPE_VIRTUAL_P (basetype)) - { - /* If there's going to be a destructor needed, make - sure it will be virtual. */ - b->needs_virtual_dtor = 1; - - /* 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. */ - BINFO_VTABLE (t_binfo) = TYPE_BINFO_VTABLE (basetype); - BINFO_VIRTUALS (t_binfo) = 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. */ - BINFO_VTABLE (t_binfo) = TYPE_BINFO_VTABLE (basetype); - BINFO_VIRTUALS (t_binfo) = 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); - } - } - } - } - } - - /* Must come after offsets are fixed for all bases. */ - for (i = 0; i < n_baseclasses; i++) - { - tree base_binfo = TREE_VEC_ELT (binfos, i); - tree basetype = BINFO_TYPE (base_binfo); - - if (get_base_distance (basetype, t_binfo, 0, (tree*)0) == -2) - { - cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity", - basetype, t); - b->cant_synth_asn_ref = 1; - b->cant_synth_copy_ctor = 1; - } - } - { - tree v = get_vbase_types (t_binfo); - - for (; v; v = TREE_CHAIN (v)) - { - tree basetype = BINFO_TYPE (v); - if (get_base_distance (basetype, t_binfo, 0, (tree*)0) == -2) - { - if (extra_warnings) - cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity", - basetype, t); - b->cant_synth_asn_ref = 1; - b->cant_synth_copy_ctor = 1; - } - } - } - - { - 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; - return first_vfn_base_index; -} - -static int -typecode_p (type, code) - tree type; - enum tree_code code; -{ - return (TREE_CODE (type) == code - || (TREE_CODE (type) == REFERENCE_TYPE - && TREE_CODE (TREE_TYPE (type)) == code)); -} - -/* 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); - tree method_vec = CLASSTYPE_METHOD_VEC (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); - variants = TYPE_NEXT_VARIANT (variants); - } - - if (n_baseclasses && max_has_virtual) - { - /* Done by `finish_struct' for classes without baseclasses. */ - int might_have_abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (t) != 0; - tree binfos = TYPE_BINFO_BASETYPES (t); - for (i = n_baseclasses-1; i >= 0; i--) - { - might_have_abstract_virtuals - |= (CLASSTYPE_ABSTRACT_VIRTUALS (BINFO_TYPE (TREE_VEC_ELT (binfos, i))) != 0); - if (might_have_abstract_virtuals) - break; - } - if (might_have_abstract_virtuals) - { - /* We use error_mark_node from override_one_vtable to signal - an artificial abstract. */ - if (CLASSTYPE_ABSTRACT_VIRTUALS (t) == error_mark_node) - CLASSTYPE_ABSTRACT_VIRTUALS (t) = NULL_TREE; - 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)); - - if (TYPE_HAS_CONVERSION (basetype)) - { - TYPE_HAS_CONVERSION (t) = 1; - TYPE_HAS_INT_CONVERSION (t) |= TYPE_HAS_INT_CONVERSION (basetype); - TYPE_HAS_REAL_CONVERSION (t) |= TYPE_HAS_REAL_CONVERSION (basetype); - } - if (CLASSTYPE_MAX_DEPTH (basetype) >= CLASSTYPE_MAX_DEPTH (t)) - CLASSTYPE_MAX_DEPTH (t) = CLASSTYPE_MAX_DEPTH (basetype) + 1; - } - } - - /* Need to test METHOD_VEC here in case all methods - (conversions and otherwise) are inherited. */ - if (TYPE_HAS_CONVERSION (t) && method_vec != NULL_TREE) - { - tree first_conversions[last_conversion_type]; - tree last_conversions[last_conversion_type]; - enum conversion_type conv_index; - tree *tmp; - int i; - - bzero ((char *) first_conversions, sizeof (first_conversions)); - bzero ((char *) last_conversions, sizeof (last_conversions)); - for (tmp = &TREE_VEC_ELT (method_vec, 1); - tmp != TREE_VEC_END (method_vec); tmp += 1) - { - /* ??? This should compare DECL_NAME (*tmp) == ansi_opname[TYPE_EXPR]. */ - if (IDENTIFIER_TYPENAME_P (DECL_ASSEMBLER_NAME (*tmp))) - { - tree fntype = TREE_TYPE (*tmp); - tree return_type = TREE_TYPE (fntype); - my_friendly_assert (TREE_CODE (fntype) == METHOD_TYPE, 171); - - if (typecode_p (return_type, POINTER_TYPE)) - { - if (TYPE_READONLY (TREE_TYPE (return_type))) - conv_index = constptr_conv; - else - conv_index = ptr_conv; - } - else if (typecode_p (return_type, INTEGER_TYPE) - || typecode_p (return_type, BOOLEAN_TYPE) - || typecode_p (return_type, ENUMERAL_TYPE)) - { - TYPE_HAS_INT_CONVERSION (t) = 1; - conv_index = int_conv; - } - else if (typecode_p (return_type, REAL_TYPE)) - { - TYPE_HAS_REAL_CONVERSION (t) = 1; - conv_index = real_conv; - } - else - continue; - - if (first_conversions[(int) conv_index] == NULL_TREE) - first_conversions[(int) conv_index] = *tmp; - last_conversions[(int) conv_index] = *tmp; - } - } - - for (i = 0; i < (int) last_conversion_type; i++) - if (first_conversions[i] != last_conversions[i]) - CLASSTYPE_CONVERSION (t, i) = error_mark_node; - else - CLASSTYPE_CONVERSION (t, i) = first_conversions[i]; - } - - /* If this type has constructors, force its mode to be BLKmode, - and force its TREE_ADDRESSABLE bit to be nonzero. */ - if (TYPE_NEEDS_CONSTRUCTING (t) || TYPE_NEEDS_DESTRUCTOR (t)) - { - tree variants = t; - - if (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL) - DECL_MODE (TYPE_NAME (t)) = BLKmode; - while (variants) - { - TYPE_MODE (variants) = BLKmode; - TREE_ADDRESSABLE (variants) = 1; - variants = TYPE_NEXT_VARIANT (variants); - } - } -} - -/* Warn about duplicate methods in fn_fields. Also compact method - lists so that lookup can be made faster. - - Algorithm: Outer loop builds lists by method name. Inner loop - checks for redundant method names within a list. - - 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 TREE_CHAIN of the FUNCTION_DECLs. Friends are - chained in the same way as member functions, 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 tree -finish_struct_methods (t, fn_fields, nonprivate_method) - tree t; - tree fn_fields; - int nonprivate_method; -{ - tree method_vec; - tree name = constructor_name (t); - int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t); - - /* Now prepare to gather fn_fields into vector. */ - struct obstack *ambient_obstack = current_obstack; - current_obstack = &class_obstack; - method_vec = make_node (TREE_VEC); - /* Room has been saved for constructors and destructors. */ - current_obstack = ambient_obstack; - /* Now make this a live vector. */ - obstack_free (&class_obstack, method_vec); - obstack_blank (&class_obstack, sizeof (struct tree_vec)); - - while (fn_fields) - { - /* NEXT Pointer, TEST Pointer, and BASE Pointer. */ - tree nextp, *testp; - tree fn_name = DECL_NAME (fn_fields); - if (fn_name == NULL_TREE) - fn_name = name; - - nextp = TREE_CHAIN (fn_fields); - TREE_CHAIN (fn_fields) = NULL_TREE; - - /* 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 == 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; - } - } - - /* Constructors are handled easily in search routines. */ - if (fn_name == name) - { - DECL_CHAIN (fn_fields) = TREE_VEC_ELT (method_vec, 0); - TREE_VEC_ELT (method_vec, 0) = fn_fields; - } - else - { - testp = &TREE_VEC_ELT (method_vec, 0); - if (*testp == NULL_TREE) - testp++; - while (((HOST_WIDE_INT) testp - < (HOST_WIDE_INT) obstack_next_free (&class_obstack)) - && DECL_NAME (*testp) != fn_name) - testp++; - if ((HOST_WIDE_INT) testp - < (HOST_WIDE_INT) obstack_next_free (&class_obstack)) - { - tree x, prev_x; - - for (x = *testp; x; x = DECL_CHAIN (x)) - { - if (DECL_NAME (fn_fields) == ansi_opname[(int) DELETE_EXPR] - || DECL_NAME (fn_fields) - == ansi_opname[(int) VEC_DELETE_EXPR]) - { - /* ANSI C++ June 5 1992 WP 12.5.5.1 */ - cp_error_at ("`%D' overloaded", fn_fields); - cp_error_at ("previous declaration as `%D' here", x); - } - if (DECL_ASSEMBLER_NAME (fn_fields)==DECL_ASSEMBLER_NAME (x)) - { - /* We complain about multiple destructors on sight, - so we do not repeat the warning here. Friend-friend - ambiguities are warned about outside this loop. */ - if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fn_fields))) - cp_error_at ("ambiguous method `%#D' in structure", - fn_fields); - break; - } - prev_x = x; - } - if (x == 0) - { - if (*testp) - DECL_CHAIN (prev_x) = fn_fields; - else - *testp = fn_fields; - } - } - else - { - obstack_ptr_grow (&class_obstack, fn_fields); - method_vec = (tree)obstack_base (&class_obstack); - } - } - fn_fields = nextp; - } - - TREE_VEC_LENGTH (method_vec) = (tree *)obstack_next_free (&class_obstack) - - (&TREE_VEC_ELT (method_vec, 0)); - obstack_finish (&class_obstack); - CLASSTYPE_METHOD_VEC (t) = method_vec; - - if (nonprivate_method == 0 - && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE - && DECL_FRIENDLIST (TYPE_NAME (t)) == NULL_TREE) - { - tree binfos = BINFO_BASETYPES (TYPE_BINFO (t)); - for (i = 0; i < n_baseclasses; i++) - if (TREE_VIA_PUBLIC (TREE_VEC_ELT (binfos, i)) - || TREE_VIA_PROTECTED (TREE_VEC_ELT (binfos, i))) - { - nonprivate_method = 1; - break; - } - if (nonprivate_method == 0) - cp_warning ("all member functions in class `%T' are private", t); - } - - /* If there are constructors (and destructors), they are at the - front. Place destructors at very front. Also warn if all - constructors and/or destructors are private (in which case this - class is effectively unusable. */ - if (TYPE_HAS_DESTRUCTOR (t)) - { - tree dtor, prev; - - for (dtor = TREE_VEC_ELT (method_vec, 0); - dtor; - prev = dtor, dtor = DECL_CHAIN (dtor)) - { - if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (dtor))) - { - if (TREE_PRIVATE (dtor) - && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE - && DECL_FRIENDLIST (TYPE_NAME (t)) == NULL_TREE - && warn_ctor_dtor_privacy) - cp_warning ("`%#T' only defines a private destructor and has no friends", - t); - break; - } - } - - /* Wild parse errors can cause this to happen. */ - if (dtor == NULL_TREE) - TYPE_HAS_DESTRUCTOR (t) = 0; - else if (dtor != TREE_VEC_ELT (method_vec, 0)) - { - DECL_CHAIN (prev) = DECL_CHAIN (dtor); - DECL_CHAIN (dtor) = TREE_VEC_ELT (method_vec, 0); - TREE_VEC_ELT (method_vec, 0) = dtor; - } - } - - /* 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 - && TREE_VEC_LENGTH (method_vec) > 1) - { - 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 = 1; i < len; i++) - { - TREE_VEC_ELT (baselink_vec, i) - = get_baselinks (baselink_binfo, t, DECL_NAME (TREE_VEC_ELT (method_vec, i))); - 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); - } - - /* Now add the methods to the TYPE_METHODS of T, arranged in a chain. */ - { - tree x, last_x = NULL_TREE; - int limit = TREE_VEC_LENGTH (method_vec); - - for (i = 1; i < limit; i++) - { - for (x = TREE_VEC_ELT (method_vec, i); x; x = DECL_CHAIN (x)) - { - if (last_x != NULL_TREE) - TREE_CHAIN (last_x) = x; - last_x = x; - } - } - - /* Put ctors and dtors at the front of the list. */ - x = TREE_VEC_ELT (method_vec, 0); - if (x) - { - while (DECL_CHAIN (x)) - { - /* Let's avoid being circular about this. */ - if (x == DECL_CHAIN (x)) - break; - TREE_CHAIN (x) = DECL_CHAIN (x); - x = DECL_CHAIN (x); - } - if (TREE_VEC_LENGTH (method_vec) > 1) - TREE_CHAIN (x) = TREE_VEC_ELT (method_vec, 1); - else - TREE_CHAIN (x) = NULL_TREE; - } - } - - TYPE_METHODS (t) = method_vec; - - return method_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); - - /* 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 tv = CLASSTYPE_METHOD_VEC(t); - int i, len = TREE_VEC_LENGTH (tv); - for (i = 0; i < len; i++) - { - tree unchain = TREE_VEC_ELT (tv, i); - while (unchain != NULL_TREE) - { - TREE_CHAIN (unchain) = NULL_TREE; - unchain = DECL_CHAIN(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); - CLASSTYPE_VBASE_SIZE (t) = integer_zero_node; - 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, t; - int do_self; -{ - 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 (write_virtuals >= 0 - && DECL_INITIAL (decl) != BINFO_VIRTUALS (binfo)) - DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE, - BINFO_VIRTUALS (binfo)); - finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 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 rettype, base_rettype, 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_READONLY (TREE_TYPE (TREE_VALUE (base_types))) - == TYPE_READONLY (TREE_TYPE (TREE_VALUE (types)))) - && compparms (TREE_CHAIN (base_types), TREE_CHAIN (types), 3)) - 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; -} - -static void -modify_one_vtable (binfo, t, fndecl, pfn) - tree binfo, t, fndecl, pfn; -{ - tree virtuals = BINFO_VIRTUALS (binfo); - unsigned HOST_WIDE_INT n; - - n = 0; - /* Skip initial vtable length field and RTTI fake object. */ - for (; virtuals && n < 1 + flag_dossier; n++) - virtuals = TREE_CHAIN (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 bewteen 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 = size_binop (MINUS_EXPR, offset, base_offset); - - /* Make sure we can modify the derived association with immunity. */ - if (TREE_USED (binfo)) { - my_friendly_assert (0, 999); -#if 0 - my_friendly_assert (*binfo2_ptr == binfo, 999); - *binfo2_ptr = copy_binfo (binfo); -#endif - } - 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, t, fndecl, pfn; - int do_self; -{ - 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 vtable 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, t) - tree binfo, t; -{ - tree virtuals = BINFO_VIRTUALS (binfo); - unsigned HOST_WIDE_INT n; - - n = 0; - /* Skip initial vtable length field and RTTI fake object. */ - for (; virtuals && n < 1 + flag_dossier; n++) - virtuals = TREE_CHAIN (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 bewteen 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 = size_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 (TREE_USED (binfo)) - my_friendly_assert (0, 999); - - 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); - } -} - -/* 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, t, fndecl, pfn; - int do_self, via_virtual; -{ - 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 size entry. */ - virtuals = TREE_CHAIN (virtuals); - /* Skip RTTI fake object. */ - if (flag_dossier) - { - virtuals = TREE_CHAIN (virtuals); - } - - /* Skip size entry. */ - old_virtuals = TREE_CHAIN (old_virtuals); - /* Skip RTTI fake object. */ - if (flag_dossier) - { - old_virtuals = TREE_CHAIN (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 overriden, or the class is ill-formed. */ - /* For now, we just make it abstract. */ - tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0); - tree vfn; - - fndecl = copy_node (fndecl); - copy_lang_decl (fndecl); - DECL_ABSTRACT_VIRTUAL_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 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, t; - int do_self; -{ - 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); - } -} - -/* 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. - - LIST_OF_FIELDLISTS is just that. The elements of the list are - TREE_LIST elements, whose TREE_PURPOSE field tells what access - the list has, and the TREE_VALUE slot gives the actual fields. - - If flag_all_virtual == 1, then we lay all functions into - the virtual function table, as though they were declared - virtual. Constructors do not lay down in the virtual function table. - - If flag_all_virtual == 2, then we lay all functions into - the virtual function table, such that virtual functions - occupy a space by themselves, and then all functions - of the class occupy a space by themselves. This is illustrated - in the following diagram: - - class A; class B : A; - - Class A's vtbl: Class B's vtbl: - -------------------------------------------------------------------- - | A's virtual functions| | B's virtual functions | - | | | (may inherit some from A). | - -------------------------------------------------------------------- - | All of A's functions | | All of A's functions | - | (such as a->A::f). | | (such as b->A::f) | - -------------------------------------------------------------------- - | B's new virtual functions | - | (not defined in A.) | - ------------------------------- - | All of B's functions | - | (such as b->B::f) | - ------------------------------- - - this allows the program to make references to any function, virtual - or otherwise in a type-consistent manner. */ - -tree -finish_struct (t, list_of_fieldlists, warn_anon) - tree t; - tree list_of_fieldlists; - int warn_anon; -{ - extern int interface_only, interface_unknown; - - int old; - int round_up_size = 1; - - enum tree_code code = TREE_CODE (t); - register tree x, last_x, method_vec; - int needs_virtual_dtor; - tree name = TYPE_NAME (t), fields, fn_fields, *tail; - tree *tail_user_methods = &CLASSTYPE_METHODS (t); - enum access_type access; - int all_virtual; - int has_virtual; - int max_has_virtual; - tree pending_virtuals = NULL_TREE; - tree abstract_virtuals = NULL_TREE; - tree vfield; - tree vfields; - int cant_have_default_ctor; - int cant_have_const_ctor; - int cant_synth_copy_ctor; - int cant_synth_asn_ref; - int no_const_asn_ref; - - /* 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; - int nonprivate_method = 0; - tree t_binfo = TYPE_BINFO (t); - tree access_decls = NULL_TREE; - - if (TREE_CODE (name) == TYPE_DECL) - { -#if 0 /* Maybe later. -jason */ - struct tinst_level *til = tinst_for_decl(); - - if (til) - { - DECL_SOURCE_FILE (name) = til->file; - if (DECL_SOURCE_LINE (name)) - DECL_SOURCE_LINE (name) = til->line; - } - else -#endif - { - 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; - CLASSTYPE_SOURCE_LINE (t) = lineno; - } - name = DECL_NAME (name); - } - - if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (name)) - 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; - } - - /* Append the fields we need for constructing signature tables. */ - if (IS_SIGNATURE (t)) - append_signature_fields (list_of_fieldlists); - - 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 - - if (flag_dossier) - build_t_desc (t, 0); - - TYPE_BINFO (t) = NULL_TREE; - - 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 (t_binfo && BINFO_BASETYPES (t_binfo)) - n_baseclasses = TREE_VEC_LENGTH (BINFO_BASETYPES (t_binfo)); - else - n_baseclasses = 0; - - if (n_baseclasses > 0) - { - struct base_info base_info; - - /* If using multiple inheritance, this may cause variants of our - basetypes to be used (instead of their canonical forms). */ - fields = layout_basetypes (t, BINFO_BASETYPES (t_binfo)); - last_x = tree_last (fields); - - first_vfn_base_index = finish_base_struct (t, &base_info, t_binfo); - /* 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; - cant_have_default_ctor = base_info.cant_have_default_ctor; - cant_have_const_ctor = base_info.cant_have_const_ctor; - cant_synth_copy_ctor = base_info.cant_synth_copy_ctor; - cant_synth_asn_ref = base_info.cant_synth_asn_ref; - no_const_asn_ref = base_info.no_const_asn_ref; - needs_virtual_dtor = base_info.needs_virtual_dtor; - n_baseclasses = TREE_VEC_LENGTH (BINFO_BASETYPES (t_binfo)); - } - else - { - first_vfn_base_index = -1; - has_virtual = 0; - max_has_virtual = has_virtual; - vfield = NULL_TREE; - vfields = NULL_TREE; - fields = NULL_TREE; - last_x = NULL_TREE; - cant_have_default_ctor = 0; - cant_have_const_ctor = 0; - cant_synth_copy_ctor = 0; - cant_synth_asn_ref = 0; - no_const_asn_ref = 0; - needs_virtual_dtor = 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. */ - TREE_CHAIN (t_binfo) = TYPE_BINFO (t); - TYPE_BINFO (t) = t_binfo; - CLASSTYPE_VFIELDS (t) = vfields; - CLASSTYPE_VFIELD (t) = vfield; - - tail = &fn_fields; - if (last_x && list_of_fieldlists) - TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists); - - if (IS_SIGNATURE (t)) - all_virtual = 0; - else if (flag_all_virtual == 1 && TYPE_OVERLOADS_METHOD_CALL_EXPR (t)) - all_virtual = 1; - else - all_virtual = 0; - - /* For signatures, we made all methods `public' in the parser and - reported an error if a access specifier was used. */ - if (CLASSTYPE_DECLARED_CLASS (t) == 0) - { - nonprivate_method = 1; - if (list_of_fieldlists - && TREE_PURPOSE (list_of_fieldlists) == (tree)access_default) - TREE_PURPOSE (list_of_fieldlists) = (tree)access_public; - } - else if (list_of_fieldlists - && TREE_PURPOSE (list_of_fieldlists) == (tree)access_default) - TREE_PURPOSE (list_of_fieldlists) = (tree)access_private; - - while (list_of_fieldlists) - { - access = (enum access_type)TREE_PURPOSE (list_of_fieldlists); - - for (x = TREE_VALUE (list_of_fieldlists); x; x = TREE_CHAIN (x)) - { - TREE_PRIVATE (x) = access == access_private; - TREE_PROTECTED (x) = access == access_protected; - GNU_xref_member (current_class_name, x); - - if (TREE_CODE (x) == TYPE_DECL) - { - /* Make sure we set this up. In find_scoped_type, it explicitly - looks for a TYPE_DECL in the TYPE_FIELDS list. If we don't - do this here, we'll miss including this TYPE_DECL in the - list. */ - if (! fields) - fields = x; - last_x = x; - continue; - } - - /* Check for inconsistent use of this name in the class body. - Enums, types and static vars have already been checked. */ - if (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; - - if (icv - /* 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_error_at ("declaration of identifier `%D' as `%+#D'", - name, x); - cp_error_at ("conflicts with other use in class as `%#D'", - icv); - } - } - - if (TREE_CODE (x) == FUNCTION_DECL) - { - nonprivate_method |= ! TREE_PRIVATE (x); - - /* If this was an evil function, don't keep it in class. */ - if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x))) - continue; - - if (last_x) - TREE_CHAIN (last_x) = TREE_CHAIN (x); - /* Link x onto end of fn_fields and CLASSTYPE_METHODS. */ - *tail = x; - tail = &TREE_CHAIN (x); - *tail_user_methods = x; - tail_user_methods = &DECL_NEXT_METHOD (x); - - DECL_CLASS_CONTEXT (x) = t; - - DECL_FIELD_SIZE (x) = 0; - - /* The name of the field is the original field name - Save this in auxiliary field for later overloading. */ - if (DECL_VINDEX (x) - || (all_virtual == 1 && ! DECL_CONSTRUCTOR_P (x))) - { - pending_virtuals = add_virtual_function (pending_virtuals, - &has_virtual, x, t); - if (DECL_ABSTRACT_VIRTUAL_P (x)) - abstract_virtuals = tree_cons (NULL_TREE, x, abstract_virtuals); - } - continue; - } - - /* Handle access declarations. */ - if (DECL_NAME (x) && TREE_CODE (DECL_NAME (x)) == SCOPE_REF) - { - tree fdecl = TREE_OPERAND (DECL_NAME (x), 1); - - if (last_x) - TREE_CHAIN (last_x) = TREE_CHAIN (x); - access_decls = tree_cons ((tree) access, fdecl, access_decls); - 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 (DECL_NAME (x) == constructor_name (t)) - cant_have_default_ctor = cant_synth_copy_ctor = 1; - - if (TREE_TYPE (x) == error_mark_node) - continue; - - if (! fields) - fields = x; - last_x = x; - - 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 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_synth_asn_ref = 1; - cant_have_default_ctor = 1; - TYPE_HAS_COMPLEX_INIT_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 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_synth_asn_ref = 1; - cant_have_default_ctor = 1; - TYPE_HAS_COMPLEX_INIT_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_BIT_FIELD tentatively in grokbitfield. - If the type and width are valid, we'll keep it set. - Otherwise, the flag is cleared. */ - if (DECL_BIT_FIELD (x)) - { - DECL_BIT_FIELD (x) = 0; - /* 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)) - { - register int width = TREE_INT_CST_LOW (DECL_INITIAL (x)); - - if (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 ((unsigned)width > TYPE_PRECISION (TREE_TYPE (x))) - { - DECL_INITIAL (x) = NULL; - cp_error_at ("width of `%D' exceeds its type", x); - } - } - - /* Process valid field width. */ - if (DECL_INITIAL (x)) - { - register int width = TREE_INT_CST_LOW (DECL_INITIAL (x)); - - if (width == 0) - { -#ifdef EMPTY_FIELD_BOUNDARY - /* field size 0 => mark following field as "aligned" */ - if (TREE_CHAIN (x)) - DECL_ALIGN (TREE_CHAIN (x)) - = MAX (DECL_ALIGN (TREE_CHAIN (x)), EMPTY_FIELD_BOUNDARY); - /* field of size 0 at the end => round up the size. */ - else - round_up_size = EMPTY_FIELD_BOUNDARY; -#endif -#ifdef PCC_BITFIELD_TYPE_MATTERS - DECL_ALIGN (x) = MAX (DECL_ALIGN (x), - TYPE_ALIGN (TREE_TYPE (x))); -#endif - } - else - { - DECL_INITIAL (x) = NULL_TREE; - DECL_FIELD_SIZE (x) = width; - DECL_BIT_FIELD (x) = 1; - /* Traditionally a bit field is unsigned - even if declared signed. */ - if (flag_traditional - && TREE_CODE (TREE_TYPE (x)) == INTEGER_TYPE) - TREE_TYPE (x) = unsigned_type_node; - } - } - 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); - - if (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_REAL_ASSIGNMENT (type)) - fie = "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) - || TYPE_NEEDS_CONSTRUCTING (type)); - } - - if (! TYPE_HAS_INIT_REF (type) - || (TYPE_HAS_NONPUBLIC_CTOR (type) - && ! is_friend (t, type))) - cant_synth_copy_ctor = 1; - else if (!TYPE_HAS_CONST_INIT_REF (type)) - cant_have_const_ctor = 1; - - if (! TYPE_HAS_ASSIGN_REF (type) - || (TYPE_HAS_NONPUBLIC_ASSIGN_REF (type) - && ! is_friend (t, type))) - cant_synth_asn_ref = 1; - else 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 (! 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); - } - } - } - 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; - } - } - } - list_of_fieldlists = TREE_CHAIN (list_of_fieldlists); - /* link the tail while we have it! */ - if (last_x) - { - TREE_CHAIN (last_x) = NULL_TREE; - - if (list_of_fieldlists - && TREE_VALUE (list_of_fieldlists) - && TREE_CODE (TREE_VALUE (list_of_fieldlists)) != FUNCTION_DECL) - TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists); - } - } - - /* 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; - - /* Synthesize any needed methods. Note that methods will be synthesized - for anonymous unions; grok_x_components undoes that. */ - - if (TYPE_NEEDS_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t) - && !IS_SIGNATURE (t)) - { - /* Here we must cons up a destructor on the fly. */ - tree dtor = cons_up_default_function (t, name, needs_virtual_dtor != 0); - - /* If we couldn't make it work, then pretend we didn't need it. */ - if (dtor == void_type_node) - TYPE_NEEDS_DESTRUCTOR (t) = 0; - else - { - /* Link dtor onto end of fn_fields. */ - *tail = dtor; - tail = &TREE_CHAIN (dtor); - - if (DECL_VINDEX (dtor) == NULL_TREE - && ! CLASSTYPE_DECLARED_EXCEPTION (t) - && (needs_virtual_dtor - || pending_virtuals != NULL_TREE - || pending_hard_virtuals != NULL_TREE)) - DECL_VINDEX (dtor) = error_mark_node; - if (DECL_VINDEX (dtor)) - pending_virtuals = add_virtual_function (pending_virtuals, - &has_virtual, dtor, t); - nonprivate_method = 1; - } - } - - *tail = NULL_TREE; - *tail_user_methods = NULL_TREE; - - TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t); - - if (! fn_fields) - nonprivate_method = 1; - - TYPE_HAS_COMPLEX_INIT_REF (t) - |= (TYPE_HAS_INIT_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t) - || has_virtual || any_default_members || first_vfn_base_index >= 0); - TYPE_NEEDS_CONSTRUCTING (t) - |= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_USES_VIRTUAL_BASECLASSES (t) - || has_virtual || any_default_members || first_vfn_base_index >= 0); - - /* ARM $12.1: A default constructor will be generated for a class X - only if no constructor has been declared for class X. So we - check TYPE_HAS_CONSTRUCTOR also, to make sure we don't generate - one if they declared a constructor in this class. */ - if (! TYPE_HAS_CONSTRUCTOR (t) && ! cant_have_default_ctor - && ! IS_SIGNATURE (t)) - { - tree default_fn = cons_up_default_function (t, name, 2); - TREE_CHAIN (default_fn) = fn_fields; - fn_fields = default_fn; - } - - /* Create default copy constructor, if needed. */ - if (! TYPE_HAS_INIT_REF (t) && ! cant_synth_copy_ctor - && ! IS_SIGNATURE (t)) - { - /* ARM 12.18: You get either X(X&) or X(const X&), but - not both. --Chip */ - tree default_fn = cons_up_default_function (t, name, - 3 + cant_have_const_ctor); - TREE_CHAIN (default_fn) = fn_fields; - fn_fields = default_fn; - } - - 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) - || has_virtual || first_vfn_base_index >= 0); - - if (! TYPE_HAS_ASSIGN_REF (t) && ! cant_synth_asn_ref - && ! IS_SIGNATURE (t)) - { - tree default_fn = cons_up_default_function (t, name, - 5 + no_const_asn_ref); - TREE_CHAIN (default_fn) = fn_fields; - fn_fields = default_fn; - } - - if (fn_fields) - { - method_vec = finish_struct_methods (t, fn_fields, nonprivate_method); - - if (TYPE_HAS_CONSTRUCTOR (t) - && ! CLASSTYPE_DECLARED_EXCEPTION (t) - && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE - && DECL_FRIENDLIST (TYPE_NAME (t)) == NULL_TREE) - { - int nonprivate_ctor = 0; - tree ctor; - - for (ctor = TREE_VEC_ELT (method_vec, 0); - ctor; - ctor = DECL_CHAIN (ctor)) - if (! TREE_PRIVATE (ctor)) - { - nonprivate_ctor = 1; - break; - } - - if (nonprivate_ctor == 0 && warn_ctor_dtor_privacy) - cp_warning ("`%#T' only defines private constructors and has no friends", - 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; - } - - { - int n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0; - - for (access_decls = nreverse (access_decls); access_decls; - access_decls = TREE_CHAIN (access_decls)) - { - tree fdecl = TREE_VALUE (access_decls); - tree flist = NULL_TREE; - tree name; - enum access_type access = (enum access_type)TREE_PURPOSE(access_decls); - int i = TREE_VEC_ELT (method_vec, 0) ? 0 : 1; - tree tmp; - - if (TREE_CODE (fdecl) == TREE_LIST) - { - flist = fdecl; - fdecl = TREE_VALUE (flist); - } - - name = DECL_NAME (fdecl); - - for (; i < n_methods; i++) - if (DECL_NAME (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", - TREE_VEC_ELT (method_vec, i)); - fdecl = NULL_TREE; - break; - } - - if (! fdecl) - continue; - - 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); - fdecl = NULL_TREE; - break; - } - - if (!fdecl) - continue; - - /* Make type T see field decl FDECL with access ACCESS.*/ - if (flist) - { - fdecl = TREE_VALUE (flist); - while (fdecl) - { - if (alter_access (t, fdecl, access) == 0) - break; - fdecl = DECL_CHAIN (fdecl); - } - } - else - alter_access (t, fdecl, access); - } - - } - - if (vfield == NULL_TREE && has_virtual) - { - /* We build this decl with ptr_type_node, and - change the type when we know what it should be. */ - vfield = build_lang_field_decl (FIELD_DECL, get_vfield_name (t), - 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_FIELD_CONTEXT (vfield) = t; - DECL_CLASS_CONTEXT (vfield) = t; - DECL_FCONTEXT (vfield) = t; - DECL_FIELD_SIZE (vfield) = 0; - DECL_ALIGN (vfield) = TYPE_ALIGN (ptr_type_node); - if (CLASSTYPE_DOSSIER (t)) - { - /* 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; - vfields = chainon (vfields, CLASSTYPE_AS_LIST (t)); - } - - /* Now DECL_INITIAL is null on all members except for zero-width bit-fields. - And they have already done their work. - - C++: maybe we will support default field initialization some day... */ - - /* Delete all zero-width bit-fields from the front of the fieldlist */ - while (fields && DECL_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_BIT_FIELD (TREE_CHAIN (x)) - && DECL_INITIAL (TREE_CHAIN (x))) - TREE_CHAIN (x) = TREE_CHAIN (TREE_CHAIN (x)); - else - x = TREE_CHAIN (x); - } - /* 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 = /*TREE_VEC_ELT (method_vec, 0) ? 0 : */ 1; - for (; i < n_methods; ++i) - if (DECL_NAME (TREE_VEC_ELT (method_vec, i)) == name) - { - cp_error_at ("data member `%#D' conflicts with", x); - cp_error_at ("function member `%#D'", - TREE_VEC_ELT (method_vec, i)); - break; - } - } - } - - /* Now we have the final fieldlist for the data fields. Record it, - then lay out the structure or union (including the fields). */ - - TYPE_FIELDS (t) = fields; - - /* If there's a :0 field at the end, round the size to the - EMPTY_FIELD_BOUNDARY. */ - TYPE_ALIGN (t) = round_up_size; - - /* Pass layout information about base classes to layout_type, if any. */ - - { - 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 this field is an anonymous union, - give each union-member the same position as the union has. - - ??? This is a real kludge because it makes the structure - of the types look strange. This feature is only used by - C++, which should have build_component_ref build two - COMPONENT_REF operations, one for the union and one for - the inner field. We set the offset of this field to zero - so that either the old or the correct method will work. - Setting DECL_FIELD_CONTEXT is wrong unless the inner fields are - moved into the type of this field, but nothing seems to break - by doing this. */ - - 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 (TREE_CODE (uelt) != FIELD_DECL) - continue; - - DECL_FIELD_CONTEXT (uelt) = DECL_FIELD_CONTEXT (field); - DECL_FIELD_BITPOS (uelt) = DECL_FIELD_BITPOS (field); - } - - DECL_FIELD_BITPOS (field) = integer_zero_node; - } - } - } - - if (n_baseclasses) - { - tree pseudo_basetype = TREE_TYPE (base_layout_decl); - - TREE_CHAIN (base_layout_decl) = TYPE_FIELDS (t); - TYPE_FIELDS (t) = base_layout_decl; - - TYPE_SIZE (pseudo_basetype) = CLASSTYPE_SIZE (t); - TYPE_MODE (pseudo_basetype) = TYPE_MODE (t); - TYPE_ALIGN (pseudo_basetype) = CLASSTYPE_ALIGN (t); - DECL_ALIGN (base_layout_decl) = TYPE_ALIGN (pseudo_basetype); - /* Don't re-use old size. */ - DECL_SIZE (base_layout_decl) = NULL_TREE; - } - - layout_type (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 this field is an anonymous union, - give each union-member the same position as the union has. - - ??? This is a real kludge because it makes the structure - of the types look strange. This feature is only used by - C++, which should have build_component_ref build two - COMPONENT_REF operations, one for the union and one for - the inner field. We set the offset of this field to zero - so that either the old or the correct method will work. - Setting DECL_FIELD_CONTEXT is wrong unless the inner fields are - moved into the type of this field, but nothing seems to break - by doing this. */ - - 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 (TREE_CODE (uelt) != FIELD_DECL) - continue; - - DECL_FIELD_CONTEXT (uelt) = DECL_FIELD_CONTEXT (field); - DECL_FIELD_BITPOS (uelt) = DECL_FIELD_BITPOS (field); - } - - DECL_FIELD_BITPOS (field) = integer_zero_node; - } - } - } - - if (n_baseclasses) - TYPE_FIELDS (t) = TREE_CHAIN (TYPE_FIELDS (t)); - - /* C++: do not let empty structures exist. */ - if (integer_zerop (TYPE_SIZE (t))) - TYPE_SIZE (t) = TYPE_SIZE (char_type_node); - - /* Set the TYPE_DECL for this type to contain the right - value for DECL_OFFSET, so that we can use it as part - of a COMPONENT_REF for multiple inheritance. */ - - if (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL) - layout_decl (TYPE_NAME (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. */ - doing_hard_virtuals = 1; - pending_hard_virtuals = nreverse (pending_hard_virtuals); - - if (TYPE_USES_VIRTUAL_BASECLASSES (t)) - { - tree vbases; - - max_has_virtual = layout_vbasetypes (t, max_has_virtual); - vbases = CLASSTYPE_VBASECLASSES (t); - CLASSTYPE_N_VBASECLASSES (t) = list_length (vbases); - - while (vbases) - { - /* The rtti code should do this. (mrs) */ - /* Update dossier info with offsets for virtual baseclasses. */ - if (flag_dossier && ! BINFO_NEW_VTABLE_MARKED (vbases)) - prepare_fresh_vtable (vbases, t); - vbases = TREE_CHAIN (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); - } - } - } - - /* Now fixup any virtual function entries from virtual bases - that have different deltas. */ - vbases = CLASSTYPE_VBASECLASSES (t); - while (vbases) - { - /* We might be able to shorten the ammount 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, 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 - 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); - } - doing_hard_virtuals = 0; - - /* Under our model of GC, every C++ class gets its own virtual - function table, at least virtually. */ - if (pending_virtuals || CLASSTYPE_DOSSIER (t)) - { - pending_virtuals = nreverse (pending_virtuals); - /* We must enter these virtuals into the table. */ - if (first_vfn_base_index < 0) - { - if (flag_dossier) - pending_virtuals = tree_cons (NULL_TREE, - build_vtable_entry (integer_zero_node, - build_t_desc (t, 0)), - pending_virtuals); - pending_virtuals = tree_cons (NULL_TREE, the_null_vtable_entry, - pending_virtuals); - 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); - - /* Update the dossier pointer for this class. */ - if (flag_dossier) - TREE_VALUE (TREE_CHAIN (TYPE_BINFO_VIRTUALS (t))) - = build_vtable_entry (integer_zero_node, build_t_desc (t, 0)); - } - - /* 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 (has_virtual > max_has_virtual) - max_has_virtual = has_virtual; - if (max_has_virtual || first_vfn_base_index >= 0) - { - TYPE_VIRTUAL_P (t) = 1; - 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; - if (write_virtuals >= 0) - DECL_VIRTUAL_P (TYPE_BINFO_VTABLE (t)) = 1; - } - } - - /* Now lay out the virtual function table. */ - if (has_virtual) - { - tree atype, itype; - - if (TREE_TYPE (vfield) == ptr_type_node) - { - /* We must create a pointer to this table because - the one inherited from base class does not exist. - We will fill in the type when we know what it - should really be. Use `size_int' so values are memoized - in common cases. */ - itype = build_index_type (size_int (has_virtual)); - atype = build_array_type (vtable_entry_type, itype); - layout_type (atype); - TREE_TYPE (vfield) = build_pointer_type (atype); - } - else - { - atype = TREE_TYPE (TREE_TYPE (vfield)); - - if (has_virtual != TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (atype)))) - { - /* We must extend (or create) the boundaries on this array, - because we picked up virtual functions from multiple - base classes. */ - itype = build_index_type (size_int (has_virtual)); - atype = build_array_type (vtable_entry_type, itype); - layout_type (atype); - vfield = copy_node (vfield); - TREE_TYPE (vfield) = build_pointer_type (atype); - } - } - - CLASSTYPE_VFIELD (t) = vfield; - if (TREE_TYPE (TYPE_BINFO_VTABLE (t)) != atype) - { - TREE_TYPE (TYPE_BINFO_VTABLE (t)) = atype; - 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); - - /* Promote each bit-field's type to int if it is narrower than that. - There's more: complete the rtl for any static member objects which - is of the same type we're working on. */ - for (x = fields; x; x = TREE_CHAIN (x)) - { - if (DECL_BIT_FIELD (x) - && (C_PROMOTING_INTEGER_TYPE_P (TREE_TYPE (x)) - || DECL_FIELD_SIZE (x) < TYPE_PRECISION (integer_type_node))) - { - tree type = TREE_TYPE (x); - - /* Preserve unsignedness if traditional or if not really getting - any wider. */ - if (TREE_UNSIGNED (type) - && (flag_traditional - || - (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node) - && DECL_FIELD_SIZE (x) == TYPE_PRECISION (integer_type_node)))) - TREE_TYPE (x) = unsigned_type_node; - else - TREE_TYPE (x) = integer_type_node; - } - - 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); - } - } - - /* Now add the tags, if any, to the list of TYPE_DECLs - defined for this type. */ - if (CLASSTYPE_TAGS (t)) - { - x = CLASSTYPE_TAGS (t); - last_x = tree_last (TYPE_FIELDS (t)); - while (x) - { -#if 0 /* What's wrong with using the decl the type already has? */ - tree tag = build_decl (TYPE_DECL, TREE_PURPOSE (x), TREE_VALUE (x)); - DECL_CONTEXT (tag) = t; -#else - tree tag = TYPE_NAME (TREE_VALUE (x)); -#endif - -#ifdef DWARF_DEBUGGING_INFO - if (write_symbols == DWARF_DEBUG) - { - /* Notify dwarfout.c that this TYPE_DECL node represent a - gratuitous typedef. */ - DECL_IGNORED_P (tag) = 1; - } -#endif /* DWARF_DEBUGGING_INFO */ - - TREE_NONLOCAL_FLAG (TREE_VALUE (x)) = 0; - x = TREE_CHAIN (x); - last_x = chainon (last_x, tag); - } - if (TYPE_FIELDS (t) == NULL_TREE) - TYPE_FIELDS (t) = last_x; - CLASSTYPE_LOCAL_TYPEDECLS (t) = 1; - } - - 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); - - if (! CLASSTYPE_DECLARED_EXCEPTION (t) && ! IS_SIGNATURE (t)) - embrace_waiting_friends (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 ((flag_this_is_variable & 1) == 0) - { - tree vtbl_ptr = build_decl (VAR_DECL, get_identifier (VPTR_NAME), - TREE_TYPE (vfield)); - DECL_REGISTER (vtbl_ptr) = 1; - CLASSTYPE_VTBL_PTR (t) = vtbl_ptr; - } -#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, 0)) == 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); - TYPE_BEING_DEFINED (t) = 0; - - if (flag_dossier && CLASSTYPE_VTABLE_NEEDS_WRITING (t)) - { - tree variants; - tree tdecl; - - /* Now instantiate its type descriptors. */ - tdecl = TREE_OPERAND (build_t_desc (t, 1), 0); - variants = TYPE_POINTER_TO (t); - build_type_variant (variants, 1, 0); - while (variants) - { - build_t_desc (variants, 1); - variants = TYPE_NEXT_VARIANT (variants); - } - variants = build_reference_type (t); - build_type_variant (variants, 1, 0); - while (variants) - { - build_t_desc (variants, 1); - variants = TYPE_NEXT_VARIANT (variants); - } - DECL_CONTEXT (tdecl) = t; - } - /* Still need to instantiate this C struct's type descriptor. */ - else if (flag_dossier && ! CLASSTYPE_DOSSIER (t)) - build_t_desc (t, 1); - -#if 0 - if (TYPE_NAME (t) && TYPE_IDENTIFIER (t)) - undo_template_name_overload (TYPE_IDENTIFIER (t), 1); -#endif - if (current_class_type) - popclass (0); - else - error ("trying to finish struct, but kicked out due to previous parse errors."); - - hack_incomplete_structures (t); - - resume_momentary (old); - - if (flag_cadillac) - cadillac_finish_struct (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_CONTEXT (TYPE_NAME (t)) - && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (TYPE_NAME (t)))) == 't') - DECL_IGNORED_P (TYPE_NAME (t)) = TREE_ASM_WRITTEN (TYPE_NAME (t)); - } -#endif - - if (write_symbols != DWARF_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. */ - if (CLASSTYPE_METHOD_VEC (t)) - { - extern tree pending_vtables; - - /* Don't output full info about any type - which does not have its implementation defined here. */ - if (TYPE_VIRTUAL_P (t) && write_virtuals == 2) - TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) - = (value_member (TYPE_IDENTIFIER (t), pending_vtables) == 0); - else if (CLASSTYPE_INTERFACE_ONLY (t)) - TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 1; - else if (CLASSTYPE_INTERFACE_UNKNOWN (t)) - /* Only a first approximation! */ - TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 1; - } - else if (CLASSTYPE_INTERFACE_ONLY (t)) - TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (t)) = 1; - } - - /* Finish debugging output for this type. */ - rest_of_type_compilation (t, global_bindings_p ()); - - return t; -} - -/* Return non-zero if the effective type of INSTANCE is static. - 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; -{ - 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 1; - } - return 0; - - 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 1; - } - return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull); - - case RTL_EXPR: - /* This is a call to `new', hence it's never zero. */ - if (TREE_CALLS_NEW (instance)) - { - if (nonnull) - *nonnull = 1; - return 1; - } - return 0; - - case PLUS_EXPR: - case MINUS_EXPR: - if (TREE_CODE (TREE_OPERAND (instance, 1)) == INTEGER_CST) - /* Propagate nonnull. */ - resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull); - if (TREE_CODE (TREE_OPERAND (instance, 0)) == ADDR_EXPR) - return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull); - return 0; - - case NOP_EXPR: - case CONVERT_EXPR: - return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull); - - case ADDR_EXPR: - if (nonnull) - *nonnull = 1; - return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull); - - case COMPONENT_REF: - return resolves_to_fixed_type_p (TREE_OPERAND (instance, 1), nonnull); - - case WITH_CLEANUP_EXPR: - if (TREE_CODE (TREE_OPERAND (instance, 0)) == ADDR_EXPR) - return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull); - /* fall through... */ - 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 1; - } - /* fall through... */ - case TARGET_EXPR: - case PARM_DECL: - if (IS_AGGR_TYPE (TREE_TYPE (instance))) - { - if (nonnull) - *nonnull = 1; - return 1; - } - else if (nonnull) - { - if (instance == current_class_decl - && flag_this_is_variable <= 0) - { - /* Some people still use `this = 0' inside destructors. */ - *nonnull = ! DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (current_function_decl)); - /* In a constructor, we know our type. */ - if (flag_this_is_variable < 0) - return 1; - } - else if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE) - /* Reference variables should be references to objects. */ - *nonnull = 1; - } - return 0; - - default: - return 0; - } -} - -void -init_class_processing () -{ - current_class_depth = 0; - current_class_stacksize = 10; - current_class_base = (tree *)xmalloc(current_class_stacksize * sizeof (tree)); - current_class_stack = current_class_base; - - current_lang_stacksize = 10; - current_lang_base = (tree *)xmalloc(current_lang_stacksize * sizeof (tree)); - current_lang_stack = current_lang_base; - - /* Keep these values lying around. */ - the_null_vtable_entry = build_vtable_entry (integer_zero_node, integer_zero_node); - 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; -{ - push_memoized_context (type, modify); - - current_class_depth++; - *current_class_stack++ = current_class_name; - *current_class_stack++ = current_class_type; - if (current_class_stack >= current_class_base + current_class_stacksize) - { - current_class_base = - (tree *)xrealloc (current_class_base, - sizeof (tree) * (current_class_stacksize + 10)); - current_class_stack = current_class_base + current_class_stacksize; - current_class_stacksize += 10; - } - - 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; - - 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; - } - - pushlevel_class (); - - 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 (TREE_CODE (type) == UNINSTANTIATED_P_TYPE) - declare_uninstantiated_type_level (); - else if (type != previous_class_type || current_class_depth > 1) - { - build_mi_matrix (type); - push_class_decls (type); - free_mi_matrix (); - if (current_class_depth == 1) - previous_class_type = type; - } - else - { - tree item; - - /* Hooray, our cacheing was successful, let's just install the - cached class_shadowed list, and walk through it to get the - IDENTIFIER_TYPE_VALUEs correct. */ - set_class_shadows (previous_class_values); - for (item = previous_class_values; item; item = TREE_CHAIN (item)) - { - tree id = TREE_PURPOSE (item); - tree decl = IDENTIFIER_CLASS_VALUE (id); - - if (TREE_CODE (decl) == TYPE_DECL) - set_identifier_type_value (id, TREE_TYPE (decl)); - } - unuse_fields (type); - } - - if (IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (type))) - overload_template_name (current_class_name, 0); - - for (tags = CLASSTYPE_TAGS (type); tags; tags = TREE_CHAIN (tags)) - { - TREE_NONLOCAL_FLAG (TREE_VALUE (tags)) = 1; - if (! TREE_PURPOSE (tags)) - continue; - pushtag (TREE_PURPOSE (tags), TREE_VALUE (tags), 0); - } - - current_function_decl = this_fndecl; - } - - if (flag_cadillac) - cadillac_push_class (type); -} - -/* 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 (flag_cadillac) - cadillac_pop_class (); - - 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); - } - goto ret; - } - - 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); - } - if (IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (current_class_type))) - undo_template_name_overload (current_class_name, 0); - } - - /* 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_type); - - current_class_depth--; - current_class_type = *--current_class_stack; - current_class_name = *--current_class_stack; - - if (current_class_type) - { - if (CLASSTYPE_VTBL_PTR (current_class_type)) - { - current_vtable_decl - = lookup_name (DECL_NAME (CLASSTYPE_VTBL_PTR (current_class_type)), - 0); - if (current_vtable_decl) - current_vtable_decl = build_indirect_ref (current_vtable_decl, - NULL_PTR); - } - current_class_decl = lookup_name (this_identifier, 0); - if (current_class_decl) - { - if (TREE_CODE (TREE_TYPE (current_class_decl)) == POINTER_TYPE) - { - tree temp; - /* Can't call build_indirect_ref here, because it has special - logic to return C_C_D given this argument. */ - C_C_D = build1 (INDIRECT_REF, current_class_type, current_class_decl); - temp = TREE_TYPE (TREE_TYPE (current_class_decl)); - TREE_READONLY (C_C_D) = TYPE_READONLY (temp); - TREE_SIDE_EFFECTS (C_C_D) = TYPE_VOLATILE (temp); - TREE_THIS_VOLATILE (C_C_D) = TYPE_VOLATILE (temp); - } - else - C_C_D = current_class_decl; - } - else - C_C_D = NULL_TREE; - } - else - { - current_class_decl = NULL_TREE; - current_vtable_decl = NULL_TREE; - C_C_D = NULL_TREE; - } - - pop_memoized_context (modify); - - ret: - ; -} - -/* 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; - - if (type == error_mark_node || ! IS_AGGR_TYPE (type)) - return; - - context = DECL_CONTEXT (TYPE_NAME (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_NAME (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) - { - 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)); - - if (flag_cadillac) - cadillac_push_lang (name); -} - -/* Get out of the current language scope. */ -void -pop_lang_context () -{ - if (flag_cadillac) - cadillac_pop_lang (); - - current_lang_name = *--current_lang_stack; - if (current_lang_name == lang_name_cplusplus) - strict_prototype = strict_prototypes_lang_cplusplus; - else if (current_lang_name == lang_name_c) - strict_prototype = strict_prototypes_lang_c; -} - -int -root_lang_context_p () -{ - return current_lang_stack == current_lang_base; -} - -/* Type instantiation routines. */ - -/* This function will instantiate the type of the expression given - in RHS to match the type of LHSTYPE. If LHSTYPE is NULL_TREE, - or other errors exist, the TREE_TYPE of RHS will be ERROR_MARK_NODE. - - This function is used in build_modify_expr, convert_arguments, - build_c_cast, and compute_conversion_costs. */ -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))) - return 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_TYPE (rhs) = lhstype; - lhstype = build_pointer_type (lhstype); - TREE_OPERAND (rhs, 0) - = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain); - if (TREE_OPERAND (rhs, 0) == error_mark_node) - return error_mark_node; - - 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); - if (TREE_CODE (field) == TREE_LIST) - { - tree function = instantiate_type (lhstype, field, complain); - if (function == error_mark_node) - return error_mark_node; - my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 185); - if (DECL_VINDEX (function)) - { - tree base = TREE_OPERAND (rhs, 0); - tree base_ptr = build_unary_op (ADDR_EXPR, base, 0); - if (base_ptr == error_mark_node) - return error_mark_node; - base_ptr = convert_pointer_to (DECL_CONTEXT (function), base_ptr); - if (base_ptr == error_mark_node) - return error_mark_node; - return build_vfn_ref (&base_ptr, base, DECL_VINDEX (function)); - } - return function; - } - - my_friendly_assert (TREE_CODE (field) == FIELD_DECL, 178); - my_friendly_assert (!(TREE_CODE (TREE_TYPE (field)) == FUNCTION_TYPE - || TREE_CODE (TREE_TYPE (field)) == METHOD_TYPE), - 179); - - TREE_TYPE (rhs) = lhstype; - /* First look for an exact match */ - - while (field && TREE_TYPE (field) != lhstype) - field = TREE_CHAIN (field); - if (field) - { - TREE_OPERAND (rhs, 1) = field; - return rhs; - } - - /* No exact match found, look for a compatible function. */ - field = TREE_OPERAND (rhs, 1); - while (field && ! comptypes (lhstype, TREE_TYPE (field), 0)) - field = TREE_CHAIN (field); - if (field) - { - TREE_OPERAND (rhs, 1) = field; - field = TREE_CHAIN (field); - while (field && ! comptypes (lhstype, TREE_TYPE (field), 0)) - field = TREE_CHAIN (field); - if (field) - { - if (complain) - error ("ambiguous overload for COMPONENT_REF requested"); - return error_mark_node; - } - } - else - { - if (complain) - error ("no appropriate overload exists for COMPONENT_REF"); - return error_mark_node; - } - return rhs; - } - - case TREE_LIST: - { - tree elem, baselink, name; - int globals = overloaded_globals_p (rhs); - -#if 0 /* obsolete */ - /* If there's only one function we know about, return that. */ - if (globals > 0 && TREE_CHAIN (rhs) == NULL_TREE) - return TREE_VALUE (rhs); -#endif - - /* First look for an exact match. Search either overloaded - functions or member functions. May have to undo what - `default_conversion' might do to lhstype. */ - - if (TREE_CODE (lhstype) == POINTER_TYPE) - if (TREE_CODE (TREE_TYPE (lhstype)) == FUNCTION_TYPE - || TREE_CODE (TREE_TYPE (lhstype)) == METHOD_TYPE) - lhstype = TREE_TYPE (lhstype); - else - { - if (complain) - error ("invalid type combination for overload"); - return error_mark_node; - } - - if (TREE_CODE (lhstype) != FUNCTION_TYPE && globals > 0) - { - if (complain) - cp_error ("cannot resolve overloaded function `%D' based on non-function type", - TREE_PURPOSE (rhs)); - return error_mark_node; - } - - if (globals > 0) - { - elem = get_first_fn (rhs); - while (elem) - if (! comptypes (lhstype, TREE_TYPE (elem), 1)) - elem = DECL_CHAIN (elem); - else - return elem; - - /* No exact match found, look for a compatible template. */ - { - tree save_elem = 0; - for (elem = get_first_fn (rhs); elem; elem = DECL_CHAIN (elem)) - if (TREE_CODE (elem) == TEMPLATE_DECL) - { - int n = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (elem)); - tree *t = (tree *) alloca (sizeof (tree) * n); - int i, d; - i = type_unification (DECL_TEMPLATE_PARMS (elem), t, - TYPE_ARG_TYPES (TREE_TYPE (elem)), - TYPE_ARG_TYPES (lhstype), &d, 0); - if (i == 0) - { - if (save_elem) - { - cp_error ("ambiguous template instantiation converting to `%#T'", lhstype); - return error_mark_node; - } - save_elem = instantiate_template (elem, t); - /* Check the return type. */ - if (! comptypes (TREE_TYPE (lhstype), - TREE_TYPE (TREE_TYPE (save_elem)), 1)) - save_elem = 0; - } - } - if (save_elem) - return save_elem; - } - - /* No match found, look for a compatible function. */ - elem = get_first_fn (rhs); - while (elem && ! comp_target_types (lhstype, TREE_TYPE (elem), 1)) - elem = DECL_CHAIN (elem); - if (elem) - { - tree save_elem = elem; - elem = DECL_CHAIN (elem); - while (elem && ! comp_target_types (lhstype, TREE_TYPE (elem), - 0)) - elem = DECL_CHAIN (elem); - if (elem) - { - if (complain) - { - cp_error ("cannot resolve overload to target type `%#T'", - lhstype); - cp_error_at (" ambiguity between `%#D'", save_elem); - cp_error_at (" and `%#D', at least", elem); - } - return error_mark_node; - } - return save_elem; - } - if (complain) - { - cp_error ("cannot resolve overload to target type `%#T'", - lhstype); - cp_error (" because no suitable overload of function `%D' exists", - TREE_PURPOSE (rhs)); - } - return error_mark_node; - } - - if (TREE_NONLOCAL_FLAG (rhs)) - { - /* Got to get it as a baselink. */ - rhs = lookup_fnfields (TYPE_BINFO (current_class_type), - TREE_PURPOSE (rhs), 0); - } - else - { - my_friendly_assert (TREE_CHAIN (rhs) == NULL_TREE, 181); - if (TREE_CODE (TREE_VALUE (rhs)) == TREE_LIST) - rhs = TREE_VALUE (rhs); - my_friendly_assert (TREE_CODE (TREE_VALUE (rhs)) == FUNCTION_DECL, - 182); - } - - for (baselink = rhs; baselink; - baselink = next_baselink (baselink)) - { - elem = TREE_VALUE (baselink); - while (elem) - if (comptypes (lhstype, TREE_TYPE (elem), 1)) - return elem; - else - elem = TREE_CHAIN (elem); - } - - /* No exact match found, look for a compatible method. */ - for (baselink = rhs; baselink; - baselink = next_baselink (baselink)) - { - elem = TREE_VALUE (baselink); - while (elem && ! comp_target_types (lhstype, TREE_TYPE (elem), 1)) - elem = TREE_CHAIN (elem); - if (elem) - { - tree save_elem = elem; - elem = TREE_CHAIN (elem); - while (elem && ! comp_target_types (lhstype, TREE_TYPE (elem), 0)) - elem = TREE_CHAIN (elem); - if (elem) - { - if (complain) - error ("ambiguous overload for overloaded method requested"); - return error_mark_node; - } - return save_elem; - } - name = DECL_NAME (TREE_VALUE (rhs)); -#if 0 - if (TREE_CODE (lhstype) == FUNCTION_TYPE && globals < 0) - { - /* Try to instantiate from non-member functions. */ - rhs = lookup_name_nonclass (name); - if (rhs && TREE_CODE (rhs) == TREE_LIST) - { - /* This code seems to be missing a `return'. */ - my_friendly_abort (4); - instantiate_type (lhstype, rhs, complain); - } - } -#endif - } - if (complain) - error ("no static member functions named `%s'", - IDENTIFIER_POINTER (name)); - return error_mark_node; - } - - 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 ("illegal 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: - if (TYPE_PTRMEMFUNC_P (lhstype)) - lhstype = TYPE_PTRMEMFUNC_FN_TYPE (lhstype); - else if (TREE_CODE (lhstype) != POINTER_TYPE) - { - if (complain) - error ("type for resolving address of overloaded function must be pointer type"); - return error_mark_node; - } - TREE_TYPE (rhs) = lhstype; - lhstype = TREE_TYPE (lhstype); - { - tree fn = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain); - if (fn == error_mark_node) - return error_mark_node; - mark_addressable (fn); - TREE_OPERAND (rhs, 0) = fn; - TREE_CONSTANT (rhs) = staticp (fn); - } - return rhs; - - 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. For now, let's - use the permanent obstack, later we may create a dedicated obstack just - for this purpose. The effect is undone by pop_obstacks. */ -void -maybe_push_cache_obstack () -{ - push_obstacks_nochange (); - if (current_class_depth == 1) - current_obstack = &permanent_obstack; -} |