aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2003-08-11 02:49:44 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2003-08-11 02:49:44 +0000
commitd9148cf498826028803b6e00a2ca60ac83113cfb (patch)
tree435bbfbc71784aee4588349e3b26519977005e65 /gcc
parent5a05675643f4695565a48f52a298a670974dc354 (diff)
downloadgcc-d9148cf498826028803b6e00a2ca60ac83113cfb.zip
gcc-d9148cf498826028803b6e00a2ca60ac83113cfb.tar.gz
gcc-d9148cf498826028803b6e00a2ca60ac83113cfb.tar.bz2
re PR c++/11789 (rejects legal, multiple inheritance (inheriting from same class twice))
PR c++/11789 * cp-tree.h (get_vbase): Remove. (get_vbase_types): Remove. * init.c (expand_member_init): Correct logic for looking up base classes. PR c++/11789.C * g++.dg/inherit/multiple1.C: New test. From-SVN: r70316
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/init.c49
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/inherit/multiple1.C20
5 files changed, 75 insertions, 9 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index fde090e..191879fe 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+2003-08-10 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/11789
+ * cp-tree.h (get_vbase): Remove.
+ (get_vbase_types): Remove.
+ * init.c (expand_member_init): Correct logic for looking up base
+ classes.
+
2003-08-10 Gabriel Dos Reis <gdr@integrable-solutions.net>
* error.c (dump_expr): Tidy.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d47c307..a740142 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4018,7 +4018,6 @@ extern bool emit_tinfo_decl (tree);
extern bool accessible_base_p (tree, tree);
extern tree lookup_base (tree, tree, base_access, base_kind *);
extern int types_overlap_p (tree, tree);
-extern tree get_vbase (tree, tree);
extern tree get_dynamic_cast_base_type (tree, tree);
extern int accessible_p (tree, tree);
extern tree lookup_field_1 (tree, tree, bool);
@@ -4028,7 +4027,6 @@ extern tree lookup_fnfields (tree, tree, int);
extern tree lookup_member (tree, tree, int, bool);
extern int look_for_overrides (tree, tree);
extern void get_pure_virtuals (tree);
-extern void get_vbase_types (tree);
extern void maybe_suppress_debug_info (tree);
extern void note_debug_info_needed (tree);
extern void push_class_decls (tree);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 1774af4..9582451 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -963,16 +963,50 @@ expand_member_init (tree name)
if (basetype)
{
- tree binfo;
+ tree class_binfo;
+ tree direct_binfo;
+ tree virtual_binfo;
+ int i;
if (current_template_parms)
return basetype;
- binfo = lookup_base (current_class_type, basetype,
- ba_ignore, NULL);
- if (!binfo || (!TREE_VIA_VIRTUAL (binfo)
- && (BINFO_INHERITANCE_CHAIN (binfo)
- != TYPE_BINFO (current_class_type))))
+ class_binfo = TYPE_BINFO (current_class_type);
+ direct_binfo = NULL_TREE;
+ virtual_binfo = NULL_TREE;
+
+ /* Look for a direct base. */
+ for (i = 0; i < BINFO_N_BASETYPES (class_binfo); ++i)
+ if (same_type_p (basetype,
+ TYPE_BINFO_BASETYPE (current_class_type, i)))
+ {
+ direct_binfo = BINFO_BASETYPE (class_binfo, i);
+ break;
+ }
+ /* Look for a virtual base -- unless the direct base is itself
+ virtual. */
+ if (!direct_binfo || !TREE_VIA_VIRTUAL (direct_binfo))
+ {
+ virtual_binfo
+ = purpose_member (basetype,
+ CLASSTYPE_VBASECLASSES (current_class_type));
+ if (virtual_binfo)
+ virtual_binfo = TREE_VALUE (virtual_binfo);
+ }
+
+ /* [class.base.init]
+
+ If a mem-initializer-id is ambiguous because it designates
+ both a direct non-virtual base class and an inherited virtual
+ base class, the mem-initializer is ill-formed. */
+ if (direct_binfo && virtual_binfo)
+ {
+ error ("'%D' is both a direct base and an indirect virtual base",
+ basetype);
+ return NULL_TREE;
+ }
+
+ if (!direct_binfo && !virtual_binfo)
{
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
error ("type `%D' is not a direct or virtual base of `%T'",
@@ -982,7 +1016,8 @@ expand_member_init (tree name)
name, current_class_type);
return NULL_TREE;
}
- return binfo;
+
+ return direct_binfo ? direct_binfo : virtual_binfo;
}
else
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 0c82d52..9580129 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2003-08-10 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/11789.C
+ * g++.dg/inherit/multiple1.C: New test.
+
2003-08-10 Nathan Sidwell <nathan@codesourcery.com>
* gcc.dg/spe1.c: New test.
diff --git a/gcc/testsuite/g++.dg/inherit/multiple1.C b/gcc/testsuite/g++.dg/inherit/multiple1.C
new file mode 100644
index 0000000..3eb9fe7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/inherit/multiple1.C
@@ -0,0 +1,20 @@
+// { dg-options "-w" }
+
+struct Base {
+ int b;
+
+ Base(int b) : b(b) { }
+};
+
+struct Derived : public Base {
+ Derived(int d) : Base(d) { }
+};
+
+struct Final : public Derived, public Base {
+ Final(int f) : Derived(f), Base(f-1) { }
+};
+
+int main()
+{
+ Final f(5);
+}