From 8d1f0f67e87a1f925ea281d1ad3aacb45e54300b Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 25 Apr 2002 14:04:50 -0400 Subject: [PATCH] re PR c++/5607 (No pointer adjustment in covariant return types) PR c++/5607 * search.c (check_final_overrider): No longer static. * class.c (update_vtable_entry_for_fn): Call it. * cp-tree.h: Adjust. From-SVN: r52760 --- gcc/cp/ChangeLog | 7 ++++ gcc/cp/class.c | 4 +++ gcc/cp/cp-tree.h | 1 + gcc/cp/search.c | 3 +- gcc/testsuite/g++.dg/inherit/covariant1.C | 39 +++++++++++++++++++++++ 5 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/inherit/covariant1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ee39ddc5442..22d45277ea3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2002-04-25 Jason Merrill + + PR c++/5607 + * search.c (check_final_overrider): No longer static. + * class.c (update_vtable_entry_for_fn): Call it. + * cp-tree.h: Adjust. + 2002-04-25 Neil Booth * cp-lang.c (LANG_HOOKS_SET_YYDEBUG): Remove. diff --git a/gcc/cp/class.c b/gcc/cp/class.c index c8627fb36fd..92f43298bdb 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -2555,6 +2555,10 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) if (overrider == error_mark_node) return; + /* Check for unsupported covariant returns again now that we've + calculated the base offsets. */ + check_final_overrider (TREE_PURPOSE (overrider), fn); + /* Assume that we will produce a thunk that convert all the way to the final overrider, and not to an intermediate virtual base. */ virtual_base = NULL_TREE; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 43b17c88cb3..8be1e6f4e05 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4098,6 +4098,7 @@ extern tree lookup_conversions PARAMS ((tree)); extern tree binfo_for_vtable PARAMS ((tree)); extern tree binfo_from_vbase PARAMS ((tree)); extern tree look_for_overrides_here PARAMS ((tree, tree)); +extern int check_final_overrider PARAMS ((tree, tree)); extern tree dfs_walk PARAMS ((tree, tree (*) (tree, void *), tree (*) (tree, void *), diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 779b37a6e33..38841589dfd 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -100,7 +100,6 @@ static tree dfs_push_decls PARAMS ((tree, void *)); static tree dfs_unuse_fields PARAMS ((tree, void *)); static tree add_conversions 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 *)); @@ -1798,7 +1797,7 @@ covariant_return_p (brettype, drettype) /* Check that virtual overrider OVERRIDER is acceptable for base function BASEFN. Issue diagnostic, and return zero, if unacceptable. */ -static int +int check_final_overrider (overrider, basefn) tree overrider, basefn; { diff --git a/gcc/testsuite/g++.dg/inherit/covariant1.C b/gcc/testsuite/g++.dg/inherit/covariant1.C new file mode 100644 index 00000000000..516047e95e3 --- /dev/null +++ b/gcc/testsuite/g++.dg/inherit/covariant1.C @@ -0,0 +1,39 @@ +// PR c++/5607 + +// Currently we don't support covariant returns that would actually require +// a pointer adjustment. We were failing to recognize this as such a case, +// so were silently generating bad code. When we do support covariant +// returns properly, the expected error should go away, and the testcase +// should pass execution. + +// { NOT YET dg-do run } + +class A { +public: + virtual A* getThis() { return this; } +}; + +class B { +int a; +public: + virtual B* getThis() { return this; } +}; + +class AB : public A, public B { // { dg-error "covariant" } +public: + virtual AB* getThis() { return this; } +}; + +int main () +{ + AB* ab = new AB(); + + A* a = ab; + B* b = ab; + + if (a->getThis() != a + || b->getThis() != b) + return 1; + + return 0; +} -- 2.30.2