#include "toplev.h"
#include "stack.h"
-/* Obstack used for remembering decision points of breadth-first. */
-
-static struct obstack search_obstack;
-
-/* Methods for pushing and popping objects to and from obstacks. */
-
-struct stack_level *
-push_stack_level (struct obstack *obstack, char *tp,/* Sony NewsOS 5.0 compiler doesn't like void * here. */
- int size)
-{
- struct stack_level *stack;
- obstack_grow (obstack, tp, size);
- stack = (struct stack_level *) ((char*)obstack_next_free (obstack) - size);
- obstack_finish (obstack);
- stack->obstack = obstack;
- stack->first = (tree *) obstack_base (obstack);
- stack->limit = obstack_room (obstack) / sizeof (tree *);
- return stack;
-}
-
-struct stack_level *
-pop_stack_level (struct stack_level *stack)
-{
- struct stack_level *tem = stack;
- struct obstack *obstack = tem->obstack;
- stack = tem->prev;
- obstack_free (obstack, tem);
- return stack;
-}
-
-#define search_level stack_level
-static struct search_level *search_stack;
-
struct vbase_info
{
/* The class dominating the hierarchy. */
static tree dfs_no_overlap_yet (tree, int, void *);
static base_kind lookup_base_r (tree, tree, base_access, bool, tree *);
static int dynamic_cast_base_recurse (tree, tree, bool, tree *);
-static tree marked_pushdecls_p (tree, int, void *);
-static tree unmarked_pushdecls_p (tree, int, void *);
static tree dfs_debug_unmarkedp (tree, int, void *);
static tree dfs_debug_mark (tree, void *);
-static tree dfs_push_type_decls (tree, void *);
-static tree dfs_push_decls (tree, void *);
-static tree dfs_unuse_fields (tree, void *);
-static tree add_conversions (tree, void *);
+static int check_hidden_convs (tree, int, int, tree, tree, tree);
+static tree split_conversions (tree, tree, tree, tree);
+static int lookup_conversions_r (tree, int, int,
+ tree, tree, tree, tree, tree *, tree *);
static int look_for_overrides_r (tree, tree);
-static struct search_level *push_search_level (struct stack_level *,
- struct obstack *);
-static struct search_level *pop_search_level (struct stack_level *);
static tree bfs_walk (tree, tree (*) (tree, void *),
tree (*) (tree, int, void *), void *);
static tree lookup_field_queue_p (tree, int, void *);
static access_kind access_in_type (tree, tree);
static int protected_accessible_p (tree, tree, tree);
static int friend_accessible_p (tree, tree, tree);
-static void setup_class_bindings (tree, int);
static int template_self_reference_p (tree, tree);
static tree dfs_get_pure_virtuals (tree, void *);
-/* Allocate a level of searching. */
-
-static struct search_level *
-push_search_level (struct stack_level *stack, struct obstack *obstack)
-{
- struct search_level tem;
-
- tem.prev = stack;
- return push_stack_level (obstack, (char *)&tem, sizeof (tem));
-}
-
-/* Discard a level of search allocation. */
-
-static struct search_level *
-pop_search_level (struct stack_level *obstack)
-{
- struct search_level *stack = pop_stack_level (obstack);
-
- return stack;
-}
\f
/* Variables for gathering statistics. */
#ifdef GATHER_STATISTICS
tree *binfo_ptr)
{
int i;
- tree bases, accesses;
+ tree base_binfo;
base_kind found = bk_not_base;
if (same_type_p (BINFO_TYPE (binfo), base))
return found;
}
- bases = BINFO_BASETYPES (binfo);
- accesses = BINFO_BASEACCESSES (binfo);
- if (!bases)
- return bk_not_base;
-
- for (i = TREE_VEC_LENGTH (bases); i--;)
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
{
- tree base_binfo = TREE_VEC_ELT (bases, i);
base_kind bk;
bk = lookup_base_r (base_binfo, base,
tree
lookup_base (tree t, tree base, base_access access, base_kind *kind_ptr)
{
- tree binfo = NULL; /* The binfo we've found so far. */
- tree t_binfo = NULL;
+ tree binfo = NULL_TREE; /* The binfo we've found so far. */
+ tree t_binfo = NULL_TREE;
base_kind bk;
if (t == error_mark_node || base == error_mark_node)
t_binfo = t;
t = BINFO_TYPE (t);
}
- else
- t_binfo = TYPE_BINFO (t);
-
- /* Ensure that the types are instantiated. */
- t = complete_type (TYPE_MAIN_VARIANT (t));
- base = complete_type (TYPE_MAIN_VARIANT (base));
+ else
+ {
+ t = complete_type (TYPE_MAIN_VARIANT (t));
+ t_binfo = TYPE_BINFO (t);
+ }
- bk = lookup_base_r (t_binfo, base, access, 0, &binfo);
+ base = complete_type (TYPE_MAIN_VARIANT (base));
+
+ if (t_binfo)
+ bk = lookup_base_r (t_binfo, base, access, 0, &binfo);
+ else
+ bk = bk_not_base;
/* Check that the base is unambiguous and accessible. */
if (access != ba_any)
dynamic_cast_base_recurse (tree subtype, tree binfo, bool is_via_virtual,
tree *offset_ptr)
{
- tree binfos, accesses;
- int i, n_baselinks;
+ tree accesses;
+ tree base_binfo;
+ int i;
int worst = -2;
if (BINFO_TYPE (binfo) == subtype)
}
}
- binfos = BINFO_BASETYPES (binfo);
- accesses = BINFO_BASEACCESSES (binfo);
- n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- for (i = 0; i < n_baselinks; i++)
+ accesses = BINFO_BASE_ACCESSES (binfo);
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
{
- tree base_binfo = TREE_VEC_ELT (binfos, i);
tree base_access = TREE_VEC_ELT (accesses, i);
int rval;
return temp;
}
if (TREE_CODE (field) == USING_DECL)
- /* For now, we're just treating member using declarations as
- old ARM-style access declarations. Thus, there's no reason
- to return a USING_DECL, and the rest of the compiler can't
- handle it. Once the class is defined, these are purged
- from TYPE_FIELDS anyhow; see handle_using_decl. */
- continue;
+ {
+ /* We generally treat class-scope using-declarations as
+ ARM-style access specifications, because support for the
+ ISO semantics has not been implemented. So, in general,
+ there's no reason to return a USING_DECL, and the rest of
+ the compiler cannot handle that. Once the class is
+ defined, USING_DECLs are purged from TYPE_FIELDS; see
+ handle_using_decl. However, we make special efforts to
+ make using-declarations in template classes work
+ correctly. */
+ if (CLASSTYPE_TEMPLATE_INFO (type)
+ && !CLASSTYPE_USE_TEMPLATE (type)
+ && !TREE_TYPE (field))
+ ;
+ else
+ continue;
+ }
if (DECL_NAME (field) == name
&& (!want_type
if (!access)
{
int i;
- int n_baselinks;
- tree binfos, accesses;
+ tree base_binfo, accesses;
/* Otherwise, scan our baseclasses, and pick the most favorable
access. */
- binfos = BINFO_BASETYPES (binfo);
- accesses = BINFO_BASEACCESSES (binfo);
- n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- for (i = 0; i < n_baselinks; ++i)
+ accesses = BINFO_BASE_ACCESSES (binfo);
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
{
- tree base_binfo = TREE_VEC_ELT (binfos, i);
tree base_access = TREE_VEC_ELT (accesses, i);
access_kind base_access_now = BINFO_ACCESS (base_binfo);
static tree
dfs_accessible_queue_p (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
{
- tree binfo = BINFO_BASETYPE (derived, ix);
+ tree binfo = BINFO_BASE_BINFO (derived, ix);
if (BINFO_MARKED (binfo))
return NULL_TREE;
/* If this class is inherited via private or protected inheritance,
then we can't see it, unless we are a friend of the derived class. */
- if (BINFO_BASEACCESS (derived, ix) != access_public_node
+ if (BINFO_BASE_ACCESS (derived, ix) != access_public_node
&& !is_friend (BINFO_TYPE (derived), current_scope ()))
return NULL_TREE;
static tree
lookup_field_queue_p (tree derived, int ix, void *data)
{
- tree binfo = BINFO_BASETYPE (derived, ix);
+ tree binfo = BINFO_BASE_BINFO (derived, ix);
struct lookup_field_info *lfi = (struct lookup_field_info *) data;
/* Don't look for constructors or destructors in base classes. */
{
int idx = lookup_fnfields_1 (type, lfi->name);
if (idx >= 0)
- nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
+ nval = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), idx);
}
if (!nval)
{
my_friendly_assert (IS_AGGR_TYPE_CODE (TREE_CODE (xbasetype)), 20030624);
type = xbasetype;
- basetype_path = TYPE_BINFO (type);
- my_friendly_assert (!BINFO_INHERITANCE_CHAIN (basetype_path), 980827);
+ xbasetype = NULL_TREE;
}
- if (type == current_class_type && TYPE_BEING_DEFINED (type)
- && IDENTIFIER_CLASS_VALUE (name))
- {
- tree field = IDENTIFIER_CLASS_VALUE (name);
- if (! is_overloaded_fn (field)
- && ! (want_type && TREE_CODE (field) != TYPE_DECL))
- /* We're in the scope of this class, and the value has already
- been looked up. Just return the cached value. */
- return field;
- }
+ type = complete_type (type);
+ if (!basetype_path)
+ basetype_path = TYPE_BINFO (type);
- complete_type (type);
+ if (!basetype_path)
+ return NULL_TREE;
#ifdef GATHER_STATISTICS
n_calls_lookup_field++;
static int
lookup_conversion_operator (tree class_type, tree type)
{
- int pass;
- int i;
+ int tpl_slot = -1;
- tree methods = CLASSTYPE_METHOD_VEC (class_type);
-
- for (pass = 0; pass < 2; ++pass)
- for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
- i < TREE_VEC_LENGTH (methods);
- ++i)
- {
- tree fn = TREE_VEC_ELT (methods, i);
- /* The size of the vector may have some unused slots at the
- end. */
- if (!fn)
- break;
-
- /* All the conversion operators come near the beginning of the
- class. Therefore, if FN is not a conversion operator, there
- is no matching conversion operator in CLASS_TYPE. */
- fn = OVL_CURRENT (fn);
- if (!DECL_CONV_FN_P (fn))
- break;
-
- if (pass == 0)
- {
- /* On the first pass we only consider exact matches. If
- the types match, this slot is the one where the right
- conversion operators can be found. */
- if (TREE_CODE (fn) != TEMPLATE_DECL
- && same_type_p (DECL_CONV_FN_TYPE (fn), type))
- return i;
- }
- else
- {
- /* On the second pass we look for template conversion
- operators. It may be possible to instantiate the
- template to get the type desired. All of the template
- conversion operators share a slot. By looking for
- templates second we ensure that specializations are
- preferred over templates. */
- if (TREE_CODE (fn) == TEMPLATE_DECL)
- return i;
- }
- }
+ if (TYPE_HAS_CONVERSION (class_type))
+ {
+ int i;
+ tree fn;
+ VEC(tree) *methods = CLASSTYPE_METHOD_VEC (class_type);
+
+ for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ VEC_iterate (tree, methods, i, fn); ++i)
+ {
+ /* All the conversion operators come near the beginning of
+ the class. Therefore, if FN is not a conversion
+ operator, there is no matching conversion operator in
+ CLASS_TYPE. */
+ fn = OVL_CURRENT (fn);
+ if (!DECL_CONV_FN_P (fn))
+ break;
+
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ /* All the templated conversion functions are on the same
+ slot, so remember it. */
+ tpl_slot = i;
+ else if (same_type_p (DECL_CONV_FN_TYPE (fn), type))
+ return i;
+ }
+ }
- return -1;
+ return tpl_slot;
}
/* TYPE is a class type. Return the index of the fields within
int
lookup_fnfields_1 (tree type, tree name)
{
- tree method_vec;
- tree *methods;
+ VEC(tree) *method_vec;
+ tree fn;
tree tmp;
- int i;
- int len;
-
+ size_t i;
+
if (!CLASS_TYPE_P (type))
return -1;
- method_vec = CLASSTYPE_METHOD_VEC (type);
+ if (COMPLETE_TYPE_P (type))
+ {
+ if ((name == ctor_identifier
+ || name == base_ctor_identifier
+ || name == complete_ctor_identifier))
+ {
+ if (CLASSTYPE_LAZY_DEFAULT_CTOR (type))
+ lazily_declare_fn (sfk_constructor, type);
+ if (CLASSTYPE_LAZY_COPY_CTOR (type))
+ lazily_declare_fn (sfk_copy_constructor, type);
+ }
+ else if (name == ansi_assopname(NOP_EXPR)
+ && CLASSTYPE_LAZY_ASSIGNMENT_OP (type))
+ lazily_declare_fn (sfk_assignment_operator, type);
+ }
+ method_vec = CLASSTYPE_METHOD_VEC (type);
if (!method_vec)
return -1;
- methods = &TREE_VEC_ELT (method_vec, 0);
- len = TREE_VEC_LENGTH (method_vec);
-
#ifdef GATHER_STATISTICS
n_calls_lookup_fnfields_1++;
#endif /* GATHER_STATISTICS */
/* Constructors are first... */
if (name == ctor_identifier)
- return (methods[CLASSTYPE_CONSTRUCTOR_SLOT]
- ? CLASSTYPE_CONSTRUCTOR_SLOT : -1);
+ {
+ fn = CLASSTYPE_CONSTRUCTORS (type);
+ return fn ? CLASSTYPE_CONSTRUCTOR_SLOT : -1;
+ }
/* and destructors are second. */
if (name == dtor_identifier)
- return (methods[CLASSTYPE_DESTRUCTOR_SLOT]
- ? CLASSTYPE_DESTRUCTOR_SLOT : -1);
+ {
+ fn = CLASSTYPE_DESTRUCTORS (type);
+ return fn ? CLASSTYPE_DESTRUCTOR_SLOT : -1;
+ }
if (IDENTIFIER_TYPENAME_P (name))
return lookup_conversion_operator (type, TREE_TYPE (name));
/* Skip the conversion operators. */
- i = CLASSTYPE_FIRST_CONVERSION_SLOT;
- while (i < len && methods[i] && DECL_CONV_FN_P (OVL_CURRENT (methods[i])))
- i++;
+ for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ VEC_iterate (tree, method_vec, i, fn);
+ ++i)
+ if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
+ break;
/* If the type is complete, use binary search. */
if (COMPLETE_TYPE_P (type))
{
- int lo = i;
- int hi = len;
+ int lo;
+ int hi;
+ lo = i;
+ hi = VEC_length (tree, method_vec);
while (lo < hi)
{
i = (lo + hi) / 2;
n_outer_fields_searched++;
#endif /* GATHER_STATISTICS */
- tmp = methods[i];
- /* This slot may be empty; we allocate more slots than we
- need. In that case, the entry we're looking for is
- closer to the beginning of the list. */
- if (tmp)
- tmp = DECL_NAME (OVL_CURRENT (tmp));
- if (!tmp || tmp > name)
+ tmp = VEC_index (tree, method_vec, i);
+ tmp = DECL_NAME (OVL_CURRENT (tmp));
+ if (tmp > name)
hi = i;
else if (tmp < name)
lo = i + 1;
}
}
else
- for (; i < len && methods[i]; ++i)
+ for (; VEC_iterate (tree, method_vec, i, fn); ++i)
{
#ifdef GATHER_STATISTICS
n_outer_fields_searched++;
#endif /* GATHER_STATISTICS */
-
- tmp = OVL_CURRENT (methods[i]);
- if (DECL_NAME (tmp) == name)
+ if (DECL_NAME (OVL_CURRENT (fn)) == name)
return i;
}
if (rval)
goto done;
- n_bases = BINFO_N_BASETYPES (binfo);
+ n_bases = BINFO_N_BASE_BINFOS (binfo);
for (ix = 0; ix != n_bases; ix++)
{
tree base_binfo;
if (qfn)
base_binfo = (*qfn) (binfo, ix, data);
else
- base_binfo = BINFO_BASETYPE (binfo, ix);
+ base_binfo = BINFO_BASE_BINFO (binfo, ix);
if (base_binfo)
{
tree (*qfn) (tree, int, void *),
void *data)
{
+ int i;
+ tree base_binfo;
tree rval = NULL_TREE;
/* Call the pre-order walking function. */
}
/* Process the basetypes. */
- if (BINFO_BASETYPES (binfo))
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
{
- int i, n = TREE_VEC_LENGTH (BINFO_BASETYPES (binfo));
- for (i = 0; i != n; i++)
+ if (qfn)
{
- tree base_binfo;
-
- if (qfn)
- base_binfo = (*qfn) (binfo, i, data);
- else
- base_binfo = BINFO_BASETYPE (binfo, i);
-
- if (base_binfo)
- {
- rval = dfs_walk_real (base_binfo, prefn, postfn, qfn, data);
- if (rval)
- return rval;
- }
+ base_binfo = (*qfn) (binfo, i, data);
+ if (!base_binfo)
+ continue;
}
+ rval = dfs_walk_real (base_binfo, prefn, postfn, qfn, data);
+ if (rval)
+ return rval;
}
/* Call the post-order walking function. */
look_for_overrides (tree type, tree fndecl)
{
tree binfo = TYPE_BINFO (type);
- tree basebinfos = BINFO_BASETYPES (binfo);
- int nbasebinfos = basebinfos ? TREE_VEC_LENGTH (basebinfos) : 0;
+ tree base_binfo;
int ix;
int found = 0;
- for (ix = 0; ix != nbasebinfos; ix++)
+ for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++)
{
- tree basetype = BINFO_TYPE (TREE_VEC_ELT (basebinfos, ix));
+ tree basetype = BINFO_TYPE (base_binfo);
if (TYPE_POLYMORPHIC_P (basetype))
found += look_for_overrides_r (basetype, fndecl);
{
int ix;
+ /* If there are no methods in TYPE (meaning that only implicitly
+ declared methods will ever be provided for TYPE), then there are
+ no virtual functions. */
+ if (!CLASSTYPE_METHOD_VEC (type))
+ return NULL_TREE;
+
if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fndecl))
ix = CLASSTYPE_DESTRUCTOR_SLOT;
else
ix = lookup_fnfields_1 (type, DECL_NAME (fndecl));
if (ix >= 0)
{
- tree fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), ix);
+ tree fns = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix);
for (; fns; fns = OVL_NEXT (fns))
{
{
unsigned ix;
tree binfo;
+ VEC (tree) *vbases;
/* Clear the CLASSTYPE_PURE_VIRTUALS list; whatever is already there
is going to be overridden. */
/* Put the pure virtuals in dfs order. */
CLASSTYPE_PURE_VIRTUALS (type) = nreverse (CLASSTYPE_PURE_VIRTUALS (type));
- for (ix = 0; (binfo = VEC_iterate
- (tree, CLASSTYPE_VBASECLASSES (type), ix)); ix++)
+ for (vbases = CLASSTYPE_VBASECLASSES (type), ix = 0;
+ VEC_iterate (tree, vbases, ix, binfo); ix++)
{
tree virtuals;
tree
markedp (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
{
- tree binfo = BINFO_BASETYPE (derived, ix);
+ tree binfo = BINFO_BASE_BINFO (derived, ix);
return BINFO_MARKED (binfo) ? binfo : NULL_TREE;
}
tree
unmarkedp (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
{
- tree binfo = BINFO_BASETYPE (derived, ix);
+ tree binfo = BINFO_BASE_BINFO (derived, ix);
return !BINFO_MARKED (binfo) ? binfo : NULL_TREE;
}
-static tree
-marked_pushdecls_p (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
-{
- tree binfo = BINFO_BASETYPE (derived, ix);
-
- return (!BINFO_DEPENDENT_BASE_P (binfo)
- && BINFO_PUSHDECLS_MARKED (binfo)) ? binfo : NULL_TREE;
-}
-
-static tree
-unmarked_pushdecls_p (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
-{
- tree binfo = BINFO_BASETYPE (derived, ix);
-
- return (!BINFO_DEPENDENT_BASE_P (binfo)
- && !BINFO_PUSHDECLS_MARKED (binfo)) ? binfo : NULL_TREE;
-}
-
/* The worker functions for `dfs_walk'. These do not need to
test anything (vis a vis marking) if they are paired with
a predicate function (above). */
static tree
dfs_debug_unmarkedp (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
{
- tree binfo = BINFO_BASETYPE (derived, ix);
+ tree binfo = BINFO_BASE_BINFO (derived, ix);
return (!CLASSTYPE_DEBUG_REQUESTED (BINFO_TYPE (binfo))
? binfo : NULL_TREE);
dfs_walk (TYPE_BINFO (type), dfs_debug_mark, dfs_debug_unmarkedp, 0);
}
\f
-/* Subroutines of push_class_decls (). */
-
-static void
-setup_class_bindings (tree name, int type_binding_p)
-{
- tree type_binding = NULL_TREE;
- tree value_binding;
-
- /* If we've already done the lookup for this declaration, we're
- done. */
- if (IDENTIFIER_CLASS_VALUE (name))
- return;
-
- /* First, deal with the type binding. */
- if (type_binding_p)
- {
- type_binding = lookup_member (current_class_type, name,
- /*protect=*/2, /*want_type=*/true);
- if (TREE_CODE (type_binding) == TREE_LIST
- && TREE_TYPE (type_binding) == error_mark_node)
- /* NAME is ambiguous. */
- push_class_level_binding (name, type_binding);
- else
- pushdecl_class_level (type_binding);
- }
-
- /* Now, do the value binding. */
- value_binding = lookup_member (current_class_type, name,
- /*protect=*/2, /*want_type=*/false);
-
- if (type_binding_p
- && (TREE_CODE (value_binding) == TYPE_DECL
- || DECL_CLASS_TEMPLATE_P (value_binding)
- || (TREE_CODE (value_binding) == TREE_LIST
- && TREE_TYPE (value_binding) == error_mark_node
- && (TREE_CODE (TREE_VALUE (value_binding))
- == TYPE_DECL))))
- /* We found a type-binding, even when looking for a non-type
- binding. This means that we already processed this binding
- above. */;
- else if (value_binding)
- {
- if (TREE_CODE (value_binding) == TREE_LIST
- && TREE_TYPE (value_binding) == error_mark_node)
- /* NAME is ambiguous. */
- push_class_level_binding (name, value_binding);
- else
- {
- if (BASELINK_P (value_binding))
- /* NAME is some overloaded functions. */
- value_binding = BASELINK_FUNCTIONS (value_binding);
- /* Two conversion operators that convert to the same type
- may have different names. (See
- mangle_conv_op_name_for_type.) To avoid recording the
- same conversion operator declaration more than once we
- must check to see that the same operator was not already
- found under another name. */
- if (IDENTIFIER_TYPENAME_P (name)
- && is_overloaded_fn (value_binding))
- {
- tree fns;
- for (fns = value_binding; fns; fns = OVL_NEXT (fns))
- if (IDENTIFIER_CLASS_VALUE (DECL_NAME (OVL_CURRENT (fns))))
- return;
- }
- pushdecl_class_level (value_binding);
- }
- }
-}
-
-/* Push class-level declarations for any names appearing in BINFO that
- are TYPE_DECLS. */
-
-static tree
-dfs_push_type_decls (tree binfo, void *data ATTRIBUTE_UNUSED)
-{
- tree type;
- tree fields;
-
- type = BINFO_TYPE (binfo);
- for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
- if (DECL_NAME (fields) && TREE_CODE (fields) == TYPE_DECL
- && !(!same_type_p (type, current_class_type)
- && template_self_reference_p (type, fields)))
- setup_class_bindings (DECL_NAME (fields), /*type_binding_p=*/1);
-
- /* We can't just use BINFO_MARKED because envelope_add_decl uses
- DERIVED_FROM_P, which calls get_base_distance. */
- BINFO_PUSHDECLS_MARKED (binfo) = 1;
-
- return NULL_TREE;
-}
-
-/* Push class-level declarations for any names appearing in BINFO that
- are not TYPE_DECLS. */
-
-static tree
-dfs_push_decls (tree binfo, void *data)
-{
- tree type = BINFO_TYPE (binfo);
- tree method_vec;
- tree fields;
-
- for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
- if (DECL_NAME (fields)
- && TREE_CODE (fields) != TYPE_DECL
- && TREE_CODE (fields) != USING_DECL
- && !DECL_ARTIFICIAL (fields))
- setup_class_bindings (DECL_NAME (fields), /*type_binding_p=*/0);
- else if (TREE_CODE (fields) == FIELD_DECL
- && ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
- dfs_push_decls (TYPE_BINFO (TREE_TYPE (fields)), data);
-
- method_vec = (CLASS_TYPE_P (type)
- ? CLASSTYPE_METHOD_VEC (type) : NULL_TREE);
-
- if (method_vec && TREE_VEC_LENGTH (method_vec) >= 3)
- {
- tree *methods;
- tree *end;
-
- /* Farm out constructors and destructors. */
- end = TREE_VEC_END (method_vec);
-
- for (methods = &TREE_VEC_ELT (method_vec, 2);
- methods < end && *methods;
- methods++)
- setup_class_bindings (DECL_NAME (OVL_CURRENT (*methods)),
- /*type_binding_p=*/0);
- }
-
- BINFO_PUSHDECLS_MARKED (binfo) = 0;
-
- return NULL_TREE;
-}
-
-/* When entering the scope of a class, we cache all of the
- fields that that class provides within its inheritance
- lattice. Where ambiguities result, we mark them
- with `error_mark_node' so that if they are encountered
- without explicit qualification, we can emit an error
- message. */
-
-void
-push_class_decls (tree type)
-{
- search_stack = push_search_level (search_stack, &search_obstack);
-
- /* Enter type declarations and mark. */
- dfs_walk (TYPE_BINFO (type), dfs_push_type_decls, unmarked_pushdecls_p, 0);
-
- /* Enter non-type declarations and unmark. */
- dfs_walk (TYPE_BINFO (type), dfs_push_decls, marked_pushdecls_p, 0);
-}
-
-/* Here's a subroutine we need because C lacks lambdas. */
-
-static tree
-dfs_unuse_fields (tree binfo, void *data ATTRIBUTE_UNUSED)
-{
- tree type = TREE_TYPE (binfo);
- tree fields;
-
- if (TREE_CODE (type) == TYPENAME_TYPE)
- fields = TYPENAME_TYPE_FULLNAME (type);
- else if (TREE_CODE (type) == TYPEOF_TYPE)
- fields = TYPEOF_TYPE_EXPR (type);
- else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
- || TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
- || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
- fields = TEMPLATE_TYPE_PARM_INDEX (type);
- else
- fields = TYPE_FIELDS (type);
-
- for (; fields; fields = TREE_CHAIN (fields))
- {
- if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
- continue;
-
- TREE_USED (fields) = 0;
- if (DECL_NAME (fields) == NULL_TREE
- && ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
- unuse_fields (TREE_TYPE (fields));
- }
-
- return NULL_TREE;
-}
-
-void
-unuse_fields (tree type)
-{
- dfs_walk (TYPE_BINFO (type), dfs_unuse_fields, unmarkedp, 0);
-}
-
-void
-pop_class_decls (void)
-{
- /* We haven't pushed a search level when dealing with cached classes,
- so we'd better not try to pop it. */
- if (search_stack)
- search_stack = pop_search_level (search_stack);
-}
-
void
print_search_statistics (void)
{
}
void
-init_search_processing (void)
-{
- gcc_obstack_init (&search_obstack);
-}
-
-void
reinit_search_statistics (void)
{
#ifdef GATHER_STATISTICS
#endif /* GATHER_STATISTICS */
}
+/* Helper for lookup_conversions_r. TO_TYPE is the type converted to
+ by a conversion op in base BINFO. VIRTUAL_DEPTH is non-zero if
+ BINFO is morally virtual, and VIRTUALNESS is non-zero if virtual
+ bases have been encountered already in the tree walk. PARENT_CONVS
+ is the list of lists of conversion functions that could hide CONV
+ and OTHER_CONVS is the list of lists of conversion functions that
+ could hide or be hidden by CONV, should virtualness be involved in
+ the hierarchy. Merely checking the conversion op's name is not
+ enough because two conversion operators to the same type can have
+ different names. Return non-zero if we are visible. */
+
+static int
+check_hidden_convs (tree binfo, int virtual_depth, int virtualness,
+ tree to_type, tree parent_convs, tree other_convs)
+{
+ tree level, probe;
+
+ /* See if we are hidden by a parent conversion. */
+ for (level = parent_convs; level; level = TREE_CHAIN (level))
+ for (probe = TREE_VALUE (level); probe; probe = TREE_CHAIN (probe))
+ if (same_type_p (to_type, TREE_TYPE (probe)))
+ return 0;
+
+ if (virtual_depth || virtualness)
+ {
+ /* In a virtual hierarchy, we could be hidden, or could hide a
+ conversion function on the other_convs list. */
+ for (level = other_convs; level; level = TREE_CHAIN (level))
+ {
+ int we_hide_them;
+ int they_hide_us;
+ tree *prev, other;
+
+ if (!(virtual_depth || TREE_STATIC (level)))
+ /* Neither is morally virtual, so cannot hide each other. */
+ continue;
+
+ if (!TREE_VALUE (level))
+ /* They evaporated away already. */
+ continue;
+
+ they_hide_us = (virtual_depth
+ && original_binfo (binfo, TREE_PURPOSE (level)));
+ we_hide_them = (!they_hide_us && TREE_STATIC (level)
+ && original_binfo (TREE_PURPOSE (level), binfo));
+
+ if (!(we_hide_them || they_hide_us))
+ /* Neither is within the other, so no hiding can occur. */
+ continue;
+
+ for (prev = &TREE_VALUE (level), other = *prev; other;)
+ {
+ if (same_type_p (to_type, TREE_TYPE (other)))
+ {
+ if (they_hide_us)
+ /* We are hidden. */
+ return 0;
+
+ if (we_hide_them)
+ {
+ /* We hide the other one. */
+ other = TREE_CHAIN (other);
+ *prev = other;
+ continue;
+ }
+ }
+ prev = &TREE_CHAIN (other);
+ other = *prev;
+ }
+ }
+ }
+ return 1;
+}
+
+/* Helper for lookup_conversions_r. PARENT_CONVS is a list of lists
+ of conversion functions, the first slot will be for the current
+ binfo, if MY_CONVS is non-NULL. CHILD_CONVS is the list of lists
+ of conversion functions from childen of the current binfo,
+ concatenated with conversions from elsewhere in the heirarchy --
+ that list begins with OTHER_CONVS. Return a single list of lists
+ containing only conversions from the current binfo and its
+ children. */
+
static tree
-add_conversions (tree binfo, void *data)
+split_conversions (tree my_convs, tree parent_convs,
+ tree child_convs, tree other_convs)
{
- int i;
- tree method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo));
- tree *conversions = (tree *) data;
+ tree t;
+ tree prev;
+
+ /* Remove the original other_convs portion from child_convs. */
+ for (prev = NULL, t = child_convs;
+ t != other_convs; prev = t, t = TREE_CHAIN (t))
+ continue;
+
+ if (prev)
+ TREE_CHAIN (prev) = NULL_TREE;
+ else
+ child_convs = NULL_TREE;
- /* Some builtin types have no method vector, not even an empty one. */
- if (!method_vec)
- return NULL_TREE;
+ /* Attach the child convs to any we had at this level. */
+ if (my_convs)
+ {
+ my_convs = parent_convs;
+ TREE_CHAIN (my_convs) = child_convs;
+ }
+ else
+ my_convs = child_convs;
+
+ return my_convs;
+}
+
+/* Worker for lookup_conversions. Lookup conversion functions in
+ BINFO and its children. VIRTUAL_DEPTH is non-zero, if BINFO is in
+ a morally virtual base, and VIRTUALNESS is non-zero, if we've
+ encountered virtual bases already in the tree walk. PARENT_CONVS &
+ PARENT_TPL_CONVS are lists of list of conversions within parent
+ binfos. OTHER_CONVS and OTHER_TPL_CONVS are conversions found
+ elsewhere in the tree. Return the conversions found within this
+ portion of the graph in CONVS and TPL_CONVS. Return non-zero is we
+ encountered virtualness. We keep template and non-template
+ conversions separate, to avoid unnecessary type comparisons.
+
+ The located conversion functions are held in lists of lists. The
+ TREE_VALUE of the outer list is the list of conversion functions
+ found in a particular binfo. The TREE_PURPOSE of both the outer
+ and inner lists is the binfo at which those conversions were
+ found. TREE_STATIC is set for those lists within of morally
+ virtual binfos. The TREE_VALUE of the inner list is the conversion
+ function or overload itself. The TREE_TYPE of each inner list node
+ is the converted-to type. */
- for (i = 2; i < TREE_VEC_LENGTH (method_vec); ++i)
+static int
+lookup_conversions_r (tree binfo,
+ int virtual_depth, int virtualness,
+ tree parent_convs, tree parent_tpl_convs,
+ tree other_convs, tree other_tpl_convs,
+ tree *convs, tree *tpl_convs)
+{
+ int my_virtualness = 0;
+ tree my_convs = NULL_TREE;
+ tree my_tpl_convs = NULL_TREE;
+ tree child_convs = NULL_TREE;
+ tree child_tpl_convs = NULL_TREE;
+ unsigned i;
+ tree base_binfo;
+ VEC(tree) *method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo));
+ tree conv;
+
+ /* If we have no conversion operators, then don't look. */
+ if (!TYPE_HAS_CONVERSION (BINFO_TYPE (binfo)))
{
- tree tmp = TREE_VEC_ELT (method_vec, i);
- tree name;
+ *convs = *tpl_convs = NULL_TREE;
+
+ return 0;
+ }
+
+ if (BINFO_VIRTUAL_P (binfo))
+ virtual_depth++;
+
+ /* First, locate the unhidden ones at this level. */
+ for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ VEC_iterate (tree, method_vec, i, conv);
+ ++i)
+ {
+ tree cur = OVL_CURRENT (conv);
- if (!tmp || ! DECL_CONV_FN_P (OVL_CURRENT (tmp)))
+ if (!DECL_CONV_FN_P (cur))
break;
- name = DECL_NAME (OVL_CURRENT (tmp));
-
- /* Make sure we don't already have this conversion. */
- if (! IDENTIFIER_MARKED (name))
+ if (TREE_CODE (cur) == TEMPLATE_DECL)
{
- tree t;
+ /* Only template conversions can be overloaded, and we must
+ flatten them out and check each one individually. */
+ tree tpls;
- /* Make sure that we do not already have a conversion
- operator for this type. Merely checking the NAME is not
- enough because two conversion operators to the same type
- may not have the same NAME. */
- for (t = *conversions; t; t = TREE_CHAIN (t))
+ for (tpls = conv; tpls; tpls = OVL_NEXT (tpls))
{
- tree fn;
- for (fn = TREE_VALUE (t); fn; fn = OVL_NEXT (fn))
- if (same_type_p (TREE_TYPE (name),
- DECL_CONV_FN_TYPE (OVL_CURRENT (fn))))
- break;
- if (fn)
- break;
+ tree tpl = OVL_CURRENT (tpls);
+ tree type = DECL_CONV_FN_TYPE (tpl);
+
+ if (check_hidden_convs (binfo, virtual_depth, virtualness,
+ type, parent_tpl_convs, other_tpl_convs))
+ {
+ my_tpl_convs = tree_cons (binfo, tpl, my_tpl_convs);
+ TREE_TYPE (my_tpl_convs) = type;
+ if (virtual_depth)
+ {
+ TREE_STATIC (my_tpl_convs) = 1;
+ my_virtualness = 1;
+ }
+ }
}
- if (!t)
+ }
+ else
+ {
+ tree name = DECL_NAME (cur);
+
+ if (!IDENTIFIER_MARKED (name))
{
- *conversions = tree_cons (binfo, tmp, *conversions);
- IDENTIFIER_MARKED (name) = 1;
+ tree type = DECL_CONV_FN_TYPE (cur);
+
+ if (check_hidden_convs (binfo, virtual_depth, virtualness,
+ type, parent_convs, other_convs))
+ {
+ my_convs = tree_cons (binfo, conv, my_convs);
+ TREE_TYPE (my_convs) = type;
+ if (virtual_depth)
+ {
+ TREE_STATIC (my_convs) = 1;
+ my_virtualness = 1;
+ }
+ IDENTIFIER_MARKED (name) = 1;
+ }
}
}
}
- return NULL_TREE;
+
+ if (my_convs)
+ {
+ parent_convs = tree_cons (binfo, my_convs, parent_convs);
+ if (virtual_depth)
+ TREE_STATIC (parent_convs) = 1;
+ }
+
+ if (my_tpl_convs)
+ {
+ parent_tpl_convs = tree_cons (binfo, my_tpl_convs, parent_tpl_convs);
+ if (virtual_depth)
+ TREE_STATIC (parent_convs) = 1;
+ }
+
+ child_convs = other_convs;
+ child_tpl_convs = other_tpl_convs;
+
+ /* Now iterate over each base, looking for more conversions. */
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+ {
+ tree base_convs, base_tpl_convs;
+ unsigned base_virtualness;
+
+ base_virtualness = lookup_conversions_r (base_binfo,
+ virtual_depth, virtualness,
+ parent_convs, parent_tpl_convs,
+ child_convs, child_tpl_convs,
+ &base_convs, &base_tpl_convs);
+ if (base_virtualness)
+ my_virtualness = virtualness = 1;
+ child_convs = chainon (base_convs, child_convs);
+ child_tpl_convs = chainon (base_tpl_convs, child_tpl_convs);
+ }
+
+ /* Unmark the conversions found at this level */
+ for (conv = my_convs; conv; conv = TREE_CHAIN (conv))
+ IDENTIFIER_MARKED (DECL_NAME (OVL_CURRENT (TREE_VALUE (conv)))) = 0;
+
+ *convs = split_conversions (my_convs, parent_convs,
+ child_convs, other_convs);
+ *tpl_convs = split_conversions (my_tpl_convs, parent_tpl_convs,
+ child_tpl_convs, other_tpl_convs);
+
+ return my_virtualness;
}
/* Return a TREE_LIST containing all the non-hidden user-defined
conversion functions for TYPE (and its base-classes). The
- TREE_VALUE of each node is a FUNCTION_DECL or an OVERLOAD
- containing the conversion functions. The TREE_PURPOSE is the BINFO
- from which the conversion functions in this node were selected. */
+ TREE_VALUE of each node is the FUNCTION_DECL of the conversion
+ function. The TREE_PURPOSE is the BINFO from which the conversion
+ functions in this node were selected. This function is effectively
+ performing a set of member lookups as lookup_fnfield does, but
+ using the type being converted to as the unique key, rather than the
+ field name. */
tree
lookup_conversions (tree type)
{
- tree t;
- tree conversions = NULL_TREE;
-
+ tree convs, tpl_convs;
+ tree list = NULL_TREE;
+
complete_type (type);
- bfs_walk (TYPE_BINFO (type), add_conversions, 0, &conversions);
+ if (!TYPE_BINFO (type))
+ return NULL_TREE;
+
+ lookup_conversions_r (TYPE_BINFO (type), 0, 0,
+ NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE,
+ &convs, &tpl_convs);
+
+ /* Flatten the list-of-lists */
+ for (; convs; convs = TREE_CHAIN (convs))
+ {
+ tree probe, next;
- for (t = conversions; t; t = TREE_CHAIN (t))
- IDENTIFIER_MARKED (DECL_NAME (OVL_CURRENT (TREE_VALUE (t)))) = 0;
+ for (probe = TREE_VALUE (convs); probe; probe = next)
+ {
+ next = TREE_CHAIN (probe);
- return conversions;
+ TREE_CHAIN (probe) = list;
+ list = probe;
+ }
+ }
+
+ for (; tpl_convs; tpl_convs = TREE_CHAIN (tpl_convs))
+ {
+ tree probe, next;
+
+ for (probe = TREE_VALUE (tpl_convs); probe; probe = next)
+ {
+ next = TREE_CHAIN (probe);
+
+ TREE_CHAIN (probe) = list;
+ list = probe;
+ }
+ }
+
+ return list;
}
struct overlap_info
{
struct overlap_info *oi = (struct overlap_info *) data;
tree binfo;
+
for (binfo = TYPE_BINFO (oi->compare_type);
;
- binfo = BINFO_BASETYPE (binfo, 0))
+ binfo = BINFO_BASE_BINFO (binfo, 0))
{
if (BINFO_TYPE (binfo) == BINFO_TYPE (empty_binfo))
{
oi->found_overlap = 1;
break;
}
- else if (BINFO_BASETYPES (binfo) == NULL_TREE)
+ else if (!BINFO_N_BASE_BINFOS (binfo))
break;
}
static tree
dfs_no_overlap_yet (tree derived, int ix, void *data)
{
- tree binfo = BINFO_BASETYPE (derived, ix);
+ tree binfo = BINFO_BASE_BINFO (derived, ix);
struct overlap_info *oi = (struct overlap_info *) data;
return !oi->found_overlap ? binfo : NULL_TREE;
return oi.found_overlap;
}
-/* Given a vtable VAR, determine which of the inherited classes the vtable
- inherits (in a loose sense) functions from.
-
- FIXME: This does not work with the new ABI. */
-
-tree
-binfo_for_vtable (tree var)
-{
- tree main_binfo = TYPE_BINFO (DECL_CONTEXT (var));
- tree binfos = TYPE_BINFO_BASETYPES (BINFO_TYPE (main_binfo));
- int n_baseclasses = CLASSTYPE_N_BASECLASSES (BINFO_TYPE (main_binfo));
- int i;
-
- for (i = 0; i < n_baseclasses; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- if (base_binfo != NULL_TREE && BINFO_VTABLE (base_binfo) == var)
- return base_binfo;
- }
-
- /* If no secondary base classes matched, return the primary base, if
- there is one. */
- if (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (main_binfo)))
- return get_primary_binfo (main_binfo);
-
- return main_binfo;
-}
-
/* Returns the binfo of the first direct or indirect virtual base derived
from BINFO, or NULL if binfo is not via virtual. */
}
else if (BINFO_INHERITANCE_CHAIN (binfo))
{
- tree base_binfos;
- int ix, n;
+ tree cbinfo;
+ tree base_binfo;
+ int ix;
- base_binfos = copied_binfo (BINFO_INHERITANCE_CHAIN (binfo), here);
- base_binfos = BINFO_BASETYPES (base_binfos);
- n = TREE_VEC_LENGTH (base_binfos);
- for (ix = 0; ix != n; ix++)
- {
- tree base = TREE_VEC_ELT (base_binfos, ix);
-
- if (BINFO_TYPE (base) == BINFO_TYPE (binfo))
- {
- result = base;
- break;
- }
- }
+ cbinfo = copied_binfo (BINFO_INHERITANCE_CHAIN (binfo), here);
+ for (ix = 0; BINFO_BASE_ITERATE (cbinfo, ix, base_binfo); ix++)
+ if (BINFO_TYPE (base_binfo) == BINFO_TYPE (binfo))
+ {
+ result = base_binfo;
+ break;
+ }
}
else
{
{
unsigned ix;
tree binfo;
+ VEC (tree) *vbases;
- for (ix = 0; (binfo = VEC_iterate
- (tree, CLASSTYPE_VBASECLASSES (t), ix)); ix++)
+ for (vbases = CLASSTYPE_VBASECLASSES (t), ix = 0;
+ VEC_iterate (tree, vbases, ix, binfo); ix++)
if (BINFO_TYPE (binfo) == base)
return binfo;
return NULL;
base_binfos = original_binfo (BINFO_INHERITANCE_CHAIN (binfo), here);
if (base_binfos)
{
- int ix, n;
+ int ix;
+ tree base_binfo;
- base_binfos = BINFO_BASETYPES (base_binfos);
- n = TREE_VEC_LENGTH (base_binfos);
- for (ix = 0; ix != n; ix++)
- {
- tree base = TREE_VEC_ELT (base_binfos, ix);
-
- if (BINFO_TYPE (base) == BINFO_TYPE (binfo))
- {
- result = base;
- break;
- }
- }
+ for (ix = 0; (base_binfo = BINFO_BASE_BINFO (base_binfos, ix)); ix++)
+ if (BINFO_TYPE (base_binfo) == BINFO_TYPE (binfo))
+ {
+ result = base_binfo;
+ break;
+ }
}
}