aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/search.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/search.c')
-rw-r--r--gcc/cp/search.c89
1 files changed, 59 insertions, 30 deletions
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 3af71f1..14e1ce9 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -117,6 +117,7 @@ static tree get_virtuals_named_this PROTO((tree, tree));
static tree get_virtual_destructor PROTO((tree, void *));
static tree tree_has_any_destructor_p PROTO((tree, void *));
static int covariant_return_p PROTO((tree, tree));
+static int check_final_overrider PROTO((tree, tree));
static struct search_level *push_search_level
PROTO((struct stack_level *, struct obstack *));
static struct search_level *pop_search_level
@@ -1884,6 +1885,63 @@ covariant_return_p (brettype, drettype)
return 1;
}
+/* Check that virtual overrider OVERRIDER is acceptable for base function
+ BASEFN. Issue diagnostic, and return zero, if unacceptable. */
+
+int
+check_final_overrider (overrider, basefn)
+ tree overrider, basefn;
+{
+ tree over_type = TREE_TYPE (overrider);
+ tree base_type = TREE_TYPE (basefn);
+ tree over_return = TREE_TYPE (over_type);
+ tree base_return = TREE_TYPE (base_type);
+ tree over_throw = TYPE_RAISES_EXCEPTIONS (over_type);
+ tree base_throw = TYPE_RAISES_EXCEPTIONS (base_type);
+ int i;
+
+ if (same_type_p (base_return, over_return))
+ /* OK */;
+ else if ((i = covariant_return_p (base_return, over_return)))
+ {
+ if (i == 2)
+ sorry ("adjusting pointers for covariant returns");
+
+ 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);
+ }
+ }
+ 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);
+ 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);
+ SET_IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider),
+ DECL_CLASS_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. */
+ 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);
+ 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.
@@ -1897,7 +1955,6 @@ get_matching_virtual (binfo, fndecl, dtorp)
int dtorp;
{
tree tmp = NULL_TREE;
- int i;
if (TREE_CODE (fndecl) == TEMPLATE_DECL)
/* In [temp.mem] we have:
@@ -1914,9 +1971,7 @@ get_matching_virtual (binfo, fndecl, dtorp)
else
{
tree drettype, dtypes, btypes, instptr_type;
- tree basetype = DECL_CLASS_CONTEXT (fndecl);
tree baselink, best = NULL_TREE;
- tree name = DECL_ASSEMBLER_NAME (fndecl);
tree declarator = DECL_NAME (fndecl);
if (IDENTIFIER_VIRTUAL_P (declarator) == 0)
return NULL_TREE;
@@ -1958,33 +2013,7 @@ get_matching_virtual (binfo, fndecl, dtorp)
== TYPE_QUALS (instptr_type))
&& compparms (TREE_CHAIN (btypes), TREE_CHAIN (dtypes)))
{
- tree brettype = TREE_TYPE (TREE_TYPE (tmp));
- if (same_type_p (brettype, drettype))
- /* OK */;
- else if ((i = covariant_return_p (brettype, drettype)))
- {
- if (i == 2)
- sorry ("adjusting pointers for covariant returns");
-
- if (pedantic && i == -1)
- {
- cp_pedwarn_at ("invalid covariant return type for `%#D' (must be pointer or reference to class)", fndecl);
- cp_pedwarn_at (" overriding `%#D'", tmp);
- }
- }
- else if (IS_AGGR_TYPE_2 (brettype, drettype)
- && same_or_base_type_p (brettype, drettype))
- {
- error ("invalid covariant return type (must use pointer or reference)");
- cp_error_at (" overriding `%#D'", tmp);
- cp_error_at (" with `%#D'", fndecl);
- }
- else if (IDENTIFIER_ERROR_LOCUS (name) == NULL_TREE)
- {
- cp_error_at ("conflicting return type specified for virtual function `%#D'", fndecl);
- cp_error_at (" overriding definition as `%#D'", tmp);
- SET_IDENTIFIER_ERROR_LOCUS (name, basetype);
- }
+ check_final_overrider (fndecl, tmp);
/* FNDECL overrides this function. We continue to
check all the other functions in order to catch