diff options
author | nathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-12-05 15:50:06 +0000 |
---|---|---|
committer | nathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-12-05 15:50:06 +0000 |
commit | 4c481f71f8775801d6269420d5e979ef6f4839c5 (patch) | |
tree | af97c282c8bf12e05febc3bd5655a95d3b143a54 /gcc/cp | |
parent | 1bbb5947018b45db17d79d27e3f6e63980f95cc9 (diff) | |
download | gcc-4c481f71f8775801d6269420d5e979ef6f4839c5.tar.gz |
cp:
* cp-tree.h (IDENTIFIER_VIRTUAL_P): Document.
(get_matching_virtual): Remove.
(look_for_overrides): Declare new function.
* decl.c (grokfndecl): Don't set IDENTIFIER_VIRTUAL_P or
DECL_VINDEX here.
* class.c (check_for_override): Move base class iteration code
to look_for_overrides.
* search.c (next_baselink): Remove.
(get_virtuals_named_this): Remove.
(get_virtual_destructor): Remove.
(tree_has_any_destructors_p): Remove.
(struct gvnt_info): Remove.
(check_final_overrider): Remove `virtual' from error messages.
(get_matching_virtuals): Remove. Move functionality to ...
(look_for_overrides): ... here, and ...
(look_for_overrides_r): ... here. Set DECL_VIRTUAL_P, if found
to be overriding.
testsuite:
* g++.old-deja/g++.h/spec6.C: Remove some of the XFAILS.
* g++.old-deja/g++.other/virtual10.C: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@38040 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 20 | ||||
-rw-r--r-- | gcc/cp/class.c | 66 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 5 | ||||
-rw-r--r-- | gcc/cp/decl.c | 7 | ||||
-rw-r--r-- | gcc/cp/search.c | 274 |
5 files changed, 129 insertions, 243 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e2d72266547..10fff7f0544 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,25 @@ 2000-12-05 Nathan Sidwell <nathan@codesourcery.com> + * cp-tree.h (IDENTIFIER_VIRTUAL_P): Document. + (get_matching_virtual): Remove. + (look_for_overrides): Declare new function. + * decl.c (grokfndecl): Don't set IDENTIFIER_VIRTUAL_P or + DECL_VINDEX here. + * class.c (check_for_override): Move base class iteration code + to look_for_overrides. + * search.c (next_baselink): Remove. + (get_virtuals_named_this): Remove. + (get_virtual_destructor): Remove. + (tree_has_any_destructors_p): Remove. + (struct gvnt_info): Remove. + (check_final_overrider): Remove `virtual' from error messages. + (get_matching_virtuals): Remove. Move functionality to ... + (look_for_overrides): ... here, and ... + (look_for_overrides_r): ... here. Set DECL_VIRTUAL_P, if found + to be overriding. + +2000-12-05 Nathan Sidwell <nathan@codesourcery.com> + * typeck.c (get_delta_difference): If via a virtual base, return zero. * cvt.c (cp_convert_to_pointer): If via a virtual base, do no diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 9a71203258a..ff3d26456c0 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -2910,56 +2910,24 @@ static void check_for_override (decl, ctype) tree decl, ctype; { - tree binfos = BINFO_BASETYPES (TYPE_BINFO (ctype)); - int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; - int virtualp = DECL_VIRTUAL_P (decl); - int found_overriden_fn = 0; + if (TREE_CODE (decl) == TEMPLATE_DECL) + /* In [temp.mem] we have: - for (i = 0; i < n_baselinks; i++) - { - tree base_binfo = TREE_VEC_ELT (binfos, i); - if (TYPE_POLYMORPHIC_P (BINFO_TYPE (base_binfo))) - { - tree tmp = get_matching_virtual - (base_binfo, decl, DECL_DESTRUCTOR_P (decl)); - - if (tmp && !found_overriden_fn) - { - /* If this function overrides some virtual in some base - class, then the function itself is also necessarily - virtual, even if the user didn't explicitly say so. */ - DECL_VIRTUAL_P (decl) = 1; - - /* The TMP we really want is the one from the deepest - baseclass on this path, taking care not to - duplicate if we have already found it (via another - path to its virtual baseclass. */ - if (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE) - { - cp_error_at ("`static %#D' cannot be declared", decl); - cp_error_at (" since `virtual %#D' declared in base class", - tmp); - break; - } - virtualp = 1; - - /* Set DECL_VINDEX to a value that is neither an - INTEGER_CST nor the error_mark_node so that - add_virtual_function will realize this is an - overridden function. */ - DECL_VINDEX (decl) - = tree_cons (tmp, NULL_TREE, DECL_VINDEX (decl)); - - /* We now know that DECL overrides something, - which is all that is important. But, we must - continue to iterate through all the base-classes - in order to allow get_matching_virtual to check for - various illegal overrides. */ - found_overriden_fn = 1; - } - } - } - if (virtualp) + A specialization of a member function template does not + override a virtual function from a base class. */ + return; + if ((DECL_DESTRUCTOR_P (decl) + || IDENTIFIER_VIRTUAL_P (DECL_NAME (decl))) + && look_for_overrides (ctype, decl) + && !DECL_STATIC_FUNCTION_P (decl)) + { + /* Set DECL_VINDEX to a value that is neither an + INTEGER_CST nor the error_mark_node so that + add_virtual_function will realize this is an + overriding function. */ + DECL_VINDEX (decl) = decl; + } + if (DECL_VIRTUAL_P (decl)) { if (DECL_VINDEX (decl) == NULL_TREE) DECL_VINDEX (decl) = error_mark_node; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index c8cfa255653..5b7eca90ac0 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -514,7 +514,8 @@ struct tree_srcloc #define SET_IDENTIFIER_ERROR_LOCUS(NODE,VALUE) \ SET_LANG_ID(NODE, VALUE, error_locus) - +/* Nonzero if this identifier is used as a virtual function name somewhere + (optimizes searches). */ #define IDENTIFIER_VIRTUAL_P(NODE) TREE_LANG_FLAG_1(NODE) /* Nonzero if this identifier is the prefix for a mangled C++ operator @@ -4250,7 +4251,7 @@ extern tree lookup_field PARAMS ((tree, tree, int, int)); extern int lookup_fnfields_1 PARAMS ((tree, tree)); extern tree lookup_fnfields PARAMS ((tree, tree, int)); extern tree lookup_member PARAMS ((tree, tree, int, int)); -extern tree get_matching_virtual PARAMS ((tree, tree, int)); +extern int look_for_overrides PARAMS ((tree, tree)); extern void get_pure_virtuals PARAMS ((tree)); extern tree init_vbase_pointers PARAMS ((tree, tree)); extern void get_vbase_types PARAMS ((tree)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index b84e847384a..24b24dfbe30 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -9038,12 +9038,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals, return decl; if (virtualp) - { - DECL_VIRTUAL_P (decl) = 1; - if (DECL_VINDEX (decl) == NULL_TREE) - DECL_VINDEX (decl) = error_mark_node; - IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1; - } + DECL_VIRTUAL_P (decl) = 1; return decl; } diff --git a/gcc/cp/search.c b/gcc/cp/search.c index aa48b7d90e2..601f08b0dc1 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -83,7 +83,6 @@ struct vbase_info tree inits; }; -static tree next_baselink PARAMS ((tree)); static tree get_vbase_1 PARAMS ((tree, tree, unsigned int *)); static tree lookup_field_1 PARAMS ((tree, tree)); static int lookup_fnfields_here PARAMS ((tree, tree)); @@ -110,11 +109,9 @@ static tree dfs_push_type_decls PARAMS ((tree, void *)); static tree dfs_push_decls PARAMS ((tree, void *)); static tree dfs_unuse_fields PARAMS ((tree, void *)); static tree add_conversions PARAMS ((tree, void *)); -static tree get_virtuals_named_this PARAMS ((tree, tree)); -static tree get_virtual_destructor PARAMS ((tree, void *)); -static tree tree_has_any_destructor_p PARAMS ((tree, void *)); static int covariant_return_p PARAMS ((tree, tree)); static int check_final_overrider PARAMS ((tree, tree)); +static int look_for_overrides_r PARAMS ((tree, tree)); static struct search_level *push_search_level PARAMS ((struct stack_level *, struct obstack *)); static struct search_level *pop_search_level @@ -124,7 +121,6 @@ static tree bfs_walk void *)); static tree lookup_field_queue_p PARAMS ((tree, void *)); static tree lookup_field_r PARAMS ((tree, void *)); -static tree get_virtuals_named_this_r PARAMS ((tree, void *)); static tree context_for_name_lookup PARAMS ((tree)); static tree canonical_binfo PARAMS ((tree)); static tree shared_marked_p PARAMS ((tree, void *)); @@ -1867,87 +1863,6 @@ dfs_walk (binfo, fn, qfn, data) return dfs_walk_real (binfo, 0, fn, qfn, data); } -struct gvnt_info -{ - /* The name of the function we are looking for. */ - tree name; - /* The overloaded functions we have found. */ - tree fields; -}; - -/* Called from get_virtuals_named_this via bfs_walk. */ - -static tree -get_virtuals_named_this_r (binfo, data) - tree binfo; - void *data; -{ - struct gvnt_info *gvnti = (struct gvnt_info *) data; - tree type = BINFO_TYPE (binfo); - int idx; - - idx = lookup_fnfields_here (BINFO_TYPE (binfo), gvnti->name); - if (idx >= 0) - gvnti->fields - = tree_cons (binfo, - TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx), - gvnti->fields); - - return NULL_TREE; -} - -/* Return the virtual functions with the indicated NAME in the type - indicated by BINFO. The result is a TREE_LIST whose TREE_PURPOSE - indicates the base class from which the TREE_VALUE (an OVERLOAD or - just a FUNCTION_DECL) originated. */ - -static tree -get_virtuals_named_this (binfo, name) - tree binfo; - tree name; -{ - struct gvnt_info gvnti; - tree fields; - - gvnti.name = name; - gvnti.fields = NULL_TREE; - - bfs_walk (binfo, get_virtuals_named_this_r, 0, &gvnti); - - /* Get to the function decls, and return the first virtual function - with this name, if there is one. */ - for (fields = gvnti.fields; fields; fields = next_baselink (fields)) - { - tree fndecl; - - for (fndecl = TREE_VALUE (fields); fndecl; fndecl = OVL_NEXT (fndecl)) - if (DECL_VINDEX (OVL_CURRENT (fndecl))) - return fields; - } - return NULL_TREE; -} - -static tree -get_virtual_destructor (binfo, data) - tree binfo; - void *data ATTRIBUTE_UNUSED; -{ - tree type = BINFO_TYPE (binfo); - if (TYPE_HAS_DESTRUCTOR (type) - && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 1))) - return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 1); - return 0; -} - -static tree -tree_has_any_destructor_p (binfo, data) - tree binfo; - void *data ATTRIBUTE_UNUSED; -{ - tree type = BINFO_TYPE (binfo); - return TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type) ? binfo : NULL_TREE; -} - /* Returns > 0 if a function with type DRETTYPE overriding a function with type BRETTYPE is covariant, as defined in [class.virtual]. @@ -2026,124 +1941,128 @@ check_final_overrider (overrider, basefn) if (pedantic && i == -1) { - cp_pedwarn_at ("invalid covariant return type for `virtual %#D'", overrider); - cp_pedwarn_at (" overriding `virtual %#D' (must be pointer or reference to class)", basefn); + cp_pedwarn_at ("invalid covariant return type for `%#D'", overrider); + cp_pedwarn_at (" overriding `%#D' (must be pointer or reference to class)", basefn); } } else if (IS_AGGR_TYPE_2 (base_return, over_return) && same_or_base_type_p (base_return, over_return)) { - cp_error_at ("invalid covariant return type for `virtual %#D'", overrider); - cp_error_at (" overriding `virtual %#D' (must use pointer or reference)", basefn); + cp_error_at ("invalid covariant return type for `%#D'", overrider); + cp_error_at (" overriding `%#D' (must use pointer or reference)", basefn); return 0; } else if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider)) == NULL_TREE) { - cp_error_at ("conflicting return type specified for `virtual %#D'", overrider); - cp_error_at (" overriding `virtual %#D'", basefn); + cp_error_at ("conflicting return type specified for `%#D'", overrider); + cp_error_at (" overriding `%#D'", basefn); SET_IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider), DECL_CONTEXT (overrider)); return 0; } /* Check throw specifier is subset. */ - /* XXX At the moment, punt on an overriding artificial function. We - don't generate its exception specifier, so can't check it properly. */ + /* XXX At the moment, punt with artificial functions. We + don't generate their exception specifiers, so can't check properly. */ if (! DECL_ARTIFICIAL (overrider) && !comp_except_specs (base_throw, over_throw, 0)) { - cp_error_at ("looser throw specifier for `virtual %#F'", overrider); - cp_error_at (" overriding `virtual %#F'", basefn); + cp_error_at ("looser throw specifier for `%#F'", overrider); + cp_error_at (" overriding `%#F'", basefn); return 0; } return 1; } -/* Given a class type TYPE, and a function decl FNDECL, look for a - virtual function in TYPE's hierarchy which FNDECL could match as a - virtual function. It doesn't matter which one we find. - - DTORP is nonzero if we are looking for a destructor. Destructors - need special treatment because they do not match by name. */ +/* Given a class TYPE, and a function decl FNDECL, look for + virtual functions in TYPE's hierarchy which FNDECL overrides. + We do not look in TYPE itself, only its bases. + + Returns non-zero, if we find any. Set FNDECL's DECL_VIRTUAL_P, if we + find that it overrides anything. + + We check that every function which is overridden, is correctly + overridden. */ -tree -get_matching_virtual (binfo, fndecl, dtorp) - tree binfo, fndecl; - int dtorp; +int +look_for_overrides (type, fndecl) + tree type, fndecl; { - tree tmp = NULL_TREE; + tree binfo = TYPE_BINFO (type); + tree basebinfos = BINFO_BASETYPES (binfo); + int nbasebinfos = basebinfos ? TREE_VEC_LENGTH (basebinfos) : 0; + int ix; + int found = 0; - if (TREE_CODE (fndecl) == TEMPLATE_DECL) - /* In [temp.mem] we have: + for (ix = 0; ix != nbasebinfos; ix++) + { + tree basetype = BINFO_TYPE (TREE_VEC_ELT (basebinfos, ix)); + + if (TYPE_POLYMORPHIC_P (basetype)) + found += look_for_overrides_r (basetype, fndecl); + } + return found; +} - A specialization of a member function template does not - override a virtual function from a base class. */ - return NULL_TREE; +/* Look in TYPE for virtual functions overridden by FNDECL. Check both + TYPE itself and its bases. */ - /* Breadth first search routines start searching basetypes - of TYPE, so we must perform first ply of search here. */ - if (dtorp) - return bfs_walk (binfo, get_virtual_destructor, - tree_has_any_destructor_p, 0); +static int +look_for_overrides_r (type, fndecl) + tree type, fndecl; +{ + int ix; + + if (DECL_DESTRUCTOR_P (fndecl)) + ix = CLASSTYPE_DESTRUCTOR_SLOT; else + ix = lookup_fnfields_here (type, DECL_NAME (fndecl)); + if (ix >= 0) { - tree drettype, dtypes, btypes, instptr_type; - tree baselink, best = NULL_TREE; - tree declarator = DECL_NAME (fndecl); - if (IDENTIFIER_VIRTUAL_P (declarator) == 0) - return NULL_TREE; - - baselink = get_virtuals_named_this (binfo, declarator); - if (baselink == NULL_TREE) - return NULL_TREE; - - drettype = TREE_TYPE (TREE_TYPE (fndecl)); - dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); - if (DECL_STATIC_FUNCTION_P (fndecl)) - instptr_type = NULL_TREE; - else - instptr_type = TREE_TYPE (TREE_VALUE (dtypes)); - - for (; baselink; baselink = next_baselink (baselink)) - { - tree tmps; - for (tmps = TREE_VALUE (baselink); tmps; tmps = OVL_NEXT (tmps)) + tree fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), ix); + tree dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); + tree thistype = DECL_STATIC_FUNCTION_P (fndecl) + ? NULL_TREE : TREE_TYPE (TREE_VALUE (dtypes)); + + for (; fns; fns = OVL_NEXT (fns)) + { + tree fn = OVL_CURRENT (fns); + tree btypes = TYPE_ARG_TYPES (TREE_TYPE (fn)); + + if (!DECL_VIRTUAL_P (fn)) + ; + else if (thistype == NULL_TREE) { - tmp = OVL_CURRENT (tmps); - if (! DECL_VINDEX (tmp)) - continue; - - btypes = TYPE_ARG_TYPES (TREE_TYPE (tmp)); - if (instptr_type == NULL_TREE) - { - if (compparms (TREE_CHAIN (btypes), dtypes)) - /* Caller knows to give error in this case. */ - return tmp; - return NULL_TREE; - } - - if (/* The first parameter is the `this' parameter, - which has POINTER_TYPE, and we can therefore - safely use TYPE_QUALS, rather than + if (compparms (TREE_CHAIN (btypes), dtypes)) + { + /* A static member function cannot match an inherited + virtual member function. */ + cp_error_at ("`%#D' cannot be declared", fndecl); + cp_error_at (" since `%#D' declared in base class", fn); + return 1; + } + } + else + { + if (/* The first parameter is the `this' parameter, + which has POINTER_TYPE, and we can therefore + safely use TYPE_QUALS, rather than CP_TYPE_QUALS. */ - (TYPE_QUALS (TREE_TYPE (TREE_VALUE (btypes))) - == TYPE_QUALS (instptr_type)) - && compparms (TREE_CHAIN (btypes), TREE_CHAIN (dtypes))) - { - check_final_overrider (fndecl, tmp); - - /* FNDECL overrides this function. We continue to - check all the other functions in order to catch - errors; it might be that in some other baseclass - a virtual function was declared with the same - parameter types, but a different return type. */ - best = tmp; - } + (TYPE_QUALS (TREE_TYPE (TREE_VALUE (btypes))) + == TYPE_QUALS (thistype)) + && compparms (TREE_CHAIN (btypes), TREE_CHAIN (dtypes))) + { + /* It's definitely virtual, even if not explicitly set. */ + DECL_VIRTUAL_P (fndecl) = 1; + check_final_overrider (fndecl, fn); + + return 1; + } } } - - return best; } + /* We failed to find one declared in this class. Look in its bases. */ + return look_for_overrides (type, fndecl); } /* A queue function for dfs_walk that skips any nonprimary virtual @@ -2320,23 +2239,6 @@ get_pure_virtuals (type) } } } - -static tree -next_baselink (baselink) - tree baselink; -{ - tree tmp = TREE_TYPE (baselink); - baselink = TREE_CHAIN (baselink); - while (tmp) - { - /* @@ does not yet add previous base types. */ - baselink = tree_cons (TREE_PURPOSE (tmp), TREE_VALUE (tmp), - baselink); - TREE_TYPE (baselink) = TREE_TYPE (tmp); - tmp = TREE_CHAIN (tmp); - } - return baselink; -} /* DEPTH-FIRST SEARCH ROUTINES. */ |