aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2002-10-18 09:21:06 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2002-10-18 09:21:06 +0000
commit9368208b083671159eaf9cdd55dd10aeb221ae88 (patch)
treec4f47126f106010ed5a2c2829b560d5739b22f0b
parent5275f2bf280fa76d637b1a6f4bfd522a6de2d507 (diff)
downloadgcc-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/ChangeLog9
-rw-r--r--gcc/cp/class.c154
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/g++.dg/inherit/override1.C18
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 {};