home *** CD-ROM | disk | FTP | other *** search
- /* Functions related to building and playing with classes.
- Copyright (C) 1987 Free Software Foundation, Inc.
- Contributed by Michael Tiemann (tiemann@mcc.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 1, 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 "cplus-tree.h"
- #include "flags.h"
- #include "rtl.h"
- #include "assert.h"
- #include <stdio.h>
-
- #include "obstack.h"
- #define obstack_chunk_alloc xmalloc
- #define obstack_chunk_free free
-
- extern int xmalloc ();
- extern void free ();
-
- #define NULL 0
- #define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
- #define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
-
- /* See cplus-decl.c for comment of this variable. */
- extern int flag_int_enum_equivalence;
-
- /* some statistics gathering help. */
- static int n_vtables, n_vtable_entries, n_vtable_searches, n_vtable_elems;
- static int n_convert_harshness, n_compute_conversion_costs, n_build_method_call;
- static int n_inner_fields_searched;
-
- /* Compute the ease with which a conversion can be performed
- between an expected and the given type. */
- static int convert_harshness ();
-
- /* in decl.c. */
- extern tree lookup_tag_current_binding_level ();
-
- /* in method.c. */
- extern void do_inline_function_hair ();
-
- /* Way of stacking class types. */
- static tree *current_class_base, *current_class_stack;
- static int current_class_stacksize;
-
- 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 prev_class_type; /* _TYPE: the previous type that was a class */
-
- static tree get_vtable_name (), get_vfield_name ();
- tree the_null_vtable_entry;
-
- /* Way of stacking langauge names. */
- static tree *current_lang_base, *current_lang_stack;
- static int current_lang_stacksize;
-
- /* Names of languages we recognize. */
- tree lang_name_c, lang_name_cplusplus;
- tree current_lang_name;
-
- tree minus_one_node;
-
- /* 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;
-
- #if 0
- /* Make sure that the tag NAME is defined *in the current binding level*
- at least as a forward reference.
- CODE says which kind of tag NAME ought to be.
-
- Not used for C++. Not maintained. */
-
- tree
- start_struct (code, name)
- enum tree_code code;
- tree name;
- {
- /* If there is already a tag defined at this binding level
- (as a forward reference), just return it. */
- register tree ref = 0;
-
- if (name != 0)
- ref = lookup_tag (code, name, current_binding_level, 1);
- if (ref && TREE_CODE (ref) == code)
- {
- if (TYPE_FIELDS (ref))
- error ((code == UNION_TYPE ? "redefinition of `union %s'"
- : "redefinition of `struct %s'"),
- IDENTIFIER_POINTER (name));
-
- return ref;
- }
-
- /* Otherwise create a forward-reference just so the tag is in scope. */
-
- ref = make_lang_type (code);
- /* Must re-synch this with xref_tag if you are going to use it. */
- assert (0);
- pushtag (name, ref);
- return ref;
- }
- #endif
-
- /* 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);
- }
-
- /* 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;
- tree expr;
- tree path;
- int alias_this;
- {
- register int changed = 0;
- tree last = NULL_TREE, last_virtual = NULL_TREE;
- int fixed_type_p = 0 && resolves_to_fixed_type_p (expr);
- tree basetype;
- tree offset = integer_zero_node;
-
- if (TREE_CHAIN (path))
- path = nreverse (copy_list (path));
-
- basetype = TREE_VALUE (path);
- while (path)
- {
- if (TREE_VIA_VIRTUAL (path))
- {
- last_virtual = TYPE_MAIN_VARIANT (TREE_VALUE (path));
- if (code == PLUS_EXPR)
- {
- changed = ! fixed_type_p;
-
- if (last)
- expr = convert_pointer_to (TREE_VALUE (last), expr);
- if (changed)
- expr = build_vbase_pointer (build_indirect_ref (expr, 0),
- last_virtual);
- else
- offset = ASSOC_OFFSET (value_member (last_virtual,
- CLASSTYPE_VBASECLASSES (basetype)));
- }
- else
- {
- error_with_aggr_type (last_virtual, "cannot cast up from virtual baseclass `%s'");
- return error_mark_node;
- }
- }
- last = path;
- path = TREE_CHAIN (path);
- }
- /* LAST is now the last basetype on the path. */
- last = TREE_VALUE (last);
-
- /* 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) == TYPE_MAIN_VARIANT (last))
- basetype = intype;
- else
- {
- basetype = get_base_type (last, TYPE_MAIN_VARIANT (intype), 0);
- offset = CLASSTYPE_OFFSET (basetype);
- }
- }
- else
- {
- if (last_virtual && last != last_virtual)
- basetype = get_base_type (last, last_virtual, 0);
- else
- basetype = last;
-
- offset = genop (code, offset, CLASSTYPE_OFFSET (basetype));
- }
-
- 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. */
- tree addr = TREE_CODE (expr) == ADDR_EXPR
- ? expr : save_expr (expr);
- expr = build (code, type, addr, offset);
-
- if (alias_this == 0 || flag_this_is_variable)
- return build (COND_EXPR, type,
- build (EQ_EXPR, integer_type_node, addr, integer_zero_node),
- build1 (NOP_EXPR, type, addr),
- expr);
- }
- return build1 (NOP_EXPR, type, expr);
- }
-
- /* Virtual function things. */
-
- /* Virtual functions to be dealt with after laying out our
- virtual base classes (only if the type has any). */
- static tree pending_hard_virtuals;
-
- /* The names of the entries in the virtual table structure. */
- static tree delta_name, pfn_name;
-
- /* Temporary assoc list to memoize lookups of the left-most non-virtual
- baseclass B in a lattice topped by T. B can appear multiple times
- in the lattice.
- TREE_PURPOSE is B's TYPE_MAIN_VARIANT.
- TREE_VALUE is the path by which B is reached from T.
- TREE_TYPE is B's real type.
-
- If TREE_TYPE is NULL_TREE, it means that B was reached via
- a virtual baseclass.
- N.B.: This list consists of nodes on the temporary obstack. */
- static tree leftmost_baseclasses;
-
- /* 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;
- {
- 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);
- TREE_LITERAL (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, index)
- tree *ptr_to_instptr, instance;
- tree index;
- {
- 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
- || get_base_type (DECL_FCONTEXT (CLASSTYPE_VFIELD (current_class_type)), basetype, 0) == NULL_TREE)
- vtbl = build_indirect_ref (build_vfield_ref (instance, basetype));
- 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 = 0;
-
- 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) == REFERENCE_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 (instance)
- && (TREE_CODE (instance) == RESULT_DECL
- || TREE_CODE (instance) == PARM_DECL
- || TREE_CODE (instance) == VAR_DECL))
- vtbl = CLASS_ASSOC_VTABLE (basetype);
- else
- vtbl = build_indirect_ref (build_vfield_ref (instance, basetype), 0);
- }
- aref = build_array_ref (vtbl, index);
- if (!building_cleanup && TREE_CODE (aref) == INDIRECT_REF)
- TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0));
-
- *ptr_to_instptr = build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr),
- *ptr_to_instptr,
- convert (integer_type_node, build_component_ref (aref, delta_name, 0, 0)));
- return build_component_ref (aref, pfn_name, 0, 0);
- }
-
- /* Build a virtual function for type TYPE.
- If ASSOC is non-NULL, build the vtable starting with the intial
- approximation that it is the same as the one which is the head of
- the assocation list. */
- static tree
- build_vtable (assoc, type)
- tree assoc, type;
- {
- tree name = get_vtable_name (type);
- tree virtuals, decl;
-
- if (assoc)
- {
- virtuals = copy_list (ASSOC_VIRTUALS (assoc));
- decl = build_decl (VAR_DECL, name, TREE_TYPE (ASSOC_VTABLE (assoc)));
- }
- 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
-
- if (write_virtuals > 0)
- TREE_PUBLIC (decl) = 1;
- else if (write_virtuals < 0)
- TREE_EXTERNAL (decl) = 1;
- IDENTIFIER_GLOBAL_VALUE (name) = decl = pushdecl_top_level (decl);
- /* Initialize the association list for this type, based
- on our first approximation. */
- CLASS_ASSOC_VTABLE (type) = decl;
- CLASS_ASSOC_VIRTUALS (type) = virtuals;
-
- TREE_STATIC (decl) = 1;
- DECL_ALIGN (decl) = MAX (TYPE_ALIGN (double_type_node),
- DECL_ALIGN (decl));
-
- if (assoc && write_virtuals >= 0)
- DECL_VIRTUAL_P (decl) = 1;
- /* Remember which class this vtable is really for. */
- DECL_VPARENT (decl) = type;
- CLASSTYPE_MARKED3 (type) = 1;
- CLASSTYPE_MARKED4 (type) = 1;
- return decl;
- }
-
- /* 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.
-
- ASSOC is the type association which provided TYPE for FOR_TYPE.
-
- The way we update BASE_ASSOC's vtable information is just to change the
- association information in FOR_TYPE's association list. */
- static void
- prepare_fresh_vtable (assoc, base_assoc, for_type)
- tree assoc, base_assoc, for_type;
- {
- tree basetype = ASSOC_TYPE (assoc);
- tree orig_decl = ASSOC_VTABLE (assoc);
- 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;
-
- assert (TREE_USED (assoc) == 0);
-
- /* Remember which class this vtable is really for. */
- DECL_VPARENT (new_decl) = ASSOC_TYPE (base_assoc);
-
- /* `new_decl' has the right PUBLIC and EXTERNAL bits set. */
- TREE_STATIC (new_decl) = 1;
- ASSOC_VTABLE (assoc) = pushdecl_top_level (new_decl);
- DECL_VIRTUAL_P (new_decl) = 1;
- DECL_ALIGN (new_decl) = DECL_ALIGN (orig_decl);
-
- /* Make fresh virtual list, so we can smash it later. */
- assert (ASSOC_VIRTUALS (assoc));
- ASSOC_VIRTUALS (assoc) = copy_list (ASSOC_VIRTUALS (assoc));
-
- #ifdef GATHER_STATISTICS
- n_vtables += 1;
- n_vtable_elems += list_length (ASSOC_VIRTUALS (assoc));
- #endif
-
- CLASSTYPE_MARKED3 (basetype) = 1;
- CLASSTYPE_MARKED4 (basetype) = 1;
-
- /* Mark all types between FOR_TYPE and TYPE as having been
- touched, so that if we change virtual function table entries,
- new vtables will be initialized. We may reach the virtual
- baseclass via ambiguous intervening baseclasses. This
- loop makes sure we get through to the actual baseclass we marked. */
-
- do
- {
- result = get_base_distance (basetype, for_type, 0, &path);
- for_type = TREE_VALUE (path);
- while (path)
- {
- CLASSTYPE_MARKED3 (TREE_VALUE (path)) = 1;
- path = TREE_CHAIN (path);
- }
- }
- while (result == -2);
- }
-
- /* Access the virtual function table entry that logically
- contains BASE_FNDECL. VIRTUALS is the virtual function table's
- initializer. */
- static tree
- get_vtable_entry (virtuals, base_fndecl)
- tree virtuals, base_fndecl;
- {
- int i = (HOST_BITS_PER_INT >= BITS_PER_WORD
- #ifdef VTABLE_USES_MASK
- && 0
- #endif
- ? (TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl))
- & ((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 = TREE_CHAIN (virtuals);
- i -= 1;
- }
- return virtuals;
- }
-
- /* Put new entry ENTRY into virtual function table initializer
- VIRTUALS. The virtual function table is for type CONTEXT.
-
- Also update DECL_VINDEX (FNDECL). */
-
- static void
- modify_vtable_entry (old_entry_in_list, new_entry, fndecl, context)
- tree old_entry_in_list, new_entry, fndecl, context;
- {
- tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (old_entry_in_list));
- tree vindex;
-
- /* We can't put in the really right offset information
- here, since we have not yet laid out the class to
- take into account virtual base classes. */
- TREE_VALUE (old_entry_in_list) = new_entry;
- vindex = DECL_VINDEX (TREE_OPERAND (base_pfn, 0));
- if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
- SET_DECL_VINDEX (fndecl, vindex);
- else
- {
- if (! tree_int_cst_equal (DECL_VINDEX (fndecl), vindex))
- {
- tree elts = CONSTRUCTOR_ELTS (new_entry);
- tree vfield = CLASSTYPE_VFIELD (context);
- /* Compute the relative offset of vtable we are really looking for. */
- TREE_VALUE (elts) = genop (PLUS_EXPR,
- build_int (DECL_OFFSET (vfield)
- / DECL_SIZE_UNIT (vfield)),
- TREE_VALUE (elts));
- /* Say what index to use when we use that vtable. */
- #ifndef VTABLE_USES_MASK
- vindex = build_int_2 (TREE_INT_CST_LOW (vindex) & ~(1 << (BITS_PER_WORD -1)), 0);
- #endif
- TREE_VALUE (TREE_CHAIN (elts)) = vindex;
- }
- }
- }
-
- /* Modify virtual function tables in lattice topped by T to
- place FNDECL in tables which previously held BASE_FNDECL.
- PFN is just FNDECL wrapped in an ADDR_EXPR, so that it
- is suitable for placement directly into an initializer.
-
- All distinct virtual function tables that this type uses
- must be updated. */
- static void
- modify_vtable_entries (t, fndecl, base_fndecl, pfn)
- tree t;
- tree fndecl, base_fndecl, pfn;
- {
- tree base_offset, offset;
- tree context = DECL_CONTEXT (base_fndecl);
- tree vfield = CLASSTYPE_VFIELD (t);
- tree vslots, vbases;
-
- DECL_VCONTEXT (fndecl) = DECL_VCONTEXT (base_fndecl);
-
- if (DECL_CONTEXT (fndecl) == t
- || !(TYPE_USES_VIRTUAL_BASECLASSES (t)
- || TYPE_USES_MULTIPLE_INHERITANCE (t)))
- offset = integer_zero_node;
- else
- {
- tree assoc = value_member (DECL_CONTEXT (fndecl), CLASSTYPE_VBASECLASSES (t));
- if (assoc == NULL_TREE)
- assoc = assoc_value (DECL_CONTEXT (fndecl), t);
- assert (assoc != NULL_TREE);
- offset = ASSOC_OFFSET (assoc);
- }
-
- /* For each layer of base class (i.e., the first base class, and each
- virtual base class from that one), modify the virtual function table
- of the derived class to contain the new virtual function.
- A class has as many vfields as it has virtual base classes (total). */
- for (vslots = CLASSTYPE_VFIELDS (t); vslots; vslots = TREE_CHAIN (vslots))
- {
- int normal = 1;
- tree assoc, this_offset;
- tree base, path;
-
- /* Find the right base class for this derived class, call it BASE. */
- base = TREE_VALUE (vslots);
-
- if (base != context)
- {
- /* If BASE_FNDECL is not contained in the vtable accessed by
- the vslot, don't try to modify the vtable.
-
- Virtual functions from virtual baseclasses are not in derived
- virtual function tables. This is an implementation decision;
- it keeps there from being a combinatorial exposion in the
- number of different vtables which must be maintained. */
-
- if (get_base_distance (base, context, 0, &path) == -1)
- continue;
-
- /* BASE_FNDECL is defined in a class derived from
- the base class owning this VFIELD. */
- }
- /* Get the path starting from the deepest base class CONTEXT
- of T (i.e., first defn of BASE_FNDECL). */
- get_base_distance (context, t, 0, &path);
-
- /* Get our best approximation of what to use for constructing
- the virtual function table for T. */
- do
- {
- /* Walk from base toward derived, stopping at the
- most derived baseclass that matters. */
- if (TREE_VIA_VIRTUAL (path))
- {
- base = TREE_VALUE (path);
- assoc = value_member (TYPE_MAIN_VARIANT (base), CLASSTYPE_VBASECLASSES (t));
- break;
- }
- if (TREE_CHAIN (path) == NULL_TREE
- || (CLASSTYPE_BASECLASS (TREE_VALUE (TREE_CHAIN (path)), 1)
- != TREE_VALUE (path))
- || TREE_CHAIN (TREE_CHAIN (path)) == NULL_TREE)
- {
- base = TREE_VALUE (path);
- assoc = assoc_value (TYPE_MAIN_VARIANT (base), t);
- break;
- }
- path = TREE_CHAIN (path);
- }
- while (1);
-
- /* Find the right offset for the this pointer based on the base
- class we just found. */
- base_offset = ASSOC_OFFSET (assoc);
- if (base_offset == integer_zero_node)
- this_offset = offset;
- else
- this_offset = genop (MINUS_EXPR, offset, base_offset);
-
- /* Make sure we can modify the derived association with immunity. */
- if (TREE_USED (CLASSTYPE_ASSOC (t)))
- CLASSTYPE_ASSOC (t) = copy_assoc (CLASSTYPE_ASSOC (t));
-
- /* We call this case NORMAL iff this virtual function table
- pointer field has its storage reserved in this class.
- This is normally the case without virtual baseclasses
- or off-center multiple baseclasses. */
- normal = (vfield != NULL_TREE
- && TREE_VALUE (vslots) == DECL_FCONTEXT (vfield)
- && (TREE_PURPOSE (vslots) == NULL_TREE
- || ! TREE_VIA_VIRTUAL (TREE_PURPOSE (vslots))));
-
- if (normal && TREE_PURPOSE (vslots))
- /* Everything looks normal so far...check that we are really
- working from VFIELD's basetype, and not some other appearance
- of that basetype in the lattice. */
- normal = (TREE_PURPOSE (vslots) == get_base_type (TREE_VALUE (vslots), t, 0));
-
- if (normal)
- {
- /* In this case, it is *type*'s vtable we are modifying. */
- context = t;
- if (! CLASSTYPE_MARKED4 (t))
- build_vtable (assoc, t);
- assoc = CLASSTYPE_ASSOC (t);
- }
- else
- {
- /* This is our very own copy of `basetype' to play with. */
- if (! CLASSTYPE_MARKED4 (ASSOC_TYPE (assoc)))
- prepare_fresh_vtable (assoc, CLASSTYPE_ASSOC (base), t);
- }
-
- modify_vtable_entry (get_vtable_entry (ASSOC_VIRTUALS (assoc), base_fndecl),
- build_vtable_entry (this_offset, pfn),
- fndecl, context);
- }
- for (vbases = CLASSTYPE_VBASECLASSES (t); vbases; vbases = TREE_CHAIN (vbases))
- {
- tree this_offset;
- tree base, path;
-
- if (! ASSOC_VTABLE (vbases))
- /* There are only two ways that a type can fail to have
- virtual functions: neither it nor any of its base
- types define virtual functions (in which case
- no updating need be done), or virtual functions
- accessible to it come from virtual base classes
- (in which case we have or will get them modified
- in other passes of this loop). */
- continue;
-
- base = TREE_VALUE (vbases);
- path = NULL_TREE;
-
- if (base != context
- && get_base_distance (context, base, 0, &path) == -1)
- continue;
-
- /* Doesn't matter if not actually from this virtual base class,
- but shouldn't come from deeper virtual baseclasses. The enclosing
- loop should take care of such baseclasses. */
- while (path)
- {
- if (TREE_VIA_VIRTUAL (path))
- goto skip;
- path = TREE_CHAIN (path);
- }
-
- base_offset = ASSOC_OFFSET (vbases);
- if (base_offset == integer_zero_node)
- this_offset = offset;
- else
- this_offset = genop (MINUS_EXPR, offset, base_offset);
-
- /* Make sure we can modify the derived association with immunity. */
- if (TREE_USED (CLASSTYPE_ASSOC (t)))
- CLASSTYPE_ASSOC (t) = copy_assoc (CLASSTYPE_ASSOC (t));
-
- /* This is our very own copy of `basetype' to play with. */
- if (! CLASSTYPE_MARKED4 (ASSOC_TYPE (vbases)))
- {
- tree context_assoc = assoc_value (context, base);
- prepare_fresh_vtable (vbases, context_assoc, t);
- }
- modify_vtable_entry (get_vtable_entry (ASSOC_VIRTUALS (vbases), base_fndecl),
- build_vtable_entry (this_offset, pfn),
- fndecl, context);
- skip: {}
- }
- }
-
- static tree
- add_virtual_function (pending_virtuals, has_virtual, x, first)
- tree pending_virtuals;
- int *has_virtual;
- tree x;
- int first;
- {
- int debug_vbase = 1;
-
- /* FUNCTION_TYPEs and OFFSET_TYPEs no longer freely
- convert to void *. Make such a conversion here. */
- tree vfn = build1 (ADDR_EXPR, ptr_type_node, x);
- TREE_LITERAL (vfn) = 1;
- TREE_ADDRESSABLE (x) = CLASSTYPE_VTABLE_NEEDS_WRITING (current_class_type);
-
- /* 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 (x) == NULL_TREE)
- {
- tree entry = build_vtable_entry (integer_zero_node, vfn);
-
- /* Build a new INT_CST for this DECL_VINDEX. */
- #ifdef VTABLE_USES_MASK
- SET_DECL_VINDEX (x, build_int_2 (++(*has_virtual), 0));
- #else
- SET_DECL_VINDEX (x, build_int_2 (((1 << (BITS_PER_WORD - 1)) | ++(*has_virtual)), ~0));
- #endif
- pending_virtuals = tree_cons (DECL_VINDEX (x), entry, pending_virtuals);
- }
- /* Happens if declared twice in class. We will give error
- later. */
- else if (TREE_CODE (DECL_VINDEX (x)) == INTEGER_CST)
- return pending_virtuals;
- else if (debug_vbase && TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
- {
- /* 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 (x, vfn, pending_hard_virtuals);
- }
- else
- {
- /* Need an entry in some other virtual function table.
- We can do this now. */
- tree base_fndecls = DECL_VINDEX (x);
- while (base_fndecls)
- {
- modify_vtable_entries (current_class_type, x,
- TREE_VALUE (base_fndecls), vfn);
- base_fndecls = TREE_CHAIN (base_fndecls);
- }
- }
- 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 TREE_CHAIN. */
- int temp = allocation_temporary_p ();
- tree decl;
-
- if (temp)
- end_temporary_allocation ();
- {
- decl = copy_node (method);
- if (DECL_RTL (decl) == 0)
- make_function_rtl (decl);
- }
-
- if (fields && *fields)
- {
- /* Take care not to hide destructor. */
- TREE_CHAIN (decl) = TREE_CHAIN (*fields);
- TREE_CHAIN (*fields) = decl;
- }
- else if (CLASSTYPE_METHOD_VEC (type) == 0)
- {
- tree method_vec = make_node (TREE_VEC);
- if (DECL_NAME (TYPE_NAME (type)) == DECL_ORIGINAL_NAME (decl))
- {
- TREE_VEC_ELT (method_vec, 0) = decl;
- TREE_VEC_LENGTH (method_vec) = 1;
- }
- else
- {
- 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. */
- if (DECL_NAME (TYPE_NAME (type)) == DECL_ORIGINAL_NAME (decl))
- TREE_VEC_ELT (method_vec, 0) = decl;
- else
- {
- tree *end = (tree *)obstack_next_free (&class_obstack);
- if (end != TREE_VEC_END (method_vec))
- {
- tree tmp_vec = copy_node (method_vec);
- obstack_copy (current_obstack, &TREE_VEC_ELT (method_vec, 1), len);
- obstack_blank (current_obstack, sizeof (tree *));
- obstack_finish (current_obstack);
- method_vec = tmp_vec;
- }
- else
- {
- /* We can easily extend the last such method_vec created. */
- obstack_free (&class_obstack, method_vec);
- obstack_blank (&class_obstack,
- ((char *)end - (char *)method_vec) + sizeof (tree *));
- method_vec = (tree)obstack_base (&class_obstack);
- obstack_finish (&class_obstack);
- }
- TREE_VEC_ELT (method_vec, len) = decl;
- TREE_VEC_LENGTH (method_vec) = len + 1;
- CLASSTYPE_METHOD_VEC (type) = method_vec;
-
- if (CLASSTYPE_BASELINK_VEC (type))
- {
- /* ??? May be better to know whether these can be extended? */
- tree baselink_vec = copy_node (CLASSTYPE_BASELINK_VEC (type));
-
- obstack_copy (current_obstack, &TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), 1), len);
- TREE_VEC_ELT (baselink_vec, len) = 0;
- TREE_VEC_LENGTH (baselink_vec) = len + 1;
- CLASSTYPE_BASELINK_VEC (type) = baselink_vec;
- }
- }
- }
- DECL_CONTEXT (decl) = type;
- DECL_VCONTEXT (decl) = type;
-
- if (temp)
- resume_temporary_allocation ();
- }
-
- /* 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, field_ptr, fields)
- tree field, *field_ptr, fields;
- {
- tree x;
- tree prev = field_ptr ? *field_ptr : 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, field_ptr, fields);
- if (prev)
- TREE_CHAIN (prev) = 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, 0, 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)
- error_with_decl (x, "duplicate enum value `%s'");
- else if (TREE_CODE (field) == CONST_DECL
- || TREE_CODE (x) == CONST_DECL)
- error_with_decl (x, "duplicate field `%s' (as enum and non-enum)");
- else
- error_with_decl (x, "duplicate member `%s'");
- 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, &x, TREE_CHAIN (x));
- }
-
- /* Add OFFSET to all child types of T.
-
- OFFSET, which is a type offset, is number of bytes.
-
- Note that we don't have to worry about having two paths to the
- same base type, since this type owns its association list. */
- static void
- propagate_basetype_offsets (for_type, t, offset)
- tree for_type, t;
- tree offset;
- {
- int i, n_baselinks = CLASSTYPE_N_BASECLASSES (t);
-
- for (i = 1; i <= n_baselinks; i++)
- if (! CLASSTYPE_VIA_VIRTUAL (t, i))
- {
- tree basetype = CLASSTYPE_BASECLASS (t, i);
- tree assoc = assoc_value (TYPE_MAIN_VARIANT (basetype), for_type);
- if (CLASSTYPE_OFFSET (basetype) == integer_zero_node)
- basetype = build_classtype_variant (basetype, offset, 0);
- else
- basetype = build_classtype_variant (basetype,
- genop (PLUS_EXPR, CLASSTYPE_OFFSET (basetype), offset), 0);
- /* Now make our own copy of this base type we can munge. */
- basetype = copy_node (basetype);
- copy_type_lang_specific (basetype);
-
- CLASSTYPE_BASECLASS (t, i) = basetype;
- ASSOC_TYPE (assoc) = basetype;
- ASSOC_OFFSET (assoc) = CLASSTYPE_OFFSET (basetype);
- TYPE_NAME (basetype) = copy_node (TYPE_NAME (basetype));
- TREE_TYPE (TYPE_NAME (basetype)) = basetype;
- DECL_OFFSET (TYPE_NAME (basetype))
- = TREE_INT_CST_LOW (convert_units (CLASSTYPE_OFFSET (basetype), BITS_PER_UNIT, 1));
- propagate_basetype_offsets (for_type, basetype, offset);
- if (i < n_baselinks)
- {
- offset = genop (PLUS_EXPR,
- convert_units (TYPE_SIZE (basetype), TYPE_SIZE_UNIT (basetype), BITS_PER_UNIT), offset);
- }
- }
- }
-
- /* Change the visibility of T::FDECL to VISIBILITY.
- Return 1 if change was legit, otherwise return 0. */
- static int
- alter_visibility (t, fdecl, visibility)
- tree t;
- tree fdecl;
- enum visibility_type visibility;
- {
- tree elem = purpose_member (t, DECL_VISIBILITY (fdecl));
- if (elem && TREE_VALUE (elem) != (tree)visibility)
- {
- if (TREE_CODE (TREE_TYPE (fdecl)) == FUNCTION_DECL)
- {
- error_with_decl (TREE_TYPE (fdecl), "conflicting visibility specifications for method `%s', ignored");
- }
- else error ("conflicting visibility specifications for field `%s', ignored", IDENTIFIER_POINTER (DECL_NAME (fdecl)));
- }
- else if (TREE_PRIVATE (fdecl) && visibility != visibility_private)
- error_with_decl (fdecl, "cannot make private %s non-private");
- else if (TREE_PROTECTED (fdecl) && visibility == visibility_public)
-
- error_with_decl (fdecl, "cannot make protected %s public");
- else if (elem == NULL_TREE)
- {
- DECL_VISIBILITY (fdecl) = tree_cons (t, (tree)visibility,
- DECL_VISIBILITY (fdecl));
- return 1;
- }
- return 0;
- }
-
- /* 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;
- int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (type);
-
- 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);
- 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; i > 0; i--)
- {
- tree basetype = CLASSTYPE_BASECLASS (type, i);
- tree blist;
-
- /* Don't initialize virtual baseclasses this way. */
- if (TREE_VIA_VIRTUAL (basetype))
- continue;
-
- if (TYPE_HAS_CONSTRUCTOR (basetype))
- {
- base_init_list = tree_cons (NULL_TREE, basetype,
- base_init_list);
- continue;
- }
-
- blist = CLASSTYPE_BASE_INIT_LIST (basetype);
- if (blist != NULL_TREE)
- {
- /* 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)) == RECORD_TYPE
- && (DECL_OFFSET (TYPE_NAME (basetype))
- == DECL_OFFSET (TYPE_NAME (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, basetype, base_init_list);
- else
- base_init_list = CLASSTYPE_AS_LIST (basetype);
- }
- }
- }
-
- 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 needs_default_ctor;
- char cant_have_default_ctor;
- char needs_const_ctor;
- char cant_have_const_ctor;
- };
-
- /* 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.
-
- Returns the index of the first base class to have virtual functions,
- or zero if no such base class. */
-
- static int
- finish_base_struct (t, b)
- tree t;
- struct base_info *b;
- {
- int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
- int first_vfn_base_index = 0;
-
- bzero (b, sizeof (struct base_info));
-
- for (i = 1; i <= n_baseclasses; i++)
- {
- tree basetype = CLASSTYPE_BASECLASS (t, i);
-
- /* 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)
- CLASSTYPE_BASECLASS (t, i) = NULL_TREE;
- CLASSTYPE_N_BASECLASSES (t) -= 1;
- n_baseclasses -= 1;
- for (j = i; j < n_baseclasses; j++)
- {
- CLASSTYPE_BASECLASS (t, j) = CLASSTYPE_BASECLASS (t, j+1);
- SET_CLASSTYPE_VIAS (t, j,
- CLASSTYPE_VIA_PUBLIC (t, j+1),
- CLASSTYPE_VIA_VIRTUAL (t, j+1));
- }
- }
-
- if (TYPE_WRAP_TYPE (t) == NULL_TREE)
- TYPE_WRAP_TYPE (t) = TYPE_WRAP_TYPE (basetype);
- else if (TYPE_WRAP_TYPE (basetype)
- && TYPE_WRAP_TYPE (t) != TYPE_WRAP_TYPE (basetype))
- /* Must have its own. */
- TYPE_WRAP_TYPE (t) = error_mark_node;
-
- if (TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype))
- b->needs_default_ctor = 1;
- else if (TYPE_HAS_CONSTRUCTOR (basetype))
- b->cant_have_default_ctor = 1;
- if (TYPE_GETS_CONST_INIT_REF (basetype))
- b->needs_const_ctor = 1;
- else if (TYPE_GETS_INIT_REF (basetype))
- b->cant_have_const_ctor = 1;
-
- CLASSTYPE_ALTERS_VISIBILITIES_P (t)
- |= CLASSTYPE_ALTERS_VISIBILITIES_P (basetype);
-
- b->n_ancestors += CLASSTYPE_N_SUPERCLASSES (basetype);
- TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype);
- TYPE_NEEDS_CONSTRUCTOR (t) |= TYPE_NEEDS_CONSTRUCTOR (basetype);
- TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (basetype);
- TYPE_ANY_ASSIGNS_THIS (t) |= TYPE_ANY_ASSIGNS_THIS (basetype);
- TYPE_GETS_ASSIGNMENT (t) |= TYPE_GETS_ASSIGNMENT (basetype);
- TYPE_GETS_INIT_REF (t) |= TYPE_GETS_INIT_REF (basetype);
-
- TYPE_OVERLOADS_CALL_EXPR (t) |= TYPE_OVERLOADS_CALL_EXPR (basetype);
- TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype);
-
- if (CLASSTYPE_OFFSET (basetype) != integer_zero_node)
- {
- /* Completely unshare potentially shared data, and
- update what is ours. */
- tree assoc = assoc_value (TYPE_MAIN_VARIANT (basetype), t);
- basetype = copy_node (basetype);
- copy_type_lang_specific (basetype);
- CLASSTYPE_BASECLASS (t, i) = basetype;
- ASSOC_TYPE (assoc) = basetype;
-
- /* Propagate this offset through all the children. Do this
- before uniquizing baseclasses for virtual functions. */
- CLASSTYPE_ASSOC (basetype) = copy_assoc (CLASSTYPE_ASSOC (TYPE_MAIN_VARIANT (basetype)));
-
- propagate_basetype_offsets (basetype, basetype, CLASSTYPE_OFFSET (basetype));
- }
-
- if (! CLASSTYPE_VIA_VIRTUAL (t, i))
- CLASSTYPE_N_SUPERCLASSES (t) += 1;
-
- if (TYPE_VIRTUAL_P (basetype))
- {
- if (CLASSTYPE_VSIZE (basetype) > b->max_has_virtual)
- b->max_has_virtual = CLASSTYPE_VSIZE (basetype);
-
- /* Don't borrow virtuals from virtual baseclasses. */
- if (TREE_VIA_VIRTUAL (basetype))
- continue;
-
- if (first_vfn_base_index == 0)
- {
- first_vfn_base_index = i;
-
- b->has_virtual = CLASSTYPE_VSIZE (basetype);
- b->vfield = CLASSTYPE_VFIELD (basetype);
- b->vfields = CLASSTYPE_VFIELDS (basetype);
- CLASSTYPE_VFIELD (t) = b->vfield;
- }
- else
- {
- /* Only add unique vslots, and flatten them out as we go. */
- tree vslots = CLASSTYPE_VFIELDS (basetype);
- while (vslots)
- {
- if (TREE_PURPOSE (vslots) == NULL_TREE
- || ! TREE_VIA_VIRTUAL (TREE_PURPOSE (vslots)))
- {
- tree value = TREE_VALUE (vslots);
- if (TYPE_MAIN_VARIANT (basetype) == value)
- b->vfields = tree_cons (basetype, value, b->vfields);
- else
- b->vfields = tree_cons (get_base_type (value, basetype, 0),
- value, b->vfields);
- }
- vslots = TREE_CHAIN (vslots);
- }
-
- if (b->has_virtual == 0)
- {
- first_vfn_base_index = i;
- b->has_virtual = CLASSTYPE_VSIZE (basetype);
- b->vfield = CLASSTYPE_VFIELD (basetype);
- CLASSTYPE_VFIELD (t) = b->vfield;
- }
- }
- }
- }
- if (b->vfield == 0)
- /* If all virtual functions come only from virtual baseclasses. */
- return 0;
- return first_vfn_base_index;
- }
-
- /* Set memoizing fields and bits of T (and its variants) for later use.
- FIRST_VFN_BASE_INDEX is the first baseclass of T with virtual functions.
- MAX_HAS_VIRTUAL is the largest size of any T's virtual function tables. */
- static void
- finish_struct_bits (t, first_vfn_base_index, max_has_virtual)
- tree t;
- int first_vfn_base_index, 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)
- {
- TYPE_NEEDS_CONSTRUCTOR (variants) = TYPE_NEEDS_CONSTRUCTOR (t);
- TYPE_NEEDS_CONSTRUCTING (variants) = TYPE_NEEDS_CONSTRUCTING (t);
- TYPE_NEEDS_DESTRUCTOR (variants) = TYPE_NEEDS_DESTRUCTOR (t);
- variants = TYPE_NEXT_VARIANT (variants);
- }
-
- if (n_baseclasses && max_has_virtual)
- {
- /* Done by `finish_struct' for classes without baseclasses. */
- int has_abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (t) != 0;
- if (has_abstract_virtuals == 0)
- for (i = CLASSTYPE_N_BASECLASSES (t); i >= 1; i--)
- has_abstract_virtuals
- |= (CLASSTYPE_ABSTRACT_VIRTUALS (CLASSTYPE_BASECLASS (t, i)) != 0);
- if (has_abstract_virtuals)
- CLASSTYPE_ABSTRACT_VIRTUALS (t) = get_abstract_virtuals (t);
- }
-
- if (n_baseclasses)
- {
- /* Notice whether this class has type conversion functions defined.
- Also report whether joining two types yields an ambiguity in the
- virtual function table, e.g.,
-
- struct A { virtual int f (); };
- struct B { virtual int f (); };
- struct C : A, B { / * no f (); * / }; / / error, ambiguous
- */
- tree basetypes = CLASSTYPE_VBASECLASSES (t), basetype;
- int n_vbases = list_length (basetypes), j;
-
- build_mi_virtuals (n_baseclasses + (n_vbases*n_baseclasses), max_has_virtual);
- /* Fill in virutal function table with values which do not come
- "normal"ly, i.e., those which come from virtual and/or
- non-leftmost base classes. */
- for (i = n_baseclasses; basetypes; basetypes = TREE_CHAIN (basetypes))
- {
- basetype = TREE_VALUE (basetypes);
- if (CLASSTYPE_VSIZE (basetype))
- for (j = n_baseclasses; j > 0; j--)
- {
- tree this_base = CLASSTYPE_BASECLASS (t, j);
- if (get_base_distance (basetype, TYPE_MAIN_VARIANT (this_base), 0, 0) != -1)
- add_mi_virtuals (++i, TREE_CHAIN (ASSOC_VIRTUALS (basetypes)));
- }
- }
- for (i = n_baseclasses; i > 0; i--)
- {
- basetype = CLASSTYPE_BASECLASS (t, 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 (TREE_VIA_VIRTUAL (basetype))
- /* Virtual functions from virtual baseclasses are done above. */;
- else if (i == first_vfn_base_index)
- add_mi_virtuals (i, TREE_CHAIN (CLASS_ASSOC_VIRTUALS (t)));
- else if (CLASSTYPE_VSIZE (basetype) != 0)
- add_mi_virtuals (i, TREE_CHAIN (CLASS_ASSOC_VIRTUALS (basetype)));
- }
- report_ambiguous_mi_virtuals (n_baseclasses + (n_vbases*n_baseclasses), t);
-
- /* Now that we know what the virtual functiond table looks like,
- fix up offsets in the presence of virtual base classes. */
- if (n_vbases)
- fixup_vbase_offsets (t);
- }
-
- if (TYPE_HAS_CONVERSION (t))
- {
- tree first_ptr_conversion = NULL_TREE, last_ptr_conversion;
- tree first_constptr_conversion = NULL_TREE, last_constptr_conversion;
- tree *tmp = &TREE_VEC_ELT (method_vec, 1);
- int need_int = ! TYPE_HAS_INT_CONVERSION (t);
- int need_real = ! TYPE_HAS_REAL_CONVERSION (t);
-
- while (tmp != TREE_VEC_END (method_vec))
- {
- if (OPERATOR_TYPENAME_P (DECL_ORIGINAL_NAME (*tmp)))
- {
- tree fntype = TREE_TYPE (*tmp);
- tree return_type = TREE_TYPE (fntype);
- assert (TREE_CODE (fntype) == METHOD_TYPE);
-
- if (TREE_CODE (return_type) == POINTER_TYPE
- || (TREE_CODE (return_type) == REFERENCE_TYPE
- && TREE_CODE (TREE_TYPE (return_type)) == POINTER_TYPE))
- {
- if (TREE_READONLY (TREE_TYPE (return_type)))
- {
- if (first_constptr_conversion == NULL_TREE)
- first_constptr_conversion = *tmp;
- last_constptr_conversion = *tmp;
- }
- else
- {
- if (first_ptr_conversion == NULL_TREE)
- first_ptr_conversion = *tmp;
- last_ptr_conversion = *tmp;
- }
- }
- else if (need_int
- && (TREE_CODE (return_type) == INTEGER_TYPE
- || (TREE_CODE (return_type) == REFERENCE_TYPE
- && TREE_CODE (TREE_TYPE (return_type)) == INTEGER_TYPE)))
- {
- TYPE_HAS_INT_CONVERSION (t) = 1;
- need_int = 0;
- if (need_real == 0)
- break;
- }
- else if (need_real
- && (TREE_CODE (return_type) == REAL_TYPE
- || (TREE_CODE (return_type) == REFERENCE_TYPE
- && TREE_CODE (TREE_TYPE (return_type)) == REAL_TYPE)))
- {
- TYPE_HAS_REAL_CONVERSION (t) = 1;
- need_real = 0;
- if (need_int == 0)
- break;
- }
- }
- tmp++;
- }
- if (first_ptr_conversion)
- {
- if (first_ptr_conversion != last_ptr_conversion)
- CLASSTYPE_PTR_CONVERSION (t) = error_mark_node;
- else
- CLASSTYPE_PTR_CONVERSION (t) = first_ptr_conversion;
- }
- else
- CLASSTYPE_PTR_CONVERSION (t) = NULL_TREE;
- if (first_constptr_conversion)
- {
- if (first_constptr_conversion != last_constptr_conversion)
- CLASSTYPE_CONSTPTR_CONVERSION (t) = error_mark_node;
- else
- CLASSTYPE_CONSTPTR_CONVERSION (t) = first_constptr_conversion;
- }
- else
- CLASSTYPE_CONSTPTR_CONVERSION (t) = NULL_TREE;
- }
-
- /* 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);
- }
- }
- }
-
- /* 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_OFFSET
- 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 visibility
- the list has, and the TREE_VALUE slot gives the actual fields.
-
- EMPTY is non-zero if this structure has no declarations following it.
-
- 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 funcitions |
- | | | (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-consistant manner. */
-
- tree
- finish_struct (t, list_of_fieldlists, empty, warn_anon)
- tree t;
- tree list_of_fieldlists;
- int empty;
- int warn_anon;
- {
- int old;
- int round_up_size = 1;
- /* Set non-zero to debug using default functions.
- Not set by program. */
- static int debug_default_functions = 0;
-
- enum tree_code code = TREE_CODE (t);
- register tree x, y, method_vec;
- int needs_ctor = 0, needs_dtor = 0;
- int members_need_dtors = 0;
- tree name = TYPE_NAME (t), fields, fn_fields, tail;
- enum visibility_type visibility;
- 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 needs_default_ctor;
- int cant_have_default_ctor;
- int needs_const_ctor;
- int cant_have_const_ctor;
-
- /* The index of the first base class which has virtual
- functions. Only applied to non-virtual baseclasses. */
- int first_vfn_base_index;
-
- int i, n_baseclasses;
- int any_default_members = 0;
- char *err_name;
- int const_sans_init = 0;
- int ref_sans_init = 0;
- int nonprivate_method = 0;
-
- if (TREE_CODE (name) == TYPE_DECL)
- name = DECL_NAME (name);
- err_name = IDENTIFIER_POINTER (name);
-
- if (warn_anon && code != UNION_TYPE && ANON_AGGRNAME_P (name))
- {
- warning ("un-usable class ignored (anonymous classes and unions are useless)");
- err_name = "(anon)";
- }
-
- leftmost_baseclasses = NULL_TREE;
- if (TYPE_SIZE (t))
- {
- if (TREE_CODE (t) == UNION_TYPE)
- error ("redefinition of `union %s'", err_name);
- else if (TREE_CODE (t) == RECORD_TYPE)
- error ("redefinition of `struct %s'", err_name);
- else
- assert (0);
- popclass (0);
- return t;
- }
-
- /* If this type was previously laid out as a forward reference,
- make sure we lay it out again. */
-
- TYPE_SIZE (t) = 0;
- CLASSTYPE_GOT_SEMICOLON (t) = 0;
-
- old = suspend_momentary ();
-
- /* Install struct as DECL_FIELD_CONTEXT of each field decl.
- Also process specified field sizes.
- Set DECL_SIZE_UNIT 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). */
-
- n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
- if (n_baseclasses >= 1)
- {
- 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);
- y = tree_last (fields);
-
- first_vfn_base_index = finish_base_struct (t, &base_info);
- 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;
- needs_default_ctor = base_info.needs_default_ctor;
- cant_have_default_ctor = base_info.cant_have_default_ctor;
- needs_const_ctor = base_info.needs_const_ctor;
- cant_have_const_ctor = base_info.cant_have_const_ctor;
- n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
- }
- else
- {
- first_vfn_base_index = 0;
- has_virtual = 0;
- max_has_virtual = 0;
- vfield = NULL_TREE;
- vfields = NULL_TREE;
- fields = NULL_TREE;
- y = NULL_TREE;
- needs_default_ctor = 0;
- cant_have_default_ctor = 0;
- needs_const_ctor = 0;
- cant_have_const_ctor = 0;
- }
-
- /* The three of these are approximations which may later be
- modified. Needed at this point to make add_virtual_function
- and modify_vtable_entries work. */
- CLASSTYPE_ASSOC (t) = make_assoc (integer_zero_node, t,
- 0, 0, CLASSTYPE_ASSOC (t));
- CLASSTYPE_VFIELDS (t) = vfields;
- CLASSTYPE_VFIELD (t) = vfield;
-
- fn_fields = NULL_TREE;
- tail = NULL_TREE;
- if (y && list_of_fieldlists)
- TREE_CHAIN (y) = TREE_VALUE (list_of_fieldlists);
-
- #ifdef SOS
- if (flag_all_virtual == 2)
- all_virtual = 2;
- else
- #endif
- {
- if (flag_all_virtual == 1 && TYPE_OVERLOADS_METHOD_CALL_EXPR (t))
- all_virtual = 1;
- else
- all_virtual = 0;
- }
-
- if (CLASSTYPE_DECLARED_CLASS (t) == 0)
- {
- nonprivate_method = 1;
- if (list_of_fieldlists
- && TREE_PURPOSE (list_of_fieldlists) == (tree)visibility_default)
- TREE_PURPOSE (list_of_fieldlists) = (tree)visibility_public;
- }
- else if (list_of_fieldlists
- && TREE_PURPOSE (list_of_fieldlists) == (tree)visibility_default)
- TREE_PURPOSE (list_of_fieldlists) = (tree)visibility_private;
-
- while (list_of_fieldlists)
- {
- visibility = (enum visibility_type)TREE_PURPOSE (list_of_fieldlists);
-
- for (x = TREE_VALUE (list_of_fieldlists); x; x = TREE_CHAIN (x))
- {
- TREE_PRIVATE (x) = visibility == visibility_private;
- TREE_PROTECTED (x) = visibility == visibility_protected;
- if (TREE_CODE (x) == FUNCTION_DECL)
- {
- /* Clear out this flag.
-
- @@ Doug may figure out how to break
- @@ this with nested classes and friends. */
- DECL_IN_AGGR_P (x) = 0;
-
- nonprivate_method |= ! TREE_PRIVATE (x);
-
- /* If this was an evil function, don't keep it in class. */
- if (IDENTIFIER_ERROR_LOCUS (DECL_NAME (x)))
- continue;
-
- if (y) TREE_CHAIN (y) = TREE_CHAIN (x);
- if (! fn_fields) fn_fields = x;
- else TREE_CHAIN (tail) = x;
- tail = x;
- if (DECL_CONTEXT (x))
- continue;
-
- DECL_CONTEXT (x) = t;
- DECL_VCONTEXT (x) = t;
-
- DECL_SIZE_UNIT (x) = 0;
-
- /* The name of the field is the original field name
- Save this in auxiliary field for later overloading. */
- if (DECL_VIRTUAL_P (x)
- || (all_virtual == 1 && ! DECL_CONSTRUCTOR_P (x)))
- {
- pending_virtuals = add_virtual_function (pending_virtuals,
- &has_virtual, x,
- first_vfn_base_index);
- if (DECL_ABSTRACT_VIRTUAL_P (x))
- abstract_virtuals = tree_cons (NULL_TREE, x, abstract_virtuals);
- }
- continue;
- }
-
- /* Handle visibility declarations. */
- if (DECL_NAME (x) && TREE_CODE (DECL_NAME (x)) == SCOPE_REF)
- {
- tree fdecl = TREE_OPERAND (DECL_NAME (x), 1);
-
- if (y) TREE_CHAIN (y) = TREE_CHAIN (x);
- /* Make type T see field decl FDECL with
- the visibility VISIBILITY. */
- if (TREE_CODE (fdecl) == TREE_LIST)
- {
- fdecl = TREE_VALUE (fdecl);
- while (fdecl)
- {
- if (alter_visibility (t, fdecl, visibility) == 0)
- break;
- fdecl = TREE_CHAIN (fdecl);
- }
- }
- else alter_visibility (t, fdecl, visibility);
- CLASSTYPE_ALTERS_VISIBILITIES_P (t) = 1;
- continue;
- }
-
- /* Perform error checking that did not get done in grokdeclarator. */
- if (TREE_CODE (TREE_TYPE (x)) == FUNCTION_TYPE)
- {
- error_with_decl (x, "field `%s' invalidly declared function type");
- TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x));
- }
- else if (TREE_CODE (TREE_TYPE (x)) == METHOD_TYPE)
- {
- error_with_decl (x, "field `%s' invalidly declared method type");
- TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x));
- }
- else if (TREE_CODE (TREE_TYPE (x)) == OFFSET_TYPE)
- {
- error_with_decl (x, "field `%s' invalidly declared offset type");
- TREE_TYPE (x) = build_pointer_type (TREE_TYPE (x));
- }
- /* If this is of reference type, check if it needs an init. */
- if (TREE_CODE (TREE_TYPE (x)) == REFERENCE_TYPE
- && DECL_INITIAL (x) == 0)
- ref_sans_init = 1;
-
- /* When this goes into scope, it will be a non-local reference. */
- TREE_NONLOCAL (x) = 1;
-
- if (TREE_CODE (x) == FIELD_DECL)
- {
- /* Never let anything with uninheritable virutals
- make it through without complaint. */
- if (TYPE_LANG_SPECIFIC (TREE_TYPE (x))
- && CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (x)))
- abstract_virtuals_error (x, TREE_TYPE (x));
-
- if (TYPE_LANG_SPECIFIC (TREE_TYPE (x)))
- {
- if (TYPE_HAS_DEFAULT_CONSTRUCTOR (TREE_TYPE (x)))
- needs_default_ctor = 1;
- if (TYPE_GETS_CONST_INIT_REF (TREE_TYPE (x)))
- needs_const_ctor = 1;
- else if (TYPE_GETS_INIT_REF (TREE_TYPE (x)))
- cant_have_const_ctor = 1;
- }
- else if (DECL_INITIAL (x) == NULL_TREE
- && (TYPE_HAS_CONSTRUCTOR (TREE_TYPE (x))
- || TREE_CODE (TREE_TYPE (x)) == REFERENCE_TYPE))
- cant_have_default_ctor = 1;
-
- /* If any field is const, the structure type is pseudo-const. */
- if (TREE_READONLY (x))
- {
- C_TYPE_FIELDS_READONLY (t) = 1;
- if (DECL_INITIAL (x) == 0)
- const_sans_init = 1;
- }
- 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;
- }
- }
- }
- else if (TREE_STATIC (x) && TREE_CODE (t) == UNION_TYPE)
- /* Unions cannot have static members. */
- error_with_decl (x, "field `%s' declared static in union");
-
- if (! fields) fields = x;
- DECL_FIELD_CONTEXT (x) = t;
- DECL_SIZE_UNIT (x) = 0;
-
- if (TREE_PACKED (x))
- {
- /* Invalid bit-field size done by grokfield. */
- /* Detect invalid bit-field type. */
- if (DECL_INITIAL (x)
- && TREE_CODE (TREE_TYPE (x)) != INTEGER_TYPE
- && TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE)
- {
- error_with_decl (x, "bit-field `%s' has invalid type");
- DECL_INITIAL (x) = NULL;
- }
- if (DECL_INITIAL (x) && pedantic
- && TREE_TYPE (x) != integer_type_node
- && TREE_TYPE (x) != unsigned_type_node)
- warning_with_decl (x, "bit-field `%s' type invalid in ANSI C");
-
- /* 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;
- warning_with_decl (x, "negative width in bit-field `%s'");
- }
- else if (width == 0 && DECL_NAME (x) != 0)
- {
- error_with_decl (x, "zero width for bit-field `%s'");
- DECL_INITIAL (x) = NULL;
- }
- else if (width > TYPE_PRECISION (TREE_TYPE (x)))
- {
- DECL_INITIAL (x) = NULL;
- warning_with_decl (x, "width of `%s' exceeds its type");
- }
- }
-
- /* Process valid field width. */
- if (DECL_INITIAL (x))
- {
- register int width = TREE_INT_CST_LOW (DECL_INITIAL (x));
-
- if (width == 0)
- {
- /* 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;
- }
- else
- {
- DECL_INITIAL (x) = NULL_TREE;
- DECL_SIZE_UNIT (x) = width;
- TREE_PACKED (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 if (TREE_CODE (x) == FIELD_DECL)
- {
- tree type = TREE_TYPE (x);
- if (TREE_CODE (type) == ARRAY_TYPE)
- type = TREE_TYPE (type);
- if (code == UNION_TYPE)
- {
- if (TYPE_NEEDS_CONSTRUCTING (type))
- error ("member %s::%s with constructor not allowed in union",
- IDENTIFIER_POINTER (name), IDENTIFIER_POINTER (DECL_NAME (x)));
- if (TYPE_NEEDS_DESTRUCTOR (type))
- error ("member %s::%s with destructor (also) not allowed in union",
- IDENTIFIER_POINTER (name), IDENTIFIER_POINTER (DECL_NAME (x)));
- }
- else if (code == RECORD_TYPE)
- {
- /* Array of record type doesn't matter for this bit. */
- TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (type);
- if (IS_AGGR_TYPE (type))
- {
- needs_ctor |= TYPE_NEEDS_CONSTRUCTOR (type);
- needs_dtor |= TYPE_NEEDS_DESTRUCTOR (type);
- members_need_dtors |= TYPE_NEEDS_DESTRUCTOR (type);
- TYPE_GETS_ASSIGNMENT (t) |= TYPE_GETS_ASSIGNMENT (type);
- }
- }
- if (DECL_INITIAL (x) != NULL_TREE)
- {
- /* `build_class_init_list' does not recognize non-FIELD_DECLs. */
- if (code == UNION_TYPE && any_default_members != 0)
- error ("multiple fields in union initialized");
- any_default_members = 1;
- }
- }
- y = x;
- }
- list_of_fieldlists = TREE_CHAIN (list_of_fieldlists);
- /* link the tail while we have it! */
- if (y)
- {
- TREE_CHAIN (y) = NULL_TREE;
-
- if (list_of_fieldlists
- && TREE_VALUE (list_of_fieldlists)
- && TREE_CODE (TREE_VALUE (list_of_fieldlists)) != FUNCTION_DECL)
- TREE_CHAIN (y) = TREE_VALUE (list_of_fieldlists);
- }
- }
-
- if (tail) TREE_CHAIN (tail) = NULL_TREE;
-
- /* 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;
-
- if (fields == 0 && n_baseclasses == 0
- && (pedantic || extra_warnings))
- warning ((code == UNION_TYPE ? "union has no data members"
- : "structure has no data members"));
-
- if (vfield == 0
- && (has_virtual
- #ifdef SOS
- || TYPE_DYNAMIC (t)
- #endif
- ))
- {
- /* We build this decl with ptr_type_node, and
- change the type when we know what it should be. */
- vfield = build_decl (FIELD_DECL, get_vfield_name (t), ptr_type_node);
- CLASSTYPE_VFIELD (t) = vfield;
- DECL_FIELD_CONTEXT (vfield) = t;
- SET_DECL_FCONTEXT (vfield, t);
- DECL_SIZE_UNIT (vfield) = 0;
- if (y)
- {
- assert (TREE_CHAIN (y) == 0);
- TREE_CHAIN (y) = vfield;
- y = 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 && TREE_PACKED (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) && TREE_PACKED (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);
-
- /* 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;
-
- if (debug_default_functions)
- {
- if ((TYPE_NEEDS_CONSTRUCTOR (t) || TYPE_HAS_CONSTRUCTOR (t) || needs_ctor)
- && ! TYPE_HAS_INIT_REF (t))
- {
- tree default_fn = cons_up_default_function (t, name, 1);
- TREE_CHAIN (default_fn) = fn_fields;
- DECL_CONTEXT (default_fn) = t;
- DECL_VCONTEXT (default_fn) = t;
- fn_fields = default_fn;
- TYPE_HAS_INIT_REF (t) = 1;
- default_fn = cons_up_default_function (t, name, 3);
- TREE_CHAIN (default_fn) = fn_fields;
- DECL_CONTEXT (default_fn) = t;
- DECL_VCONTEXT (default_fn) = t;
- fn_fields = default_fn;
- nonprivate_method = 1;
- }
-
- if (! TYPE_HAS_DEFAULT_CONSTRUCTOR (t)
- && needs_default_ctor && ! cant_have_default_ctor)
- {
- tree default_fn = cons_up_default_function (t, name, 2);
- TREE_CHAIN (default_fn) = fn_fields;
- DECL_CONTEXT (default_fn) = t;
- DECL_VCONTEXT (default_fn) = t;
- fn_fields = default_fn;
- TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 1;
- nonprivate_method = 1;
- }
- }
- /* 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 quicky 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. */
-
- if (fn_fields)
- {
- /* 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;
-
- nextp = TREE_CHAIN (fn_fields);
- TREE_CHAIN (fn_fields) = NULL_TREE;
- /* Constrcutors are handled easily in search routines.
- Besides, we know we wont find any, so do not bother looking. */
- if (DECL_ORIGINAL_NAME (fn_fields) == name
- && TREE_VEC_ELT (method_vec, 0) == 0)
- TREE_VEC_ELT (method_vec, 0) = fn_fields;
- else
- {
- testp = &TREE_VEC_ELT (method_vec, 0);
- if (*testp == NULL_TREE)
- testp++;
- while ((int)testp < (int)obstack_next_free (&class_obstack)
- && DECL_ORIGINAL_NAME (*testp) != DECL_ORIGINAL_NAME (fn_fields))
- testp++;
- if ((int)testp < (int)obstack_next_free (&class_obstack))
- {
- for (x = *testp; x; x = TREE_CHAIN (x))
- {
- if (DECL_NAME (fn_fields) == DECL_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_NAME (fn_fields)))
- error_with_file_and_line (DECL_SOURCE_FILE (fn_fields),
- DECL_SOURCE_LINE (fn_fields),
- "ambiguous method `%s' in structure",
- lang_printable_name (fn_fields));
- break;
- }
- y = x;
- }
- if (x == 0)
- if (*testp)
- TREE_CHAIN (y) = 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)
- {
- for (i = 0; i <= n_baseclasses; i++)
- if (CLASSTYPE_VIA_PUBLIC (t, i))
- {
- nonprivate_method = 1;
- break;
- }
- if (nonprivate_method == 0)
- warning ("all class member functions are private");
- }
- }
- else
- {
- method_vec = 0;
-
- /* Just in case these got accidently
- filled in by syntax errors. */
- TYPE_HAS_CONSTRUCTOR (t) = 0;
- TYPE_HAS_DESTRUCTOR (t) = 0;
- }
-
- /* 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 = TREE_CHAIN (dtor))
- {
- if (DESTRUCTOR_NAME_P (DECL_NAME (dtor)))
- {
- if (TREE_PRIVATE (dtor)
- && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE
- && DECL_FRIENDLIST (TYPE_NAME (t)) == NULL_TREE)
- warning_with_decl (TYPE_NAME (t), "class `%s' only defines a private destructor and has no friends");
- 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))
- {
- TREE_CHAIN (prev) = TREE_CHAIN (dtor);
- TREE_CHAIN (dtor) = TREE_VEC_ELT (method_vec, 0);
- TREE_VEC_ELT (method_vec, 0) = dtor;
- }
- }
- else if (members_need_dtors
- || (TYPE_USES_VIRTUAL_BASECLASSES (t)
- || TYPE_USES_MULTIPLE_INHERITANCE (t)))
- {
- /* Here we must cons up a destructor on the fly. */
- tree dtor = cons_up_default_function (t, name, 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
- {
- DECL_CONTEXT (dtor) = t;
- DECL_VCONTEXT (dtor) = t;
- if (DECL_VIRTUAL_P (dtor))
- pending_virtuals = add_virtual_function (pending_virtuals,
- &has_virtual, dtor);
- if (TYPE_HAS_CONSTRUCTOR (t))
- TREE_CHAIN (dtor) = TREE_VEC_ELT (method_vec, 0);
- else if (method_vec == 0)
- {
- /* 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;
- TREE_VEC_LENGTH (method_vec) = 1;
- CLASSTYPE_METHOD_VEC (t) = method_vec;
- }
- TREE_VEC_ELT (method_vec, 0) = dtor;
- TYPE_HAS_DESTRUCTOR (t) = 1;
- }
- }
- 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 = TREE_CHAIN (ctor))
- if (! TREE_PRIVATE (ctor))
- {
- nonprivate_ctor = 1;
- break;
- }
- if (nonprivate_ctor == 0)
- warning ("class %s only defines private constructors and has no friends",
- TYPE_NAME_STRING (t));
- }
-
- /* Now for each member function (except for constructors and
- destructors), compute where member functions of the same
- name reside in base classes. */
- if (n_baseclasses != 0
- && method_vec != NULL_TREE
- && TREE_VEC_LENGTH (method_vec) > 1)
- {
- int len = TREE_VEC_LENGTH (method_vec);
- tree baselink_vec = make_tree_vec (len);
- int any_links = 0;
-
- for (i = 1; i < len; i++)
- {
- TREE_VEC_ELT (baselink_vec, i)
- = get_baselinks (t, DECL_ORIGINAL_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);
- }
-
- /* We can't know this information until we have seen all of the
- constructors. */
- TYPE_NONE_ASSIGN_THIS (t) = 0;
-
- /* Pass layout information about base classes to layout_type, if any. */
-
- 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_SIZE_UNIT (pseudo_basetype) = TYPE_SIZE_UNIT (t);
- TYPE_MODE (pseudo_basetype) = TYPE_MODE (t);
- TYPE_ALIGN (pseudo_basetype) = CLASSTYPE_ALIGN (t);
- DECL_ALIGN (base_layout_decl) = TYPE_ALIGN (pseudo_basetype);
- }
-
- layout_type (t);
-
- 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));
-
- 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);
-
- /* Now fix up any virtual base class types that we
- left lying around. We must get these done
- before we try to lay out the virtual function table. */
- pending_hard_virtuals = nreverse (pending_hard_virtuals);
- #if 1
- /* This loop makes all the entries in the virtual function tables
- of interest contain the "latest" version of the functions
- we have defined. */
-
- while (vbases)
- {
- tree virtuals = ASSOC_VIRTUALS (vbases);
-
- if (virtuals)
- virtuals = TREE_CHAIN (virtuals);
-
- while (virtuals != NULL_TREE)
- {
- tree pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals));
- tree base_fndecl = TREE_OPERAND (pfn, 0);
- tree decl = get_first_matching_virtual (t, base_fndecl, 0);
- tree context = DECL_CONTEXT (decl);
- if (decl != base_fndecl && context != t)
- {
- tree assoc = NULL_TREE, these_virtuals;
- int i = TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl)) & ((1<<(BITS_PER_WORD-1))-1);
-
- if (TYPE_USES_VIRTUAL_BASECLASSES (context))
- assoc = value_member (DECL_CONTEXT (base_fndecl),
- CLASSTYPE_VBASECLASSES (context));
- if (assoc == NULL_TREE)
- assoc = assoc_value (DECL_CONTEXT (base_fndecl), context);
- if (assoc != NULL_TREE)
- {
- these_virtuals = ASSOC_VIRTUALS (assoc);
-
- while (i-- > 0)
- these_virtuals = TREE_CHAIN (these_virtuals);
- pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (these_virtuals));
- modify_vtable_entries (t, decl, base_fndecl, pfn);
- }
- }
- virtuals = TREE_CHAIN (virtuals);
- }
- vbases = TREE_CHAIN (vbases);
- }
- #endif /* 1 */
- while (pending_hard_virtuals)
- {
- /* Need an entry in some other virtual function table. */
- tree base_fndecls = DECL_VINDEX (TREE_PURPOSE (pending_hard_virtuals));
- while (base_fndecls)
- {
- modify_vtable_entries (t, TREE_PURPOSE (pending_hard_virtuals),
- TREE_VALUE (base_fndecls),
- TREE_VALUE (pending_hard_virtuals));
- base_fndecls = TREE_CHAIN (base_fndecls);
- }
- pending_hard_virtuals = TREE_CHAIN (pending_hard_virtuals);
- }
- }
- else
- CLASSTYPE_VBASE_SIZE (t) = integer_zero_node;
-
- if (pending_virtuals)
- {
- pending_virtuals = nreverse (pending_virtuals);
- /* We must enter these virtuals into the table. */
- if (first_vfn_base_index == 0)
- {
- pending_virtuals = tree_cons (NULL_TREE, the_null_vtable_entry,
- pending_virtuals);
- build_vtable (0, t);
- }
- else
- {
- /* Here we know enough to change the type of our virtual
- function table, but we will wait until later this function. */
- if (! CLASSTYPE_MARKED4 (t))
- build_vtable (assoc_value (TYPE_MAIN_VARIANT (CLASSTYPE_BASECLASS (t, first_vfn_base_index)), t), t);
- }
-
- /* If this type has basetypes with constructors, then those
- constructors might clobber the virtual function table. But
- they don't if the derived class shares the exact vtable of the base
- class. */
-
- CLASSTYPE_NEEDS_VIRTUAL_REINIT (t) = 1;
- }
- else if (first_vfn_base_index)
- {
- tree basetype = get_base_type (DECL_FIELD_CONTEXT (vfield), t, 0);
- tree assoc;
-
- if (TREE_VIA_VIRTUAL (basetype))
- assoc = value_member (DECL_FIELD_CONTEXT (vfield), CLASSTYPE_VBASECLASSES (t));
- else
- assoc = assoc_value (TYPE_MAIN_VARIANT (basetype), t);
-
- /* 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. */
-
- #ifdef SOS
- /* Don't define this ahead of time if we have more
- fields to add later. */
- if (all_virtual == 2 && fn_fields != NULL_TREE)
- ;
- else
- #endif
- {
- /* See if we should steal the virtual info from base class. */
- if (CLASS_ASSOC_VTABLE (t) == NULL_TREE)
- CLASS_ASSOC_VTABLE (t) = ASSOC_VTABLE (assoc);
- if (CLASS_ASSOC_VIRTUALS (t) == NULL_TREE)
- CLASS_ASSOC_VIRTUALS (t) = ASSOC_VIRTUALS (assoc);
- }
- if (CLASS_ASSOC_VTABLE (t) != ASSOC_VTABLE (assoc))
- 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)
- {
- #ifdef VTABLE_USES_MASK
- if (max_has_virtual >= VINDEX_MAX)
- {
- error ("too many virtual functions for class `%s' (VINDEX_MAX < %d)", TYPE_NAME_STRING (t), has_virtual);
- }
- #endif
- TYPE_VIRTUAL_P (t) = 1;
- CLASSTYPE_VSIZE (t) = has_virtual;
- if (first_vfn_base_index)
- {
- if (pending_virtuals)
- CLASS_ASSOC_VIRTUALS (t) = chainon (CLASS_ASSOC_VIRTUALS (t),
- pending_virtuals);
- }
- else if (has_virtual)
- {
- CLASS_ASSOC_VIRTUALS (t) = pending_virtuals;
- if (write_virtuals >= 0)
- DECL_VIRTUAL_P (CLASS_ASSOC_VTABLE (t)) = 1;
- }
- }
-
- #ifdef SOS
- if (all_virtual == 2 && (max_has_virtual || method_vec))
- {
- /* Now that we know the size of the virtual table, lay out
- the absolute table following it. */
- int i;
- tree tmp;
- tree pending_absolutes = NULL_TREE;
- int has_absolute = has_virtual;
-
- /* Local variables for building a table filled with strings
- containing the names of interesting things. */
- tree decl, init;
- tree start = NULL_TREE, next = NULL_TREE;
- tree *outer = &TREE_VEC_ELT (method_vec, 0);
-
- while (outer != TREE_VEC_END (method_vec))
- {
- tree inner;
- for (inner = *outer; inner; inner = TREE_CHAIN (inner))
- {
- tree entry;
- tree fn;
-
- /* Don't bother with functions which appear
- for visibility reasons. */
- if (DECL_FIELD_CONTEXT (inner) != t)
- continue;
-
- /* Must lay this function into its absolute table as well.
- This forces an inline function to be written out. */
- fn = build1 (ADDR_EXPR, ptr_type_node, inner);
- TREE_LITERAL (fn) = 1;
- DECL_DINDEX (inner) = build_int_2 (++has_absolute, 0);
- entry = build_vtable_entry (integer_zero_node, fn);
- pending_absolutes = tree_cons (DECL_DINDEX (inner), entry,
- pending_absolutes);
- }
- outer++;
- }
-
- CLASS_ASSOC_VIRTUALS (t) = chainon (CLASS_ASSOC_VIRTUALS (t),
- nreverse (pending_absolutes));
- if (TYPE_DYNAMIC (t))
- {
- for (outer = &TREE_VEC_ELT (method_vec, 0);
- outer != TREE_VEC_END (method_vec);
- outer++)
- {
- tree inner;
- for (inner = *outer; inner; inner = TREE_CHAIN (inner))
- {
- tree str = make_node (STRING_CST);
- TREE_STRING_LENGTH (str) = IDENTIFIER_LENGTH (DECL_NAME (inner));
- TREE_STRING_POINTER (str) = IDENTIFIER_POINTER (DECL_NAME (inner));
- TREE_LITERAL (str) = 1;
- TREE_STATIC (str) = 1;
- TREE_TYPE (str)
- = build_cplus_array_type (char_type_node,
- build_index_type (build_int_2 (TREE_STRING_LENGTH (str) - 1, 0)));
-
- if (start)
- {
- TREE_CHAIN (next) = build_tree_list (NULL_TREE, str);
- next = TREE_CHAIN (next);
- }
- else
- {
- start = build_tree_list (NULL_TREE, str);
- next = start;
- }
- }
- }
-
- /* Lay out dynamic link table for SOS. */
-
- decl = finish_table (get_linktable_name (t),
- string_type_node, start, 0);
- }
- has_virtual = has_absolute;
- CLASSTYPE_VSIZE (t) = has_virtual;
- if (has_virtual > max_has_virtual)
- max_has_virtual = has_virtual;
- if (vfield == 0)
- {
- /* We build this decl with ptr_type_node, and
- change the type when we know what it should be. */
- vfield = build_decl (FIELD_DECL, get_vfield_name (t), ptr_type_node);
- CLASSTYPE_VFIELD (t) = vfield;
- DECL_FIELD_CONTEXT (vfield) = t;
- SET_DECL_FCONTEXT (vfield, t);
- DECL_SIZE_UNIT (vfield) = 0;
- y = tree_last (fields);
- if (y)
- TREE_CHAIN (y) = vfield;
- else
- fields = vfield;
- vfields = chainon (vfields, CLASSTYPE_AS_LIST (t));
- }
- }
- #endif
-
- /* 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. */
- itype = build_index_type (build_int_2 (has_virtual, 0));
- 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 (build_int_2 (has_virtual, 0));
- atype = build_array_type (vtable_entry_type, itype);
- layout_type (atype);
- vfield = copy_node (vfield);
- TREE_TYPE (vfield) = build_pointer_type (atype);
- #if 0
- /* In the case of single inheritance, we can
- just move up the tree, since we share the
- same vptr slot. */
- if (TREE_CHAIN (vfields) == NULL_TREE)
- vfields = CLASSTYPE_AS_LIST (t);
- #endif
- }
- }
-
- CLASSTYPE_VFIELD (t) = vfield;
- if (TREE_TYPE (CLASS_ASSOC_VTABLE (t)) != atype)
- {
- TREE_TYPE (CLASS_ASSOC_VTABLE (t)) = atype;
- layout_decl (CLASS_ASSOC_VTABLE (t));
- DECL_ALIGN (CLASS_ASSOC_VTABLE (t))
- = MAX (TYPE_ALIGN (double_type_node),
- DECL_ALIGN (CLASS_ASSOC_VTABLE (t)));
- }
- }
- else if (first_vfn_base_index)
- CLASSTYPE_VFIELD (t) = vfield;
- CLASSTYPE_VFIELDS (t) = vfields;
-
- /* Set all appropriate CLASSTYPE_... flags for this type
- and its variants. */
- TYPE_NEEDS_CONSTRUCTOR (t) |= needs_ctor || TYPE_HAS_CONSTRUCTOR (t);
- TYPE_NEEDS_CONSTRUCTING (t)
- |= ((TYPE_NEEDS_CONSTRUCTOR (t)|TYPE_USES_VIRTUAL_BASECLASSES (t))
- || (has_virtual | first_vfn_base_index)
- || any_default_members);
- TYPE_NEEDS_DESTRUCTOR (t) |= needs_dtor || TYPE_HAS_DESTRUCTOR (t);
- finish_struct_bits (t, first_vfn_base_index, max_has_virtual);
-
- /* Promote each bit-field's type to int if it is narrower than that.
- Also warn (or error) if static members are specified for a class
- which takes a constructor. */
- for (x = fields; x; x = TREE_CHAIN (x))
- {
- if (TREE_PACKED (x)
- && TREE_CODE (TREE_TYPE (x)) == INTEGER_TYPE
- && (TREE_INT_CST_LOW (DECL_SIZE (x)) * DECL_SIZE_UNIT (x)
- < TYPE_PRECISION (integer_type_node)))
- TREE_TYPE (x) = integer_type_node;
- }
-
- if ((! TYPE_HAS_CONSTRUCTOR (t) && TYPE_NEEDS_CONSTRUCTING (t))
- || any_default_members != 0)
- build_class_init_list (t);
-
- if (current_lang_name == lang_name_cplusplus)
- {
- if (! CLASSTYPE_DECLARED_EXCEPTION (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)
- {
- TYPE_NONCOPIED_PARTS (t) = build_tree_list (default_conversion (CLASS_ASSOC_VTABLE (t)), vfield);
-
- if (! flag_this_is_variable)
- {
- tree vtbl_ptr = build_decl (VAR_DECL, get_identifier (VPTR_NAME),
- TREE_TYPE (vfield));
- TREE_REGDECL (vtbl_ptr) = 1;
- CLASSTYPE_VTBL_PTR (t) = vtbl_ptr;
- }
- if (DECL_FIELD_CONTEXT (vfield) != t)
- {
- tree assoc = assoc_value (DECL_FIELD_CONTEXT (vfield), t);
- tree offset = ASSOC_OFFSET (assoc);
-
- vfield = copy_node (vfield);
-
- if (! integer_zerop (offset))
- offset = convert_units (offset, BITS_PER_UNIT, 1);
- if (DECL_OFFSET (vfield))
- offset = genop (PLUS_EXPR, offset, build_int (DECL_OFFSET (vfield)));
- DECL_FIELD_CONTEXT (vfield) = t;
- DECL_OFFSET (vfield) = TREE_INT_CST_LOW (offset);
- CLASSTYPE_VFIELD (t) = vfield;
- }
- }
-
- /* Make the rtl for any new vtables we have created, and unmark
- the base types we marked. */
- unmark_finished_struct (t);
-
- /* Now out of this class's scope. However, if this class defined
- any new typedefs, then we must export those to the outer
- binding level. This is unpleasant. */
- x = gettags ();
-
- popclass (0);
-
- #if 0
- /* Remove aggregate types from the list of tags,
- since these appear at global scope. */
- while (x && IS_AGGR_TYPE (TREE_VALUE (x)))
- x = TREE_CHAIN (x);
- CLASSTYPE_TAGS (t) = x;
- y = x;
- while (x)
- {
- if (IS_AGGR_TYPE (TREE_VALUE (x)))
- TREE_CHAIN (y) = TREE_CHAIN (x);
- x = TREE_CHAIN (x);
- }
- #endif
-
- hack_incomplete_structures (t);
-
- resume_momentary (old);
-
- 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. */
- int
- resolves_to_fixed_type_p (instance)
- tree instance;
- {
- switch (TREE_CODE (instance))
- {
- case ADDR_EXPR:
- return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0));
-
- case COMPONENT_REF:
- /* Don't let pointers to members look like they hold a fixed type. */
- if (TREE_CODE (TREE_OPERAND (instance, 1)) != FIELD_DECL)
- return 0;
-
- case VAR_DECL:
- case PARM_DECL:
- case NEW_EXPR:
- if (IS_AGGR_TYPE (TREE_TYPE (instance)))
- return 1;
-
- default:
- return 0;
- }
- }
-
- /* Ordering function for overload resolution. */
- int
- rank_for_overload (x, y)
- struct candidate *x, *y;
- {
- if (y->evil - x->evil)
- return y->evil - x->evil;
- if ((y->harshness[0] & 128) ^ (x->harshness[0] & 128))
- return y->harshness[0] - x->harshness[0];
- if (y->user - x->user)
- return y->user - x->user;
- if (y->b_or_d - x->b_or_d)
- return y->b_or_d - x->b_or_d;
- return y->easy - x->easy;
- }
-
- /* TYPE is the type we wish to convert to. PARM is the parameter
- we have to work with. We use a somewhat arbitrary cost function
- to measure this conversion. */
- static int
- convert_harshness (type, parmtype, parm)
- register tree type, parmtype;
- tree parm;
- {
- register enum tree_code codel = TREE_CODE (type);
- register enum tree_code coder = TREE_CODE (parmtype);
-
- #ifdef GATHER_STATISTICS
- n_convert_harshness++;
- #endif
-
- if (TYPE_MAIN_VARIANT (parmtype) == TYPE_MAIN_VARIANT (type))
- return 0;
-
- if (coder == ERROR_MARK)
- return 1;
-
- if (codel == POINTER_TYPE
- && (coder == METHOD_TYPE || coder == FUNCTION_TYPE))
- {
- tree p1, p2;
- int harshness, new_harshness;
-
- /* Get to the METHOD_TYPE or FUNCTION_TYPE that this might be. */
- type = TREE_TYPE (type);
-
- if (coder != TREE_CODE (type))
- return 1;
-
- harshness = 0;
-
- /* We allow the default conversion between function type
- and pointer-to-function type for free. */
- if (type == parmtype)
- return 0;
-
- /* Compare return types. */
- harshness |= convert_harshness (TREE_TYPE (type), TREE_TYPE (parmtype), 0);
- if (harshness & 1)
- return 1;
- p1 = TYPE_ARG_TYPES (type);
- p2 = TYPE_ARG_TYPES (parmtype);
- while (p1 && p2)
- {
- new_harshness = convert_harshness (TREE_VALUE (p1), TREE_VALUE (p2), 0);
- if (new_harshness & 1)
- return 1;
- if ((new_harshness & 7) == 0)
- harshness += new_harshness;
- else
- harshness |= new_harshness;
- p1 = TREE_CHAIN (p1);
- p2 = TREE_CHAIN (p2);
- }
- if (p1 == p2)
- return harshness;
- if (p2)
- return 1;
- if (p1)
- return harshness | (TREE_PURPOSE (p1) == NULL_TREE);
- }
- else if (codel == POINTER_TYPE && coder == OFFSET_TYPE)
- {
- int harshness;
-
- /* Get to the OFFSET_TYPE that this might be. */
- type = TREE_TYPE (type);
-
- if (coder != TREE_CODE (type))
- return 1;
-
- harshness = 0;
-
- if (TYPE_OFFSET_BASETYPE (type) == TYPE_OFFSET_BASETYPE (parmtype))
- harshness = 0;
- else if (get_base_type (TYPE_OFFSET_BASETYPE (type),
- TYPE_OFFSET_BASETYPE (parmtype), 0))
- harshness = (1<<3);
- else
- return 1;
- /* Now test the OFFSET_TYPE's target compatability. */
- type = TREE_TYPE (type);
- parmtype = TREE_TYPE (parmtype);
- }
-
- if (coder == UNKNOWN_TYPE)
- {
- if (codel == FUNCTION_TYPE
- || codel == METHOD_TYPE
- || (codel == POINTER_TYPE
- && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)))
- return 0;
- return 1;
- }
-
- if (coder == VOID_TYPE)
- return 1;
-
- if (codel == ENUMERAL_TYPE || codel == INTEGER_TYPE)
- {
- /* Control equivalence of ints an enums. */
-
- if (codel == ENUMERAL_TYPE
- && flag_int_enum_equivalence == 0)
- {
- /* Enums can be converted to ints, but not vice-versa. */
- if (coder != ENUMERAL_TYPE
- || TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (parmtype))
- return 1;
- }
-
- /* else enums and ints (almost) freely interconvert. */
-
- if (coder == INTEGER_TYPE || coder == ENUMERAL_TYPE)
- {
- int easy = TREE_UNSIGNED (type) ^ TREE_UNSIGNED (parmtype);
- if (codel != coder)
- easy += 1;
- if (TYPE_MODE (type) != TYPE_MODE (parmtype))
- easy += 2;
- return (easy << 4);
- }
- else if (coder == REAL_TYPE)
- return (4<<4);
- }
-
- if (codel == REAL_TYPE)
- if (coder == REAL_TYPE)
- /* Shun converting between float and double if a choice exists. */
- {
- if (TYPE_MODE (type) != TYPE_MODE (parmtype))
- return (2<<4);
- return 0;
- }
- else if (coder == INTEGER_TYPE || coder == ENUMERAL_TYPE)
- return (4<<4);
-
- /* convert arrays which have not previously been converted. */
- if (codel == ARRAY_TYPE)
- codel = POINTER_TYPE;
- if (coder == ARRAY_TYPE)
- coder = POINTER_TYPE;
-
- /* Conversions among pointers */
- if (codel == POINTER_TYPE && coder == POINTER_TYPE)
- {
- register tree ttl = TYPE_MAIN_VARIANT (TREE_TYPE (type));
- register tree ttr = TYPE_MAIN_VARIANT (TREE_TYPE (parmtype));
- int penalty = 4 * (ttl != ttr);
- /* Anything converts to void *. void * converts to anything.
- Since these may be `const void *' (etc.) use VOID_TYPE
- instead of void_type_node.
- Otherwise, the targets must be the same,
- except that we do allow (at some cost) conversion
- between signed and unsinged pointer types. */
-
- if ((TREE_CODE (ttl) == METHOD_TYPE
- || TREE_CODE (ttl) == FUNCTION_TYPE)
- && TREE_CODE (ttl) == TREE_CODE (ttr))
- {
- if (comptypes (ttl, ttr, -1))
- return penalty<<4;
- return 1;
- }
-
- if (!(TREE_CODE (ttl) == VOID_TYPE
- || TREE_CODE (ttr) == VOID_TYPE
- || (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (ttr)
- && (ttl = unsigned_type (ttl),
- ttr = unsigned_type (ttr),
- penalty = 10, 0))
- || (comp_target_types (ttl, ttr, 0))))
- return 1;
-
- if (ttr == ttl)
- return 4;
-
- if (IS_AGGR_TYPE (ttl) && IS_AGGR_TYPE (ttr))
- {
- int b_or_d = get_base_distance (ttl, ttr, 0, 0);
- if (b_or_d < 0)
- return 1;
- return (b_or_d<<3) | 4;
- }
-
- return (penalty<<4);
- }
-
- if (codel == POINTER_TYPE && coder == INTEGER_TYPE)
- {
- /* This is not a bad match, but don't let it beat
- integer-enum combinations. */
- if (parm && integer_zerop (parm))
- return (4<<4);
- }
-
- /* C++: one of the types must be a reference type. */
- {
- tree ttl, ttr;
- register tree intype = TYPE_MAIN_VARIANT (parmtype);
- register enum tree_code form = TREE_CODE (intype);
- int penalty;
-
- if (codel == REFERENCE_TYPE || coder == REFERENCE_TYPE)
- {
- ttl = TYPE_MAIN_VARIANT (type);
-
- if (codel == REFERENCE_TYPE)
- {
- ttl = TYPE_MAIN_VARIANT (TREE_TYPE (ttl));
-
- if (form == OFFSET_TYPE)
- {
- intype = TREE_TYPE (intype);
- form = TREE_CODE (intype);
- }
-
- if (form == REFERENCE_TYPE)
- {
- intype = TYPE_MAIN_VARIANT (TREE_TYPE (intype));
-
- if (ttl == intype)
- return 0;
- penalty = 2;
- }
- else
- {
- /* Can reference be built up? */
- if (ttl == intype)
- {
- return 0;
- }
- else
- penalty = 2;
- }
- }
- else if (form == REFERENCE_TYPE)
- {
- if (parm)
- {
- tree tmp = convert_from_reference (parm);
- intype = TYPE_MAIN_VARIANT (TREE_TYPE (tmp));
- }
- else
- {
- intype = parmtype;
- do
- {
- intype = TREE_TYPE (intype);
- }
- while (TREE_CODE (intype) == REFERENCE_TYPE);
- intype = TYPE_MAIN_VARIANT (intype);
- }
-
- if (ttl == intype)
- return 0;
- else
- penalty = 2;
- }
-
- if (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (intype))
- {
- ttl = unsigned_type (ttl);
- intype = unsigned_type (intype);
- penalty += 2;
- }
-
- ttr = intype;
-
- /* If the initializer is not an lvalue, then it does not
- matter if we make life easier for the programmer
- by creating a temporary variable with which to
- hold the result. */
- if (parm && (coder == INTEGER_TYPE
- || coder == ENUMERAL_TYPE
- || coder == REAL_TYPE)
- && ! lvalue_p (parm))
- return (convert_harshness (ttl, ttr, 0) | (penalty << 4));
-
- if (ttl == ttr)
- return 4;
-
- /* Pointers to voids always convert for pointers. But
- make them less natural than more specific matches. */
- if (TREE_CODE (ttl) == POINTER_TYPE && TREE_CODE (ttr) == POINTER_TYPE)
- if (TREE_TYPE (ttl) == void_type_node
- || TREE_TYPE (ttr) == void_type_node)
- return ((penalty+1)<<4);
-
- if (parm && codel != REFERENCE_TYPE)
- return (convert_harshness (ttl, ttr, 0) | (penalty << 4));
-
- /* Here it does matter. If this conversion is from
- derived to base, allow it. Otherwise, types must
- be compatible in the strong sense. */
- if (IS_AGGR_TYPE (ttl) && IS_AGGR_TYPE (ttr))
- {
- int b_or_d = get_base_distance (ttl, ttr, 0, 0);
- if (b_or_d < 0)
- return 1;
- #if AMBIGUOUS_WORKING
- if (ttl == TYPE_MAIN_VARIANT (type)
- && TYPE_GETS_INIT_REF (type))
- return (b_or_d<<3) | 6;
- #endif
- return (b_or_d<<3) | 4;
- }
-
- if (comp_target_types (ttl, intype, 1))
- return (penalty<<4);
- }
- }
- if (codel == RECORD_TYPE && coder == RECORD_TYPE)
- {
- int b_or_d = get_base_distance (type, parmtype, 0, 0);
- if (b_or_d < 0)
- return 1;
- #if AMBIGUOUS_WORKING
- if (TYPE_GETS_INIT_REF (type))
- return (b_or_d<<3) | 6;
- #endif
- return (b_or_d<<3) | 4;
- }
- return 1;
- }
-
- /* Algorithm: Start out with no stikes against. For each argument
- which requires a (subjective) hard conversion (such as between
- floating point and integer), issue a strike. If there are the same
- number of formal and actual parameters in the list, there will be at
- least on strike, otherwise an exact match would have been found. If
- there are not the same number of arguments in the type lists, we are
- not dead yet: a `...' means that we can have more parms then were
- declared, and if we wind up in the default argument section of the
- list those can be used as well. If an exact match could be found for
- one of those cases, return it immediately. Otherwise, Rank the fields
- so that fields with fewer strikes are tried first.
-
- Conversions between builtin and user-defined types are allowed, but
- no function involving such a conversion is prefered to one which
- does not require such a conversion. Furthermore, such conversions
- must be unique. */
-
- void
- compute_conversion_costs (function, tta_in, cp, arglen)
- tree function;
- tree tta_in;
- struct candidate *cp;
- int arglen;
- {
- tree ttf_in = TYPE_ARG_TYPES (TREE_TYPE (function));
- tree ttf = ttf_in;
- tree tta = tta_in;
-
- /* Start out with no strikes against. */
- int evil_strikes = 0;
- int user_strikes = 0;
- int b_or_d_strikes = 0;
- int easy_strikes = 0;
-
- int strike_index = 0, win, lose;
-
- #ifdef GATHER_STATISTICS
- n_compute_conversion_costs++;
- #endif
-
- cp->function = function;
- cp->arg = tta ? TREE_VALUE (tta) : NULL_TREE;
- cp->u.bad_arg = 0; /* optimistic! */
-
- bzero (cp->harshness, (arglen+1) * sizeof (short));
-
- while (ttf && tta)
- {
- int harshness;
-
- if (ttf == void_list_node)
- break;
-
- if (type_unknown_p (TREE_VALUE (tta)))
- {
- /* Must perform some instantiation here. */
- tree rhs = TREE_VALUE (tta);
- tree lhstype = TREE_VALUE (ttf);
-
- /* @@ This is to undo what `grokdeclarator' does to
- parameter types. It really should go through
- something more general. */
-
- TREE_TYPE (tta) = unknown_type_node;
- if (TREE_CODE (rhs) == OP_IDENTIFIER)
- rhs = build_instantiated_decl (lhstype, rhs);
- else
- {
- /* Keep quiet about possible contravariance violations. */
- extern int inhibit_warnings;
- int old_inhibit_warnings = inhibit_warnings;
- inhibit_warnings = 1;
-
- rhs = instantiate_type (lhstype, rhs, 0);
-
- inhibit_warnings = old_inhibit_warnings;
- }
-
- if (TREE_CODE (rhs) == ERROR_MARK)
- harshness = 1;
- else
- {
- harshness = convert_harshness (lhstype, TREE_TYPE (rhs), rhs);
- /* harshness |= 2; */
- }
- }
- else
- harshness = convert_harshness (TREE_VALUE (ttf), TREE_TYPE (TREE_VALUE (tta)), TREE_VALUE (tta));
-
- cp->harshness[strike_index] = harshness;
- if (harshness & 1)
- {
- cp->u.bad_arg = strike_index;
- evil_strikes = 1;
- }
- else if (harshness & 2)
- {
- user_strikes += 1;
- }
- else if (harshness & 4)
- {
- b_or_d_strikes += (harshness >> 3);
- }
- else
- easy_strikes += harshness >> 4;
- ttf = TREE_CHAIN (ttf);
- tta = TREE_CHAIN (tta);
- strike_index += 1;
- }
-
- if (tta)
- {
- /* ran out of formals, and parmlist is fixed size. */
- if (ttf /* == void_type_node */)
- {
- cp->evil = 1;
- cp->u.bad_arg = -1;
- return;
- }
- }
- else if (ttf && ttf != void_list_node)
- {
- /* ran out of actuals, and no defaults. */
- if (TREE_PURPOSE (ttf) == NULL_TREE)
- {
- cp->evil = 1;
- cp->u.bad_arg = -2;
- return;
- }
- /* Store index of first default. */
- cp->harshness[arglen] = strike_index+1;
- }
- else cp->harshness[arglen] = 0;
-
- /* Argument list lengths work out, so don't need to check them again. */
- if (evil_strikes)
- {
- /* We do not check for derived->base conversions here, since in
- no case would they give evil strike counts, unless such conversions
- are somehow ambiguous. */
-
- /* See if any user-defined conversions apply.
- But make sure that we do not loop. */
- static int dont_convert_types = 0;
-
- if (dont_convert_types)
- {
- cp->evil = 1;
- return;
- }
-
- win = 0; /* Only get one chance to win. */
- ttf = TYPE_ARG_TYPES (TREE_TYPE (function));
- tta = tta_in;
- strike_index = 0;
- evil_strikes = 0;
-
- while (ttf && tta)
- {
- if (ttf == void_list_node)
- break;
-
- lose = cp->harshness[strike_index];
- if (lose&1)
- {
- tree actual_type = TREE_TYPE (TREE_VALUE (tta));
- tree formal_type = TREE_VALUE (ttf);
-
- dont_convert_types = 1;
-
- if (TREE_CODE (formal_type) == REFERENCE_TYPE)
- formal_type = TREE_TYPE (formal_type);
- if (TREE_CODE (actual_type) == REFERENCE_TYPE)
- actual_type = TREE_TYPE (actual_type);
-
- if (formal_type != error_mark_node
- && actual_type != error_mark_node)
- {
- formal_type = TYPE_MAIN_VARIANT (formal_type);
- actual_type = TYPE_MAIN_VARIANT (actual_type);
-
- if (TYPE_HAS_CONSTRUCTOR (formal_type))
- {
- /* If it has a constructor for this type, try to use it. */
- if (convert_to_aggr (formal_type, TREE_VALUE (tta), 0, 1)
- != error_mark_node)
- {
- /* @@ There is no way to save this result yet.
- @@ So success is NULL_TREE for now. */
- win++;
- }
- }
- if (TYPE_LANG_SPECIFIC (actual_type) && TYPE_HAS_CONVERSION (actual_type))
- {
- if (TREE_CODE (formal_type) == INTEGER_TYPE
- && TYPE_HAS_INT_CONVERSION (actual_type))
- win++;
- else if (TREE_CODE (formal_type) == REAL_TYPE
- && TYPE_HAS_REAL_CONVERSION (actual_type))
- win++;
- else
- {
- tree conv = build_type_conversion (CALL_EXPR, TREE_VALUE (ttf), TREE_VALUE (tta), 0);
- if (conv)
- if (conv == error_mark_node)
- win += 2;
- else
- win++;
- }
- }
- }
- dont_convert_types = 0;
-
- if (win == 1)
- {
- user_strikes += 1;
- cp->harshness[strike_index] = 2;
- win = 0;
- }
- else
- {
- if (cp->u.bad_arg > strike_index)
- cp->u.bad_arg = strike_index;
-
- evil_strikes = win ? 2 : 1;
- break;
- }
- }
-
- ttf = TREE_CHAIN (ttf);
- tta = TREE_CHAIN (tta);
- strike_index += 1;
- }
- }
-
- /* Calling a non-const member function from a const member function
- is probably invalid, but for now we let it only draw a warning.
- We indicate that such a mismatch has occured by setting the
- harshness to a maximum value. */
- if (TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE
- && TREE_CODE (TREE_TYPE (TREE_VALUE (tta_in))) == POINTER_TYPE
- && (TREE_READONLY (TREE_TYPE (TREE_TYPE (TREE_VALUE (tta_in))))
- > TREE_READONLY (TREE_TYPE (TREE_VALUE (ttf_in)))))
- cp->harshness[0] |= 128;
-
- cp->evil = evil_strikes;
- cp->user = user_strikes;
- cp->b_or_d = b_or_d_strikes;
- cp->easy = easy_strikes;
- }
-
- struct candidate *
- ideal_candidate (basetype, candidates, n_candidates, parms, len)
- tree basetype;
- struct candidate *candidates;
- int n_candidates;
- tree parms;
- int len;
- {
- struct candidate *cp = candidates + n_candidates;
- int index, i;
- tree ttf;
-
- qsort (candidates, /* char *base */
- n_candidates, /* int nel */
- sizeof (struct candidate), /* int width */
- rank_for_overload); /* int (*compar)() */
-
- /* If the best candidate requires user-defined conversions,
- and its user-defined conversions are a strict subset
- of all other candidates requiring user-defined conversions,
- then it is, in fact, the best. */
- for (i = -1; cp + i != candidates; i--)
- if (cp[i].user == 0)
- break;
-
- if (i < -1)
- {
- tree ttf0;
-
- /* Check that every other candidate requires those conversions
- as a strict subset of their conversions. */
- if (cp[i].user == cp[-1].user)
- goto non_subset;
-
- /* Look at subset relationship more closely. */
- while (i != -1)
- {
- for (ttf = TYPE_ARG_TYPES (TREE_TYPE (cp[i].function)),
- ttf0 = TYPE_ARG_TYPES (TREE_TYPE (cp[-1].function)),
- index = 0;
- index < len;
- ttf = TREE_CHAIN (ttf), ttf0 = TREE_CHAIN (ttf0), index++)
- if (cp[i].harshness[index] & 2)
- {
- /* If our "best" candidate also needs a conversion,
- it must be the same one. */
- if ((cp[-1].harshness[index] & 2)
- && TREE_VALUE (ttf) != TREE_VALUE (ttf0))
- goto non_subset;
- }
- i++;
- }
- /* The best was the best. */
- return cp - 1;
- non_subset:
- /* Use other rules for determining "bestness". */
- ;
- }
-
- /* If the best two candidates we find require user-defined
- conversions, we may need to report and error message. */
- if (cp[-1].user && cp[-2].user
- && (cp[-1].b_or_d || cp[-2].b_or_d == 0))
- {
- /* If the best two methods found involved user-defined
- type conversions, then we must see whether one
- of them is exactly what we wanted. If not, then
- we have an ambiguity. */
- int best = 0;
- tree tta = parms;
- tree f1, p1;
-
- #if AMBIGUOUS_WORKING
- if (cp[-1].b_or_d == 0
- && cp[-1].easy == 0
- && (cp[-2].b_or_d | cp[-2].easy) > 0)
- return cp - 1;
- #endif
-
- /* Stash all of our parameters in safe places
- so that we can perform type conversions in place. */
- while (tta)
- {
- TREE_PURPOSE (tta) = TREE_VALUE (tta);
- tta = TREE_CHAIN (tta);
- }
-
- i = 0;
- do
- {
- int exact_conversions = 0;
-
- i -= 1;
- tta = parms;
- if (DECL_STATIC_FUNCTION_P (cp[i].function))
- tta = TREE_CHAIN (tta);
- for (ttf = TYPE_ARG_TYPES (TREE_TYPE (cp[i].function)), index = 0;
- index < len;
- tta = TREE_CHAIN (tta), ttf = TREE_CHAIN (ttf), index++)
- {
- if (cp[i].harshness[index] & 2)
- {
- TREE_VALUE (tta)
- = build_type_conversion (CALL_EXPR, TREE_VALUE (ttf), TREE_PURPOSE (tta), 2);
- if (TREE_VALUE (tta))
- {
- if (TREE_CODE (TREE_VALUE (tta)) != CONVERT_EXPR
- && (TREE_CODE (TREE_VALUE (tta)) != NOP_EXPR
- || comp_target_types (TREE_TYPE (TREE_VALUE (tta)),
- TREE_TYPE (TREE_OPERAND (TREE_VALUE (tta), 0)), 1)))
- exact_conversions += 1;
- }
- else if (IS_AGGR_TYPE (TREE_VALUE (ttf))
- || (TREE_CODE (TREE_VALUE (ttf)) == REFERENCE_TYPE
- && IS_AGGR_TYPE (TREE_TYPE (TREE_VALUE (ttf)))))
- {
- /* To get here we had to have succeeded via
- a constructor. */
- TREE_VALUE (tta) = TREE_PURPOSE (tta);
- exact_conversions += 1;
- }
- }
- }
- if (exact_conversions == cp[i].user)
- {
- if (best == 0)
- {
- best = i;
- f1 = cp[best].function;
- p1 = TYPE_ARG_TYPES (TREE_TYPE (f1));
- }
- else
- {
- /* Don't complain if next best is from base class. */
- tree f2 = cp[i].function;
- tree p2 = TYPE_ARG_TYPES (TREE_TYPE (f2));
-
- if (TREE_CODE (TREE_TYPE (f1)) == METHOD_TYPE
- && TREE_CODE (TREE_TYPE (f2)) == METHOD_TYPE
- && (cp[i].harshness[0] & 4) != 0
- && cp[best].harshness[0] < cp[i].harshness[0])
- {
- if (! compparms (TREE_CHAIN (p1), TREE_CHAIN (p2), 1))
- goto ret0;
- else
- continue;
- }
- else goto ret0;
- }
- }
- } while (cp + i != candidates);
-
- if (best)
- {
- int exact_conversions = cp[best].user;
- tta = parms;
- if (DECL_STATIC_FUNCTION_P (cp[best].function))
- tta = TREE_CHAIN (parms);
- for (ttf = TYPE_ARG_TYPES (TREE_TYPE (cp[best].function)), index = 0;
- exact_conversions > 0;
- tta = TREE_CHAIN (tta), ttf = TREE_CHAIN (ttf), index++)
- if (cp[best].harshness[index] & 2)
- {
- /* We must now fill in the slot we left behind.
- @@ This could be optimized to use the value previously
- @@ computed by build_type_conversion in some cases. */
- TREE_VALUE (tta) = convert (TREE_VALUE (ttf), TREE_PURPOSE (tta));
- exact_conversions -= 1;
- }
- return cp + best;
- }
- goto ret0;
- }
- /* If the best two candidates we find both use default parameters,
- we may need to report and error. Don't need to worry if next-best
- candidate is forced to use user-defined conversion when best is not. */
- if (cp[-2].user == 0
- && cp[-1].harshness[len] != 0 && cp[-2].harshness[len] != 0)
- {
- tree tt1 = TYPE_ARG_TYPES (TREE_TYPE (cp[-1].function));
- tree tt2 = TYPE_ARG_TYPES (TREE_TYPE (cp[-2].function));
- int i = cp[-1].harshness[len];
- if (cp[-2].harshness[len] < i)
- i = cp[-2].harshness[len];
- while (--i > 0)
- {
- if (TYPE_MAIN_VARIANT (TREE_VALUE (tt1))
- != TYPE_MAIN_VARIANT (TREE_VALUE (tt2)))
- /* These lists are not identical, so we can choose our best candidate. */
- return cp - 1;
- tt1 = TREE_CHAIN (tt1);
- tt2 = TREE_CHAIN (tt2);
- }
- /* To get here, both lists had the same parameters up to the defaults
- which were used. This is an ambiguous request. */
- goto ret0;
- }
-
- /* Otherwise, return our best candidate. Note that if we get candidates
- from independent base classes, we have an ambiguity, even if one
- argument list look a little better than another one. */
- if (cp[-1].b_or_d && basetype && TYPE_USES_MULTIPLE_INHERITANCE (basetype))
- {
- int i = n_candidates - 1, best;
- tree base1 = NULL_TREE;
-
- if (TREE_CODE (TREE_TYPE (candidates[i].function)) == FUNCTION_TYPE)
- return cp - 1;
-
- for (; i >= 0 && candidates[i].user == 0 && candidates[i].evil == 0; i--)
- {
- if (TREE_CODE (TREE_TYPE (candidates[i].function)) == METHOD_TYPE)
- {
- tree newbase = TYPE_METHOD_BASETYPE (TREE_TYPE (candidates[i].function));
-
- if (base1 != NULL_TREE)
- {
- if (newbase != base1
- && ! get_base_type (newbase, base1, 0))
- {
- char *buf = (char *)alloca (8192);
- error ("ambiguous request for function from distinct base classes of type `%s'", TYPE_NAME_STRING (basetype));
- error ("first candidate is `%s'", fndecl_as_string (buf, 0, candidates[best].function, 1));
- error ("second candidates is `%s'", fndecl_as_string (buf, 0, candidates[i].function, 1));
- return cp - 1;
- }
- }
- else
- {
- best = i;
- base1 = newbase;
- }
- }
- else return cp - 1;
- }
- }
-
- #if AMBIGUOUS_WORKING
- if (cp[-1].user == cp[-2].user
- && cp[-1].b_or_d == cp[-2].b_or_d
- && cp[-1].easy == cp[-2].easy)
- goto ret0;
- #endif
-
- return cp - 1;
-
- ret0:
- /* In the case where there is no ideal candidate, restore
- TREE_VALUE slots of PARMS from TREE_PURPOSE slots. */
- while (parms)
- {
- TREE_VALUE (parms) = TREE_PURPOSE (parms);
- parms = TREE_CHAIN (parms);
- }
- return 0;
- }
-
- /* Assume that if the class referred to is not in the
- current class hierarchy, that it may be remote.
- PARENT is assumed to be of aggregate type here. */
- static int
- may_be_remote (parent)
- tree parent;
- {
- if (TYPE_OVERLOADS_METHOD_CALL_EXPR (parent) == 0)
- return 0;
-
- if (current_class_type == NULL_TREE)
- return 0;
- if (parent == current_class_type)
- return 0;
-
- if (get_base_type (parent, current_class_type, 0))
- return 0;
- return 1;
- }
-
- /* Return the number of bytes that the arglist in PARMS would
- occupy on the stack. */
- int
- get_arglist_len_in_bytes (parms)
- tree parms;
- {
- register tree parm;
- register int bytecount = 0;
-
- for (parm = parms; parm; parm = TREE_CHAIN (parm))
- {
- register tree pval = TREE_VALUE (parm);
- register int used, size;
-
- if (TREE_CODE (pval) == ERROR_MARK)
- continue;
- else if (TYPE_MODE (TREE_TYPE (pval)) != BLKmode)
- {
- used = size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (pval)));
- #ifdef PUSH_ROUNDING
- size = PUSH_ROUNDING (size);
- #endif
- used = (((size + PARM_BOUNDARY / BITS_PER_UNIT - 1)
- / (PARM_BOUNDARY / BITS_PER_UNIT))
- * (PARM_BOUNDARY / BITS_PER_UNIT));
- }
- else
- {
- register tree size = size_in_bytes (TREE_TYPE (pval));
- register tree used_t = convert_units (convert_units (size, BITS_PER_UNIT, PARM_BOUNDARY),
- PARM_BOUNDARY, BITS_PER_UNIT);
- used = TREE_INT_CST_LOW (used_t);
- }
- bytecount += used;
- }
- return bytecount;
- }
-
- tree
- build_vfield_ref (datum, type)
- tree datum, type;
- {
- if (TREE_CODE (TREE_TYPE (datum)) == REFERENCE_TYPE)
- datum = convert_from_reference (datum);
-
- if (! TYPE_USES_VIRTUAL_BASECLASSES (type))
- return build (COMPONENT_REF, TREE_TYPE (CLASSTYPE_VFIELD (type)),
- datum, CLASSTYPE_VFIELD (type));
- return build_component_ref (datum, DECL_NAME (CLASSTYPE_VFIELD (type)), 0, 0);
- }
-
- /* Build a call to a member of an object. I.e., one that overloads
- operator ()(), or is a pointer-to-function or pointer-to-method. */
- static tree
- build_field_call (basetype_path, instance_ptr, name, parms, err_name)
- tree basetype_path;
- tree instance_ptr, name, parms;
- char *err_name;
- {
- tree field, instance;
-
- if (instance_ptr == current_class_decl)
- {
- /* Check to see if we really have a reference to an instance variable
- with `operator()()' overloaded. */
- #if 1
- field = IDENTIFIER_CLASS_VALUE (name);
- #else
- field = identifier_class_value (name);
- #endif
-
- if (field == NULL_TREE)
- {
- error ("`this' has no member named `%s'", err_name);
- return error_mark_node;
- }
-
- if (TREE_CODE (field) == FIELD_DECL)
- {
- /* If it's a field, try overloading operator (),
- or calling if the field is a pointer-to-function. */
- instance = build_component_ref_1 (C_C_D, field, 0, 1);
- if (instance == error_mark_node)
- return error_mark_node;
-
- if (TYPE_LANG_SPECIFIC (TREE_TYPE (instance))
- && TYPE_OVERLOADS_CALL_EXPR (TREE_TYPE (instance)))
- return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, instance, parms);
-
- if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE)
- if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == FUNCTION_TYPE)
- return build_function_call (instance, parms);
- else if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == METHOD_TYPE)
- return build_function_call (instance, tree_cons (NULL_TREE, current_class_decl, parms));
- }
- return NULL_TREE;
- }
-
- /* Check to see if this is not really a reference to an instance variable
- with `operator()()' overloaded. */
- field = lookup_field (basetype_path, name, 1);
-
- /* This can happen if the reference was ambiguous
- or for visibility violations. */
- if (field == error_mark_node)
- return error_mark_node;
- if (field)
- {
- tree basetype;
- tree ftype = TREE_TYPE (field);
-
- if (TYPE_LANG_SPECIFIC (ftype) && TYPE_OVERLOADS_CALL_EXPR (ftype))
- {
- /* Make the next search for this field very short. */
- basetype = DECL_FIELD_CONTEXT (field);
- instance_ptr = convert_pointer_to (basetype, instance_ptr);
-
- instance = build_indirect_ref (instance_ptr, 0);
- return build_opfncall (CALL_EXPR, LOOKUP_NORMAL,
- build_component_ref_1 (instance, field, 0, 0),
- parms);
- }
- if (TREE_CODE (ftype) == POINTER_TYPE)
- {
- if (TREE_CODE (TREE_TYPE (ftype)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (ftype)) == METHOD_TYPE)
- {
- /* This is a member which is a pointer to function. */
- tree ref = build_component_ref_1 (build_indirect_ref (instance_ptr, 0, 0),
- field, LOOKUP_COMPLAIN);
- if (ref == error_mark_node)
- return error_mark_node;
- return build_function_call (ref, parms);
- }
- }
- else if (TREE_CODE (ftype) == METHOD_TYPE)
- {
- error ("invalid call via pointer-to-member function");
- return error_mark_node;
- }
- else
- return NULL_TREE;
- }
- return NULL_TREE;
- }
-
- /* Build a method call of the form `EXP->SCOPES::NAME (PARMS)'.
- This is how virtual function calls are avoided. */
- tree
- build_scoped_method_call (exp, scopes, name, parms)
- tree exp;
- tree scopes;
- tree name;
- tree parms;
- {
- /* Because this syntactic form does not allow
- a pointer to a base class to be `stolen',
- we need not protect the drived->base conversion
- that happens here.
-
- @@ But we do have to check visibility privileges later. */
- tree basename = (TREE_CODE (scopes) == SCOPE_REF) ? TREE_OPERAND (scopes, 1) : scopes;
- tree basetype, decl;
- tree type = TREE_TYPE (exp);
-
- if (type == error_mark_node
- || ! is_aggr_typedef (basename, 1))
- return error_mark_node;
-
- basetype = TREE_TYPE (TREE_TYPE (basename));
-
- if (basetype = basetype_or_else (basetype, type))
- {
- if (basetype == error_mark_node)
- return error_mark_node;
- if (TREE_CODE (exp) == INDIRECT_REF)
- decl = build_indirect_ref (convert_pointer_to (basetype,
- build_unary_op (ADDR_EXPR, exp, 0)), 0);
- else
- decl = build_scoped_ref (exp, scopes);
-
- /* Call to a destructor. */
- if (TREE_CODE (name) == BIT_NOT_EXPR)
- {
- /* Explicit call to destructor. */
- name = TREE_OPERAND (name, 0);
- if (! is_aggr_typedef (name, 1))
- return error_mark_node;
- if (TREE_TYPE (decl) != TREE_TYPE (TREE_TYPE (name)))
- {
- error_with_aggr_type (TREE_TYPE (decl),
- "qualified type `%s' does not match destructor type `%s'",
- IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
- return build_delete (TREE_TYPE (TREE_TYPE (name)),
- decl, integer_one_node,
- LOOKUP_NORMAL, 0);
- }
-
- /* Call to a method. */
- return build_method_call (decl, name, parms, NULL_TREE,
- LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);
- }
- return error_mark_node;
- }
-
- /* Build something of the form ptr->method (args)
- or object.method (args). This can also build
- calls to constructors, and find friends.
-
- Member functions always take their class variable
- as a pointer.
-
- INSTANCE is a class instance.
-
- NAME is the NAME field of the struct, union, or class
- whose type is that of INSTANCE.
-
- PARMS help to figure out what that NAME really refers to.
-
- BASETYPE_PATH, if non-NULL, tells which basetypes of INSTANCE
- we should be traversed before starting our search. We need
- this information to get protected accesses correct.
-
- FLAGS is the logical disjunction of zero or more LOOKUP_
- flags. See cplus-tree.h for more info.
-
- If this is all OK, calls build_function_call with the resolved
- member function.
-
- This function must also handle being called to perform
- initialization, promotion/coercion of arguments, and
- instantiation of default parameters.
-
- Note that NAME may refer to an instance variable name. If
- `operator()()' is defined for the type of that field, then we return
- that result. */
- tree
- build_method_call (instance, name, parms, basetype_path, flags)
- tree instance, name, parms, basetype_path;
- int flags;
- {
- register tree function, fntype, value_type;
- register tree basetype, save_basetype;
- register tree baselink, result, method_name, parmtypes, parm;
- tree last;
- int pass;
- enum visibility_type visibility;
- int rank_for_overload ();
- int need_vtbl = 0;
- char *err_name;
- char *name_kind;
- int ever_seen = 0;
- int wrap;
- tree wrap_type;
- tree instance_ptr = NULL_TREE;
- int all_virtual = flag_all_virtual;
- int static_call_context;
- tree saw_private = 0;
- tree saw_protected = 0;
- #ifdef SOS
- /* If call is a call to a constructor, then `dtbl'
- will first be initialized with the function table pointer
- of the appropriate type (calling "sosFindCode" as a last
- resort), the the call to the constructor will go through there. */
- tree dtbl = (flags & LOOKUP_DYNAMIC) ? TREE_VALUE (parms) : NULL_TREE;
-
- /* Flag saying whether or not `dtbl' has been inserted into the
- parameter list. This is needed because we cannot tell (until
- we have a match) whether this parameter should go in or not.
-
- If 1, then `dtbl' is living naturally.
- If 0, then `dtbl' is not among the parms that we know about.
- If -1, the `dtbl' was place into the parms unnaturally.
-
- Note that we may side-effect the parameter list, but in such a way
- that the caller of this function would never know. */
- int dtbl_inserted = (flags & LOOKUP_DYNAMIC);
- #endif
-
- /* Keep track of `const' and `volatile' objects. */
- int constp, volatilep;
-
- #ifdef GATHER_STATISTICS
- n_build_method_call++;
- #endif
-
- if (instance == error_mark_node
- || name == error_mark_node
- || parms == error_mark_node
- || (instance != 0 && TREE_TYPE (instance) == error_mark_node))
- return error_mark_node;
-
- if (TREE_CODE (name) == BIT_NOT_EXPR)
- {
- error ("invalid call to destructor, use qualified name `%s::~%s'",
- IDENTIFIER_POINTER (name), IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
- if (TREE_CODE (name) == WRAPPER_EXPR)
- {
- wrap_type = TREE_OPERAND (name, 0);
- name = TREE_OPERAND (name, 1);
- wrap = 1;
- }
- else if (TREE_CODE (name) == ANTI_WRAPPER_EXPR)
- {
- wrap_type = TREE_OPERAND (name, 0);
- name = TREE_OPERAND (name, 1);
- wrap = -1;
- }
- else
- {
- wrap_type = NULL_TREE;
- wrap = 0;
- }
-
- /* Initialize name for error reporting. */
- if (TREE_CODE (name) == OP_IDENTIFIER)
- name = build_operator_fnname (&name, parms, 1);
-
- if (OPERATOR_NAME_P (name))
- {
- char *p = operator_name_string (name);
- err_name = (char *)alloca (strlen (p) + 10);
- sprintf (err_name, "operator %s", p);
- }
- else if (name == wrapper_name)
- err_name = "wrapper";
- else if (OPERATOR_TYPENAME_P (name))
- err_name = "type conversion operator";
- else if (TREE_CODE (name) == SCOPE_REF)
- err_name = IDENTIFIER_POINTER (TREE_OPERAND (name, 1));
- else
- err_name = IDENTIFIER_POINTER (name);
-
- if (wrap)
- {
- char *p = (char *)alloca (strlen (err_name) + 32);
- sprintf (p, "%s for `%s'", wrap < 0 ? "anti-wrapper" : "wrapper", err_name);
- err_name = p;
- }
-
- if (instance == NULL_TREE)
- {
- static_call_context = 0;
-
- basetype = NULL_TREE;
- /* Check cases where this is really a call to raise
- an exception. */
- if (current_class_type && TREE_CODE (name) == IDENTIFIER_NODE)
- {
- basetype = purpose_member (name, CLASSTYPE_TAGS (current_class_type));
- if (basetype)
- basetype = TREE_VALUE (basetype);
- }
- else if (TREE_CODE (name) == SCOPE_REF
- && TREE_CODE (TREE_OPERAND (name, 0)) == IDENTIFIER_NODE)
- {
- if (! is_aggr_typedef (TREE_OPERAND (name, 0), 1))
- return error_mark_node;
- basetype = purpose_member (TREE_OPERAND (name, 1),
- CLASSTYPE_TAGS (TREE_TYPE (TREE_TYPE (TREE_OPERAND (name, 0)))));
- if (basetype)
- basetype = TREE_VALUE (basetype);
- }
-
- if (basetype != NULL_TREE)
- ;
- /* call to a constructor... */
- else if (TREE_TYPE (name))
- basetype = TREE_TYPE (TREE_TYPE (name));
- else
- {
- tree typedef_name = lookup_name (name);
- if (typedef_name && TREE_CODE (typedef_name) == TYPE_DECL)
- {
- /* Cannonicalize the typedef name. */
- basetype = TREE_TYPE (typedef_name);
- name = DECL_NAME (TYPE_NAME (basetype));
- }
- else
- {
- error ("no constructor named `%s' in visible scope",
- IDENTIFIER_POINTER (name));
- return error_mark_node;
- }
- }
- if (wrap_type && wrap_type != basetype)
- {
- error_with_aggr_type (wrap_type, "invalid constructor `%s::%s'",
- TYPE_NAME_STRING (basetype));
- return error_mark_node;
- }
- if (TYPE_VIRTUAL_P (basetype))
- {
- wrap_type = basetype;
- }
-
- if (! IS_AGGR_TYPE (basetype))
- {
- non_aggr_error:
- if ((flags & LOOKUP_COMPLAIN) && TREE_CODE (basetype) != ERROR_MARK)
- error ("request for member `%s' in something not a structure or union", err_name);
-
- return error_mark_node;
- }
- }
- else if (instance == C_C_D || instance == current_class_decl)
- {
- static_call_context = 0;
- instance = C_C_D;
- instance_ptr = current_class_decl;
- result = build_field_call (CLASSTYPE_AS_LIST (current_class_type),
- instance_ptr, name, parms, err_name);
-
- if (result)
- return result;
-
- /* When doing initialization, we side-effect the TREE_TYPE of
- C_C_D, hence we cannot set up BASETYPE from CURRENT_CLASS_TYPE. */
- basetype = TREE_TYPE (instance);
- if (!(flags & LOOKUP_NONVIRTUAL) && TYPE_VIRTUAL_P (basetype)
- && wrap_type == NULL_TREE)
- need_vtbl = 1;
- }
- else if (TREE_CODE (instance) == RESULT_DECL)
- {
- static_call_context = 0;
- basetype = TREE_TYPE (instance);
- if (wrap_type)
- {
- if (basetype_or_else (basetype, wrap_type))
- basetype = wrap_type;
- else
- return error_mark_node;
- }
- /* Should we ever have to make a virtual function reference
- from a RESULT_DECL, know that it must be of fixed type
- within the scope of this function. */
- else if (!(flags & LOOKUP_NONVIRTUAL) && TYPE_VIRTUAL_P (basetype))
- need_vtbl = 1;
- instance_ptr = build1 (ADDR_EXPR, TYPE_POINTER_TO (basetype), instance);
- }
- else if (instance == current_exception_object)
- {
- instance_ptr = build1 (ADDR_EXPR, TYPE_POINTER_TO (current_exception_type),
- TREE_OPERAND (current_exception_object, 0));
- mark_addressable (TREE_OPERAND (current_exception_object, 0));
- result = build_field_call (CLASSTYPE_AS_LIST (current_exception_type),
- instance_ptr, name, parms, err_name);
- if (result)
- return result;
- error ("exception member `%s' cannot be invoked", err_name);
- return error_mark_node;
- }
- else
- {
- /* The MAIN_VARIANT of the type that `instance_ptr' winds up being. */
- tree inst_ptr_basetype;
-
- /* from the file "cplus-typeck.c". */
- extern tree unary_complex_lvalue ();
-
- static_call_context = (TREE_CODE (instance) == NOP_EXPR
- && TREE_OPERAND (instance, 0) == error_mark_node);
-
- /* the base type of an instance variable is pointer to class */
- basetype = TREE_TYPE (instance);
-
- if (TREE_CODE (basetype) == REFERENCE_TYPE)
- {
- basetype = TYPE_MAIN_VARIANT (TREE_TYPE (basetype));
- if (! IS_AGGR_TYPE (basetype))
- goto non_aggr_error;
- /* Call to convert not needed because we are remaining
- within the same type. */
- instance_ptr = build1 (NOP_EXPR, TYPE_POINTER_TO (basetype), instance);
- inst_ptr_basetype = basetype;
- }
- else
- {
- if (TREE_CODE (basetype) == POINTER_TYPE)
- {
- basetype = TREE_TYPE (basetype);
- instance_ptr = instance;
- }
-
- if (! IS_AGGR_TYPE (basetype))
- goto non_aggr_error;
-
- if (! instance_ptr)
- {
- if ((lvalue_p (instance)
- && (instance_ptr = build_unary_op (ADDR_EXPR, instance, 0)))
- || (instance_ptr = unary_complex_lvalue (ADDR_EXPR, instance)))
- {
- if (instance_ptr == error_mark_node)
- return error_mark_node;
- }
- else if (TREE_CODE (instance) == NOP_EXPR
- || TREE_CODE (instance) == CONSTRUCTOR)
- {
- /* A cast is not an lvalue. Initialize a fresh temp
- with the value we are casting from, and proceed with
- that temporary. We can't cast to a reference type,
- so that simplifies the initialization to something
- we can manage. */
- tree temp = get_temp_name (TREE_TYPE (instance), 0);
- if (IS_AGGR_TYPE (TREE_TYPE (instance)))
- expand_aggr_init (temp, instance, 0);
- else
- {
- store_init_value (temp, instance);
- expand_decl_init (temp);
- }
- instance = temp;
- instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);
- }
- else
- {
- assert (TREE_CODE (instance) == CALL_EXPR);
- if (TYPE_NEEDS_CONSTRUCTOR (basetype))
- instance = build_cplus_new (basetype, instance);
- else
- {
- instance = get_temp_name (basetype, 0);
- TREE_ADDRESSABLE (instance) = 1;
- }
- instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);
- }
- /* @@ Should we call comp_target_types here? */
- inst_ptr_basetype = TREE_TYPE (TREE_TYPE (instance_ptr));
- if (TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (inst_ptr_basetype))
- basetype = inst_ptr_basetype;
- else
- instance_ptr = convert (TYPE_POINTER_TO (basetype), instance_ptr);
- }
- else
- inst_ptr_basetype = TREE_TYPE (TREE_TYPE (instance_ptr));
- }
-
- if (basetype_path == NULL_TREE)
- basetype_path = CLASSTYPE_AS_LIST (inst_ptr_basetype);
-
- result = build_field_call (basetype_path, instance_ptr, name, parms, err_name);
- if (result)
- return result;
-
- if (wrap_type)
- {
- if (basetype_or_else (basetype, wrap_type))
- basetype = wrap_type;
- else
- return error_mark_node;
- }
- else if (!(flags & LOOKUP_NONVIRTUAL) && TYPE_VIRTUAL_P (basetype))
- {
- if (TREE_VOLATILE (instance_ptr))
- {
- /* This action is needed because the instance is needed
- for providing the base of the virtual function table.
- Without using a SAVE_EXPR, the function we are building
- may be called twice, or side effects on the instance
- variable (such as a post-increment), may happen twice. */
- instance_ptr = save_expr (instance_ptr);
- instance = build_indirect_ref (instance_ptr, 0);
- }
- else if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE)
- {
- /* This happens when called for operator new (). */
- instance = build_indirect_ref (instance, 0);
- }
-
- need_vtbl = 1;
- }
- }
-
- if (TYPE_SIZE (basetype) == 0)
- {
- /* This is worth complaining about, I think. */
- error_with_aggr_type (basetype, "cannot lookup method in incomplete type `%s'");
- return error_mark_node;
- }
-
- /* Are we building a non-virtual wrapper? */
- if (flags & LOOKUP_NONVIRTUAL)
- {
- if (all_virtual)
- sorry ("non-virtual call with -fall-virtual");
- if (wrap)
- wrap_type = basetype;
- }
-
- save_basetype = basetype;
-
- if (all_virtual == 1
- && (! strncmp (IDENTIFIER_POINTER (name), OPERATOR_METHOD_FORMAT,
- OPERATOR_METHOD_LENGTH)
- || instance_ptr == NULL_TREE
- || (TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype) == 0
- && TYPE_NEEDS_WRAPPER (basetype) == 0)))
- all_virtual = 0;
-
- last = NULL_TREE;
- for (parmtypes = 0, parm = parms; parm; parm = TREE_CHAIN (parm))
- {
- tree t = TREE_TYPE (TREE_VALUE (parm));
- if (TREE_CODE (t) == OFFSET_TYPE)
- {
- /* Convert OFFSET_TYPE entities to their normal selves. */
- TREE_VALUE (parm) = resolve_offset_ref (TREE_VALUE (parm));
- t = TREE_TYPE (TREE_VALUE (parm));
- }
- if (TREE_CODE (t) == ARRAY_TYPE)
- {
- /* Perform the conversion from ARRAY_TYPE to POINTER_TYPE in place.
- This eliminates needless calls to `compute_conversion_costs'. */
- TREE_VALUE (parm) = default_conversion (TREE_VALUE (parm));
- t = TREE_TYPE (TREE_VALUE (parm));
- }
- if (t == error_mark_node)
- return error_mark_node;
- last = build_tree_list (NULL_TREE, t);
- parmtypes = chainon (parmtypes, last);
- }
-
- if (instance)
- {
- constp = TREE_READONLY (instance);
- volatilep = TREE_THIS_VOLATILE (instance);
- parms = tree_cons (NULL_TREE, instance_ptr, parms);
- }
- else
- {
- /* Raw constructors are always in charge. */
- if (TYPE_USES_VIRTUAL_BASECLASSES (basetype)
- && ! (flags & LOOKUP_HAS_IN_CHARGE))
- {
- flags |= LOOKUP_HAS_IN_CHARGE;
- parms = tree_cons (NULL_TREE, integer_one_node, parms);
- parmtypes = tree_cons (NULL_TREE, integer_type_node, parmtypes);
- }
-
- if (flag_this_is_variable)
- {
- constp = 0;
- volatilep = 0;
- parms = tree_cons (NULL_TREE, build1 (NOP_EXPR, TYPE_POINTER_TO (basetype), integer_zero_node), parms);
- }
- else
- {
- constp = 0;
- volatilep = 0;
- instance_ptr = save_expr (build_new (NULL_TREE, basetype, void_type_node));
- TREE_CALLS_NEW (instance_ptr) = 1;
- instance = build_indirect_ref (instance_ptr, 0);
- parms = tree_cons (NULL_TREE, instance_ptr, parms);
- }
- }
- parmtypes = tree_cons (NULL_TREE,
- build_pointer_type (build_type_variant (basetype, constp, volatilep)),
- parmtypes);
- if (last == NULL_TREE)
- last = parmtypes;
-
- /* Look up function name in the structure type definition. */
-
- if (wrap)
- {
- if (wrap > 0)
- name_kind = "wrapper";
- else
- name_kind = "anti-wrapper";
- baselink = get_wrapper (basetype);
- }
- else
- {
- if (TREE_TYPE (name)
- && TREE_CODE (TREE_TYPE (name)) == TYPE_DECL
- && IS_AGGR_TYPE (TREE_TYPE (TREE_TYPE (name))))
- {
- tree tmp = NULL_TREE;
- if (TREE_TYPE (name) == TYPE_NAME (basetype))
- tmp = basetype;
- else
- tmp = get_base_type (TREE_TYPE (TREE_TYPE (name)), basetype, 0);
- if (tmp != 0)
- {
- name_kind = "constructor";
-
- if (TYPE_USES_VIRTUAL_BASECLASSES (basetype)
- && ! (flags & LOOKUP_HAS_IN_CHARGE))
- {
- /* Constructors called for initialization
- only are never in charge. */
- tree tmplist;
-
- flags |= LOOKUP_HAS_IN_CHARGE;
- tmplist = tree_cons (NULL_TREE, integer_zero_node,
- TREE_CHAIN (parms));
- TREE_CHAIN (parms) = tmplist;
- tmplist = tree_cons (NULL_TREE, integer_type_node, TREE_CHAIN (parmtypes));
- TREE_CHAIN (parmtypes) = tmplist;
- }
-
- #ifdef SOS
- if (TYPE_DYNAMIC (basetype) && dtbl_inserted == 0)
- {
- tree parm, parmtype;
- dtbl = get_sos_dtable (basetype);
- parm = tree_cons (NULL_TREE, dtbl, TREE_CHAIN (parms));
- parmtype = tree_cons (NULL_TREE, build_pointer_type (ptr_type_node), TREE_CHAIN (parmtypes));
- TREE_CHAIN (parms) = parm;
- TREE_CHAIN (parmtypes) = parmtype;
- dtbl_inserted = -1;
- }
- #endif
- /* constructors are in very specific places. */
- #ifdef SOS
- if (dtbl_inserted == -1)
- {
- TREE_CHAIN (parmtypes) = TREE_CHAIN (TREE_CHAIN (parmtypes));
- TREE_CHAIN (parms) = TREE_CHAIN (TREE_CHAIN (parms));
- dtbl_inserted = 0;
- }
- #endif
- basetype = tmp;
- }
- else
- name_kind = "method";
- }
- else name_kind = "method";
-
- if (basetype_path == NULL_TREE)
- basetype_path = CLASSTYPE_AS_LIST (basetype);
- result = lookup_fnfields (basetype_path, name,
- (flags & LOOKUP_COMPLAIN));
- if (result == error_mark_node)
- return error_mark_node;
- }
-
- /* Now, go look for this method name. We do not find destructors here.
-
- Putting `void_list_node' on the end of the parmtypes
- fakes out `build_decl_overload' into doing the right thing. */
- TREE_CHAIN (last) = void_list_node;
- method_name = build_decl_overload (IDENTIFIER_POINTER (name),
- parmtypes,
- 1 + (name == DECL_NAME (TYPE_NAME (save_basetype))));
- TREE_CHAIN (last) = NULL_TREE;
-
- for (pass = 0; pass < 2; pass++)
- {
- struct candidate *candidates;
- struct candidate *cp;
- int len, best = 2;
-
- /* This increments every time we go up the type hierarchy.
- The idea is to prefer a function of the derived class if possible. */
- int b_or_d;
-
- baselink = result;
-
- if (pass > 0)
- {
- candidates = (struct candidate *) alloca ((ever_seen+1) * sizeof (struct candidate));
- cp = candidates;
- len = list_length (parms);
- b_or_d = 0;
-
- /* First see if a global function has a shot at it. */
- if (flags & LOOKUP_GLOBAL)
- {
- tree friend_parms;
- tree parm = TREE_VALUE (parms);
-
- if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE)
- friend_parms = parms;
- else if (TREE_CODE (TREE_TYPE (parm)) == POINTER_TYPE)
- {
- parm = build_indirect_ref (parm, "friendifying parms (compiler error)");
- parm = convert (build_reference_type (TREE_TYPE (parm)), parm);
- friend_parms = tree_cons (NULL_TREE, parm, TREE_CHAIN (parms));
- }
- else
- assert (0);
-
- cp->harshness
- = (unsigned short *)alloca ((len+1) * sizeof (short));
- result = build_overload_call (name, friend_parms, 0, cp);
- /* If it turns out to be the one we were actually looking for
- (it was probably a friend function), the return the
- good result. */
- if (TREE_CODE (result) == CALL_EXPR)
- return result;
-
- while (cp->evil == 0)
- {
- /* non-standard uses: set the field to 0 to indicate
- we are using a non-member function. */
- cp->u.field = 0;
- if (cp->harshness[len] == 0
- && cp->harshness[len] == 0
- && cp->user == 0 && cp->b_or_d == 0
- && cp->easy < best)
- best = cp->easy;
- cp += 1;
- }
- }
- }
-
- while (baselink)
- {
- /* We have a hit (of sorts). If the parameter list is
- "error_mark_node", or some variant thereof, it won't
- match any methods. Since we have verified that the is
- some method vaguely matching this one (in name at least),
- silently return.
-
- Don't stop for friends, however. */
- tree basetypes = TREE_PURPOSE (baselink);
-
- function = TREE_VALUE (baselink);
- basetype = TREE_VALUE (basetypes);
-
- /* Cast the instance variable to the approriate type. */
- TREE_VALUE (parmtypes) = TYPE_POINTER_TO (basetype);
-
- if (DESTRUCTOR_NAME_P (DECL_NAME (function)))
- function = TREE_CHAIN (function);
-
- for (; function; function = TREE_CHAIN (function))
- {
- #ifdef GATHER_STATISTICS
- n_inner_fields_searched++;
- #endif
- ever_seen++;
-
- /* Not looking for friends here. */
- if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE
- && ! DECL_STATIC_FUNCTION_P (function))
- continue;
-
- if (pass == 0
- && DECL_NAME (function) == method_name)
- {
- if (flags & LOOKUP_PROTECT)
- {
- visibility = compute_visibility (basetypes, function);
- if (visibility == visibility_protected
- && flags & LOOKUP_PROTECTED_OK)
- visibility = visibility_public;
- }
-
- if ((flags & LOOKUP_PROTECT) == 0
- || visibility == visibility_public)
- goto found_and_ok;
- else if (visibility == visibility_private)
- saw_private = function;
- else if (visibility == visibility_protected)
- saw_protected = function;
- /* If we fail on the exact match, we have
- an immediate failure. */
- goto found;
- }
- if (pass > 0)
- {
- tree these_parms = parms;
-
- #ifdef GATHER_STATISTICS
- n_inner_fields_searched++;
- #endif
- cp->harshness
- = (unsigned short *)alloca ((len+1) * sizeof (short));
- if (DECL_STATIC_FUNCTION_P (function))
- these_parms = TREE_CHAIN (these_parms);
- compute_conversion_costs (function, these_parms, cp, len);
- cp->b_or_d += b_or_d;
- if (cp->evil == 0)
- {
- cp->u.field = function;
- cp->function = function;
- if (flags & LOOKUP_PROTECT)
- {
- enum visibility_type this_v;
- this_v = compute_visibility (basetypes, function);
- if (this_v == visibility_protected
- && (flags & LOOKUP_PROTECTED_OK))
- this_v = visibility_public;
- if (this_v != visibility_public)
- {
- if (this_v == visibility_private)
- saw_private = function;
- else
- saw_protected = function;
- continue;
- }
- }
-
- /* No "two-level" conversions. */
- if (flags & LOOKUP_NO_CONVERSION && cp->user != 0)
- continue;
-
- /* If we used default parameters, we must
- check to see whether anyone else might
- use them also, and report a possible
- ambiguity. */
- if (! TYPE_USES_MULTIPLE_INHERITANCE (save_basetype)
- && cp->harshness[len] == 0
- && (cp->harshness[0] & 128) == 0
- && cp->user == 0 && cp->b_or_d == 0
- && cp->easy < best)
- {
- if (! DECL_STATIC_FUNCTION_P (function))
- TREE_VALUE (parms) = cp->arg;
- if (best == 2)
- goto found_and_maybe_warn;
- }
- cp++;
- }
- }
- }
- /* Now we have run through one link's member functions.
- arrange to head-insert this link's links. */
- baselink = next_baselink (baselink);
- b_or_d += 1;
- }
- if (pass == 0)
- {
- /* No exact match could be found. Now try to find match
- using default conversions. */
- if ((flags & LOOKUP_GLOBAL) && IDENTIFIER_GLOBAL_VALUE (name))
- if (TREE_CODE (IDENTIFIER_GLOBAL_VALUE (name)) == FUNCTION_DECL)
- ever_seen += 1;
- else if (TREE_CODE (IDENTIFIER_GLOBAL_VALUE (name)) == TREE_LIST)
- ever_seen += list_length (IDENTIFIER_GLOBAL_VALUE (name));
-
- if (ever_seen == 0)
- {
- if (flags & LOOKUP_GLOBAL)
- error ("no global or member function `%s' defined", err_name);
- else
- error_with_aggr_type (save_basetype, "no member function `%s::%s'", err_name);
- return error_mark_node;
- }
- continue;
- }
-
- if (cp - candidates != 0)
- {
- /* Rank from worst to best. Then cp will point to best one.
- Private fields have their bits flipped. For unsigned
- numbers, this should make them look very large.
- If the best alternate has a (signed) negative value,
- then all we ever saw were private members. */
- if (cp - candidates > 1)
- {
- cp = ideal_candidate (save_basetype, candidates,
- cp - candidates, parms, len);
- if (cp == 0)
- {
- error ("ambiguous type conversion requested for %s `%s'",
- name_kind, err_name);
- return error_mark_node;
- }
- }
- else if (cp[-1].evil == 2)
- {
- error ("ambiguous type conversion requested for %s `%s'",
- name_kind, err_name);
- return error_mark_node;
- }
- else cp--;
-
- /* The global function was the best, so use it. */
- if (cp->u.field == 0)
- {
- /* We must convert the instance pointer into a reference type.
- Global overloaded functions can only either take
- aggregate objects (which come for free from references)
- or reference data types anyway. */
- TREE_VALUE (parms) = copy_node (instance_ptr);
- TREE_TYPE (TREE_VALUE (parms)) = build_reference_type (TREE_TYPE (TREE_TYPE (instance_ptr)));
- return build_function_call (cp->function, parms);
- }
-
- function = cp->function;
- if (DECL_STATIC_FUNCTION_P (function))
- basetype = NULL_TREE;
- else
- {
- basetype = TREE_TYPE (TREE_TYPE (cp->arg));
- TREE_VALUE (parms) = cp->arg;
- }
- goto found_and_maybe_warn;
- }
-
- if ((flags & ~LOOKUP_GLOBAL) & (LOOKUP_COMPLAIN|LOOKUP_SPECULATIVELY))
- {
- char *tag_name, *buf;
-
- if (DECL_STATIC_FUNCTION_P (cp->function))
- parms = TREE_CHAIN (parms);
- if (ever_seen)
- {
- if (((int)saw_protected|(int)saw_private) == 0)
- {
- if (flags & LOOKUP_SPECULATIVELY)
- return NULL_TREE;
- if (static_call_context && TREE_CODE (TREE_TYPE (cp->function)) == METHOD_TYPE)
- error_with_aggr_type (TREE_TYPE (TREE_TYPE (instance_ptr)),
- "object missing in call to `%s::%s'",
- err_name);
- else
- report_type_mismatch (cp, parms, name_kind, err_name);
- }
- else
- {
- char buf[80];
- char *msg;
- tree seen = saw_private;
-
- if (saw_private)
- if (saw_protected)
- msg = "%s %%s (and the like) are private or protected";
- else
- msg = "the %s %%s is private";
- else
- {
- msg = "the %s %%s is protected";
- seen = saw_protected;
- }
- sprintf (buf, msg, name_kind);
- error_with_decl (seen, buf);
- error ("within this context");
- }
- return error_mark_node;
- }
-
- if ((flags & ~LOOKUP_SPECULATIVELY) & LOOKUP_COMPLAIN)
- {
- if (TREE_CODE (save_basetype) == RECORD_TYPE)
- tag_name = "structure";
- else
- tag_name = "union";
-
- if (wrap)
- buf = "%s has no appropriate wrapper function defined";
- else
- {
- buf = (char *)alloca (30 + strlen (err_name));
- strcpy (buf, "%s has no method named `%s'");
- }
-
- error (buf, tag_name, err_name);
- return error_mark_node;
- }
- return NULL_TREE;
- }
- continue;
-
- found_and_maybe_warn:
- if (cp->harshness[0] & 128)
- {
- if (flags & LOOKUP_COMPLAIN)
- {
- error_with_decl (cp->function, "non-const member function `%s'");
- error ("called for const object at this point in file");
- }
- /* Not good enough for a match. */
- else return error_mark_node;
- }
- goto found_and_ok;
- }
- /* Silently return error_mark_node. */
- return error_mark_node;
-
- found:
- if (visibility == visibility_private)
- {
- if (flags & LOOKUP_COMPLAIN)
- error (TREE_PRIVATE (function)
- ? "%s `%s' is private"
- : "%s `%s' is from private base class",
- name_kind,
- lang_printable_name (function));
- return error_mark_node;
- }
- else if (visibility == visibility_protected)
- {
- if (flags & LOOKUP_COMPLAIN)
- error (TREE_PROTECTED (function)
- ? "%s `%s' is protected"
- : "%s `%s' has protected visibility from this point",
- name_kind,
- lang_printable_name (function));
- return error_mark_node;
- }
- abort ();
-
- found_and_ok:
-
- /* From here on down, BASETYPE is the type that INSTANCE_PTR's
- type (if it exists) is a pointer to. */
- basetype = DECL_CONTEXT (function);
- fntype = TREE_TYPE (function);
-
- if (TREE_CODE (fntype) == POINTER_TYPE)
- fntype = TREE_TYPE (fntype);
-
- if (TREE_CODE (fntype) == METHOD_TYPE && static_call_context)
- {
- /* Let's be nice to the user for now, and give reasonable
- default behavior. */
- instance_ptr = current_class_decl;
- if (instance_ptr)
- {
- if (basetype != current_class_type)
- {
- basetype = get_base_type (basetype, current_class_type, 1);
- if (basetype == 0)
- {
- error_not_base_type (DECL_CONTEXT (function), current_class_type);
- return error_mark_node;
- }
- else if (basetype == error_mark_node)
- return error_mark_node;
- }
- }
- else
- {
- error_with_aggr_type (basetype, "cannot call member function `%s::%s' without object",
- err_name);
- return error_mark_node;
- }
- }
-
- value_type = TREE_TYPE (fntype) ? TREE_TYPE (fntype) : void_type_node;
-
- if (TYPE_SIZE (value_type) == 0)
- {
- if (flags & LOOKUP_COMPLAIN)
- incomplete_type_error (0, value_type);
- return error_mark_node;
- }
-
- /* We do not pass FUNCTION into `actualparameterlist', because by
- now everything should be ok. If not, then we have a serious error. */
- if (DECL_STATIC_FUNCTION_P (function))
- parms = actualparameterlist (NULL_TREE, TYPE_ARG_TYPES (fntype),
- TREE_CHAIN (parms), NULL_TREE, LOOKUP_NORMAL);
- else
- {
- int sub_flags = DECL_CONSTRUCTOR_P (function) ? flags : LOOKUP_NORMAL;
-
- if ((flags & LOOKUP_NONVIRTUAL) == 0)
- basetype = DECL_VCONTEXT (function);
-
- /* First parm could be integer_zerop with casts like
- ((Object*)0)->Object::IsA() */
- if (!integer_zerop (TREE_VALUE (parms)))
- {
- instance_ptr = convert_pointer_to (build_type_variant (basetype, constp, volatilep),
- TREE_VALUE (parms));
- if (TREE_CODE (instance_ptr) == COND_EXPR)
- {
- instance_ptr = save_expr (instance_ptr);
- instance = build_indirect_ref (instance_ptr);
- }
- else if (TREE_CODE (instance_ptr) == NOP_EXPR
- && TREE_CODE (TREE_OPERAND (instance_ptr, 0)) == ADDR_EXPR
- && TREE_OPERAND (TREE_OPERAND (instance_ptr, 0), 0) == instance)
- ;
- else if (instance == NULL_TREE
- || TREE_CODE (instance) != INDIRECT_REF
- || TREE_OPERAND (instance, 0) != instance_ptr)
- instance = build_indirect_ref (instance_ptr);
- }
- parms = tree_cons (NULL_TREE, instance_ptr,
- actualparameterlist (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), NULL_TREE, sub_flags));
- }
-
- /* See if there is a wrapper for this thing. */
- if (wrap < 0
- || static_call_context
- || name == wrapper_name
- || name == DECL_NAME (TYPE_NAME (basetype)))
- ;
- else if (wrap > 0 || TYPE_NEEDS_WRAPPER (basetype))
- {
- flags &= ~LOOKUP_PROTECT;
- if (wrap == 0)
- {
- wrap = TYPE_NEEDS_WRAPPER (basetype);
- /* If no wrapper specified, wrapper may be virtual. */
- flags &= ~LOOKUP_NONVIRTUAL;
- }
-
- if (wrap)
- {
- tree wrapped_result, unwrapped_result;
- register int bytecount = get_arglist_len_in_bytes (parms);
-
- if (!all_virtual && TREE_CODE (function) == FUNCTION_DECL)
- parm = build_unary_op (ADDR_EXPR, function, 0);
- else
- {
- fntype = build_cplus_method_type (basetype, TREE_TYPE (fntype), TYPE_ARG_TYPES (fntype));
- parm = build1 (NOP_EXPR, build_pointer_type (fntype), DECL_VINDEX (function));
- }
-
- if (TYPE_HAS_WRAPPER_PRED (basetype))
- {
- unwrapped_result = build_nt (CALL_EXPR, default_conversion (function), parms, NULL_TREE);
-
- assert (TREE_OPERAND (unwrapped_result, 1) != error_mark_node);
-
- TREE_TYPE (unwrapped_result) = value_type;
- TREE_VOLATILE (unwrapped_result) = 1;
- TREE_RAISES (unwrapped_result) = !! TYPE_RAISES_EXCEPTIONS (fntype);
- }
-
- /* If this pointer walked as a result of multiple inheritance,
- keep its displaced value. */
- parms = tree_cons (NULL_TREE, build_int_2 (bytecount, 0),
- tree_cons (NULL_TREE, parm, TREE_CHAIN (parms)));
-
- wrapped_result = get_wrapper (basetype);
- assert (wrapped_result != NULL_TREE);
- assert (wrapped_result != error_mark_node);
-
- /* @@ Should BASETYPE_PATH get TREE_PURPOSE (wrapped_result) here? */
- wrapped_result
- = build_method_call (instance,
- DECL_ORIGINAL_NAME (TREE_VALUE (wrapped_result)),
- parms, basetype_path, flags);
- #if 0
- /* Do this if we want the result of operator->() to inherit
- the type of the function it is subbing for. */
- if (wrapped_result != error_mark_node)
- TREE_TYPE (wrapped_result) = value_type;
- #endif
-
- if (TYPE_HAS_WRAPPER_PRED (basetype))
- {
- result = build_conditional_expr
- (build_method_call (instance, wrapper_pred_name, build_tree_list (NULL_TREE, parm), basetype_path, LOOKUP_NORMAL),
- wrapped_result,
- unwrapped_result);
-
- }
- else
- {
- result = wrapped_result;
- }
-
- TREE_VOLATILE (result) = 1;
- return result;
- }
- }
- /* Constructors do not overload method calls. */
- else if (TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype)
- && name != DECL_NAME (TYPE_NAME (basetype))
- && (TREE_CODE (function) != FUNCTION_DECL
- || strncmp (IDENTIFIER_POINTER (DECL_NAME (function)),
- OPERATOR_METHOD_FORMAT,
- OPERATOR_METHOD_LENGTH))
- && (may_be_remote (basetype)
- || (C_C_D ? TREE_TYPE (instance) != current_class_type : 1)))
- {
- #ifdef ESKIT
- register int bytecount = 0;
- #else
- register int bytecount = get_arglist_len_in_bytes (parms);
- #endif
- tree fn_as_int;
-
- parms = tree_cons (NULL_TREE, build_int_2 (bytecount, 0),
- TREE_CHAIN (parms));
-
- if (!all_virtual && TREE_CODE (function) == FUNCTION_DECL)
- fn_as_int = build_unary_op (ADDR_EXPR, function, 0);
- else
- fn_as_int = convert (TREE_TYPE (default_conversion (function)), DECL_VINDEX (function));
- if (all_virtual == 1)
- fn_as_int = convert (integer_type_node, fn_as_int);
-
- result = build_opfncall (METHOD_CALL_EXPR, instance, fn_as_int, parms);
-
- if (result == NULL_TREE)
- {
- compiler_error ("could not overload `operator->()(...)'");
- return error_mark_node;
- }
- else if (result == error_mark_node)
- return error_mark_node;
-
- #if 0
- /* Do this if we want the result of operator->() to inherit
- the type of the function it is subbing for. */
- TREE_TYPE (result) = value_type;
- #endif
-
- #ifdef ESKIT
- {
- int used, size;
-
- /* Count the number of bytes of arguements to operator->(),
- not to the method itself. In the tally, don't count bytes
- for pointer to member function or for the bytecount. */
- parms = TREE_OPERAND (result, 1);
- bytecount = get_arglist_len_in_bytes (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (parms))));
- used = size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_VALUE (parms))));
- #ifdef PUSH_ROUNDING
- size = PUSH_ROUNDING (size);
- #endif
- used = (((size + PARM_BOUNDARY / BITS_PER_UNIT - 1)
- / (PARM_BOUNDARY / BITS_PER_UNIT))
- * (PARM_BOUNDARY / BITS_PER_UNIT));
- bytecount += used;
- TREE_CHAIN (TREE_CHAIN (parms))
- = tree_cons (NULL_TREE, build_int_2 (bytecount, 0),
- TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (parms))));
- }
- #endif
-
- return result;
- }
-
- /* If we are referencing a virtual function from an object
- of effectively static type, then there is no need
- to go through the virtual function table. */
- if (need_vtbl)
- {
- int use_vtable = 0;
- int fixed_type = resolves_to_fixed_type_p (instance);
-
- if (all_virtual == 1
- && DECL_VINDEX (function)
- && may_be_remote (basetype))
- use_vtable = 1;
- else if (DECL_VIRTUAL_P (function) && ! fixed_type)
- use_vtable = 1;
-
- if (fixed_type && DECL_ABSTRACT_VIRTUAL_P (function))
- {
- error_with_decl (function, "invalid call to abstract function `%s'");
- return error_mark_node;
- }
- if (use_vtable)
- {
- function = build_vfn_ref (&TREE_VALUE (parms), instance, DECL_VINDEX (function));
- TREE_TYPE (function) = build_pointer_type (fntype);
- }
- }
- #ifdef SOS
- else if (basetype && TYPE_DYNAMIC (basetype))
- {
- function = build_array_ref (dtbl, DECL_DINDEX (function));
- TREE_TYPE (function) = build_pointer_type (fntype);
- }
- #endif
-
- if (TREE_INLINE (function) && TREE_CODE (function) == FUNCTION_DECL)
- function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);
- else function = default_conversion (function);
-
- result =
- build_nt (CALL_EXPR, function, parms, NULL_TREE);
-
- TREE_TYPE (result) = value_type;
- TREE_VOLATILE (result) = 1;
- TREE_RAISES (result)
- = TYPE_RAISES_EXCEPTIONS (fntype) || (parms && TREE_RAISES (parms));
- return result;
- }
-
- /* Similar to `build_method_call', but for overloaded non-member functions.
- The name of this function comes through NAME. The name depends
- on PARMS.
-
- Note that this function must handle simple `C' promotions,
- as well as variable numbers of arguments (...), and
- default arguments to boot.
-
- If the overloading is successful, we return a treenode which
- contains the call to the function.
-
- If overloading produces candidates which are probabe, but not definite,
- we hold these candidates. If FINAL_CP is non-zero, then we are free
- to assume that final_cp points to enough storage for all candidates that
- this function might generate. The `harshness' array is preallocated for
- the first candidate, but not for subsequent ones.
-
- Note that the DECL_RTL of FUNCTION must be made to agree with this
- function's new name. */
-
- tree
- build_overload_call (fnname, parms, complain, final_cp)
- tree fnname, parms;
- int complain;
- struct candidate *final_cp;
- {
- /* must check for overloading here */
- tree overload_name, functions, function, parm;
- tree parmtypes = NULL_TREE, last = NULL_TREE;
- register tree outer;
- int length;
- int parmlength = list_length (parms);
-
- struct candidate *candidates, *cp;
- int rank_for_overload ();
-
- if (final_cp)
- {
- final_cp[0].evil = 0;
- final_cp[0].user = 0;
- final_cp[0].b_or_d = 0;
- final_cp[0].easy = 0;
- final_cp[0].function = 0;
- /* end marker. */
- final_cp[1].evil = 1;
- }
-
- for (parm = parms; parm; parm = TREE_CHAIN (parm))
- {
- register tree t = TREE_TYPE (TREE_VALUE (parm));
-
- if (t == error_mark_node)
- return error_mark_node;
- if (TREE_CODE (t) == ARRAY_TYPE || TREE_CODE (t) == OFFSET_TYPE)
- {
- /* Perform the conversion from ARRAY_TYPE to POINTER_TYPE in place.
- Also convert OFFSET_TYPE entities to their normal selves.
- This eliminates needless calls to `compute_conversion_costs'. */
- TREE_VALUE (parm) = default_conversion (TREE_VALUE (parm));
- t = TREE_TYPE (TREE_VALUE (parm));
- }
- last = build_tree_list (NULL_TREE, t);
- parmtypes = chainon (parmtypes, last);
- }
- if (last)
- TREE_CHAIN (last) = void_list_node;
- else
- parmtypes = void_list_node;
- overload_name = build_decl_overload (IDENTIFIER_POINTER (fnname), parmtypes, 0);
-
- /* Now check to see whether or not we can win.
- Note that if we are called from `build_method_call',
- then we cannot have a mis-match, because we would have
- already found such a winning case. */
-
- if (IDENTIFIER_GLOBAL_VALUE (overload_name))
- if (TREE_CODE (IDENTIFIER_GLOBAL_VALUE (overload_name)) != TREE_LIST)
- return build_function_call (DECL_MAIN_VARIANT (IDENTIFIER_GLOBAL_VALUE (overload_name)), parms);
-
- functions = IDENTIFIER_GLOBAL_VALUE (fnname);
-
- if (functions == NULL_TREE)
- {
- if (complain)
- error ("only member functions apply");
- if (final_cp)
- final_cp->evil = 1;
- return error_mark_node;
- }
-
- if (TREE_CODE (functions) == FUNCTION_DECL)
- {
- functions = DECL_MAIN_VARIANT (functions);
- if (final_cp)
- {
- /* We are just curious whether this is a viable alternative or not. */
- compute_conversion_costs (functions, parms, final_cp, parmlength);
- return functions;
- }
- else
- return build_function_call (functions, parms);
- }
-
- if (TREE_VALUE (functions) == NULL_TREE)
- {
- if (complain)
- error ("function `%s' declared overloaded, but no instances of that function declared",
- IDENTIFIER_POINTER (TREE_PURPOSE (functions)));
- return error_mark_node;
- }
-
- if (TREE_CODE (TREE_VALUE (functions)) == TREE_LIST)
- {
- register tree outer;
- length = 0;
-
- /* The list-of-lists should only occur for class things. */
- assert (functions == IDENTIFIER_CLASS_VALUE (fnname));
-
- for (outer = functions; outer; outer = TREE_CHAIN (outer))
- {
- /* member functions. */
- length += list_length (TREE_VALUE (TREE_VALUE (outer)));
- /* friend functions. */
- length += list_length (TREE_TYPE (TREE_VALUE (outer)));
- }
- }
- else
- {
- length = list_length (functions);
- }
-
- if (final_cp)
- candidates = final_cp;
- else
- candidates = (struct candidate *)alloca ((length+1) * sizeof (struct candidate));
-
- cp = candidates;
-
- assert (TREE_CODE (TREE_VALUE (functions)) != TREE_LIST);
- /* OUTER is the list of FUNCTION_DECLS, in a TREE_LIST. */
-
- for (outer = functions; outer; outer = TREE_CHAIN (outer))
- {
- function = TREE_VALUE (outer);
- if (TREE_CODE (function) != FUNCTION_DECL)
- {
- if (TREE_CODE (function) == CONST_DECL)
- error_with_decl (function, "enumeral value `%s' conflicts with function of same name");
- else if (TREE_CODE (function) == VAR_DECL)
- if (TREE_STATIC (function))
- error_with_decl (function, "variable `%s' conflicts with function of same name");
- else
- error_with_decl (function, "constant field `%s' conflicts with function of same name");
- else if (TREE_CODE (function) == TYPE_DECL)
- continue;
- else abort ();
- error ("at this point in file");
- continue;
- }
- function = DECL_MAIN_VARIANT (function);
- /* Can't use alloca here, since result might be
- passed to calling function. */
- cp->harshness
- = (unsigned short *)oballoc ((parmlength+1) * sizeof (short));
- compute_conversion_costs (function, parms, cp, parmlength);
- if (cp[0].evil == 0)
- {
- cp[1].evil = 1;
- if (final_cp
- && cp[0].user == 0 && cp[0].b_or_d == 0
- && cp[0].easy <= 1)
- {
- final_cp[0].easy = cp[0].easy;
- return function;
- }
- cp++;
- }
- }
-
- if (cp - candidates)
- {
- tree rval = error_mark_node;
-
- /* Leave marker. */
- cp[0].evil = 1;
- if (cp - candidates > 1)
- {
- struct candidate *best_cp
- = ideal_candidate (NULL_TREE, candidates,
- cp - candidates, parms, parmlength);
- if (best_cp == 0)
- {
- if (complain)
- error ("call of overloaded `%s' is ambiguous", IDENTIFIER_POINTER (fnname));
- return error_mark_node;
- }
- else
- rval = best_cp->function;
- }
- else
- {
- cp -= 1;
- if (cp->evil > 1)
- {
- if (complain)
- error ("type conversion ambiguous");
- }
- else
- rval = cp->function;
- }
-
- if (final_cp)
- return rval;
-
- return build_function_call (rval, parms);
- }
- else if (complain)
- {
- tree name;
- char *err_name;
- /* Initialize name for error reporting. */
- if (TREE_CODE (functions) == TREE_LIST)
- name = TREE_PURPOSE (functions);
- else
- name = DECL_ORIGINAL_NAME (functions);
-
- if (OPERATOR_NAME_P (name))
- {
- char *opname = operator_name_string (name);
- err_name = (char *)alloca (strlen (opname) + 12);
- sprintf (err_name, "operator %s", opname);
- }
- else
- err_name = IDENTIFIER_POINTER (name);
-
- report_type_mismatch (cp, parms, "function", err_name);
- }
- return error_mark_node;
- }
-
- void
- init_class_processing ()
- {
- 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;
-
- delta_name = get_identifier (VTABLE_DELTA_NAME);
- pfn_name = get_identifier (VTABLE_PFN_NAME);
-
- /* Keep these values lying around. */
- minus_one_node = build_int_2 (-1, 0);
- 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);
-
- 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;") */
-
- /* Here's a subroutine we need because C lacks lambdas. */
- void
- unuse_fields (type)
- tree type;
- {
- tree fields;
-
- for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
- {
- if (TREE_CODE (fields) != FIELD_DECL)
- continue;
-
- TREE_USED (fields) = 0;
- if (DECL_ANON_UNION_ELEM (fields))
- unuse_fields (TREE_TYPE (fields));
- }
- }
-
- /* 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).
-
- So that we may avoid calls to lookup_name, we cache the TYPE_DECL
- 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_stack++ = current_class_name;
- *current_class_stack++ = current_class_type;
- if (current_class_stack >= current_class_base + current_class_stacksize - 1)
- {
- current_class_base =
- (tree *)xrealloc (current_class_base, current_class_stacksize + 10);
- current_class_stack = current_class_base + current_class_stacksize;
- current_class_stacksize += 10;
- }
-
- type = TYPE_MAIN_VARIANT (type);
- current_class_name = TYPE_NAME (type);
- if (TREE_CODE (current_class_name) == TYPE_DECL)
- current_class_name = DECL_NAME (current_class_name);
- current_class_type = type;
-
- if (type != prev_class_type && prev_class_type != NULL_TREE
- && current_class_stack == current_class_base + 2)
- {
- popclass (-1);
- prev_class_type = 0;
- }
-
- if (modify)
- {
- tree tags;
-
- if (type != prev_class_type)
- {
- build_mi_matrix (type);
- push_class_decls (type);
- free_mi_matrix ();
- prev_class_type = type;
- }
- else
- unuse_fields (type);
-
- tags = CLASSTYPE_TAGS (type);
- while (tags)
- {
- TREE_NONLOCAL (TREE_VALUE (tags)) = 1;
- pushtag (TREE_PURPOSE (tags), TREE_VALUE (tags));
- if (IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (tags)) == NULL_TREE
- && TREE_CODE (TYPE_NAME (TREE_VALUE (tags))) == TYPE_DECL)
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (tags))
- = TYPE_NAME (TREE_VALUE (tags));
- tags = TREE_CHAIN (tags);
- }
- }
- else
- pushlevel_class ();
- }
-
- /* 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 new scope. */
- void
- popclass (modify)
- int modify;
- {
- if (modify < 0)
- {
- /* Back this old class out completely. */
- tree tags = CLASSTYPE_TAGS (prev_class_type);
-
- pop_class_decls (prev_class_type);
- while (tags)
- {
- TREE_NONLOCAL (TREE_VALUE (tags)) = 0;
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (tags)) = NULL_TREE;
- tags = TREE_CHAIN (tags);
- }
- return;
- }
- if (modify)
- {
- /* Just remove from this class what didn't make
- it into IDENTIFIER_CLASS_VALUE. */
- tree tags = CLASSTYPE_TAGS (current_class_type);
-
- while (tags)
- {
- TREE_NONLOCAL (TREE_VALUE (tags)) = 0;
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (tags)) = NULL_TREE;
- tags = TREE_CHAIN (tags);
- }
- }
- else
- poplevel_class ();
-
- 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)));
- if (current_vtable_decl)
- current_vtable_decl = build_indirect_ref (current_vtable_decl, 0);
- }
- current_class_decl = lookup_name (get_identifier (THIS_NAME));
- if (current_class_decl)
- {
- if (TREE_CODE (TREE_TYPE (current_class_decl)) == POINTER_TYPE)
- {
- /* 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);
- TREE_READONLY (C_C_D) = TREE_READONLY (TREE_TYPE (TREE_TYPE (current_class_decl)));
- TREE_VOLATILE (C_C_D) = TREE_VOLATILE (TREE_TYPE (TREE_TYPE (current_class_decl)));
- }
- 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);
- }
-
- /* Set global variables CURRENT_LANG_NAME to appropriate value
- so that behavior of name-mangline 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, 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));
- }
-
- /* Get out of the current language scope. */
- void
- pop_lang_context ()
- {
- 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, actualparameterlist,
- build_c_cast, and compute_conversion_costs. */
- tree
- instantiate_type (lhstype, rhs, complain)
- tree lhstype, rhs;
- int complain;
- {
- if (TREE_CODE (rhs) == OP_IDENTIFIER)
- return build_instantiated_decl (lhstype, rhs);
-
- 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
- arithmethic 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:
- assert (0);
- 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;
- assert (TREE_CODE (function) == FUNCTION_DECL);
- if (DECL_VIRTUAL_P (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_VCONTEXT (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;
- }
-
- assert (TREE_CODE (field) == FIELD_DECL);
- assert (!(TREE_CODE (TREE_TYPE (field)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (field)) == METHOD_TYPE));
-
- 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);
-
- /* First look for an exact match. Search either overloaded
- functions or member functions. May have to undo what
- `default_conversion' or `datatype' 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)
- error ("cannot resolve overloaded function `%s' based on non-function type",
- IDENTIFIER_POINTER (TREE_PURPOSE (rhs)));
- return error_mark_node;
- }
-
- if (globals > 0)
- {
- assert (TREE_CODE (TREE_VALUE (rhs)) == FUNCTION_DECL);
- elem = rhs;
- while (elem)
- if (TREE_TYPE (TREE_VALUE (elem)) != lhstype)
- elem = TREE_CHAIN (elem);
- else
- return TREE_VALUE (elem);
- /* No exact match found, look for a compatible function. */
- elem = rhs;
- while (elem && ! comp_target_types (lhstype, TREE_TYPE (TREE_VALUE (elem)), 1))
- elem = TREE_CHAIN (elem);
- if (elem)
- {
- tree save_elem = TREE_VALUE (elem);
- elem = TREE_CHAIN (elem);
- while (elem && ! comp_target_types (lhstype, TREE_TYPE (TREE_VALUE (elem)), 0))
- elem = TREE_CHAIN (elem);
- if (elem)
- {
- if (complain)
- error ("ambiguous overload for overloaded function requested");
- return error_mark_node;
- }
- return save_elem;
- }
- if (complain)
- {
- if (TREE_CHAIN (rhs))
- error ("no appropriate overload for overloaded function `%s' exists",
- IDENTIFIER_POINTER (TREE_PURPOSE (rhs)));
- else
- error ("function `%s' has inappropriate type signature",
- IDENTIFIER_POINTER (TREE_PURPOSE (rhs)));
- }
- return error_mark_node;
- }
-
- if (TREE_NONLOCAL (rhs))
- {
- /* Got to get it as a baselink. */
- rhs = lookup_fnfields (CLASSTYPE_AS_LIST (current_class_type),
- TREE_PURPOSE (rhs), 0);
- }
- else
- {
- assert (TREE_CHAIN (rhs) == NULL_TREE);
- if (TREE_CODE (TREE_VALUE (rhs)) == TREE_LIST)
- rhs = TREE_VALUE (rhs);
- assert (TREE_CODE (TREE_VALUE (rhs)) == FUNCTION_DECL);
- }
-
- for (baselink = rhs; baselink;
- baselink = next_baselink (baselink))
- {
- elem = TREE_VALUE (baselink);
- while (elem)
- if (TREE_TYPE (elem) != lhstype)
- elem = TREE_CHAIN (elem);
- else
- return 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_ORIGINAL_NAME (TREE_VALUE (rhs));
- if (TREE_CODE (lhstype) == FUNCTION_TYPE && globals < 0)
- {
- /* Try to instantiate from non-member functions. */
- rhs = IDENTIFIER_GLOBAL_VALUE (name);
- if (rhs && TREE_CODE (rhs) == TREE_LIST)
- {
- /* This code seems to be missing a `return'. */
- abort ();
- instantiate_type (lhstype, rhs, complain);
- }
- }
-
- 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. */
- assert (0);
- 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 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 (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_OPERAND (rhs, 0) = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
- if (TREE_OPERAND (rhs, 0) == error_mark_node)
- return error_mark_node;
-
- mark_addressable (TREE_OPERAND (rhs, 0));
- return rhs;
-
- case ENTRY_VALUE_EXPR:
- assert (0);
- return error_mark_node;
-
- case ERROR_MARK:
- return error_mark_node;
-
- default:
- assert (0);
- return error_mark_node;
- }
- }
-
- /* This routine is called when we finally know the type of expression
- we are looking for. If the operator encoded by EXP can take an
- argument of type TYPE, return the FUNCTION_DECL for that operator. */
- tree
- build_instantiated_decl (type, exp)
- tree type, exp;
- {
- tree parmtypes, decl, name;
-
- assert (TREE_CODE (exp) == OP_IDENTIFIER);
- type = datatype (type);
- if (TREE_CODE (type) != POINTER_TYPE
- || (TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE
- && TREE_CODE (TREE_TYPE (type)) != METHOD_TYPE))
- {
- error ("invalid type used to resolve overloaded function");
- return error_mark_node;
- }
-
-
- /* Now we know the type of this function, so overload it. */
- parmtypes = TYPE_ARG_TYPES (TREE_TYPE (type));
- name = build_operator_fnname (&TREE_VALUE (exp), parmtypes, 0);
- if (name)
- {
- name = build_decl_overload (IDENTIFIER_POINTER (name), parmtypes, 1);
- decl = lookup_name (name);
- if (decl)
- return decl;
- error ("no suitable declaration of `operator %s' for overloading",
- operator_name_string (name));
- return error_mark_node;
- }
- return error_mark_node;
- }
-
- /* Return the name of the virtual function table (as an IDENTIFIER_NODE)
- for the given TYPE. */
- static tree
- get_vtable_name (type)
- tree type;
- {
- char *buf = (char *)alloca (sizeof (VTABLE_NAME_FORMAT)
- + TYPE_NAME_LENGTH (type)
- + 2);
- sprintf (buf, VTABLE_NAME_FORMAT, TYPE_NAME_STRING (type));
- return get_identifier (buf);
- }
-
- /* 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;
- {
- char *buf;
-
- while (CLASSTYPE_N_BASECLASSES (type)
- && TYPE_VIRTUAL_P (CLASSTYPE_BASECLASS (type, 1))
- && ! CLASSTYPE_VIA_VIRTUAL (type, 1))
- type = CLASSTYPE_BASECLASS (type, 1);
-
- 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
- }
-