Commit 78b45a24 by Mark Mitchell Committed by Mark Mitchell

class.c (find_final_overrider_data): Add `candidates'.

	* class.c (find_final_overrider_data): Add `candidates'.
	(dfs_find_final_overrider): Don't issue error messages
	prematurely.
	(find_final_overrider): Issue error messages here.
	(build_base_field): Don't warn about amgibuous direct bases here.
	(warn_about_ambiguous_direct_bases): New function.
	(layout_class_type): Use it.

From-SVN: r41224
parent 0450d74d
2001-04-10 Mark Mitchell <mark@codesourcery.com>
* class.c (find_final_overrider_data): Add `candidates'.
(dfs_find_final_overrider): Don't issue error messages
prematurely.
(find_final_overrider): Issue error messages here.
(build_base_field): Don't warn about amgibuous direct bases here.
(warn_about_ambiguous_direct_bases): New function.
(layout_class_type): Use it.
2001-04-10 Richard Henderson <rth@redhat.com> 2001-04-10 Richard Henderson <rth@redhat.com>
* typeck.c (build_array_ref): Push the array reference inside * typeck.c (build_array_ref): Push the array reference inside
......
...@@ -212,7 +212,7 @@ static void record_subobject_offsets PARAMS ((tree, tree, splay_tree, int)); ...@@ -212,7 +212,7 @@ static void record_subobject_offsets PARAMS ((tree, tree, splay_tree, int));
static int layout_conflict_p PARAMS ((tree, tree, splay_tree, int)); static int layout_conflict_p PARAMS ((tree, tree, splay_tree, int));
static int splay_tree_compare_integer_csts PARAMS ((splay_tree_key k1, static int splay_tree_compare_integer_csts PARAMS ((splay_tree_key k1,
splay_tree_key k2)); splay_tree_key k2));
static void warn_about_ambiguous_direct_bases PARAMS ((tree));
/* Macros for dfs walking during vtt construction. See /* Macros for dfs walking during vtt construction. See
dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits
...@@ -2495,6 +2495,9 @@ typedef struct find_final_overrider_data_s { ...@@ -2495,6 +2495,9 @@ typedef struct find_final_overrider_data_s {
tree most_derived_type; tree most_derived_type;
/* The final overriding function. */ /* The final overriding function. */
tree overriding_fn; tree overriding_fn;
/* The functions that we thought might be final overriders, but
aren't. */
tree candidates;
/* The BINFO for the class in which the final overriding function /* The BINFO for the class in which the final overriding function
appears. */ appears. */
tree overriding_base; tree overriding_base;
...@@ -2553,49 +2556,79 @@ dfs_find_final_overrider (binfo, data) ...@@ -2553,49 +2556,79 @@ dfs_find_final_overrider (binfo, data)
break; break;
} }
if (ffod->overriding_fn && ffod->overriding_fn != method) /* 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)
{ {
/* We've found a different overrider along a different ffod->overriding_fn = method;
path. That can be OK if the new one overrides the ffod->overriding_base = TREE_VALUE (path);
old one. Consider:
struct S { virtual void f(); };
struct T : public virtual S { virtual void f(); };
struct U : public virtual S, public virtual T {};
Here `T::f' is the final overrider for `S::f'. */
if (strictly_overrides (method, ffod->overriding_fn))
{
ffod->overriding_fn = method;
ffod->overriding_base = TREE_VALUE (path);
}
else if (!strictly_overrides (ffod->overriding_fn, method))
{
cp_error ("no unique final overrider for `%D' in `%T'",
ffod->most_derived_type,
ffod->fn);
cp_error ("candidates are: `%#D'", ffod->overriding_fn);
cp_error (" `%#D'", method);
return error_mark_node;
}
} }
else if (ffod->overriding_base /* If we found the same overrider we already have, then
&& (!tree_int_cst_equal we just need to check that we're finding it in the same
(BINFO_OFFSET (TREE_VALUE (path)), place. */
BINFO_OFFSET (ffod->overriding_base)))) else if (ffod->overriding_fn == method)
{ {
/* We've found two instances of the same base that if (ffod->overriding_base
provide overriders. */ && (!tree_int_cst_equal
cp_error ("no unique final overrider for `%D' since there two instances of `%T' in `%T'", (BINFO_OFFSET (TREE_VALUE (path)),
ffod->fn, BINFO_OFFSET (ffod->overriding_base))))
BINFO_TYPE (ffod->overriding_base), {
ffod->most_derived_type); ffod->candidates
return error_mark_node; = build_tree_list (NULL_TREE,
ffod->overriding_fn);
ffod->overriding_fn = NULL_TREE;
ffod->overriding_base = NULL_TREE;
}
} }
/* If there was already an overrider, and it overrides this
function, then the old overrider is still the best
candidate. */
else if (ffod->overriding_fn
&& strictly_overrides (ffod->overriding_fn,
method))
;
else else
{ {
ffod->overriding_fn = method; tree candidates;
ffod->overriding_base = TREE_VALUE (path); 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);
} }
} }
} }
...@@ -2639,12 +2672,16 @@ find_final_overrider (t, binfo, fn) ...@@ -2639,12 +2672,16 @@ find_final_overrider (t, binfo, fn)
ffod.most_derived_type = t; ffod.most_derived_type = t;
ffod.overriding_fn = NULL_TREE; ffod.overriding_fn = NULL_TREE;
ffod.overriding_base = NULL_TREE; ffod.overriding_base = NULL_TREE;
ffod.candidates = NULL_TREE;
dfs_walk (TYPE_BINFO (t),
dfs_find_final_overrider,
NULL,
&ffod);
if (dfs_walk (TYPE_BINFO (t), /* If there was no winner, issue an error message. */
dfs_find_final_overrider, if (!ffod.overriding_fn)
NULL, cp_error ("no unique final overrider for `%D' in `%T'", fn, t);
&ffod))
return error_mark_node;
return build_tree_list (ffod.overriding_fn, ffod.overriding_base); return build_tree_list (ffod.overriding_fn, ffod.overriding_base);
} }
...@@ -4041,13 +4078,6 @@ build_base_field (rli, binfo, empty_p, offsets) ...@@ -4041,13 +4078,6 @@ build_base_field (rli, binfo, empty_p, offsets)
layout_empty_base (binfo, size_int (eoc), offsets); layout_empty_base (binfo, size_int (eoc), offsets);
} }
/* Check for inaccessible base classes. If the same base class
appears more than once in the hierarchy, but isn't virtual, then
it's ambiguous. */
if (get_base_distance (basetype, rli->t, 0, NULL) == -2)
cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
basetype, rli->t);
/* Record the offsets of BINFO and its base subobjects. */ /* Record the offsets of BINFO and its base subobjects. */
record_subobject_offsets (BINFO_TYPE (binfo), record_subobject_offsets (BINFO_TYPE (binfo),
BINFO_OFFSET (binfo), BINFO_OFFSET (binfo),
...@@ -4830,6 +4860,32 @@ end_of_class (t, include_virtuals_p) ...@@ -4830,6 +4860,32 @@ end_of_class (t, include_virtuals_p)
return result; return result;
} }
/* Warn about direct bases of T that are inaccessible because they are
ambiguous. For example:
struct S {};
struct T : public S {};
struct U : public S, public T {};
Here, `(S*) new U' is not allowed because there are two `S'
subobjects of U. */
static void
warn_about_ambiguous_direct_bases (t)
tree t;
{
int i;
for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
{
tree basetype = TYPE_BINFO_BASETYPE (t, i);
if (get_base_distance (basetype, t, 0, NULL) == -2)
cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
basetype, t);
}
}
/* Compare two INTEGER_CSTs K1 and K2. */ /* Compare two INTEGER_CSTs K1 and K2. */
static int static int
...@@ -5035,6 +5091,10 @@ layout_class_type (t, empty_p, vfuns_p, ...@@ -5035,6 +5091,10 @@ layout_class_type (t, empty_p, vfuns_p,
base subobject fields. */ base subobject fields. */
layout_virtual_bases (t, empty_base_offsets); layout_virtual_bases (t, empty_base_offsets);
/* Warn about direct bases that can't be talked about due to
ambiguity. */
warn_about_ambiguous_direct_bases (t);
/* Clean up. */ /* Clean up. */
splay_tree_delete (empty_base_offsets); splay_tree_delete (empty_base_offsets);
} }
......
// Build don't link:
// Origin: Frank Pilhofer <fp@fpx.de>
struct A {
virtual void f ();
};
struct B : virtual public A {
void f ();
};
struct C : virtual public A {
void f ();
};
struct D : virtual public B, virtual public C {
void f ();
};
struct Di : virtual public B, virtual public C, virtual public D {};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment