summaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>2000-12-05 15:50:06 +0000
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>2000-12-05 15:50:06 +0000
commit4c481f71f8775801d6269420d5e979ef6f4839c5 (patch)
treeaf97c282c8bf12e05febc3bd5655a95d3b143a54 /gcc/cp
parent1bbb5947018b45db17d79d27e3f6e63980f95cc9 (diff)
downloadgcc-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/ChangeLog20
-rw-r--r--gcc/cp/class.c66
-rw-r--r--gcc/cp/cp-tree.h5
-rw-r--r--gcc/cp/decl.c7
-rw-r--r--gcc/cp/search.c274
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. */