diff options
Diffstat (limited to 'contrib/gcc/cp/search.c')
-rw-r--r-- | contrib/gcc/cp/search.c | 71 |
1 files changed, 45 insertions, 26 deletions
diff --git a/contrib/gcc/cp/search.c b/contrib/gcc/cp/search.c index 7a82796..4721a58 100644 --- a/contrib/gcc/cp/search.c +++ b/contrib/gcc/cp/search.c @@ -254,6 +254,28 @@ lookup_base_r (binfo, base, access, is_virtual, binfo_ptr) return found; } +/* Returns true if type BASE is accessible in T. (BASE is known to be + a 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. */ + /* 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 @@ -313,41 +335,24 @@ lookup_base (t, base, access, kind_ptr) 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; } @@ -2635,6 +2640,20 @@ setup_class_bindings (name, type_binding_p) 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); } } |