/* 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, 2004, 2005, 2007, 2008, 2009, 2010, 2011
- Free Software Foundation, Inc.
+ Copyright (C) 1987-2013 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
#include "cp-tree.h"
#include "intl.h"
#include "flags.h"
-#include "output.h"
#include "toplev.h"
#include "target.h"
\f
/* Variables for gathering statistics. */
-#ifdef GATHER_STATISTICS
static int n_fields_searched;
static int n_calls_lookup_field, n_calls_lookup_field_1;
static int n_calls_lookup_fnfields, n_calls_lookup_fnfields_1;
static int n_calls_get_base_type;
static int n_outer_fields_searched;
static int n_contexts_saved;
-#endif /* GATHER_STATISTICS */
\f
/* Data for lookup_base and its workers. */
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
- returned. If the ba_quiet bit is set, then no error is issued and
- NULL_TREE is returned. */
+ If the base is inaccessible, or ambiguous, then error_mark_node is
+ returned. If the tf_error bit of COMPLAIN is not set, no error
+ is issued. */
tree
-lookup_base (tree t, tree base, base_access access, base_kind *kind_ptr)
+lookup_base (tree t, tree base, base_access access,
+ base_kind *kind_ptr, tsubst_flags_t complain)
{
tree binfo;
tree t_binfo;
base_kind bk;
+ /* "Nothing" is definitely not derived from Base. */
+ if (t == NULL_TREE)
+ {
+ if (kind_ptr)
+ *kind_ptr = bk_not_base;
+ return NULL_TREE;
+ }
+
if (t == error_mark_node || base == error_mark_node)
{
if (kind_ptr)
break;
case bk_ambig:
- if (!(access & ba_quiet))
- {
- error ("%qT is an ambiguous base of %qT", base, t);
- binfo = error_mark_node;
- }
+ if (complain & tf_error)
+ error ("%qT is an ambiguous base of %qT", base, t);
+ binfo = error_mark_node;
break;
default:
&& COMPLETE_TYPE_P (base)
&& !accessible_base_p (t, base, !(access & ba_ignore_scope)))
{
- if (!(access & ba_quiet))
- {
- error ("%qT is an inaccessible base of %qT", base, t);
- binfo = error_mark_node;
- }
- else
- binfo = NULL_TREE;
+ if (complain & tf_error)
+ error ("%qT is an inaccessible base of %qT", base, t);
+ binfo = error_mark_node;
bk = bk_inaccessible;
}
break;
{
tree field;
+ gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
+
if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
|| TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (type) == TYPENAME_TYPE)
{
i = (lo + hi) / 2;
-#ifdef GATHER_STATISTICS
- n_fields_searched++;
-#endif /* GATHER_STATISTICS */
+ if (GATHER_STATISTICS)
+ n_fields_searched++;
if (DECL_NAME (fields[i]) > name)
hi = i;
field = TYPE_FIELDS (type);
-#ifdef GATHER_STATISTICS
- n_calls_lookup_field_1++;
-#endif /* GATHER_STATISTICS */
+ if (GATHER_STATISTICS)
+ n_calls_lookup_field_1++;
+
for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
{
tree decl = field;
-#ifdef GATHER_STATISTICS
- n_fields_searched++;
-#endif /* GATHER_STATISTICS */
+ if (GATHER_STATISTICS)
+ n_fields_searched++;
+
gcc_assert (DECL_P (field));
if (DECL_NAME (field) == NULL_TREE
&& ANON_AGGR_TYPE_P (TREE_TYPE (field)))
declared. */
tree context = DECL_CONTEXT (decl);
- while (context && TYPE_P (context) && ANON_AGGR_TYPE_P (context))
+ while (context && TYPE_P (context)
+ && (ANON_AGGR_TYPE_P (context) || UNSCOPED_ENUM_P (context)))
context = TYPE_CONTEXT (context);
if (!context)
context = global_namespace;
else
{
/* First, check for an access-declaration that gives us more
- access to the DECL. The CONST_DECL for an enumeration
- constant will not have DECL_LANG_SPECIFIC, and thus no
- DECL_ACCESS. */
+ access to the DECL. */
if (DECL_LANG_SPECIFIC (decl) && !DECL_DISCRIMINATOR_P (decl))
{
tree decl_access = purpose_member (type, DECL_ACCESS (decl));
{
int i;
tree base_binfo;
- VEC(tree,gc) *accesses;
+ vec<tree, va_gc> *accesses;
/* Otherwise, scan our baseclasses, and pick the most favorable
access. */
accesses = BINFO_BASE_ACCESSES (binfo);
for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
{
- tree base_access = VEC_index (tree, accesses, i);
+ tree base_access = (*accesses)[i];
access_kind base_access_now = BINFO_ACCESS (base_binfo);
if (base_access_now == ak_none || base_access_now == ak_private)
/* Called via dfs_walk_once_accessible from accessible_p */
static tree
-dfs_accessible_post (tree binfo, void *data ATTRIBUTE_UNUSED)
+dfs_accessible_post (tree binfo, void * /*data*/)
{
if (BINFO_ACCESS (binfo) != ak_none)
{
return NULL_TREE;
}
+/* Like accessible_p below, but within a template returns true iff DECL is
+ accessible in TYPE to all possible instantiations of the template. */
+
+int
+accessible_in_template_p (tree type, tree decl)
+{
+ int save_ptd = processing_template_decl;
+ processing_template_decl = 0;
+ int val = accessible_p (type, decl, false);
+ processing_template_decl = save_ptd;
+ return val;
+}
+
/* DECL is a declaration from a base class of TYPE, which was the
class used to name DECL. Return nonzero if, in the current
context, DECL is accessible. If TYPE is actually a BINFO node,
if (!basetype_path)
return NULL_TREE;
-#ifdef GATHER_STATISTICS
- n_calls_lookup_field++;
-#endif /* GATHER_STATISTICS */
+ if (GATHER_STATISTICS)
+ n_calls_lookup_field++;
memset (&lfi, 0, sizeof (lfi));
lfi.type = type;
only the first call to "f" is valid. However, if the function is
static, we can check. */
if (rval && protect
- && !really_overloaded_fn (rval)
- && !(TREE_CODE (rval) == FUNCTION_DECL
- && DECL_NONSTATIC_MEMBER_FUNCTION_P (rval)))
- perform_or_defer_access_check (basetype_path, rval, rval);
+ && !really_overloaded_fn (rval))
+ {
+ tree decl = is_overloaded_fn (rval) ? get_first_fn (rval) : rval;
+ if (!DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
+ && !perform_or_defer_access_check (basetype_path, decl, decl,
+ complain))
+ rval = error_mark_node;
+ }
if (errstr && protect)
{
{
int i;
tree fn;
- VEC(tree,gc) *methods = CLASSTYPE_METHOD_VEC (class_type);
+ vec<tree, va_gc> *methods = CLASSTYPE_METHOD_VEC (class_type);
for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
- VEC_iterate (tree, methods, i, fn); ++i)
+ vec_safe_iterate (methods, i, &fn); ++i)
{
/* All the conversion operators come near the beginning of
the class. Therefore, if FN is not a conversion
static int
lookup_fnfields_idx_nolazy (tree type, tree name)
{
- VEC(tree,gc) *method_vec;
+ vec<tree, va_gc> *method_vec;
tree fn;
tree tmp;
size_t i;
if (!method_vec)
return -1;
-#ifdef GATHER_STATISTICS
- n_calls_lookup_fnfields_1++;
-#endif /* GATHER_STATISTICS */
+ if (GATHER_STATISTICS)
+ n_calls_lookup_fnfields_1++;
/* Constructors are first... */
if (name == ctor_identifier)
/* Skip the conversion operators. */
for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
- VEC_iterate (tree, method_vec, i, fn);
+ vec_safe_iterate (method_vec, i, &fn);
++i)
if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
break;
int hi;
lo = i;
- hi = VEC_length (tree, method_vec);
+ hi = method_vec->length ();
while (lo < hi)
{
i = (lo + hi) / 2;
-#ifdef GATHER_STATISTICS
- n_outer_fields_searched++;
-#endif /* GATHER_STATISTICS */
+ if (GATHER_STATISTICS)
+ n_outer_fields_searched++;
- tmp = VEC_index (tree, method_vec, i);
+ tmp = (*method_vec)[i];
tmp = DECL_NAME (OVL_CURRENT (tmp));
if (tmp > name)
hi = i;
}
}
else
- for (; VEC_iterate (tree, method_vec, i, fn); ++i)
+ for (; vec_safe_iterate (method_vec, i, &fn); ++i)
{
-#ifdef GATHER_STATISTICS
- n_outer_fields_searched++;
-#endif /* GATHER_STATISTICS */
+ if (GATHER_STATISTICS)
+ n_outer_fields_searched++;
if (DECL_NAME (OVL_CURRENT (fn)) == name)
return i;
}
int ix = lookup_fnfields_1 (complete_type (type), name);
if (ix < 0)
return NULL_TREE;
- return VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix);
+ return (*CLASSTYPE_METHOD_VEC (type))[ix];
}
/* As above, but avoid lazily declaring functions. */
int ix = lookup_fnfields_idx_nolazy (complete_type (type), name);
if (ix < 0)
return NULL_TREE;
- return VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix);
+ return (*CLASSTYPE_METHOD_VEC (type))[ix];
}
/* Like lookup_fnfields_1, except that the name is extracted from
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_unique | ba_quiet, NULL);
- if (base)
+ ba_unique, NULL, tf_none);
+ if (base && base != error_mark_node)
{
BASELINK_ACCESS_BINFO (decl) = base;
BASELINK_BINFO (decl)
= lookup_base (base, BINFO_TYPE (BASELINK_BINFO (decl)),
- ba_unique | ba_quiet,
- NULL);
+ ba_unique, NULL, tf_none);
}
}
/* We are at the top of the hierarchy, and can use the
CLASSTYPE_VBASECLASSES list for unmarking the virtual
bases. */
- VEC(tree,gc) *vbases;
+ vec<tree, va_gc> *vbases;
unsigned ix;
tree base_binfo;
for (vbases = CLASSTYPE_VBASECLASSES (BINFO_TYPE (binfo)), ix = 0;
- VEC_iterate (tree, vbases, ix, base_binfo); ix++)
+ vec_safe_iterate (vbases, ix, &base_binfo); ix++)
BINFO_MARKED (base_binfo) = 0;
}
else
/* We are at the top of the hierarchy, and can use the
CLASSTYPE_VBASECLASSES list for unmarking the virtual
bases. */
- VEC(tree,gc) *vbases;
+ vec<tree, va_gc> *vbases;
unsigned ix;
tree base_binfo;
for (vbases = CLASSTYPE_VBASECLASSES (BINFO_TYPE (binfo)), ix = 0;
- VEC_iterate (tree, vbases, ix, base_binfo); ix++)
+ vec_safe_iterate (vbases, ix, &base_binfo); ix++)
BINFO_MARKED (base_binfo) = 0;
}
else
/* Strictly speaking, the standard requires the return type to be
complete even if it only differs in cv-quals, but that seems
like a bug in the wording. */
- if (!same_type_ignoring_top_level_qualifiers_p (base_return, over_return))
+ if (!same_type_ignoring_top_level_qualifiers_p (base_return,
+ over_return))
{
tree binfo = lookup_base (over_return, base_return,
- ba_check | ba_quiet, NULL);
+ ba_check, NULL, tf_none);
- if (!binfo)
+ if (!binfo || binfo == error_mark_node)
fail = 1;
}
}
else if (!pedantic
- && can_convert (TREE_TYPE (base_type), TREE_TYPE (over_type)))
+ && can_convert (TREE_TYPE (base_type), TREE_TYPE (over_type),
+ tf_warning_or_error))
/* GNU extension, allow trivial pointer conversions such as
converting to void *, or qualification conversion. */
{
ix = lookup_fnfields_1 (type, DECL_NAME (fndecl));
if (ix >= 0)
{
- tree fns = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix);
+ tree fns = (*CLASSTYPE_METHOD_VEC (type))[ix];
for (; fns; fns = OVL_NEXT (fns))
{
virtuals;
virtuals = TREE_CHAIN (virtuals))
if (DECL_PURE_VIRTUAL_P (BV_FN (virtuals)))
- VEC_safe_push (tree, gc, CLASSTYPE_PURE_VIRTUALS (type),
- BV_FN (virtuals));
+ vec_safe_push (CLASSTYPE_PURE_VIRTUALS (type), BV_FN (virtuals));
}
return NULL_TREE;
information anyway. */
static tree
-dfs_debug_mark (tree binfo, void *data ATTRIBUTE_UNUSED)
+dfs_debug_mark (tree binfo, void * /*data*/)
{
tree t = BINFO_TYPE (binfo);
void
print_search_statistics (void)
{
-#ifdef GATHER_STATISTICS
+ if (! GATHER_STATISTICS)
+ {
+ fprintf (stderr, "no search statistics\n");
+ return;
+ }
+
fprintf (stderr, "%d fields searched in %d[%d] calls to lookup_field[_1]\n",
n_fields_searched, n_calls_lookup_field, n_calls_lookup_field_1);
fprintf (stderr, "%d fnfields searched in %d calls to lookup_fnfields\n",
n_outer_fields_searched, n_calls_lookup_fnfields);
fprintf (stderr, "%d calls to get_base_type\n", n_calls_get_base_type);
-#else /* GATHER_STATISTICS */
- fprintf (stderr, "no search statistics\n");
-#endif /* GATHER_STATISTICS */
}
void
reinit_search_statistics (void)
{
-#ifdef GATHER_STATISTICS
n_fields_searched = 0;
n_calls_lookup_field = 0, n_calls_lookup_field_1 = 0;
n_calls_lookup_fnfields = 0, n_calls_lookup_fnfields_1 = 0;
n_calls_get_base_type = 0;
n_outer_fields_searched = 0;
n_contexts_saved = 0;
-#endif /* GATHER_STATISTICS */
}
/* Helper for lookup_conversions_r. TO_TYPE is the type converted to
tree child_tpl_convs = NULL_TREE;
unsigned i;
tree base_binfo;
- VEC(tree,gc) *method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo));
+ vec<tree, va_gc> *method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo));
tree conv;
/* If we have no conversion operators, then don't look. */
/* First, locate the unhidden ones at this level. */
for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
- VEC_iterate (tree, method_vec, i, conv);
+ vec_safe_iterate (method_vec, i, &conv);
++i)
{
tree cur = OVL_CURRENT (conv);
if (!IDENTIFIER_MARKED (name))
{
tree type = DECL_CONV_FN_TYPE (cur);
+ if (type_uses_auto (type))
+ {
+ mark_used (cur);
+ type = DECL_CONV_FN_TYPE (cur);
+ }
if (check_hidden_convs (binfo, virtual_depth, virtualness,
type, parent_convs, other_convs))
{
unsigned ix;
tree binfo;
- VEC(tree,gc) *vbases;
+ vec<tree, va_gc> *vbases;
for (vbases = CLASSTYPE_VBASECLASSES (t), ix = 0;
- VEC_iterate (tree, vbases, ix, binfo); ix++)
+ vec_safe_iterate (vbases, ix, &binfo); ix++)
if (SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), base))
return binfo;
return NULL;