diff options
author | Mark Mitchell <mark@codesourcery.com> | 2002-10-18 09:21:06 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2002-10-18 09:21:06 +0000 |
commit | 9368208b083671159eaf9cdd55dd10aeb221ae88 (patch) | |
tree | c4f47126f106010ed5a2c2829b560d5739b22f0b | |
parent | 5275f2bf280fa76d637b1a6f4bfd522a6de2d507 (diff) | |
download | gcc-9368208b083671159eaf9cdd55dd10aeb221ae88.zip gcc-9368208b083671159eaf9cdd55dd10aeb221ae88.tar.gz gcc-9368208b083671159eaf9cdd55dd10aeb221ae88.tar.bz2 |
class.c (find_final_overrider_data_s): Remove overriding_fn and overriding_base.
* class.c (find_final_overrider_data_s): Remove overriding_fn and
overriding_base.
(dfs_base_derived_from): New function.
(base_derived_from): Likewise.
(dfs_find_final_overrider): Use base_derived_from.
(find_final_overrider): Adjust.
* g++.dg/inherit/override1.C: New test.
From-SVN: r58283
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/class.c | 154 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/inherit/override1.C | 18 |
4 files changed, 82 insertions, 107 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index bdceab0..ced9a04 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2002-10-18 Mark Mitchell <mark@codesourcery.com> + + * class.c (find_final_overrider_data_s): Remove overriding_fn and + overriding_base. + (dfs_base_derived_from): New function. + (base_derived_from): Likewise. + (dfs_find_final_overrider): Use base_derived_from. + (find_final_overrider): Adjust. + 2002-10-18 Jason Merrill <jason@redhat.com> PR c++/8080 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 7c66098..0434337 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -208,6 +208,8 @@ static int splay_tree_compare_integer_csts PARAMS ((splay_tree_key k1, static void warn_about_ambiguous_bases PARAMS ((tree)); static bool type_requires_array_cookie PARAMS ((tree)); static bool contains_empty_class_p (tree); +static tree dfs_base_derived_from (tree, void *); +static bool base_derived_from (tree, tree); /* Macros for dfs walking during vtt construction. See dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits @@ -2204,6 +2206,29 @@ same_signature_p (fndecl, base_fndecl) return 0; } +/* Called from base_derived_from via dfs_walk. */ + +static tree +dfs_base_derived_from (tree binfo, void *data) +{ + tree base = (tree) data; + + if (same_type_p (TREE_TYPE (base), TREE_TYPE (binfo)) + && tree_int_cst_equal (BINFO_OFFSET (base), BINFO_OFFSET (binfo))) + return error_mark_node; + + return NULL_TREE; +} + +/* Returns TRUE if DERIVED is a binfo containing the binfo BASE as a + subobject. */ + +static bool +base_derived_from (tree derived, tree base) +{ + return dfs_walk (derived, dfs_base_derived_from, NULL, base); +} + typedef struct find_final_overrider_data_s { /* The function for which we are trying to find a final overrider. */ tree fn; @@ -2211,14 +2236,8 @@ typedef struct find_final_overrider_data_s { tree declaring_base; /* The most derived class in the hierarchy. */ tree most_derived_type; - /* The final overriding function. */ - tree overriding_fn; - /* The functions that we thought might be final overriders, but - aren't. */ + /* The candidate overriders. */ tree candidates; - /* The BINFO for the class in which the final overriding function - appears. */ - tree overriding_base; } find_final_overrider_data; /* Called from find_final_overrider via dfs_walk. */ @@ -2243,118 +2262,41 @@ dfs_find_final_overrider (binfo, data) /* We've found a path to the declaring base. Walk down the path looking for an overrider for FN. */ for (path = reverse_path (binfo); - path; + path; path = TREE_CHAIN (path)) { method = look_for_overrides_here (BINFO_TYPE (TREE_VALUE (path)), ffod->fn); if (method) - break; + { + path = TREE_VALUE (path); + break; + } } /* If we found an overrider, record the overriding function, and the base from which it came. */ if (path) { - tree base; - - /* Assume the path is non-virtual. See if there are any - virtual bases from (but not including) the overrider up - to and including the base where the function is - defined. */ - for (base = TREE_CHAIN (path); base; base = TREE_CHAIN (base)) - if (TREE_VIA_VIRTUAL (TREE_VALUE (base))) - { - base = ffod->declaring_base; - break; - } + tree *candidate; - /* If we didn't already have an overrider, or any - candidates, then this function is the best candidate so - far. */ - if (!ffod->overriding_fn && !ffod->candidates) + /* Remove any candidates overridden by this new function. */ + candidate = &ffod->candidates; + while (*candidate) { - ffod->overriding_fn = method; - ffod->overriding_base = TREE_VALUE (path); - } - else if (ffod->overriding_fn) - { - /* We had a best overrider; let's see how this compares. */ - - if (ffod->overriding_fn == method - && (tree_int_cst_equal - (BINFO_OFFSET (TREE_VALUE (path)), - BINFO_OFFSET (ffod->overriding_base)))) - /* We found the same overrider we already have, and in the - same place; it's still the best. */; - else if (strictly_overrides (ffod->overriding_fn, method)) - /* The old function overrides this function; it's still the - best. */; - else if (strictly_overrides (method, ffod->overriding_fn)) - { - /* The new function overrides the old; it's now the - best. */ - ffod->overriding_fn = method; - ffod->overriding_base = TREE_VALUE (path); - } + /* If *CANDIDATE overrides METHOD, then METHOD + cannot override anything else on the list. */ + if (base_derived_from (TREE_VALUE (*candidate), path)) + return NULL_TREE; + /* If METHOD overrides *CANDIDATE, remove *CANDIDATE. */ + if (base_derived_from (path, TREE_VALUE (*candidate))) + *candidate = TREE_CHAIN (*candidate); else - { - /* Ambiguous. */ - ffod->candidates - = build_tree_list (NULL_TREE, - ffod->overriding_fn); - if (method != ffod->overriding_fn) - ffod->candidates - = tree_cons (NULL_TREE, method, ffod->candidates); - ffod->overriding_fn = NULL_TREE; - ffod->overriding_base = NULL_TREE; - } + candidate = &TREE_CHAIN (*candidate); } - else - { - /* We had a list of ambiguous overrides; let's see how this - new one compares. */ - - tree candidates; - bool incomparable = false; - - /* If there were previous candidates, and this function - overrides all of them, then it is the new best - candidate. */ - for (candidates = ffod->candidates; - candidates; - candidates = TREE_CHAIN (candidates)) - { - /* If the candidate overrides the METHOD, then we - needn't worry about it any further. */ - if (strictly_overrides (TREE_VALUE (candidates), - method)) - { - method = NULL_TREE; - break; - } - - /* If the METHOD doesn't override the candidate, - then it is incomporable. */ - if (!strictly_overrides (method, - TREE_VALUE (candidates))) - incomparable = true; - } - /* If METHOD overrode all the candidates, then it is the - new best candidate. */ - if (!candidates && !incomparable) - { - ffod->overriding_fn = method; - ffod->overriding_base = TREE_VALUE (path); - ffod->candidates = NULL_TREE; - } - /* If METHOD didn't override all the candidates, then it - is another candidate. */ - else if (method && incomparable) - ffod->candidates - = tree_cons (NULL_TREE, method, ffod->candidates); - } + /* Add the new function. */ + ffod->candidates = tree_cons (method, path, ffod->candidates); } } @@ -2395,8 +2337,6 @@ find_final_overrider (t, binfo, fn) ffod.fn = fn; ffod.declaring_base = binfo; ffod.most_derived_type = t; - ffod.overriding_fn = NULL_TREE; - ffod.overriding_base = NULL_TREE; ffod.candidates = NULL_TREE; dfs_walk (TYPE_BINFO (t), @@ -2405,13 +2345,13 @@ find_final_overrider (t, binfo, fn) &ffod); /* If there was no winner, issue an error message. */ - if (!ffod.overriding_fn) + if (!ffod.candidates || TREE_CHAIN (ffod.candidates)) { error ("no unique final overrider for `%D' in `%T'", fn, t); return error_mark_node; } - return build_tree_list (ffod.overriding_fn, ffod.overriding_base); + return ffod.candidates; } /* Returns the function from the BINFO_VIRTUALS entry in T which matches diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 20fda9f..9c16af2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2002-10-18 Mark Mitchell <mark@codesourcery.com> + + * g++.dg/inherit/override1.C: New test. + + * g++.dg/abi/mangle11.C: New test. + * g++.dg/abi/mangle14.C: New test. + * g++.dg/abi/mangle17.C: New test. + 2002-10-17 Nathan Sidwell <nathan@codesourcery.com> * g++.dg/overload/member2.C: New test. diff --git a/gcc/testsuite/g++.dg/inherit/override1.C b/gcc/testsuite/g++.dg/inherit/override1.C new file mode 100644 index 0000000..04460ed --- /dev/null +++ b/gcc/testsuite/g++.dg/inherit/override1.C @@ -0,0 +1,18 @@ +struct c0 { virtual void f (); }; +struct c1 : public c0 {}; +struct c2 : public c0 {}; +struct c3 : virtual public c0, public c1, public c2 {}; +struct c5 {}; +struct c7 : virtual public c3 {}; +struct c8 : virtual public c1 { virtual void f (); }; +struct c9 {}; +struct c10 : virtual public c8, virtual public c7 {}; +struct c11 : virtual public c5 {}; +struct c12 : virtual public c8, public c7 {}; +struct c13 : public c9, public c3, virtual public c2 {}; +struct c14 : virtual public c1, virtual public c5, virtual public c0, + public c2 {}; +struct c15 : public c14, public c12, virtual public c3 {}; +struct c16 : public c12, public c10, public c2 { virtual void f (); }; +struct c17 : virtual public c13, public c15, virtual public c0, + virtual public c16 {}; |