diff options
author | Mark Mitchell <mark@markmitchell.com> | 1999-03-05 16:38:54 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 1999-03-05 16:38:54 +0000 |
commit | 7d4bdeed81155efff35f8713d203d86c5733f791 (patch) | |
tree | 681411d3b22eb93eb59b011bc9a0b990d7692239 /gcc | |
parent | 00512c3a634d9eb316968eeb2dbb5c6fbaf68915 (diff) | |
download | gcc-7d4bdeed81155efff35f8713d203d86c5733f791.zip gcc-7d4bdeed81155efff35f8713d203d86c5733f791.tar.gz gcc-7d4bdeed81155efff35f8713d203d86c5733f791.tar.bz2 |
cp-tree.h (ANON_UNION_TYPE_P): Robustify.
* cp-tree.h (ANON_UNION_TYPE_P): Robustify.
* decl.c (make_typename_type): Don't issue an error if an
immediate lookup fails; it migt be resolved later.
* friend.c (is_friend): Add comment.
* search.c (breadth_first_search): Add POSTFN and DATA
parameters. Tidy. All callers changed.
(lookup_field_queue_p): New function.
(lookup_field_r): Likewise.
(lookup_field_post): Likewise.
(lookup_field): Use them, via breadth_first_search, instead of
duplicating logic.
(compute_access): Robustify.
(lookup_fnfield_info): New structure.
From-SVN: r25607
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 5 | ||||
-rw-r--r-- | gcc/cp/decl.c | 17 | ||||
-rw-r--r-- | gcc/cp/friend.c | 2 | ||||
-rw-r--r-- | gcc/cp/search.c | 700 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.other/crash7.C | 11 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/typename15.C | 18 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/typename16.C | 31 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/typename17.C | 20 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/typename3.C | 2 |
10 files changed, 464 insertions, 358 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2c51faa..2a493dd 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,19 @@ +1999-03-05 Mark Mitchell <mark@markmitchell.com> + + * cp-tree.h (ANON_UNION_TYPE_P): Robustify. + * decl.c (make_typename_type): Don't issue an error if an + immediate lookup fails; it migt be resolved later. + * friend.c (is_friend): Add comment. + * search.c (breadth_first_search): Add POSTFN and DATA + parameters. Tidy. All callers changed. + (lookup_field_queue_p): New function. + (lookup_field_r): Likewise. + (lookup_field_post): Likewise. + (lookup_field): Use them, via breadth_first_search, instead of + duplicating logic. + (compute_access): Robustify. + (lookup_fnfield_info): New structure. + 1999-03-05 Jason Merrill <jason@yorick.cygnus.com> * pt.c (tsubst, case ARRAY_REF): Use tsubst_expr again. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 935f8f9..ab33fad 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1708,9 +1708,12 @@ extern int flag_new_for_scope; #define ANON_UNION_P(NODE) (DECL_NAME (NODE) == 0) -/* Nonzero if TYPE is an anonymous union type. */ +/* Nonzero if TYPE is an anonymous union type. We're careful + accessing TYPE_IDENTIFIER because some built-in types, like + pointer-to-member types, do not have TYPE_NAME. */ #define ANON_UNION_TYPE_P(TYPE) \ (TREE_CODE (TYPE) == UNION_TYPE \ + && TYPE_NAME (TYPE) \ && ANON_AGGRNAME_P (TYPE_IDENTIFIER (TYPE))) #define UNKNOWN_TYPE LANG_TYPE diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index f7580ba..cf7ce61 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5192,34 +5192,29 @@ make_typename_type (context, name) if (IS_AGGR_TYPE (context)) t = lookup_field (context, name, 0, 0); else - t = NULL_TREE; - - if (t == NULL_TREE || TREE_CODE (t) != TEMPLATE_DECL - || TREE_CODE (DECL_RESULT (t)) != TYPE_DECL) { cp_error ("no class template named `%#T' in `%#T'", name, context); return error_mark_node; } - return lookup_template_class (t, TREE_OPERAND (fullname, 1), - NULL_TREE, context, - /*entering_scope=*/0); + if (t && DECL_CLASS_TEMPLATE_P (t)) + return lookup_template_class (t, TREE_OPERAND (fullname, 1), + NULL_TREE, context, + /*entering_scope=*/0); } else { if (IS_AGGR_TYPE (context)) t = lookup_field (context, name, 0, 1); else - t = NULL_TREE; - - if (t == NULL_TREE) { cp_error ("no type named `%#T' in `%#T'", name, context); return error_mark_node; } - return TREE_TYPE (t); + if (t) + return TREE_TYPE (t); } } diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c index c26d695..8bcdcc4 100644 --- a/gcc/cp/friend.c +++ b/gcc/cp/friend.c @@ -32,6 +32,8 @@ static void add_friends PROTO((tree, tree, tree)); /* Friend data structures are described in cp-tree.h. */ +/* Returns non-zero if SUPPLICANT is a friend of TYPE. */ + int is_friend (type, supplicant) tree type, supplicant; diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 3b88c40..907c9d3 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -110,17 +110,21 @@ static void dfs_get_vbase_types PROTO((tree)); static void dfs_pushdecls PROTO((tree)); static void dfs_compress_decls PROTO((tree)); static void dfs_unuse_fields PROTO((tree)); -static tree add_conversions PROTO((tree)); +static tree add_conversions PROTO((tree, void *)); static tree get_virtuals_named_this PROTO((tree)); -static tree get_virtual_destructor PROTO((tree)); -static int tree_has_any_destructor_p PROTO((tree)); +static tree get_virtual_destructor PROTO((tree, void *)); +static int tree_has_any_destructor_p PROTO((tree, void *)); static int covariant_return_p PROTO((tree, tree)); static struct search_level *push_search_level PROTO((struct stack_level *, struct obstack *)); static struct search_level *pop_search_level PROTO((struct stack_level *)); static tree breadth_first_search - PROTO((tree, tree (*) (tree), int (*) (tree))); + PROTO((tree, tree (*) (tree, void *), int (*) (tree, void *), + void (*) (tree *, tree *, void *), void *)); +static int lookup_field_queue_p PROTO((tree, void *)); +static tree lookup_field_r PROTO((tree, void *)); +static void lookup_field_post PROTO((tree *, tree *, void *)); static tree vbase_types; static tree vbase_decl_ptr_intermediate, vbase_decl_ptr; @@ -673,7 +677,7 @@ compute_access (basetype_path, field) { /* Are we (or an enclosing scope) friends with the class that has FIELD? */ - if (is_friend (context, previous_scope)) + if (TYPE_P (context) && is_friend (context, previous_scope)) PUBLIC_RETURN; /* If it's private, it's private, you letch. */ @@ -689,6 +693,7 @@ compute_access (basetype_path, field) { if (current_class_type && (static_mem || DECL_CONSTRUCTOR_P (field)) + && TYPE_P (context) && ACCESSIBLY_DERIVED_FROM_P (context, current_class_type)) PUBLIC_RETURN; else @@ -750,7 +755,7 @@ compute_access (basetype_path, field) if (access == access_default_node) { - if (is_friend (context, previous_scope)) + if (TYPE_P (context) && is_friend (context, previous_scope)) access = access_public_node; else if (TREE_PRIVATE (field)) access = access_private_node; @@ -849,6 +854,270 @@ lookup_fnfields_here (type, name) return -1; } +struct lookup_field_info { + /* The name of the field for which we're looking. */ + tree name; + /* If non-NULL, the current result of the lookup. */ + tree rval; + /* The path to RVAL. */ + tree rval_binfo; + /* If non-NULL, a list of the possible candidates. */ + tree ambiguous; + /* The access computed for RVAL. */ + tree access; + /* If non-zero, we must check access. */ + int protect; + /* If non-zero, we are looking for types, not data members. */ + int want_type; + /* If something went wrong, a message indicating what. */ + char *errstr; +}; + +/* Returns non-zero if BINFO is not hidden by the value found by the + lookup so far. If BINFO is hidden, then there's no need to look in + it. DATA is really a struct lookup_field_info. Called from + lookup_field via breadth_first_search. */ + +static int +lookup_field_queue_p (binfo, data) + tree binfo; + void *data; +{ + struct lookup_field_info *lfi = (struct lookup_field_info *) data; + + return !(lfi->rval_binfo && hides (lfi->rval_binfo, binfo)); +} + +/* DATA is really a struct lookup_field_info. Look for a field with + the name indicated there in BINFO. If this function returns a + non-NULL value it is the result of the lookup. Called from + lookup_field via breadth_first_search. */ + +static tree +lookup_field_r (binfo, data) + tree binfo; + void *data; +{ + struct lookup_field_info *lfi = (struct lookup_field_info *) data; + tree type = BINFO_TYPE (binfo); + tree nval; + int idx; + + /* See if the field is present in TYPE. */ + nval = lookup_field_1 (type, lfi->name); + if (!nval) + idx = lookup_fnfields_here (type, lfi->name); + + /* If the data member wasn't present, then there's nothing further + to do for this type. */ + if (!nval && idx < 0) + 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 && !hides (binfo, lfi->rval_binfo)) + { + if (nval && nval == lfi->rval && SHARED_MEMBER_P (nval)) + /* The two things are really the same. */ + ; + else if (hides (lfi->rval_binfo, binfo)) + /* The previous value hides the new one. */ + ; + else + { + /* We have a real ambiguity. We keep a chain of all the + candidates. */ + if (!lfi->ambiguous && lfi->rval) + /* This is the first time we noticed an ambiguity. Add + what we previously thought was a reasonable candidate + to the list. */ + lfi->ambiguous = scratch_tree_cons (NULL_TREE, lfi->rval, + NULL_TREE); + /* If NVAL is NULL here, that means that we found a + function, not a data member. Pick a representative + function, from the overload set, for use in error + messages. */ + if (!nval) + nval = OVL_CURRENT (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC + (type), idx)); + + /* Add the new value. */ + lfi->ambiguous = scratch_tree_cons (NULL_TREE, nval, + lfi->ambiguous); + lfi->errstr = "request for member `%D' is ambiguous"; + } + } + else + { + /* The new lookup is the best we've got so far. Verify that + it's the kind of thing we're looking for. */ + if (nval) + { + if (lfi->want_type && TREE_CODE (nval) != TYPE_DECL) + { + nval = purpose_member (lfi->name, CLASSTYPE_TAGS (type)); + if (nval) + nval = TYPE_MAIN_DECL (TREE_VALUE (nval)); + } + else if (!lfi->want_type && TREE_CODE (nval) == TYPE_DECL + && lookup_fnfields_here (type, lfi->name) >= 0) + /* The type declaration is actually hidden by the + function declaration. */ + nval = NULL_TREE; + } + + if (nval) + { + /* The lookup found a data member. */ + lfi->rval = nval; + if (lfi->protect) + lfi->access = compute_access (binfo, nval); + /* If the thing we're looking for is a virtual base class, + then we know we've got what we want at this point; + there's no way to get an ambiguity. */ + if (VBASE_NAME_P (lfi->name)) + return nval; + } + else + /* The lookup found a function member. This lookup hides + whatever was there before, so even though we're not + interested in this value we keep track of the way in + which we found the function. Subsequent lookups + shouldn't find a data member if it is hidden by this + function member. */ + lfi->rval = NULL_TREE; + + lfi->rval_binfo = binfo; + } + + return 0; +} + +/* Check to see if the result of the field lookup (as indicated by + DATA, which is really a struct field_info) has any access other + than that we previously computed. SEARCH_HEAD and SEARCH_TAIL + bound the path taken to find the result. Called from lookup_field + via breadth_first_search. */ + +static void +lookup_field_post (search_head, search_tail, data) + tree *search_head; + tree *search_tail; + void *data; +{ + struct lookup_field_info *lfi = (struct lookup_field_info *) data; + tree rval = lfi->rval; + tree own_access = access_default_node; + tree *tp; + + /* If we didn't find anything, or we found ambiguous function + declarations, but no data members, just return. */ + if (!rval) + { + lfi->errstr = 0; + return; + } + + /* If we've already hit a snag, we're done. */ + if (lfi->errstr) + return; + + /* Check accessibility. */ + if (lfi->protect) + { + /* If is possible for one of the derived types on the path to + have defined special access for this field. Look for such + declarations and report an error if a conflict is found. */ + if (DECL_LANG_SPECIFIC (rval) && DECL_ACCESS (rval)) + for (tp = search_head; tp < search_tail; ++tp) + { + tree new_v = NULL_TREE; + + if (lfi->access != access_default_node) + new_v = compute_access (*tp, lfi->rval); + if (lfi->access != access_default_node && new_v != lfi->access) + { + lfi->errstr = "conflicting access to member `%D'"; + lfi->access = access_default_node; + return; + } + own_access = new_v; + tp++; + } + + /* Check to see that access to the member is allowed. */ + if (own_access == access_private_node) + lfi->errstr = "member `%D' declared private"; + else if (own_access == access_protected_node) + lfi->errstr = "member `%D' declared protected"; + else if (lfi->access == access_private_node) + lfi->errstr = TREE_PRIVATE (lfi->rval) + ? "member `%D' is private" + : "member `%D' is from private base class"; + else if (lfi->access== access_protected_node) + lfi->errstr = TREE_PROTECTED (rval) + ? "member `%D' is protected" + : "member `%D' is from protected base class"; + } + + /* The implicit typename extension allows us to find type + declarations in dependent base clases. It also handles + out-of-class definitions where the enclosing class is a + template. For example: + + template <class T> struct S { struct I { void f(); }; }; + template <class T> void S<T>::I::f() {} + + will come through here to handle `S<T>::I'. The bottom line is + that while searching for the field, we will have happily + descended into dependent base classes, and we must now figure out + what to do about it. */ + + /* If we're not in a template, or the search terminated in the + current class, then there's no problem. */ + if (!processing_template_decl + || currently_open_class (BINFO_TYPE (lfi->rval_binfo))) + return; + + /* We need to return a member template class so we can define partial + specializations. Is there a better way? */ + if (DECL_CLASS_TEMPLATE_P (rval)) + return; + + /* Walk the path to the base in which the search finally suceeded, + checking for dependent bases along the way. */ + for (tp = (currently_open_class (BINFO_TYPE (*search_head))) + ? search_head + 1 : search_head; + tp < search_tail; + ++tp) + { + if (!uses_template_parms (BINFO_TYPE (*tp))) + continue; + + if (TREE_CODE (rval) != TYPE_DECL) + { + /* 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. */ + lfi->rval = NULL_TREE; + return; + } + + /* We've passed a dependent base on our way to finding the + type. So, create an implicit typename type. The appropriate + context for the typename is *TP. But, there's a small catch; + the base classes for a partial instantiation are not correct, + because we don't tsubst into them when we do the partial + instantiation. So, we just use the context of the current + class type. */ + lfi->rval = TYPE_STUB_DECL (build_typename_type + (BINFO_TYPE (*search_head), + lfi->name, lfi->name, + TREE_TYPE (rval))); + return; + } +} + /* Look for a field named NAME in an inheritance lattice dominated by XBASETYPE. PROTECT is zero if we can avoid computing access information, otherwise it is 1. WANT_TYPE is 1 when we should only @@ -863,14 +1132,9 @@ lookup_field (xbasetype, name, protect, want_type) register tree xbasetype, name; int protect, want_type; { - int head = 0, tail = 0; - tree rval, rval_binfo = NULL_TREE, rval_binfo_h = NULL_TREE; - tree type = NULL_TREE, basetype_chain, basetype_path = NULL_TREE; - tree this_v = access_default_node; - tree entry, binfo, binfo_h; - tree own_access = access_default_node; - int vbase_name_p = VBASE_NAME_P (name); - tree ambiguous = NULL_TREE; + tree rval, rval_binfo = NULL_TREE; + tree type = NULL_TREE, basetype_path = NULL_TREE; + struct lookup_field_info lfi; /* rval_binfo is the binfo associated with the found member, note, this can be set with useful information, even when rval is not @@ -888,6 +1152,8 @@ lookup_field (xbasetype, name, protect, want_type) char *errstr = 0; + bzero (&lfi, sizeof (lfi)); + #if 0 /* We cannot search for constructor/destructor names like this. */ /* This can't go here, but where should it go? */ @@ -927,306 +1193,31 @@ lookup_field (xbasetype, name, protect, want_type) n_calls_lookup_field++; #endif /* GATHER_STATISTICS */ - rval = lookup_field_1 (type, name); - - if (rval || lookup_fnfields_here (type, name) >= 0) - { - if (rval) - { - if (want_type) - { - if (TREE_CODE (rval) != TYPE_DECL) - { - rval = purpose_member (name, CLASSTYPE_TAGS (type)); - if (rval) - rval = TYPE_MAIN_DECL (TREE_VALUE (rval)); - } - } - else - { - if (TREE_CODE (rval) == TYPE_DECL - && lookup_fnfields_here (type, name) >= 0) - rval = NULL_TREE; - } - } - - if (protect && rval) - { - if (TREE_PRIVATE (rval) | TREE_PROTECTED (rval)) - this_v = compute_access (basetype_path, rval); - if (TREE_CODE (rval) == CONST_DECL) - { - if (this_v == access_private_node) - errstr = "enum `%D' is a private value of class `%T'"; - else if (this_v == access_protected_node) - errstr = "enum `%D' is a protected value of class `%T'"; - } - else - { - if (this_v == access_private_node) - errstr = "member `%D' is a private member of class `%T'"; - else if (this_v == access_protected_node) - errstr = "member `%D' is a protected member of class `%T'"; - } - } - - rval_binfo = basetype_path; - goto out; - } - - basetype_chain = build_expr_list (NULL_TREE, basetype_path); - - /* The ambiguity check relies upon breadth first searching. */ - - search_stack = push_search_level (search_stack, &search_obstack); - binfo = basetype_path; - binfo_h = binfo; - - while (1) - { - tree binfos = BINFO_BASETYPES (binfo); - int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; - tree nval; - int idx = -1; - - /* Process and/or queue base types. */ - for (i = 0; i < n_baselinks; i++) - { - tree base_binfo = TREE_VEC_ELT (binfos, i); - if (BINFO_FIELDS_MARKED (base_binfo) == 0) - { - tree btypes; - - SET_BINFO_FIELDS_MARKED (base_binfo); - btypes = scratch_tree_cons (NULL_TREE, base_binfo, basetype_chain); - if (TREE_VIA_VIRTUAL (base_binfo)) - btypes = scratch_tree_cons (NULL_TREE, - TYPE_BINFO (BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i))), - btypes); - else - btypes = scratch_tree_cons (NULL_TREE, - TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i), - btypes); - obstack_ptr_grow (&search_obstack, btypes); - tail += 1; - if (tail >= search_stack->limit) - my_friendly_abort (98); - } - } - - /* Process head of queue, if one exists. */ - if (head >= tail) - break; - - basetype_chain = search_stack->first[head++]; - binfo_h = TREE_VALUE (basetype_chain); - basetype_chain = TREE_CHAIN (basetype_chain); - basetype_path = TREE_VALUE (basetype_chain); - if (TREE_CHAIN (basetype_chain)) - my_friendly_assert - ((BINFO_INHERITANCE_CHAIN (basetype_path) - == TREE_VALUE (TREE_CHAIN (basetype_chain))) - /* We only approximate base info for partial instantiations. */ - || current_template_parms, - 980827); - else - my_friendly_assert (BINFO_INHERITANCE_CHAIN (basetype_path) - == NULL_TREE, 980827); - - binfo = basetype_path; - type = BINFO_TYPE (binfo); - - /* See if we can find NAME in TYPE. If RVAL is nonzero, - and we do find NAME in TYPE, verify that such a second - sighting is in fact valid. */ - - nval = lookup_field_1 (type, name); - - if (nval || (idx = lookup_fnfields_here (type, name)) >= 0) - { - if (nval && nval == rval && SHARED_MEMBER_P (nval)) - { - /* This is ok, the member found is the same [class.ambig] */ - } - else if (rval_binfo && hides (rval_binfo_h, binfo_h)) - { - /* This is ok, the member found is in rval_binfo, not - here (binfo). */ - } - else if (rval_binfo==NULL_TREE || hides (binfo_h, rval_binfo_h)) - { - /* This is ok, the member found is here (binfo), not in - rval_binfo. */ - if (nval) - { - rval = nval; - if (protect) - this_v = compute_access (basetype_path, rval); - /* These may look ambiguous, but they really are not. */ - if (vbase_name_p) - break; - } - else - { - /* Undo finding it before, as something else hides it. */ - rval = NULL_TREE; - } - rval_binfo = binfo; - rval_binfo_h = binfo_h; - } - else - { - /* This is ambiguous. Remember it. */ - if (! ambiguous) - { - errstr = "request for member `%D' is ambiguous"; - protect += 2; - if (rval) - ambiguous = scratch_tree_cons (NULL_TREE, rval, ambiguous); - } - if (! nval) - { - nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx); - nval = OVL_CURRENT (nval); - } - ambiguous = scratch_tree_cons (NULL_TREE, nval, ambiguous); - } - } - } - { - tree *tp = search_stack->first; - tree *search_tail = tp + tail; - - if (rval_binfo) - { - type = BINFO_TYPE (rval_binfo); - - if (rval) - { - if (want_type) - { - if (TREE_CODE (rval) != TYPE_DECL) - { - rval = purpose_member (name, CLASSTYPE_TAGS (type)); - if (rval) - rval = TYPE_MAIN_DECL (TREE_VALUE (rval)); - } - } - else - { - if (TREE_CODE (rval) == TYPE_DECL - && lookup_fnfields_here (type, name) >= 0) - rval = NULL_TREE; - } - } - } - - if (rval == NULL_TREE) - errstr = 0; - - /* If this FIELD_DECL defines its own access level, deal with that. */ - if (rval && errstr == 0 - && (protect & 1) - && DECL_LANG_SPECIFIC (rval) - && DECL_ACCESS (rval)) - { - while (tp < search_tail) - { - /* If is possible for one of the derived types on the path to - have defined special access for this field. Look for such - declarations and report an error if a conflict is found. */ - tree new_v = NULL_TREE; - - if (this_v != access_default_node) - new_v = compute_access (TREE_VALUE (TREE_CHAIN (*tp)), rval); - if (this_v != access_default_node && new_v != this_v) - { - errstr = "conflicting access to member `%D'"; - this_v = access_default_node; - } - own_access = new_v; - CLEAR_BINFO_FIELDS_MARKED (TREE_VALUE (TREE_CHAIN (*tp))); - tp += 1; - } - } - else - { - while (tp < search_tail) - { - CLEAR_BINFO_FIELDS_MARKED (TREE_VALUE (TREE_CHAIN (*tp))); - tp += 1; - } - } - } - search_stack = pop_search_level (search_stack); - - if (errstr == 0) - { - if (own_access == access_private_node) - errstr = "member `%D' declared private"; - else if (own_access == access_protected_node) - errstr = "member `%D' declared protected"; - else if (this_v == access_private_node) - errstr = TREE_PRIVATE (rval) - ? "member `%D' is private" - : "member `%D' is from private base class"; - else if (this_v == access_protected_node) - errstr = TREE_PROTECTED (rval) - ? "member `%D' is protected" - : "member `%D' is from protected base class"; - } - - out: - if (protect == 2) - { - /* If we are not interested in ambiguities, don't report them, - just return NULL_TREE. */ - rval = NULL_TREE; - protect = 0; - } + lfi.name = name; + lfi.protect = protect; + lfi.want_type = want_type; + lfi.access = access_default_node; + breadth_first_search (basetype_path, &lookup_field_r, + &lookup_field_queue_p, &lookup_field_post, &lfi); + rval = lfi.rval; + rval_binfo = lfi.rval_binfo; + if (rval_binfo) + type = BINFO_TYPE (rval_binfo); + errstr = lfi.errstr; + + /* If we are not interested in ambiguities, don't report them; + just return NULL_TREE. */ + if (!protect && lfi.ambiguous) + return NULL_TREE; if (errstr && protect) { cp_error (errstr, name, type); - if (ambiguous) - print_candidates (ambiguous); + if (lfi.ambiguous) + print_candidates (lfi.ambiguous); rval = error_mark_node; } - /* Do implicit typename stuff. This code also handles out-of-class - definitions of nested classes whose enclosing class is a - template. For example: - - template <class T> struct S { struct I { void f(); }; }; - template <class T> void S<T>::I::f() {} - - will come through here to handle `S<T>::I'. */ - if (rval && processing_template_decl - && ! currently_open_class (BINFO_TYPE (rval_binfo)) - && uses_template_parms (type)) - { - /* We need to return a member template class so we can define partial - specializations. Is there a better way? */ - if (DECL_CLASS_TEMPLATE_P (rval)) - return rval; - - /* Don't return a non-type. Actually, we ought to return something - so lookup_name_real can give a warning. */ - if (TREE_CODE (rval) != TYPE_DECL) - return NULL_TREE; - - binfo = rval_binfo; - for (; ; binfo = BINFO_INHERITANCE_CHAIN (binfo)) - if (BINFO_INHERITANCE_CHAIN (binfo) == NULL_TREE - || (BINFO_TYPE (BINFO_INHERITANCE_CHAIN (binfo)) - == current_class_type)) - break; - - entry = build_typename_type (BINFO_TYPE (binfo), name, name, - TREE_TYPE (rval)); - return TYPE_STUB_DECL (entry); - } - return rval; } @@ -1625,19 +1616,29 @@ lookup_member (xbasetype, name, protect, want_type) /* Search a multiple inheritance hierarchy by breadth-first search. BINFO is an aggregate type, possibly in a multiple-inheritance hierarchy. - TESTFN is a function, which, if true, means that our condition has been met, - and its return value should be returned. + TESTFN is a function, which, if true, means that our condition has + been met, and its return value should be returned. QFN, if non-NULL, is a predicate dictating whether the type should - even be queued. */ + even be queued. + POSTFN, if non-NULL, is a function to call before returning. It is + passed an array whose first element is the most derived type in the + chain, and whose last element is the least derived type. + + All of the functions are also passed the DATA, which they may use + as they see fit. */ static tree -breadth_first_search (binfo, testfn, qfn) +breadth_first_search (binfo, testfn, qfn, postfn, data) tree binfo; - tree (*testfn) PROTO((tree)); - int (*qfn) PROTO((tree)); + tree (*testfn) PROTO((tree, void *)); + int (*qfn) PROTO((tree, void *)); + void (*postfn) PROTO((tree *, tree *, void *)); + void *data; { int head = 0, tail = 0; tree rval = NULL_TREE; + tree *tp; + tree *search_tail; search_stack = push_search_level (search_stack, &search_obstack); @@ -1645,19 +1646,32 @@ breadth_first_search (binfo, testfn, qfn) obstack_ptr_grow (&search_obstack, binfo); ++tail; - while (1) + while (head < tail) { - tree binfos = BINFO_BASETYPES (binfo); - int n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; + tree binfos; + int n_baselinks; int i; - /* Process and/or queue base types. */ + /* Pull the next type out of the queue. */ + binfo = search_stack->first[head++]; + + /* If this is the one we're looking for, we're done. */ + rval = (*testfn) (binfo, data); + if (rval) + break; + + /* Queue up the base types. */ + binfos = BINFO_BASETYPES (binfo); + n_baselinks = binfos ? TREE_VEC_LENGTH (binfos): 0; for (i = 0; i < n_baselinks; i++) { tree base_binfo = TREE_VEC_ELT (binfos, i); + if (TREE_VIA_VIRTUAL (base_binfo)) + base_binfo = TYPE_BINFO (BINFO_TYPE (base_binfo)); + if (BINFO_MARKED (base_binfo) == 0 - && (qfn == 0 || (*qfn) (base_binfo))) + && (qfn == 0 || (*qfn) (base_binfo, data))) { SET_BINFO_MARKED (base_binfo); obstack_ptr_grow (&search_obstack, base_binfo); @@ -1666,26 +1680,19 @@ breadth_first_search (binfo, testfn, qfn) my_friendly_abort (100); } } - /* Process head of queue, if one exists. */ - if (head >= tail) - { - rval = 0; - break; - } + } - binfo = search_stack->first[head++]; - if ((rval = (*testfn) (binfo))) - break; + tp = search_stack->first; + search_tail = tp + tail; + + if (postfn) + (*postfn) (tp, search_tail, data); + + while (tp < search_tail) + { + tree binfo = *tp++; + CLEAR_BINFO_MARKED (binfo); } - { - tree *tp = search_stack->first; - tree *search_tail = tp + tail; - while (tp < search_tail) - { - tree binfo = *tp++; - CLEAR_BINFO_MARKED (binfo); - } - } search_stack = pop_search_level (search_stack); return rval; @@ -1723,8 +1730,9 @@ get_virtuals_named_this (binfo) } static tree -get_virtual_destructor (binfo) +get_virtual_destructor (binfo, data) tree binfo; + void *data; { tree type = BINFO_TYPE (binfo); if (TYPE_HAS_DESTRUCTOR (type) @@ -1734,8 +1742,9 @@ get_virtual_destructor (binfo) } static int -tree_has_any_destructor_p (binfo) +tree_has_any_destructor_p (binfo, data) tree binfo; + void *data; { tree type = BINFO_TYPE (binfo); return TYPE_NEEDS_DESTRUCTOR (type); @@ -1824,7 +1833,7 @@ get_matching_virtual (binfo, fndecl, dtorp) { return breadth_first_search (binfo, get_virtual_destructor, - tree_has_any_destructor_p); + tree_has_any_destructor_p, 0, 0); } else { @@ -3310,13 +3319,14 @@ reinit_search_statistics () #define scratch_tree_cons expr_tree_cons -static tree conversions; static tree -add_conversions (binfo) +add_conversions (binfo, data) tree binfo; + void *data; { int i; tree method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo)); + tree *conversions = (tree *) data; for (i = 2; i < TREE_VEC_LENGTH (method_vec); ++i) { @@ -3331,7 +3341,7 @@ add_conversions (binfo) /* Make sure we don't already have this conversion. */ if (! IDENTIFIER_MARKED (name)) { - conversions = scratch_tree_cons (binfo, tmp, conversions); + *conversions = scratch_tree_cons (binfo, tmp, *conversions); IDENTIFIER_MARKED (name) = 1; } } @@ -3343,11 +3353,11 @@ lookup_conversions (type) tree type; { tree t; - - conversions = NULL_TREE; + tree conversions = NULL_TREE; if (TYPE_SIZE (type)) - breadth_first_search (TYPE_BINFO (type), add_conversions, 0); + breadth_first_search (TYPE_BINFO (type), add_conversions, + 0, 0, &conversions); for (t = conversions; t; t = TREE_CHAIN (t)) IDENTIFIER_MARKED (DECL_NAME (OVL_CURRENT (TREE_VALUE (t)))) = 0; diff --git a/gcc/testsuite/g++.old-deja/g++.other/crash7.C b/gcc/testsuite/g++.old-deja/g++.other/crash7.C new file mode 100644 index 0000000..c924adf --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/crash7.C @@ -0,0 +1,11 @@ +// Build don't link: + +void f() +{ + union { + private: + int i; + } u; + + u.i = 3; // ERROR - private +} diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename15.C b/gcc/testsuite/g++.old-deja/g++.pt/typename15.C new file mode 100644 index 0000000..8e26057 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/typename15.C @@ -0,0 +1,18 @@ +// Build don't link: +// Special g++ Options: + +template <class T, bool B> +struct R { + struct X {}; +}; + +template <class T, bool B = false> +struct S : public R <T, B> { +}; + +template <class T> void f() +{ + S<T>::X(); +} + +template void f<int>(); diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename16.C b/gcc/testsuite/g++.old-deja/g++.pt/typename16.C new file mode 100644 index 0000000..51a8765 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/typename16.C @@ -0,0 +1,31 @@ +// Build don't run: +// Special g++ Options: + +struct B { + typedef int I; +}; + +template <class T> +struct D1 : public B { +}; + +template <class T> +struct D2 : public D1<T> { + I i; +}; + +template <> +struct D1<int> { + typedef double I; +}; + +template <class T> +void f(T); +template <> +void f(double) {} + +int main() +{ + D2<int> d2i; + f(d2i.i); +} diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename17.C b/gcc/testsuite/g++.old-deja/g++.pt/typename17.C new file mode 100644 index 0000000..87b0ab3 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/typename17.C @@ -0,0 +1,20 @@ +// Build don't link: + +template <class T> +struct A +{ + typedef T A_Type; +}; + + +template <class U> +struct B : public A<U> +{ + typename B<U>::A_Type Func(); +}; + + +template <class U> +typename B<U>::A_Type B<U>::Func() +{ +} diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename3.C b/gcc/testsuite/g++.old-deja/g++.pt/typename3.C index 0b19d54..55d6430 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/typename3.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/typename3.C @@ -16,6 +16,6 @@ struct B : public A<U> template <class U> -A<U>::A_Type B<U>::Func() +B<U>::A_Type B<U>::Func() { } |