/* 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, 2003 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.
static struct search_level *
pop_search_level (struct stack_level *obstack)
{
- register struct search_level *stack = pop_stack_level (obstack);
+ struct search_level *stack = pop_stack_level (obstack);
return stack;
}
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;
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. If KIND_PTR is
non-NULL, fill with information about what kind of base we
break;
default:
- if (access != ba_ignore
+ 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))
+ && COMPLETE_TYPE_P (base)
+ && !accessible_base_p (t, 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. */
- /* Rather than inventing a public member, we use the implicit
- public typedef created in the scope of every class. */
- decl = TYPE_FIELDS (base);
- while (TREE_CODE (decl) != TYPE_DECL
- || !DECL_ARTIFICIAL (decl)
- || DECL_NAME (decl) != constructor_name (base))
- decl = TREE_CHAIN (decl);
- while (ANON_AGGR_TYPE_P (t))
- t = TYPE_CONTEXT (t);
- if (!accessible_p (t, decl))
+ if (!(access & ba_quiet))
{
- 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;
+ error ("`%T' is an inaccessible base of `%T'", base, t);
+ binfo = error_mark_node;
}
+ else
+ binfo = NULL_TREE;
+ bk = bk_inaccessible;
}
break;
}
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)
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
}
/* 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_PUBLIC (NODE) << 1) | TREE_PRIVATE (NODE)))
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;
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 (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
return binfo;
}
-/* Called from dfs_accessible_p via dfs_walk. */
+/* Called from accessible_p via dfs_walk. */
static tree
-dfs_accessible_p (tree binfo, void *data)
+dfs_accessible_p (tree binfo, void *data ATTRIBUTE_UNUSED)
{
- int protected_ok = data != 0;
access_kind access;
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;
{
tree binfo;
tree t;
+ tree scope;
+ access_kind access;
/* Nonzero if it's OK to access DECL if it has protected
accessibility in TYPE. */
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, 0, 0);
-
- return t != NULL_TREE;
+ access = access_in_type (type, decl);
+ if (access == ak_public
+ || (access == ak_protected && protected_ok))
+ return 1;
+ else
+ {
+ /* 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;
+ }
}
struct lookup_field_info {
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))
{
/* 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);
+ 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;
}
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);
}
}
tree type = TREE_TYPE (binfo);
tree fields;
- for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (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;
}
void
-pop_class_decls ()
+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. */
}
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 ()
+init_search_processing (void)
{
gcc_obstack_init (&search_obstack);
}
void
-reinit_search_statistics ()
+reinit_search_statistics (void)
{
#ifdef GATHER_STATISTICS
n_fields_searched = 0;
/* 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;