/* Breadth-first and depth-first routines for
searching multiple-inheritance lattice for GNU C++.
Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2002 Free Software Foundation, Inc.
+ 1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
#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 (obstack, tp, size)
- 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 (stack)
- 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. */
tree inits;
};
-static tree lookup_field_1 PARAMS ((tree, tree));
-static int is_subobject_of_p PARAMS ((tree, tree, tree));
-static int is_subobject_of_p_1 PARAMS ((tree, tree, tree));
-static tree dfs_check_overlap PARAMS ((tree, void *));
-static tree dfs_no_overlap_yet PARAMS ((tree, void *));
-static base_kind lookup_base_r
- PARAMS ((tree, tree, base_access, int, int, int, tree *));
-static int dynamic_cast_base_recurse PARAMS ((tree, tree, int, tree *));
-static tree marked_pushdecls_p PARAMS ((tree, void *));
-static tree unmarked_pushdecls_p PARAMS ((tree, void *));
-static tree dfs_debug_unmarkedp PARAMS ((tree, void *));
-static tree dfs_debug_mark PARAMS ((tree, void *));
-static tree dfs_get_vbase_types PARAMS ((tree, void *));
-static tree dfs_push_type_decls PARAMS ((tree, void *));
-static tree dfs_push_decls PARAMS ((tree, void *));
-static tree dfs_unuse_fields PARAMS ((tree, void *));
-static tree add_conversions PARAMS ((tree, void *));
-static int look_for_overrides_r PARAMS ((tree, tree));
-static struct search_level *push_search_level
- PARAMS ((struct stack_level *, struct obstack *));
-static struct search_level *pop_search_level
- PARAMS ((struct stack_level *));
-static tree bfs_walk
- PARAMS ((tree, tree (*) (tree, void *), tree (*) (tree, void *),
- void *));
-static tree lookup_field_queue_p PARAMS ((tree, void *));
-static int shared_member_p PARAMS ((tree));
-static tree lookup_field_r PARAMS ((tree, void *));
-static tree canonical_binfo PARAMS ((tree));
-static tree shared_marked_p PARAMS ((tree, void *));
-static tree shared_unmarked_p PARAMS ((tree, void *));
-static int dependent_base_p PARAMS ((tree));
-static tree dfs_accessible_queue_p PARAMS ((tree, void *));
-static tree dfs_accessible_p PARAMS ((tree, void *));
-static tree dfs_access_in_type PARAMS ((tree, void *));
-static access_kind access_in_type PARAMS ((tree, tree));
-static tree dfs_canonical_queue PARAMS ((tree, void *));
-static tree dfs_assert_unmarked_p PARAMS ((tree, void *));
-static void assert_canonical_unmarked PARAMS ((tree));
-static int protected_accessible_p PARAMS ((tree, tree, tree));
-static int friend_accessible_p PARAMS ((tree, tree, tree));
-static void setup_class_bindings PARAMS ((tree, int));
-static int template_self_reference_p PARAMS ((tree, tree));
-static tree dfs_find_vbase_instance PARAMS ((tree, void *));
-static tree dfs_get_pure_virtuals PARAMS ((tree, void *));
-static tree dfs_build_inheritance_graph_order PARAMS ((tree, void *));
-
-/* Allocate a level of searching. */
-
-static struct search_level *
-push_search_level (stack, obstack)
- struct stack_level *stack;
- struct obstack *obstack;
-{
- struct search_level tem;
+static tree dfs_check_overlap (tree, void *);
+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 dfs_debug_unmarkedp (tree, int, void *);
+static tree dfs_debug_mark (tree, void *);
+static tree add_conversions (tree, void *);
+static int look_for_overrides_r (tree, tree);
+static tree bfs_walk (tree, tree (*) (tree, void *),
+ tree (*) (tree, int, void *), void *);
+static tree lookup_field_queue_p (tree, int, void *);
+static int shared_member_p (tree);
+static tree lookup_field_r (tree, void *);
+static tree dfs_accessible_queue_p (tree, int, void *);
+static tree dfs_accessible_p (tree, void *);
+static tree dfs_access_in_type (tree, 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 int template_self_reference_p (tree, tree);
+static tree dfs_get_pure_virtuals (tree, void *);
- 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 (obstack)
- struct stack_level *obstack;
-{
- register struct search_level *stack = pop_stack_level (obstack);
-
- return stack;
-}
\f
/* Variables for gathering statistics. */
#ifdef GATHER_STATISTICS
\f
/* Worker for lookup_base. BINFO is the binfo we are searching at,
BASE is the RECORD_TYPE we are searching for. ACCESS is the
- required access checks. WITHIN_CURRENT_SCOPE, IS_NON_PUBLIC and
- IS_VIRTUAL indicate how BINFO was reached from the start of the
- search. WITHIN_CURRENT_SCOPE is true if we met the current scope,
- or friend thereof (this allows us to determine whether a protected
- base is accessible or not). IS_NON_PUBLIC indicates whether BINFO
- is accessible and IS_VIRTUAL indicates if it is morally virtual.
+ required access checks. IS_VIRTUAL indicates if BINFO is morally
+ virtual.
If BINFO is of the required type, then *BINFO_PTR is examined to
compare with any other instance of BASE we might have already
Otherwise BINFO's bases are searched. */
static base_kind
-lookup_base_r (binfo, base, access, within_current_scope,
- is_non_public, is_virtual, binfo_ptr)
- tree binfo, base;
- base_access access;
- int within_current_scope;
- int is_non_public; /* inside a non-public part */
- int is_virtual; /* inside a virtual part */
- tree *binfo_ptr;
+lookup_base_r (tree binfo, tree base, base_access access,
+ bool is_virtual, /* inside a virtual part */
+ tree *binfo_ptr)
{
int i;
- tree bases;
+ tree base_binfo;
base_kind found = bk_not_base;
- if (access == ba_check
- && !within_current_scope
- && is_friend (BINFO_TYPE (binfo), current_scope ()))
- {
- /* Do not clear is_non_public here. If A is a private base of B, A
- is not allowed to convert a B* to an A*. */
- within_current_scope = 1;
- }
-
if (same_type_p (BINFO_TYPE (binfo), base))
{
/* We have found a base. Check against what we have found
found = bk_same_type;
if (is_virtual)
found = bk_via_virtual;
- if (is_non_public)
- found = bk_inaccessible;
if (!*binfo_ptr)
*binfo_ptr = binfo;
- else if (!is_virtual || !tree_int_cst_equal (BINFO_OFFSET (binfo),
- BINFO_OFFSET (*binfo_ptr)))
+ else if (binfo != *binfo_ptr)
{
if (access != ba_any)
*binfo_ptr = NULL;
return found;
}
- bases = BINFO_BASETYPES (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);
- int this_non_public = is_non_public;
- int this_virtual = is_virtual;
base_kind bk;
- if (access <= ba_ignore)
- ; /* no change */
- else if (TREE_VIA_PUBLIC (base_binfo))
- ; /* no change */
- else if (access == ba_not_special)
- this_non_public = 1;
- else if (TREE_VIA_PROTECTED (base_binfo) && within_current_scope)
- ; /* no change */
- else if (is_friend (BINFO_TYPE (binfo), current_scope ()))
- ; /* no change */
- else
- this_non_public = 1;
-
- if (TREE_VIA_VIRTUAL (base_binfo))
- this_virtual = 1;
-
bk = lookup_base_r (base_binfo, base,
- access, within_current_scope,
- this_non_public, this_virtual,
+ access,
+ is_virtual || BINFO_VIRTUAL_P (base_binfo),
binfo_ptr);
switch (bk)
found = bk;
break;
- case bk_inaccessible:
- if (found == bk_not_base)
- found = bk;
- my_friendly_assert (found == bk_via_virtual
- || found == bk_inaccessible, 20010723);
-
- break;
-
case bk_same_type:
bk = bk_proper_base;
- /* FALLTHROUGH */
+ /* Fall through. */
case bk_proper_base:
my_friendly_assert (found == bk_not_base, 20010723);
found = bk;
case bk_not_base:
break;
+
+ default:
+ abort ();
}
}
return found;
}
+/* Returns true if type BASE is accessible in T. (BASE is known to be
+ a (possibly non-proper) base class of T.) */
+
+bool
+accessible_base_p (tree t, tree base)
+{
+ tree decl;
+
+ /* [class.access.base]
+
+ A base class is said to be accessible if an invented public
+ member of the base class is accessible.
+
+ If BASE is a non-proper base, this condition is trivially
+ true. */
+ if (same_type_p (t, base))
+ return true;
+ /* Rather than inventing a public member, we use the implicit
+ public typedef created in the scope of every class. */
+ decl = TYPE_FIELDS (base);
+ while (!DECL_SELF_REFERENCE_P (decl))
+ decl = TREE_CHAIN (decl);
+ while (ANON_AGGR_TYPE_P (t))
+ t = TYPE_CONTEXT (t);
+ return accessible_p (t, decl);
+}
+
/* Lookup BASE in the hierarchy dominated by T. Do access checking as
- ACCESS specifies. Return the binfo we discover (which might not be
- canonical). If KIND_PTR is non-NULL, fill with information about
- what kind of base we discovered.
+ ACCESS specifies. Return the binfo we discover. If KIND_PTR is
+ non-NULL, fill with information about what kind of base we
+ discovered.
If the base is inaccessible, or ambiguous, and the ba_quiet bit is
not set in ACCESS, then an error is issued and error_mark_node is
NULL_TREE is returned. */
tree
-lookup_base (t, base, access, kind_ptr)
- tree t, base;
- base_access access;
- base_kind *kind_ptr;
+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));
-
- bk = lookup_base_r (t_binfo, base, access & ~ba_quiet,
- 0, 0, 0, &binfo);
-
- switch (bk)
+ else
{
- case bk_inaccessible:
- binfo = NULL_TREE;
- if (!(access & ba_quiet))
- {
- error ("`%T' is an inaccessible base of `%T'", base, t);
- binfo = error_mark_node;
- }
- break;
- case bk_ambig:
- if (access != ba_any)
- {
- binfo = NULL_TREE;
- if (!(access & ba_quiet))
- {
- error ("`%T' is an ambiguous base of `%T'", base, t);
- binfo = error_mark_node;
- }
- }
- break;
- default:;
+ t = complete_type (TYPE_MAIN_VARIANT (t));
+ t_binfo = TYPE_BINFO (t);
}
+ 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)
+ switch (bk)
+ {
+ case bk_not_base:
+ break;
+
+ case bk_ambig:
+ binfo = NULL_TREE;
+ if (!(access & ba_quiet))
+ {
+ error ("`%T' is an ambiguous base of `%T'", base, t);
+ binfo = error_mark_node;
+ }
+ break;
+
+ default:
+ if ((access & ~ba_quiet) != ba_ignore
+ /* If BASE is incomplete, then BASE and TYPE are probably
+ the same, in which case BASE is accessible. If they
+ are not the same, then TYPE is invalid. In that case,
+ there's no need to issue another error here, and
+ there's no implicit typedef to use in the code that
+ follows, so we skip the check. */
+ && COMPLETE_TYPE_P (base)
+ && !accessible_base_p (t, base))
+ {
+ if (!(access & ba_quiet))
+ {
+ error ("`%T' is an inaccessible base of `%T'", base, t);
+ binfo = error_mark_node;
+ }
+ else
+ binfo = NULL_TREE;
+ bk = bk_inaccessible;
+ }
+ break;
+ }
+
if (kind_ptr)
*kind_ptr = bk;
/* Worker function for get_dynamic_cast_base_type. */
static int
-dynamic_cast_base_recurse (subtype, binfo, via_virtual, offset_ptr)
- tree subtype;
- tree binfo;
- int via_virtual;
- tree *offset_ptr;
+dynamic_cast_base_recurse (tree subtype, tree binfo, bool is_via_virtual,
+ tree *offset_ptr)
{
- tree binfos;
- int i, n_baselinks;
+ tree accesses;
+ tree base_binfo;
+ int i;
int worst = -2;
if (BINFO_TYPE (binfo) == subtype)
{
- if (via_virtual)
+ if (is_via_virtual)
return -1;
else
{
}
}
- binfos = BINFO_BASETYPES (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;
- if (!TREE_VIA_PUBLIC (base_binfo))
+ if (base_access != access_public_node)
continue;
rval = dynamic_cast_base_recurse
(subtype, base_binfo,
- via_virtual || TREE_VIA_VIRTUAL (base_binfo), offset_ptr);
+ is_via_virtual || BINFO_VIRTUAL_P (base_binfo), offset_ptr);
if (worst == -2)
worst = rval;
else if (rval >= 0)
BOFF == -3, SUBTYPE occurs as multiple public non-virtual bases. */
tree
-get_dynamic_cast_base_type (subtype, target)
- tree subtype;
- tree target;
+get_dynamic_cast_base_type (tree subtype, tree target)
{
tree offset = NULL_TREE;
int boff = dynamic_cast_base_recurse (subtype, TYPE_BINFO (target),
- 0, &offset);
+ false, &offset);
if (!boff)
return offset;
return offset;
}
-/* Search for a member with name NAME in a multiple inheritance lattice
- specified by TYPE. If it does not exist, return NULL_TREE.
+/* Search for a member with name NAME in a multiple inheritance
+ lattice specified by TYPE. If it does not exist, return NULL_TREE.
If the member is ambiguously referenced, return `error_mark_node'.
- Otherwise, return the FIELD_DECL. */
+ Otherwise, return a DECL with the indicated name. If WANT_TYPE is
+ true, type declarations are preferred. */
/* Do a 1-level search for NAME as a member of TYPE. The caller must
figure out whether it can access this field. (Since it is only one
level, this is reasonable.) */
-static tree
-lookup_field_1 (type, name)
- tree type, name;
+tree
+lookup_field_1 (tree type, tree name, bool want_type)
{
- register tree field;
+ tree field;
if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
|| TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM
&& DECL_LANG_SPECIFIC (TYPE_NAME (type))
&& DECL_SORTED_FIELDS (TYPE_NAME (type)))
{
- tree *fields = &TREE_VEC_ELT (DECL_SORTED_FIELDS (TYPE_NAME (type)), 0);
- int lo = 0, hi = TREE_VEC_LENGTH (DECL_SORTED_FIELDS (TYPE_NAME (type)));
+ tree *fields = &DECL_SORTED_FIELDS (TYPE_NAME (type))->elts[0];
+ int lo = 0, hi = DECL_SORTED_FIELDS (TYPE_NAME (type))->len;
int i;
while (lo < hi)
lo = i + 1;
else
{
+ field = NULL_TREE;
+
/* We might have a nested class and a field with the
same name; we sorted them appropriately via
- field_decl_cmp, so just look for the last field with
- this name. */
- while (i + 1 < hi
- && DECL_NAME (fields[i+1]) == name)
- ++i;
- return fields[i];
+ field_decl_cmp, so just look for the first or last
+ field with this name. */
+ if (want_type)
+ {
+ do
+ field = fields[i--];
+ while (i >= lo && DECL_NAME (fields[i]) == name);
+ if (TREE_CODE (field) != TYPE_DECL
+ && !DECL_CLASS_TEMPLATE_P (field))
+ field = NULL_TREE;
+ }
+ else
+ {
+ do
+ field = fields[i++];
+ while (i < hi && DECL_NAME (fields[i]) == name);
+ }
+ return field;
}
}
return NULL_TREE;
#ifdef GATHER_STATISTICS
n_calls_lookup_field_1++;
#endif /* GATHER_STATISTICS */
- while (field)
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
#ifdef GATHER_STATISTICS
n_fields_searched++;
if (DECL_NAME (field) == NULL_TREE
&& ANON_AGGR_TYPE_P (TREE_TYPE (field)))
{
- tree temp = lookup_field_1 (TREE_TYPE (field), name);
+ tree temp = lookup_field_1 (TREE_TYPE (field), name, want_type);
if (temp)
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. */
- ;
- else if (DECL_NAME (field) == name)
+ {
+ /* 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
+ || TREE_CODE (field) == TYPE_DECL
+ || DECL_CLASS_TEMPLATE_P (field)))
return field;
- field = TREE_CHAIN (field);
}
/* Not found. */
if (name == vptr_identifier)
function. If so, we know to put the decls into the class's scope. */
tree
-current_scope ()
+current_scope (void)
{
if (current_function_decl == NULL_TREE)
return current_class_type;
not within a member function body of the local class. */
int
-at_function_scope_p ()
+at_function_scope_p (void)
{
tree cs = current_scope ();
return cs && TREE_CODE (cs) == FUNCTION_DECL;
/* Returns true if the innermost active scope is a class scope. */
bool
-at_class_scope_p ()
+at_class_scope_p (void)
{
tree cs = current_scope ();
return cs && TYPE_P (cs);
}
+/* Returns true if the innermost active scope is a namespace scope. */
+
+bool
+at_namespace_scope_p (void)
+{
+ /* We are in a namespace scope if we are not it a class scope or a
+ function scope. */
+ return !current_scope();
+}
+
/* Return the scope of DECL, as appropriate when doing name-lookup. */
tree
-context_for_name_lookup (decl)
- tree decl;
+context_for_name_lookup (tree decl)
{
/* [class.union]
return context;
}
-/* Return a canonical BINFO if BINFO is a virtual base, or just BINFO
- otherwise. */
-
-static tree
-canonical_binfo (binfo)
- tree binfo;
-{
- return (TREE_VIA_VIRTUAL (binfo)
- ? TYPE_BINFO (BINFO_TYPE (binfo)) : binfo);
-}
-
-/* A queue function that simply ensures that we walk into the
- canonical versions of virtual bases. */
-
-static tree
-dfs_canonical_queue (binfo, data)
- tree binfo;
- void *data ATTRIBUTE_UNUSED;
-{
- return canonical_binfo (binfo);
-}
-
-/* Called via dfs_walk from assert_canonical_unmarked. */
-
-static tree
-dfs_assert_unmarked_p (binfo, data)
- tree binfo;
- void *data ATTRIBUTE_UNUSED;
-{
- my_friendly_assert (!BINFO_MARKED (binfo), 0);
- return NULL_TREE;
-}
-
-/* Asserts that all the nodes below BINFO (using the canonical
- versions of virtual bases) are unmarked. */
-
-static void
-assert_canonical_unmarked (binfo)
- tree binfo;
-{
- dfs_walk (binfo, dfs_assert_unmarked_p, dfs_canonical_queue, 0);
-}
-
-/* If BINFO is marked, return a canonical version of BINFO.
- Otherwise, return NULL_TREE. */
-
-static tree
-shared_marked_p (binfo, data)
- tree binfo;
- void *data;
-{
- binfo = canonical_binfo (binfo);
- return markedp (binfo, data);
-}
-
-/* If BINFO is not marked, return a canonical version of BINFO.
- Otherwise, return NULL_TREE. */
-
-static tree
-shared_unmarked_p (binfo, data)
- tree binfo;
- void *data;
-{
- binfo = canonical_binfo (binfo);
- return unmarkedp (binfo, data);
-}
-
/* The accessibility routines use BINFO_ACCESS for scratch space
- during the computation of the accssibility of some declaration. */
+ during the computation of the accessibility of some declaration. */
#define BINFO_ACCESS(NODE) \
- ((access_kind) ((TREE_LANG_FLAG_1 (NODE) << 1) | TREE_LANG_FLAG_6 (NODE)))
+ ((access_kind) ((TREE_PUBLIC (NODE) << 1) | TREE_PRIVATE (NODE)))
/* Set the access associated with NODE to ACCESS. */
#define SET_BINFO_ACCESS(NODE, ACCESS) \
- ((TREE_LANG_FLAG_1 (NODE) = ((ACCESS) & 2) != 0), \
- (TREE_LANG_FLAG_6 (NODE) = ((ACCESS) & 1) != 0))
+ ((TREE_PUBLIC (NODE) = ((ACCESS) & 2) != 0), \
+ (TREE_PRIVATE (NODE) = ((ACCESS) & 1) != 0))
/* Called from access_in_type via dfs_walk. Calculate the access to
DATA (which is really a DECL) in BINFO. */
static tree
-dfs_access_in_type (binfo, data)
- tree binfo;
- void *data;
+dfs_access_in_type (tree binfo, void *data)
{
tree decl = (tree) data;
tree type = BINFO_TYPE (binfo);
if (context_for_name_lookup (decl) == type)
{
- /* If we have desceneded to the scope of DECL, just note the
+ /* If we have descended to the scope of DECL, just note the
appropriate access. */
if (TREE_PRIVATE (decl))
access = ak_private;
if (DECL_LANG_SPECIFIC (decl) && !DECL_DISCRIMINATOR_P (decl))
{
tree decl_access = purpose_member (type, DECL_ACCESS (decl));
+
if (decl_access)
- access = ((access_kind)
- TREE_INT_CST_LOW (TREE_VALUE (decl_access)));
+ {
+ decl_access = TREE_VALUE (decl_access);
+
+ if (decl_access == access_public_node)
+ access = ak_public;
+ else if (decl_access == access_protected_node)
+ access = ak_protected;
+ else if (decl_access == access_private_node)
+ access = ak_private;
+ else
+ my_friendly_assert (false, 20030217);
+ }
}
if (!access)
{
int i;
- int n_baselinks;
- tree binfos;
+ tree base_binfo, accesses;
/* Otherwise, scan our baseclasses, and pick the most favorable
access. */
- binfos = BINFO_BASETYPES (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);
- access_kind base_access
- = BINFO_ACCESS (canonical_binfo (base_binfo));
+ tree base_access = TREE_VEC_ELT (accesses, i);
+ access_kind base_access_now = BINFO_ACCESS (base_binfo);
- if (base_access == ak_none || base_access == ak_private)
+ if (base_access_now == ak_none || base_access_now == ak_private)
/* If it was not accessible in the base, or only
accessible as a private member, we can't access it
all. */
- base_access = ak_none;
- else if (TREE_VIA_PROTECTED (base_binfo))
- /* Public and protected members in the base are
+ base_access_now = ak_none;
+ else if (base_access == access_protected_node)
+ /* Public and protected members in the base become
protected here. */
- base_access = ak_protected;
- else if (!TREE_VIA_PUBLIC (base_binfo))
- /* Public and protected members in the base are
+ base_access_now = ak_protected;
+ else if (base_access == access_private_node)
+ /* Public and protected members in the base become
private here. */
- base_access = ak_private;
+ base_access_now = ak_private;
/* See if the new access, via this base, gives more
access than our previous best access. */
- if (base_access != ak_none
- && (base_access == ak_public
- || (base_access == ak_protected
- && access != ak_public)
- || (base_access == ak_private
- && access == ak_none)))
+ if (base_access_now != ak_none
+ && (access == ak_none || base_access_now < access))
{
- access = base_access;
+ access = base_access_now;
/* If the new access is public, we can't do better. */
if (access == ak_public)
/* Mark TYPE as visited so that if we reach it again we do not
duplicate our efforts here. */
- SET_BINFO_MARKED (binfo);
+ BINFO_MARKED (binfo) = 1;
return NULL_TREE;
}
/* Return the access to DECL in TYPE. */
static access_kind
-access_in_type (type, decl)
- tree type;
- tree decl;
+access_in_type (tree type, tree decl)
{
tree binfo = TYPE_BINFO (type);
The algorithm we use is to make a post-order depth-first traversal
of the base-class hierarchy. As we come up the tree, we annotate
each node with the most lenient access. */
- dfs_walk_real (binfo, 0, dfs_access_in_type, shared_unmarked_p, decl);
- dfs_walk (binfo, dfs_unmark, shared_marked_p, 0);
- assert_canonical_unmarked (binfo);
+ dfs_walk_real (binfo, 0, dfs_access_in_type, unmarkedp, decl);
+ dfs_walk (binfo, dfs_unmark, markedp, 0);
return BINFO_ACCESS (binfo);
}
-/* Called from dfs_accessible_p via dfs_walk. */
+/* Called from accessible_p via dfs_walk. */
static tree
-dfs_accessible_queue_p (binfo, data)
- tree binfo;
- void *data ATTRIBUTE_UNUSED;
+dfs_accessible_queue_p (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
{
+ 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 subclass. */
- if (!TREE_VIA_PUBLIC (binfo)
- && !is_friend (BINFO_TYPE (BINFO_INHERITANCE_CHAIN (binfo)),
- current_scope ()))
+ then we can't see it, unless we are a friend of the derived class. */
+ if (BINFO_BASE_ACCESS (derived, ix) != access_public_node
+ && !is_friend (BINFO_TYPE (derived), current_scope ()))
return NULL_TREE;
- return canonical_binfo (binfo);
+ return binfo;
}
-/* Called from dfs_accessible_p via dfs_walk. */
+/* Called from accessible_p via dfs_walk. */
static tree
-dfs_accessible_p (binfo, data)
- tree binfo;
- void *data;
+dfs_accessible_p (tree binfo, void *data ATTRIBUTE_UNUSED)
{
- int protected_ok = data != 0;
access_kind access;
- SET_BINFO_MARKED (binfo);
+ BINFO_MARKED (binfo) = 1;
access = BINFO_ACCESS (binfo);
- if (access == ak_public || (access == ak_protected && protected_ok))
- return binfo;
- else if (access != ak_none
- && is_friend (BINFO_TYPE (binfo), current_scope ()))
+ if (access != ak_none
+ && is_friend (BINFO_TYPE (binfo), current_scope ()))
return binfo;
return NULL_TREE;
}
/* Returns nonzero if it is OK to access DECL through an object
- indiated by BINFO in the context of DERIVED. */
+ indicated by BINFO in the context of DERIVED. */
static int
-protected_accessible_p (decl, derived, binfo)
- tree decl;
- tree derived;
- tree binfo;
+protected_accessible_p (tree decl, tree derived, tree binfo)
{
access_kind access;
to access DECL through the object indicated by BINFO. */
static int
-friend_accessible_p (scope, decl, binfo)
- tree scope;
- tree decl;
- tree binfo;
+friend_accessible_p (tree scope, tree decl, tree binfo)
{
tree befriending_classes;
tree t;
at the most derived class along the path indicated by BINFO. */
int
-accessible_p (type, decl)
- tree type;
- tree decl;
-
+accessible_p (tree type, tree decl)
{
tree binfo;
tree t;
+ tree scope;
+ access_kind access;
/* Nonzero if it's OK to access DECL if it has protected
accessibility in TYPE. */
int protected_ok = 0;
- /* If we're not checking access, everything is accessible. */
- if (!scope_chain->check_access)
- return 1;
-
/* If this declaration is in a block or namespace scope, there's no
access control. */
if (!TYPE_P (context_for_name_lookup (decl)))
return 1;
+ /* There is no need to perform access checks inside a thunk. */
+ scope = current_scope ();
+ if (scope && DECL_THUNK_P (scope))
+ return 1;
+
+ /* In a template declaration, we cannot be sure whether the
+ particular specialization that is instantiated will be a friend
+ or not. Therefore, all access checks are deferred until
+ instantiation. */
+ if (processing_template_decl)
+ return 1;
+
if (!TYPE_P (type))
{
binfo = type;
/* Now, loop through the classes of which we are a friend. */
if (!protected_ok)
- protected_ok = friend_accessible_p (current_scope (), decl, binfo);
+ protected_ok = friend_accessible_p (scope, decl, binfo);
/* Standardize the binfo that access_in_type will use. We don't
need to know what path was chosen from this point onwards. */
/* Compute the accessibility of DECL in the class hierarchy
dominated by type. */
- access_in_type (type, decl);
- /* Walk the hierarchy again, looking for a base class that allows
- access. */
- t = dfs_walk (binfo, dfs_accessible_p,
- dfs_accessible_queue_p,
- protected_ok ? &protected_ok : 0);
- /* Clear any mark bits. Note that we have to walk the whole tree
- here, since we have aborted the previous walk from some point
- deep in the tree. */
- dfs_walk (binfo, dfs_unmark, dfs_canonical_queue, 0);
- assert_canonical_unmarked (binfo);
-
- return t != NULL_TREE;
-}
-
-/* Recursive helper funciton for is_subobject_of_p; see that routine
- for documentation of the parameters. */
-
-static int
-is_subobject_of_p_1 (parent, binfo, most_derived)
- tree parent, binfo, most_derived;
-{
- tree binfos;
- int i, n_baselinks;
-
- if (parent == binfo)
+ access = access_in_type (type, decl);
+ if (access == ak_public
+ || (access == ak_protected && protected_ok))
return 1;
-
- binfos = BINFO_BASETYPES (binfo);
- n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- /* Iterate through the base types. */
- for (i = 0; i < n_baselinks; i++)
+ else
{
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree base_type;
-
- base_type = TREE_TYPE (base_binfo);
- if (!CLASS_TYPE_P (base_type))
- /* If we see a TEMPLATE_TYPE_PARM, or some such, as a base
- class there's no way to descend into it. */
- continue;
-
- /* Avoid walking into the same virtual base more than once. */
- if (TREE_VIA_VIRTUAL (base_binfo))
- {
- if (CLASSTYPE_MARKED4 (base_type))
- continue;
- SET_CLASSTYPE_MARKED4 (base_type);
- base_binfo = binfo_for_vbase (base_type, most_derived);
- }
-
- if (is_subobject_of_p_1 (parent, base_binfo, most_derived))
- return 1;
+ /* Walk the hierarchy again, looking for a base class that allows
+ access. */
+ t = dfs_walk (binfo, dfs_accessible_p, dfs_accessible_queue_p, 0);
+ /* Clear any mark bits. Note that we have to walk the whole tree
+ here, since we have aborted the previous walk from some point
+ deep in the tree. */
+ dfs_walk (binfo, dfs_unmark, 0, 0);
+
+ return t != NULL_TREE;
}
- return 0;
-}
-
-/* Routine to see if the sub-object denoted by the binfo PARENT can be
- found as a base class and sub-object of the object denoted by
- BINFO. MOST_DERIVED is the most derived type of the hierarchy being
- searched. */
-
-static int
-is_subobject_of_p (tree parent, tree binfo, tree most_derived)
-{
- int result;
- tree vbase;
-
- result = is_subobject_of_p_1 (parent, binfo, most_derived);
- /* Clear the mark bits on virtual bases. */
- for (vbase = CLASSTYPE_VBASECLASSES (most_derived);
- vbase;
- vbase = TREE_CHAIN (vbase))
- CLEAR_CLASSTYPE_MARKED4 (TREE_TYPE (TREE_VALUE (vbase)));
-
- return result;
}
struct lookup_field_info {
tree ambiguous;
/* If nonzero, we are looking for types, not data members. */
int want_type;
- /* If nonzero, RVAL was found by looking through a dependent base. */
- int from_dep_base_p;
/* If something went wrong, a message indicating what. */
const char *errstr;
};
lookup_field via breadth_first_search. */
static tree
-lookup_field_queue_p (binfo, data)
- tree binfo;
- void *data;
+lookup_field_queue_p (tree derived, int ix, void *data)
{
+ 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. */
/* If this base class is hidden by the best-known value so far, we
don't need to look. */
- binfo = CANONICAL_BINFO (binfo, lfi->type);
- if (!lfi->from_dep_base_p && lfi->rval_binfo
- && is_subobject_of_p (binfo, lfi->rval_binfo, lfi->type))
+ if (lfi->rval_binfo && original_binfo (binfo, lfi->rval_binfo))
return NULL_TREE;
+ /* If this is a dependent base, don't look in it. */
+ if (BINFO_DEPENDENT_BASE_P (binfo))
+ return NULL_TREE;
+
return binfo;
}
Returns nonzero if DECL is such a declaration in a class TYPE. */
static int
-template_self_reference_p (type, decl)
- tree type;
- tree decl;
+template_self_reference_p (tree type, tree decl)
{
return (CLASSTYPE_USE_TEMPLATE (type)
&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))
This function checks that T contains no nonstatic members. */
static int
-shared_member_p (t)
- tree t;
+shared_member_p (tree t)
{
if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == TYPE_DECL \
|| TREE_CODE (t) == CONST_DECL)
lookup_field via breadth_first_search. */
static tree
-lookup_field_r (binfo, data)
- tree binfo;
- void *data;
+lookup_field_r (tree binfo, void *data)
{
struct lookup_field_info *lfi = (struct lookup_field_info *) data;
tree type = BINFO_TYPE (binfo);
tree nval = NULL_TREE;
- int from_dep_base_p;
/* First, look for a function. There can't be a function and a data
member with the same name, and if there's a function and a type
{
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)
/* Look for a data member or type. */
- nval = lookup_field_1 (type, lfi->name);
+ nval = lookup_field_1 (type, lfi->name, lfi->want_type);
/* If there is no declaration with the indicated name in this type,
then there's nothing to do. */
}
else
nval = NULL_TREE;
- if (!nval)
+ if (!nval && CLASSTYPE_NESTED_UTDS (type) != NULL)
{
- nval = purpose_member (lfi->name, CLASSTYPE_TAGS (type));
- if (nval)
- nval = TYPE_MAIN_DECL (TREE_VALUE (nval));
+ binding_entry e = binding_table_find (CLASSTYPE_NESTED_UTDS (type),
+ lfi->name);
+ if (e != NULL)
+ nval = TYPE_MAIN_DECL (e->type);
else
return NULL_TREE;
}
&& template_self_reference_p (type, nval))
return NULL_TREE;
- from_dep_base_p = dependent_base_p (binfo);
- if (lfi->from_dep_base_p && !from_dep_base_p)
- {
- /* If the new declaration is not found via a dependent base, and
- the old one was, then we must prefer the new one. We weren't
- really supposed to be able to find the old one, so we don't
- want to be affected by a specialization. Consider:
-
- struct B { typedef int I; };
- template <typename T> struct D1 : virtual public B {};
- template <typename T> struct D :
- public D1, virtual pubic B { I i; };
-
- The `I' in `D<T>' is unambigousuly `B::I', regardless of how
- D1 is specialized. */
- lfi->from_dep_base_p = 0;
- lfi->rval = NULL_TREE;
- lfi->rval_binfo = NULL_TREE;
- lfi->ambiguous = NULL_TREE;
- lfi->errstr = 0;
- }
- else if (lfi->rval_binfo && !lfi->from_dep_base_p && from_dep_base_p)
- /* Similarly, if the old declaration was not found via a dependent
- base, and the new one is, ignore the new one. */
- return NULL_TREE;
-
/* If the lookup already found a match, and the new value doesn't
hide the old one, we might have an ambiguity. */
- if (lfi->rval_binfo && !is_subobject_of_p (lfi->rval_binfo, binfo, lfi->type))
+ if (lfi->rval_binfo && !original_binfo (lfi->rval_binfo, binfo))
{
if (nval == lfi->rval && shared_member_p (nval))
/* The two things are really the same. */
;
- else if (is_subobject_of_p (binfo, lfi->rval_binfo, lfi->type))
+ else if (original_binfo (binfo, lfi->rval_binfo))
/* The previous value hides the new one. */
;
else
}
else
{
- if (from_dep_base_p && TREE_CODE (nval) == TYPE_DECL
- /* We need to return a member template class so we can
- define partial specializations. Is there a better
- way? */
- && !DECL_CLASS_TEMPLATE_P (nval))
- /* The thing we're looking for isn't a type, so the implicit
- typename extension doesn't apply, so we just pretend we
- didn't find anything. */
- return NULL_TREE;
-
lfi->rval = nval;
- lfi->from_dep_base_p = from_dep_base_p;
lfi->rval_binfo = binfo;
}
If nothing can be found return NULL_TREE and do not issue an error. */
tree
-lookup_member (xbasetype, name, protect, want_type)
- register tree xbasetype, name;
- int protect, want_type;
+lookup_member (tree xbasetype, tree name, int protect, bool want_type)
{
tree rval, rval_binfo = NULL_TREE;
tree type = NULL_TREE, basetype_path = NULL_TREE;
const char *errstr = 0;
- if (xbasetype == current_class_type && TYPE_BEING_DEFINED (xbasetype)
- && IDENTIFIER_CLASS_VALUE (name))
- {
- tree field = IDENTIFIER_CLASS_VALUE (name);
- if (TREE_CODE (field) != FUNCTION_DECL
- && ! (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;
- }
+ my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 20030624);
- if (TREE_CODE (xbasetype) == TREE_VEC)
+ if (TREE_CODE (xbasetype) == TREE_BINFO)
{
type = BINFO_TYPE (xbasetype);
basetype_path = xbasetype;
}
- else if (IS_AGGR_TYPE_CODE (TREE_CODE (xbasetype)))
+ else
{
+ 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) == NULL_TREE,
- 980827);
+ xbasetype = NULL_TREE;
}
- else
- abort ();
- complete_type (type);
+ type = complete_type (type);
+ if (!basetype_path)
+ basetype_path = TYPE_BINFO (type);
+
+ if (!basetype_path)
+ return NULL_TREE;
#ifdef GATHER_STATISTICS
n_calls_lookup_field++;
#endif /* GATHER_STATISTICS */
- memset ((PTR) &lfi, 0, sizeof (lfi));
+ memset (&lfi, 0, sizeof (lfi));
lfi.type = type;
lfi.name = name;
lfi.want_type = want_type;
In the case of overloaded function names, access control is
applied to the function selected by overloaded resolution. */
- if (rval && protect && !is_overloaded_fn (rval)
- && !enforce_access (xbasetype, rval))
- return error_mark_node;
+ if (rval && protect && !is_overloaded_fn (rval))
+ perform_or_defer_access_check (basetype_path, rval);
if (errstr && protect)
{
rval = error_mark_node;
}
- /* If the thing we found was found via the implicit typename
- extension, build the typename type. */
- if (rval && lfi.from_dep_base_p && !DECL_CLASS_TEMPLATE_P (rval))
- abort ();
-
if (rval && is_overloaded_fn (rval))
rval = build_baselink (rval_binfo, basetype_path, rval,
(IDENTIFIER_TYPENAME_P (name)
return NULL_TREE. */
tree
-lookup_field (xbasetype, name, protect, want_type)
- register tree xbasetype, name;
- int protect, want_type;
+lookup_field (tree xbasetype, tree name, int protect, bool want_type)
{
tree rval = lookup_member (xbasetype, name, protect, want_type);
- /* Ignore functions. */
- if (rval && BASELINK_P (rval))
+ /* Ignore functions, but propagate the ambiguity list. */
+ if (!error_operand_p (rval)
+ && (rval && BASELINK_P (rval)))
return NULL_TREE;
return rval;
return NULL_TREE. */
tree
-lookup_fnfields (xbasetype, name, protect)
- register tree xbasetype, name;
- int protect;
+lookup_fnfields (tree xbasetype, tree name, int protect)
{
- tree rval = lookup_member (xbasetype, name, protect, /*want_type=*/0);
+ tree rval = lookup_member (xbasetype, name, protect, /*want_type=*/false);
- /* Ignore non-functions. */
- if (rval && !BASELINK_P (rval))
+ /* Ignore non-functions, but propagate the ambiguity list. */
+ if (!error_operand_p (rval)
+ && (rval && !BASELINK_P (rval)))
return NULL_TREE;
return rval;
}
+/* Return the index in the CLASSTYPE_METHOD_VEC for CLASS_TYPE
+ corresponding to "operator TYPE ()", or -1 if there is no such
+ operator. Only CLASS_TYPE itself is searched; this routine does
+ not scan the base classes of CLASS_TYPE. */
+
+static int
+lookup_conversion_operator (tree class_type, tree type)
+{
+ int pass;
+ int i;
+ tree fn;
+ VEC(tree) *methods;
+
+ methods = CLASSTYPE_METHOD_VEC (class_type);
+
+ for (pass = 0; pass < 2; ++pass)
+ 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 (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;
+ }
+ }
+
+ return -1;
+}
+
/* TYPE is a class type. Return the index of the fields within
the method vector with name NAME, or -1 is no such field exists. */
int
-lookup_fnfields_1 (type, name)
- tree type, name;
+lookup_fnfields_1 (tree type, tree name)
{
- tree method_vec = (CLASS_TYPE_P (type)
- ? CLASSTYPE_METHOD_VEC (type)
- : NULL_TREE);
+ VEC(tree) *method_vec;
+ tree fn;
+ tree tmp;
+ size_t i;
+
+ if (!CLASS_TYPE_P (type))
+ return -1;
- if (method_vec != 0)
+ if (COMPLETE_TYPE_P (type))
{
- register int i;
- register tree *methods = &TREE_VEC_ELT (method_vec, 0);
- int len = TREE_VEC_LENGTH (method_vec);
- tree tmp;
+ 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);
+ }
-#ifdef GATHER_STATISTICS
- n_calls_lookup_fnfields_1++;
-#endif /* GATHER_STATISTICS */
+ method_vec = CLASSTYPE_METHOD_VEC (type);
+ if (!method_vec)
+ return -1;
- /* Constructors are first... */
- if (name == ctor_identifier)
- return (methods[CLASSTYPE_CONSTRUCTOR_SLOT]
- ? CLASSTYPE_CONSTRUCTOR_SLOT : -1);
- /* and destructors are second. */
- if (name == dtor_identifier)
- return (methods[CLASSTYPE_DESTRUCTOR_SLOT]
- ? CLASSTYPE_DESTRUCTOR_SLOT : -1);
-
- for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
- i < len && methods[i];
- ++i)
- {
#ifdef GATHER_STATISTICS
- n_outer_fields_searched++;
+ n_calls_lookup_fnfields_1++;
#endif /* GATHER_STATISTICS */
- tmp = OVL_CURRENT (methods[i]);
- if (DECL_NAME (tmp) == name)
- return i;
+ /* Constructors are first... */
+ if (name == ctor_identifier)
+ {
+ fn = CLASSTYPE_CONSTRUCTORS (type);
+ return fn ? CLASSTYPE_CONSTRUCTOR_SLOT : -1;
+ }
+ /* and destructors are second. */
+ if (name == dtor_identifier)
+ {
+ 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. */
+ 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 and we're past the conversion ops,
- switch to binary search. */
- if (! DECL_CONV_FN_P (tmp)
- && COMPLETE_TYPE_P (type))
- {
- int lo = i + 1, hi = len;
+ /* If the type is complete, use binary search. */
+ if (COMPLETE_TYPE_P (type))
+ {
+ int lo;
+ int hi;
- while (lo < hi)
- {
- i = (lo + hi) / 2;
+ lo = i;
+ hi = VEC_length (tree, method_vec);
+ while (lo < hi)
+ {
+ i = (lo + hi) / 2;
#ifdef GATHER_STATISTICS
- n_outer_fields_searched++;
+ n_outer_fields_searched++;
#endif /* GATHER_STATISTICS */
- tmp = DECL_NAME (OVL_CURRENT (methods[i]));
-
- if (tmp > name)
- hi = i;
- else if (tmp < name)
- lo = i + 1;
- else
- return i;
- }
- break;
- }
- }
-
- /* If we didn't find it, it might have been a template
- conversion operator to a templated type. If there are any,
- such template conversion operators will all be overloaded on
- the first conversion slot. (Note that we don't look for this
- case above so that we will always find specializations
- first.) */
- if (IDENTIFIER_TYPENAME_P (name))
- {
- i = CLASSTYPE_FIRST_CONVERSION_SLOT;
- if (i < len && methods[i])
- {
- tmp = OVL_CURRENT (methods[i]);
- if (TREE_CODE (tmp) == TEMPLATE_DECL
- && DECL_TEMPLATE_CONV_FN_P (tmp))
- return i;
- }
+ 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
+ return i;
}
}
+ else
+ for (; VEC_iterate (tree, method_vec, i, fn); ++i)
+ {
+#ifdef GATHER_STATISTICS
+ n_outer_fields_searched++;
+#endif /* GATHER_STATISTICS */
+ if (DECL_NAME (OVL_CURRENT (fn)) == name)
+ return i;
+ }
return -1;
}
my_friendly_assert (CLASS_TYPE_P (context_class), 20020808);
- /* Look for the QUALIFYING_SCOPE as a base of the
- CONTEXT_CLASS. If QUALIFYING_SCOPE is ambiguous, we cannot
- be sure yet than an error has occurred; perhaps the function
- chosen by overload resolution will be static. */
+ /* Look for the QUALIFYING_SCOPE as a base of the CONTEXT_CLASS.
+ Because we do not yet know which function will be chosen by
+ overload resolution, we cannot yet check either accessibility
+ or ambiguity -- in either case, the choice of a static member
+ function might make the usage valid. */
base = lookup_base (context_class, qualifying_scope,
ba_ignore | ba_quiet, NULL);
if (base)
type in the hierarchy, in a breadth-first preorder traversal.
If it ever returns a non-NULL value, that value is immediately
returned and the walk is terminated. At each node, FN is passed a
- BINFO indicating the path from the curently visited base-class to
+ BINFO indicating the path from the currently visited base-class to
TYPE. Before each base-class is walked QFN is called. If the
value returned is nonzero, the base-class is walked; otherwise it
is not. If QFN is NULL, it is treated as a function which always
returns 1. Both FN and QFN are passed the DATA whenever they are
- called. */
+ called.
+
+ Implementation notes: Uses a circular queue, which starts off on
+ the stack but gets moved to the malloc arena if it needs to be
+ enlarged. The underflow and overflow conditions are
+ indistinguishable except by context: if head == tail and we just
+ moved the head pointer, the queue is empty, but if we just moved
+ the tail pointer, the queue is full.
+ Start with enough room for ten concurrent base classes. That
+ will be enough for most hierarchies. */
+#define BFS_WALK_INITIAL_QUEUE_SIZE 10
static tree
-bfs_walk (binfo, fn, qfn, data)
- tree binfo;
- tree (*fn) PARAMS ((tree, void *));
- tree (*qfn) PARAMS ((tree, void *));
- void *data;
+bfs_walk (tree binfo,
+ tree (*fn) (tree, void *),
+ tree (*qfn) (tree, int, void *),
+ void *data)
{
- size_t head;
- size_t tail;
tree rval = NULL_TREE;
- /* An array of the base classes of BINFO. These will be built up in
- breadth-first order, except where QFN prunes the search. */
- varray_type bfs_bases;
- /* Start with enough room for ten base classes. That will be enough
- for most hierarchies. */
- VARRAY_TREE_INIT (bfs_bases, 10, "search_stack");
+ tree bases_initial[BFS_WALK_INITIAL_QUEUE_SIZE];
+ /* A circular queue of the base classes of BINFO. These will be
+ built up in breadth-first order, except where QFN prunes the
+ search. */
+ size_t head, tail;
+ size_t base_buffer_size = BFS_WALK_INITIAL_QUEUE_SIZE;
+ tree *base_buffer = bases_initial;
- /* Put the first type into the stack. */
- VARRAY_TREE (bfs_bases, 0) = binfo;
- tail = 1;
+ head = tail = 0;
+ base_buffer[tail++] = binfo;
- for (head = 0; head < tail; ++head)
+ while (head != tail)
{
- int i;
- int n_baselinks;
- tree binfos;
+ int n_bases, ix;
+ tree binfo = base_buffer[head++];
+ if (head == base_buffer_size)
+ head = 0;
- /* Pull the next type out of the queue. */
- binfo = VARRAY_TREE (bfs_bases, head);
-
- /* If this is the one we're looking for, we're done. */
- rval = (*fn) (binfo, data);
+ /* Is this the one we're looking for? If so, we're done. */
+ rval = fn (binfo, data);
if (rval)
- break;
+ goto done;
- /* Queue up the base types. */
- binfos = BINFO_BASETYPES (binfo);
- n_baselinks = binfos ? TREE_VEC_LENGTH (binfos): 0;
- for (i = 0; i < n_baselinks; i++)
+ n_bases = BINFO_N_BASE_BINFOS (binfo);
+ for (ix = 0; ix != n_bases; ix++)
{
- tree base_binfo = TREE_VEC_ELT (binfos, i);
-
+ tree base_binfo;
+
if (qfn)
- base_binfo = (*qfn) (base_binfo, data);
-
- if (base_binfo)
+ base_binfo = (*qfn) (binfo, ix, data);
+ else
+ base_binfo = BINFO_BASE_BINFO (binfo, ix);
+
+ if (base_binfo)
{
- if (tail == VARRAY_SIZE (bfs_bases))
- VARRAY_GROW (bfs_bases, 2 * VARRAY_SIZE (bfs_bases));
- VARRAY_TREE (bfs_bases, tail) = base_binfo;
- ++tail;
+ base_buffer[tail++] = base_binfo;
+ if (tail == base_buffer_size)
+ tail = 0;
+ if (tail == head)
+ {
+ tree *new_buffer = xmalloc (2 * base_buffer_size
+ * sizeof (tree));
+ memcpy (&new_buffer[0], &base_buffer[0],
+ tail * sizeof (tree));
+ memcpy (&new_buffer[head + base_buffer_size],
+ &base_buffer[head],
+ (base_buffer_size - head) * sizeof (tree));
+ if (base_buffer_size != BFS_WALK_INITIAL_QUEUE_SIZE)
+ free (base_buffer);
+ base_buffer = new_buffer;
+ head += base_buffer_size;
+ base_buffer_size *= 2;
+ }
}
}
}
+ done:
+ if (base_buffer_size != BFS_WALK_INITIAL_QUEUE_SIZE)
+ free (base_buffer);
return rval;
}
in postorder. */
tree
-dfs_walk_real (binfo, prefn, postfn, qfn, data)
- tree binfo;
- tree (*prefn) PARAMS ((tree, void *));
- tree (*postfn) PARAMS ((tree, void *));
- tree (*qfn) PARAMS ((tree, void *));
- void *data;
+dfs_walk_real (tree binfo,
+ tree (*prefn) (tree, void *),
+ tree (*postfn) (tree, void *),
+ tree (*qfn) (tree, int, void *),
+ void *data)
{
int i;
- int n_baselinks;
- tree binfos;
+ tree base_binfo;
tree rval = NULL_TREE;
/* Call the pre-order walking function. */
}
/* Process the basetypes. */
- binfos = BINFO_BASETYPES (binfo);
- n_baselinks = BINFO_N_BASETYPES (binfo);
- for (i = 0; i < n_baselinks; i++)
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
{
- tree base_binfo = TREE_VEC_ELT (binfos, i);
-
if (qfn)
- base_binfo = (*qfn) (base_binfo, data);
-
- 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. */
performed. */
tree
-dfs_walk (binfo, fn, qfn, data)
- tree binfo;
- tree (*fn) PARAMS ((tree, void *));
- tree (*qfn) PARAMS ((tree, void *));
- void *data;
+dfs_walk (tree binfo,
+ tree (*fn) (tree, void *),
+ tree (*qfn) (tree, int, void *),
+ void *data)
{
return dfs_walk_real (binfo, 0, fn, qfn, data);
}
BASEFN. Issue diagnostic, and return zero, if unacceptable. */
int
-check_final_overrider (overrider, basefn)
- tree overrider, basefn;
+check_final_overrider (tree overrider, tree basefn)
{
tree over_type = TREE_TYPE (overrider);
tree base_type = TREE_TYPE (basefn);
tree over_throw = TYPE_RAISES_EXCEPTIONS (over_type);
tree base_throw = TYPE_RAISES_EXCEPTIONS (base_type);
int fail = 0;
-
+
+ if (DECL_INVALID_OVERRIDER_P (overrider))
+ return 0;
+
if (same_type_p (base_return, over_return))
/* OK */;
else if ((CLASS_TYPE_P (over_return) && CLASS_TYPE_P (base_return))
|| (TREE_CODE (base_return) == TREE_CODE (over_return)
&& POINTER_TYPE_P (base_return)))
{
- /* Potentially covariant. */
+ /* Potentially covariant. */
unsigned base_quals, over_quals;
fail = !POINTER_TYPE_P (base_return);
converting to void *, or qualification conversion. */
{
/* can_convert will permit user defined conversion from a
- (reference to) class type. We must reject them. */
- over_return = TREE_TYPE (over_type);
- if (TREE_CODE (over_return) == REFERENCE_TYPE)
- over_return = TREE_TYPE (over_return);
+ (reference to) class type. We must reject them. */
+ over_return = non_reference (TREE_TYPE (over_type));
if (CLASS_TYPE_P (over_return))
fail = 2;
}
fail = 2;
if (!fail)
/* OK */;
- else if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider)))
- return 0;
else
{
if (fail == 1)
overrider);
cp_error_at (" overriding `%#D'", basefn);
}
- SET_IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider),
- DECL_CONTEXT (overrider));
+ DECL_INVALID_OVERRIDER_P (overrider) = 1;
return 0;
}
/* Check throw specifier is at least as strict. */
if (!comp_except_specs (base_throw, over_throw, 0))
{
- if (!IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider)))
- {
- cp_error_at ("looser throw specifier for `%#F'", overrider);
- cp_error_at (" overriding `%#F'", basefn);
- SET_IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider),
- DECL_CONTEXT (overrider));
- }
+ cp_error_at ("looser throw specifier for `%#F'", overrider);
+ cp_error_at (" overriding `%#F'", basefn);
+ DECL_INVALID_OVERRIDER_P (overrider) = 1;
return 0;
}
overridden. */
int
-look_for_overrides (type, fndecl)
- tree type, fndecl;
+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);
FNDECL. */
tree
-look_for_overrides_here (type, fndecl)
- tree type, fndecl;
+look_for_overrides_here (tree type, tree 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))
{
TYPE itself and its bases. */
static int
-look_for_overrides_r (type, fndecl)
- tree type, fndecl;
+look_for_overrides_r (tree type, tree fndecl)
{
tree fn = look_for_overrides_here (type, fndecl);
if (fn)
return look_for_overrides (type, fndecl);
}
-/* A queue function to use with dfs_walk that only walks into
- canonical bases. DATA should be the type of the complete object,
- or a TREE_LIST whose TREE_PURPOSE is the type of the complete
- object. By using this function as a queue function, you will walk
- over exactly those BINFOs that actually exist in the complete
- object, including those for virtual base classes. If you
- SET_BINFO_MARKED for each binfo you process, you are further
- guaranteed that you will walk into each virtual base class exactly
- once. */
-
-tree
-dfs_unmarked_real_bases_queue_p (binfo, data)
- tree binfo;
- void *data;
-{
- if (TREE_VIA_VIRTUAL (binfo))
- {
- tree type = (tree) data;
-
- if (TREE_CODE (type) == TREE_LIST)
- type = TREE_PURPOSE (type);
- binfo = binfo_for_vbase (BINFO_TYPE (binfo), type);
- }
- return unmarkedp (binfo, NULL);
-}
-
-/* Like dfs_unmarked_real_bases_queue_p but walks only into things
- that are marked, rather than unmarked. */
-
-tree
-dfs_marked_real_bases_queue_p (binfo, data)
- tree binfo;
- void *data;
-{
- if (TREE_VIA_VIRTUAL (binfo))
- {
- tree type = (tree) data;
-
- if (TREE_CODE (type) == TREE_LIST)
- type = TREE_PURPOSE (type);
- binfo = binfo_for_vbase (BINFO_TYPE (binfo), type);
- }
- return markedp (binfo, NULL);
-}
-
-/* A queue function that skips all virtual bases (and their
- bases). */
-
-tree
-dfs_skip_vbases (binfo, data)
- tree binfo;
- void *data ATTRIBUTE_UNUSED;
-{
- if (TREE_VIA_VIRTUAL (binfo))
- return NULL_TREE;
-
- return binfo;
-}
-
/* Called via dfs_walk from dfs_get_pure_virtuals. */
static tree
-dfs_get_pure_virtuals (binfo, data)
- tree binfo;
- void *data;
+dfs_get_pure_virtuals (tree binfo, void *data)
{
tree type = (tree) data;
CLASSTYPE_PURE_VIRTUALS (type));
}
- SET_BINFO_MARKED (binfo);
+ BINFO_MARKED (binfo) = 1;
return NULL_TREE;
}
/* Set CLASSTYPE_PURE_VIRTUALS for TYPE. */
void
-get_pure_virtuals (type)
- tree type;
+get_pure_virtuals (tree type)
{
- tree vbases;
+ unsigned ix;
+ tree binfo;
+ VEC (tree) *vbases;
/* Clear the CLASSTYPE_PURE_VIRTUALS list; whatever is already there
is going to be overridden. */
(A primary base is not interesting because the derived class of
which it is a primary base will contain vtable entries for the
pure virtuals in the base class. */
- dfs_walk (TYPE_BINFO (type), dfs_get_pure_virtuals,
- dfs_unmarked_real_bases_queue_p, type);
- dfs_walk (TYPE_BINFO (type), dfs_unmark,
- dfs_marked_real_bases_queue_p, type);
+ dfs_walk (TYPE_BINFO (type), dfs_get_pure_virtuals, unmarkedp, type);
+ dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, type);
/* Put the pure virtuals in dfs order. */
CLASSTYPE_PURE_VIRTUALS (type) = nreverse (CLASSTYPE_PURE_VIRTUALS (type));
- for (vbases = CLASSTYPE_VBASECLASSES (type);
- vbases;
- vbases = TREE_CHAIN (vbases))
+ for (vbases = CLASSTYPE_VBASECLASSES (type), ix = 0;
+ VEC_iterate (tree, vbases, ix, binfo); ix++)
{
tree virtuals;
-
- for (virtuals = BINFO_VIRTUALS (TREE_VALUE (vbases));
- virtuals;
+
+ for (virtuals = BINFO_VIRTUALS (binfo); virtuals;
virtuals = TREE_CHAIN (virtuals))
{
tree base_fndecl = BV_FN (virtuals);
/* DEPTH-FIRST SEARCH ROUTINES. */
tree
-markedp (binfo, data)
- tree binfo;
- void *data ATTRIBUTE_UNUSED;
-{
- return BINFO_MARKED (binfo) ? binfo : NULL_TREE;
-}
-
-tree
-unmarkedp (binfo, data)
- tree binfo;
- void *data ATTRIBUTE_UNUSED;
+markedp (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
{
- return !BINFO_MARKED (binfo) ? binfo : NULL_TREE;
-}
-
-tree
-marked_vtable_pathp (binfo, data)
- tree binfo;
- void *data ATTRIBUTE_UNUSED;
-{
- return BINFO_VTABLE_PATH_MARKED (binfo) ? binfo : NULL_TREE;
+ tree binfo = BINFO_BASE_BINFO (derived, ix);
+
+ return BINFO_MARKED (binfo) ? binfo : NULL_TREE;
}
tree
-unmarked_vtable_pathp (binfo, data)
- tree binfo;
- void *data ATTRIBUTE_UNUSED;
-{
- return !BINFO_VTABLE_PATH_MARKED (binfo) ? binfo : NULL_TREE;
-}
-
-static tree
-marked_pushdecls_p (binfo, data)
- tree binfo;
- void *data ATTRIBUTE_UNUSED;
+unmarkedp (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
{
- return (CLASS_TYPE_P (BINFO_TYPE (binfo))
- && !dependent_base_p (binfo)
- && BINFO_PUSHDECLS_MARKED (binfo)) ? binfo : NULL_TREE;
-}
-
-static tree
-unmarked_pushdecls_p (binfo, data)
- tree binfo;
- void *data ATTRIBUTE_UNUSED;
-{
- return (CLASS_TYPE_P (BINFO_TYPE (binfo))
- && !dependent_base_p (binfo)
- && !BINFO_PUSHDECLS_MARKED (binfo)) ? binfo : NULL_TREE;
+ tree binfo = BINFO_BASE_BINFO (derived, ix);
+
+ return !BINFO_MARKED (binfo) ? binfo : NULL_TREE;
}
/* The worker functions for `dfs_walk'. These do not need to
a predicate function (above). */
tree
-dfs_unmark (binfo, data)
- tree binfo;
- void *data ATTRIBUTE_UNUSED;
-{
- CLEAR_BINFO_MARKED (binfo);
- return NULL_TREE;
-}
-
-/* get virtual base class types.
- This adds type to the vbase_types list in reverse dfs order.
- Ordering is very important, so don't change it. */
-
-static tree
-dfs_get_vbase_types (binfo, data)
- tree binfo;
- void *data;
+dfs_unmark (tree binfo, void *data ATTRIBUTE_UNUSED)
{
- tree type = (tree) data;
-
- if (TREE_VIA_VIRTUAL (binfo))
- CLASSTYPE_VBASECLASSES (type)
- = tree_cons (BINFO_TYPE (binfo),
- binfo,
- CLASSTYPE_VBASECLASSES (type));
- SET_BINFO_MARKED (binfo);
+ BINFO_MARKED (binfo) = 0;
return NULL_TREE;
}
-/* Called via dfs_walk from mark_primary_bases. Builds the
- inheritance graph order list of BINFOs. */
-
-static tree
-dfs_build_inheritance_graph_order (binfo, data)
- tree binfo;
- void *data;
-{
- tree *last_binfo = (tree *) data;
-
- if (*last_binfo)
- TREE_CHAIN (*last_binfo) = binfo;
- *last_binfo = binfo;
- SET_BINFO_MARKED (binfo);
- return NULL_TREE;
-}
-
-/* Set CLASSTYPE_VBASECLASSES for TYPE. */
-
-void
-get_vbase_types (type)
- tree type;
-{
- tree last_binfo;
-
- CLASSTYPE_VBASECLASSES (type) = NULL_TREE;
- dfs_walk (TYPE_BINFO (type), dfs_get_vbase_types, unmarkedp, type);
- /* Rely upon the reverse dfs ordering from dfs_get_vbase_types, and now
- reverse it so that we get normal dfs ordering. */
- CLASSTYPE_VBASECLASSES (type) = nreverse (CLASSTYPE_VBASECLASSES (type));
- dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, 0);
- /* Thread the BINFOs in inheritance-graph order. */
- last_binfo = NULL;
- dfs_walk_real (TYPE_BINFO (type),
- dfs_build_inheritance_graph_order,
- NULL,
- unmarkedp,
- &last_binfo);
- dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, NULL);
-}
-
-/* Called from find_vbase_instance via dfs_walk. */
-
-static tree
-dfs_find_vbase_instance (binfo, data)
- tree binfo;
- void *data;
-{
- tree base = TREE_VALUE ((tree) data);
-
- if (BINFO_PRIMARY_P (binfo)
- && same_type_p (BINFO_TYPE (binfo), base))
- return binfo;
-
- return NULL_TREE;
-}
-
-/* Find the real occurrence of the virtual BASE (a class type) in the
- hierarchy dominated by TYPE. */
-
-tree
-find_vbase_instance (base, type)
- tree base;
- tree type;
-{
- tree instance;
-
- instance = binfo_for_vbase (base, type);
- if (!BINFO_PRIMARY_P (instance))
- return instance;
-
- return dfs_walk (TYPE_BINFO (type),
- dfs_find_vbase_instance,
- NULL,
- build_tree_list (type, base));
-}
-
\f
/* Debug info for C++ classes can get very large; try to avoid
emitting it everywhere.
linker. */
void
-maybe_suppress_debug_info (t)
- tree t;
+maybe_suppress_debug_info (tree t)
{
/* We can't do the usual TYPE_DECL_SUPPRESS_DEBUG thing with DWARF, which
does not support name references between translation units. It supports
information anyway. */
static tree
-dfs_debug_mark (binfo, data)
- tree binfo;
- void *data ATTRIBUTE_UNUSED;
+dfs_debug_mark (tree binfo, void *data ATTRIBUTE_UNUSED)
{
tree t = BINFO_TYPE (binfo);
info for this base class. */
static tree
-dfs_debug_unmarkedp (binfo, data)
- tree binfo;
- void *data ATTRIBUTE_UNUSED;
-{
+dfs_debug_unmarkedp (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
+{
+ tree binfo = BINFO_BASE_BINFO (derived, ix);
+
return (!CLASSTYPE_DEBUG_REQUESTED (BINFO_TYPE (binfo))
? binfo : NULL_TREE);
}
the vtables themselves, were optimized away. */
void
-note_debug_info_needed (type)
- tree type;
+note_debug_info_needed (tree type)
{
if (TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (type)))
{
dfs_walk (TYPE_BINFO (type), dfs_debug_mark, dfs_debug_unmarkedp, 0);
}
\f
-/* Subroutines of push_class_decls (). */
-
-/* Returns 1 iff BINFO is a base we shouldn't really be able to see into,
- because it (or one of the intermediate bases) depends on template parms. */
-
-static int
-dependent_base_p (binfo)
- tree binfo;
-{
- for (; binfo; binfo = BINFO_INHERITANCE_CHAIN (binfo))
- {
- if (currently_open_class (TREE_TYPE (binfo)))
- break;
- if (uses_template_parms (TREE_TYPE (binfo)))
- return 1;
- }
- return 0;
-}
-
-static void
-setup_class_bindings (name, type_binding_p)
- 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=*/1);
- 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=*/0);
-
- 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);
- 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 (binfo, data)
- 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. */
- SET_BINFO_PUSHDECLS_MARKED (binfo);
-
- return NULL_TREE;
-}
-
-/* Push class-level declarations for any names appearing in BINFO that
- are not TYPE_DECLS. */
-
-static tree
-dfs_push_decls (binfo, data)
- tree binfo;
- void *data;
-{
- tree type;
- tree method_vec;
- int dep_base_p;
-
- type = BINFO_TYPE (binfo);
- dep_base_p = (processing_template_decl && type != current_class_type
- && dependent_base_p (binfo));
- if (!dep_base_p)
- {
- 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);
- }
- }
-
- CLEAR_BINFO_PUSHDECLS_MARKED (binfo);
-
- 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 (type)
- 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 (binfo, data)
- tree binfo;
- void *data ATTRIBUTE_UNUSED;
-{
- tree type = TREE_TYPE (binfo);
- tree fields;
-
- for (fields = TYPE_FIELDS (type); 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 (type)
- tree type;
-{
- dfs_walk (TYPE_BINFO (type), dfs_unuse_fields, unmarkedp, 0);
-}
-
-void
-pop_class_decls ()
-{
- /* 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 ()
+print_search_statistics (void)
{
#ifdef GATHER_STATISTICS
fprintf (stderr, "%d fields searched in %d[%d] calls to lookup_field[_1]\n",
}
void
-init_search_processing ()
-{
- gcc_obstack_init (&search_obstack);
-}
-
-void
-reinit_search_statistics ()
+reinit_search_statistics (void)
{
#ifdef GATHER_STATISTICS
n_fields_searched = 0;
}
static tree
-add_conversions (binfo, data)
- tree binfo;
- void *data;
+add_conversions (tree binfo, void *data)
{
- int i;
- tree method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo));
+ size_t i;
+ VEC(tree) *method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo));
tree *conversions = (tree *) data;
+ tree tmp;
/* Some builtin types have no method vector, not even an empty one. */
if (!method_vec)
return NULL_TREE;
- for (i = 2; i < TREE_VEC_LENGTH (method_vec); ++i)
+ for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ VEC_iterate (tree, method_vec, i, tmp);
+ ++i)
{
- tree tmp = TREE_VEC_ELT (method_vec, i);
tree name;
- if (!tmp || ! DECL_CONV_FN_P (OVL_CURRENT (tmp)))
+ if (!DECL_CONV_FN_P (OVL_CURRENT (tmp)))
break;
name = DECL_NAME (OVL_CURRENT (tmp));
/* Make sure we don't already have this conversion. */
if (! IDENTIFIER_MARKED (name))
{
- *conversions = tree_cons (binfo, tmp, *conversions);
- IDENTIFIER_MARKED (name) = 1;
+ tree t;
+
+ /* 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))
+ {
+ 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;
+ }
+ if (!t)
+ {
+ *conversions = tree_cons (binfo, tmp, *conversions);
+ IDENTIFIER_MARKED (name) = 1;
+ }
}
}
return NULL_TREE;
from which the conversion functions in this node were selected. */
tree
-lookup_conversions (type)
- tree type;
+lookup_conversions (tree type)
{
tree t;
tree conversions = NULL_TREE;
- if (COMPLETE_TYPE_P (type))
+ complete_type (type);
+ if (TYPE_BINFO (type))
bfs_walk (TYPE_BINFO (type), add_conversions, 0, &conversions);
for (t = conversions; t; t = TREE_CHAIN (t))
at offset 0 in COMPARE_TYPE, and set found_overlap if so. */
static tree
-dfs_check_overlap (empty_binfo, data)
- tree empty_binfo;
- void *data;
+dfs_check_overlap (tree empty_binfo, void *data)
{
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;
}
/* Trivial function to stop base traversal when we find something. */
static tree
-dfs_no_overlap_yet (binfo, data)
- tree binfo;
- void *data;
+dfs_no_overlap_yet (tree derived, int ix, void *data)
{
+ tree binfo = BINFO_BASE_BINFO (derived, ix);
struct overlap_info *oi = (struct overlap_info *) data;
+
return !oi->found_overlap ? binfo : NULL_TREE;
}
offset 0 in NEXT_TYPE. Used in laying out empty base class subobjects. */
int
-types_overlap_p (empty_type, next_type)
- tree empty_type, next_type;
+types_overlap_p (tree empty_type, tree next_type)
{
struct overlap_info oi;
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 (var)
- 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. */
tree
-binfo_from_vbase (binfo)
- tree binfo;
+binfo_from_vbase (tree binfo)
{
for (; binfo; binfo = BINFO_INHERITANCE_CHAIN (binfo))
{
- if (TREE_VIA_VIRTUAL (binfo))
+ if (BINFO_VIRTUAL_P (binfo))
return binfo;
}
return NULL_TREE;
via virtual. */
tree
-binfo_via_virtual (binfo, limit)
- tree binfo;
- tree limit;
+binfo_via_virtual (tree binfo, tree limit)
{
for (; binfo && (!limit || !same_type_p (BINFO_TYPE (binfo), limit));
binfo = BINFO_INHERITANCE_CHAIN (binfo))
{
- if (TREE_VIA_VIRTUAL (binfo))
+ if (BINFO_VIRTUAL_P (binfo))
return binfo;
}
return NULL_TREE;
}
-/* Returns the BINFO (if any) for the virtual baseclass T of the class
- C from the CLASSTYPE_VBASECLASSES list. */
+/* BINFO is a base binfo in the complete type BINFO_TYPE (HERE).
+ Find the equivalent binfo within whatever graph HERE is located.
+ This is the inverse of original_binfo. */
tree
-binfo_for_vbase (basetype, classtype)
- tree basetype;
- tree classtype;
+copied_binfo (tree binfo, tree here)
{
+ tree result = NULL_TREE;
+
+ if (BINFO_VIRTUAL_P (binfo))
+ {
+ tree t;
+
+ for (t = here; BINFO_INHERITANCE_CHAIN (t);
+ t = BINFO_INHERITANCE_CHAIN (t))
+ continue;
+
+ result = binfo_for_vbase (BINFO_TYPE (binfo), BINFO_TYPE (t));
+ }
+ else if (BINFO_INHERITANCE_CHAIN (binfo))
+ {
+ tree cbinfo;
+ tree base_binfo;
+ int ix;
+
+ 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
+ {
+ my_friendly_assert (BINFO_TYPE (here) == BINFO_TYPE (binfo), 20030202);
+ result = here;
+ }
+
+ my_friendly_assert (result, 20030202);
+ return result;
+}
+
+tree
+binfo_for_vbase (tree base, tree t)
+{
+ unsigned ix;
tree binfo;
+ VEC (tree) *vbases;
+
+ for (vbases = CLASSTYPE_VBASECLASSES (t), ix = 0;
+ VEC_iterate (tree, vbases, ix, binfo); ix++)
+ if (BINFO_TYPE (binfo) == base)
+ return binfo;
+ return NULL;
+}
+
+/* BINFO is some base binfo of HERE, within some other
+ hierarchy. Return the equivalent binfo, but in the hierarchy
+ dominated by HERE. This is the inverse of copied_binfo. If BINFO
+ is not a base binfo of HERE, returns NULL_TREE. */
- binfo = purpose_member (basetype, CLASSTYPE_VBASECLASSES (classtype));
- return binfo ? TREE_VALUE (binfo) : NULL_TREE;
+tree
+original_binfo (tree binfo, tree here)
+{
+ tree result = NULL;
+
+ if (BINFO_TYPE (binfo) == BINFO_TYPE (here))
+ result = here;
+ else if (BINFO_VIRTUAL_P (binfo))
+ result = (CLASSTYPE_VBASECLASSES (BINFO_TYPE (here))
+ ? binfo_for_vbase (BINFO_TYPE (binfo), BINFO_TYPE (here))
+ : NULL_TREE);
+ else if (BINFO_INHERITANCE_CHAIN (binfo))
+ {
+ tree base_binfos;
+
+ base_binfos = original_binfo (BINFO_INHERITANCE_CHAIN (binfo), here);
+ if (base_binfos)
+ {
+ int ix;
+ tree base_binfo;
+
+ for (ix = 0; (base_binfo = BINFO_BASE_BINFO (base_binfos, ix)); ix++)
+ if (BINFO_TYPE (base_binfo) == BINFO_TYPE (binfo))
+ {
+ result = base_binfo;
+ break;
+ }
+ }
+ }
+
+ return result;
}
+