+2004-10-15 Nathan Sidwell <nathan@codesourcery.com>
+
+ * cp-tree.h (UNIQUELY_DERIVED_FROM_P): Adjust lookup_base call.
+ (ACCESSIBLY_UNIQUELY_DERIVED_P): Remove.
+ (PUBLICLY_UNIQUELY_DERIVED_P): Adjust lookup_base call.
+ (enum base_access): Reorganize.
+ (accessible_base_p, accessible_p): Add consider_local_p parameter.
+ * call.c (standard_conversion): Update comment about
+ DERIVED_FROM_P.
+ (enforce_access): Adjust accessible_p call.
+ (build_over_call): Adjust accessible_base_p call.
+ * class.c (convert_to_base): Adjust lookup_base call.
+ (build_vtbl_ref_1): Likewise.
+ (warn_about_ambiguous_bases): Likewise. Add early exit.
+ * cvt.c (convert_to_pointer_force) Adjust lookup_base call.
+ * search.c (accessible_base_p): Add consider_local_p parameter.
+ (lookup_base): Pass consider_local_p to accessible_base_p call.
+ (friend_accessible_p): Check whether scope is a class member.
+ Remove unnecessary class template check.
+ (accessible_p): Add consider_local_p parameter. Use it.
+ (adjust_result_of_qualified_name_lookup): Adjust lookup_base call.
+ * tree.c (maybe_dummy_object): Likewise.
+ * typeck.c (comp_except_type): Use PUBLICLY_UNIQUELY_DERIVED_P.
+ (build_class_member_access_expr): Adjust lookup_base call.
+ * typeck2.c (binfo_or_else): Likewise.
+ * rtti.c (build_dynamic_cast_1): Access can consider friendship
+ and current scope.
+
2004-10-17 Giovanni Bajo <giovannibajo@gcc.gnu.org>
PR c++/17743
_class.derived_) of D. If B is an inaccessible
(clause _class.access_) or ambiguous
(_class.member.lookup_) base class of D, a program
- that necessitates this conversion is ill-formed. */
- /* Therefore, we use DERIVED_FROM_P, and not
- ACCESSIBLY_UNIQUELY_DERIVED_FROM_P, in this test. */
+ that necessitates this conversion is ill-formed.
+ Therefore, we use DERIVED_FROM_P, and do not check
+ access or uniqueness. */
&& DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from)))
{
from =
{
gcc_assert (TREE_CODE (basetype_path) == TREE_BINFO);
- if (!accessible_p (basetype_path, decl))
+ if (!accessible_p (basetype_path, decl, true))
{
if (TREE_PRIVATE (decl))
cp_error_at ("%q+#D is private", decl);
1);
/* Check that the base class is accessible. */
if (!accessible_base_p (TREE_TYPE (argtype),
- BINFO_TYPE (cand->conversion_path)))
+ BINFO_TYPE (cand->conversion_path), true))
error ("%qT is not an accessible base of %qT",
BINFO_TYPE (cand->conversion_path),
TREE_TYPE (argtype));
will be to the derived class, not the base declaring fn. We
must convert from derived to base. */
base_binfo = lookup_base (TREE_TYPE (TREE_TYPE (converted_arg)),
- TREE_TYPE (parmtype), ba_ignore, NULL);
+ TREE_TYPE (parmtype), ba_unique, NULL);
converted_arg = build_base_path (PLUS_EXPR, converted_arg,
base_binfo, 1);
tree binfo;
binfo = lookup_base (TREE_TYPE (object), type,
- check_access ? ba_check : ba_ignore,
+ check_access ? ba_check : ba_unique,
NULL);
if (!binfo || binfo == error_mark_node)
return error_mark_node;
if (fixed_type && !cdtorp)
{
tree binfo = lookup_base (fixed_type, basetype,
- ba_ignore|ba_quiet, NULL);
+ ba_unique | ba_quiet, NULL);
if (binfo)
vtbl = unshare_expr (BINFO_VTABLE (binfo));
}
tree binfo;
tree base_binfo;
+ /* If there are no repeated bases, nothing can be ambiguous. */
+ if (!CLASSTYPE_REPEATED_BASE_P (t))
+ return;
+
/* Check direct bases. */
for (binfo = TYPE_BINFO (t), i = 0;
BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
{
basetype = BINFO_TYPE (base_binfo);
- if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
+ if (!lookup_base (t, basetype, ba_unique | ba_quiet, NULL))
warning ("direct base %qT inaccessible in %qT due to ambiguity",
basetype, t);
}
{
basetype = BINFO_TYPE (binfo);
- if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
+ if (!lookup_base (t, basetype, ba_unique | ba_quiet, NULL))
warning ("virtual base %qT inaccessible in %qT due to ambiguity",
basetype, t);
}
/* Nonzero iff TYPE is uniquely derived from PARENT. Ignores
accessibility. */
#define UNIQUELY_DERIVED_FROM_P(PARENT, TYPE) \
- (lookup_base ((TYPE), (PARENT), ba_ignore | ba_quiet, NULL) != NULL_TREE)
-/* Nonzero iff TYPE is accessible in the current scope and uniquely
- derived from PARENT. */
-#define ACCESSIBLY_UNIQUELY_DERIVED_P(PARENT, TYPE) \
- (lookup_base ((TYPE), (PARENT), ba_check | ba_quiet, NULL) != NULL_TREE)
+ (lookup_base ((TYPE), (PARENT), ba_unique | ba_quiet, NULL) != NULL_TREE)
/* Nonzero iff TYPE is publicly & uniquely derived from PARENT. */
#define PUBLICLY_UNIQUELY_DERIVED_P(PARENT, TYPE) \
- (lookup_base ((TYPE), (PARENT), ba_not_special | ba_quiet, NULL) \
- != NULL_TREE)
+ (lookup_base ((TYPE), (PARENT), ba_ignore_scope | ba_check | ba_quiet, \
+ NULL) != NULL_TREE)
/* Gives the visibility specification for a class type. */
#define CLASSTYPE_VISIBILITY(TYPE) \
/* The kind of checking we can do looking in a class hierarchy. */
typedef enum base_access {
- ba_any = 0, /* Do not check access, allow an ambiguous base,
+ ba_any = 0, /* Do not check access, allow an ambiguous base,
prefer a non-virtual base */
- ba_ignore = 1, /* Do not check access */
- ba_check = 2, /* Check access */
- ba_not_special = 3, /* Do not consider special privilege
- current_class_type might give. */
- ba_quiet = 4 /* Do not issue error messages (bit mask). */
+ ba_unique = 1 << 0, /* Must be a unique base. */
+ ba_check_bit = 1 << 1, /* Check access. */
+ ba_check = ba_unique | ba_check_bit,
+ ba_ignore_scope = 1 << 2, /* Ignore access allowed by local scope. */
+ ba_quiet = 1 << 3 /* Do not issue error messages. */
} base_access;
/* The various kinds of access check during parsing. */
extern bool emit_tinfo_decl (tree);
/* in search.c */
-extern bool accessible_base_p (tree, tree);
+extern bool accessible_base_p (tree, tree, bool);
extern tree lookup_base (tree, tree, base_access, base_kind *);
extern tree dcast_base_hint (tree, tree);
-extern int accessible_p (tree, tree);
+extern int accessible_p (tree, tree, bool);
extern tree lookup_field_1 (tree, tree, bool);
extern tree lookup_field (tree, tree, int, bool);
extern int lookup_fnfields_1 (tree, tree);
tree binfo;
binfo = lookup_base (TREE_TYPE (intype), TREE_TYPE (type),
- ba_ignore, NULL);
+ ba_unique, NULL);
if (!binfo)
{
binfo = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
- ba_ignore, NULL);
+ ba_unique, NULL);
code = MINUS_EXPR;
}
if (binfo == error_mark_node)
tree binfo;
binfo = lookup_base (TREE_TYPE (exprtype), TREE_TYPE (type),
- ba_not_special, NULL);
+ ba_check, NULL);
if (binfo)
{
}
/* Returns true if type BASE is accessible in T. (BASE is known to be
- a (possibly non-proper) base class of T.) */
+ a (possibly non-proper) base class of T.) If CONSIDER_LOCAL_P is
+ true, consider any special access of the current scope, or access
+ bestowed by friendship. */
bool
-accessible_base_p (tree t, tree base)
+accessible_base_p (tree t, tree base, bool consider_local_p)
{
tree decl;
decl = TREE_CHAIN (decl);
while (ANON_AGGR_TYPE_P (t))
t = TYPE_CONTEXT (t);
- return accessible_p (t, decl);
+ return accessible_p (t, decl, consider_local_p);
}
/* Lookup BASE in the hierarchy dominated by T. Do access checking as
break;
default:
- if ((access & ~ba_quiet) != ba_ignore
+ if ((access & ba_check_bit)
/* 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 implicit typedef to use in the code that
follows, so we skip the check. */
&& COMPLETE_TYPE_P (base)
- && !accessible_base_p (t, base))
+ && !accessible_base_p (t, base, !(access & ba_ignore_scope)))
{
if (!(access & ba_quiet))
{
{
/* Perhaps this SCOPE is a member of a class which is a
friend. */
- if (DECL_CLASS_SCOPE_P (decl)
+ if (DECL_CLASS_SCOPE_P (scope)
&& friend_accessible_p (DECL_CONTEXT (scope), decl, binfo))
return 1;
return ret;
}
}
- else if (CLASSTYPE_TEMPLATE_INFO (scope))
- {
- int ret;
- /* Increment processing_template_decl to make sure that
- dependent_type_p works correctly. */
- ++processing_template_decl;
- ret = friend_accessible_p (CLASSTYPE_TI_TEMPLATE (scope), decl, binfo);
- --processing_template_decl;
- return ret;
- }
return 0;
}
class used to name DECL. Return nonzero if, in the current
context, DECL is accessible. If TYPE is actually a BINFO node,
then we can tell in what context the access is occurring by looking
- at the most derived class along the path indicated by BINFO. */
+ at the most derived class along the path indicated by BINFO. If
+ CONSIDER_LOCAL is true, do consider special access the current
+ scope or friendship thereof we might have. */
int
-accessible_p (tree type, tree decl)
+accessible_p (tree type, tree decl, bool consider_local_p)
{
tree binfo;
- tree t;
tree scope;
access_kind access;
We walk the base class hierarchy, checking these conditions. */
- /* Figure out where the reference is occurring. Check to see if
- DECL is private or protected in this scope, since that will
- determine whether protected access is allowed. */
- if (current_class_type)
- protected_ok = protected_accessible_p (decl, current_class_type, binfo);
+ if (consider_local_p)
+ {
+ /* Figure out where the reference is occurring. Check to see if
+ DECL is private or protected in this scope, since that will
+ determine whether protected access is allowed. */
+ if (current_class_type)
+ protected_ok = protected_accessible_p (decl,
+ current_class_type, binfo);
- /* Now, loop through the classes of which we are a friend. */
- if (!protected_ok)
- protected_ok = friend_accessible_p (scope, decl, binfo);
+ /* Now, loop through the classes of which we are a friend. */
+ if (!protected_ok)
+ 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. */
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_once_accessible (binfo, /*friends=*/true,
- NULL, dfs_accessible_post, NULL);
-
- return t != NULL_TREE;
- }
+
+ if (!consider_local_p)
+ return 0;
+
+ /* Walk the hierarchy again, looking for a base class that allows
+ access. */
+ return dfs_walk_once_accessible (binfo, /*friends=*/true,
+ NULL, dfs_accessible_post, NULL)
+ != NULL_TREE;
}
struct lookup_field_info {
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);
+ ba_unique | ba_quiet, NULL);
if (base)
{
BASELINK_ACCESS_BINFO (decl) = base;
BASELINK_BINFO (decl)
= lookup_base (base, BINFO_TYPE (BASELINK_BINFO (decl)),
- ba_ignore | ba_quiet,
+ ba_unique | ba_quiet,
NULL);
}
}
if (current_class_type
&& (binfo = lookup_base (current_class_type, type,
- ba_ignore | ba_quiet, NULL)))
+ ba_unique | ba_quiet, NULL)))
context = current_class_type;
else
{
|| TREE_CODE (b) != RECORD_TYPE)
return false;
- if (ACCESSIBLY_UNIQUELY_DERIVED_P (a, b))
+ if (PUBLICLY_UNIQUELY_DERIVED_P (a, b))
return true;
}
return false;
base_kind kind;
binfo = lookup_base (access_path ? access_path : object_type,
- member_scope, ba_ignore, &kind);
+ member_scope, ba_unique, &kind);
if (binfo == error_mark_node)
return error_mark_node;
tree
binfo_or_else (tree base, tree type)
{
- tree binfo = lookup_base (type, base, ba_ignore, NULL);
+ tree binfo = lookup_base (type, base, ba_unique, NULL);
if (binfo == error_mark_node)
return NULL_TREE;
+2004-10-18 Nathan Sidwell <nathan@codesourcery.com>
+
+ * g++.dg/eh/shadow1.C: New.
+
2004-10-18 Jakub Jelinek <jakub@redhat.com>
* gcc.c-torture/compile/20041018-1.c: New test.
--- /dev/null
+// Copyright (C) 2004 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 15 Oct 2004 <nathan@codesourcery.com>
+
+// We forgot to ignore current context and friends when determing
+// which exceptions shadowed eachother.
+
+struct E;
+
+struct B {};
+
+struct D : private B
+{
+ friend class E;
+
+ static B *baz (D *);
+ virtual void V () throw (B); // { dg-error "overriding" "" }
+};
+
+struct E : public D
+{
+ virtual void V () throw (D); // { dg-error "looser throw" "" }
+};
+
+B* foo (D *);
+
+B *D::baz (D *p)
+{
+ try {foo (p);}
+ catch (B const &b) {}
+ catch (D const &d) {}
+ return p;
+}