aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2003-07-24 23:33:26 +0000
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2003-07-24 23:33:26 +0000
commitc1c5bfe2aa05d16af8cd782b036d378f3655e281 (patch)
tree796e409dc11901ee2b77ae057d565ef0d12f6050
parent56dcf3ccc3624a63e3e38fa393d5c80a499e37b5 (diff)
* cp-tree.h (convert_to_base_statically): Declare.
* call.c (build_special_member_call): Convert INSTANCE to the base type. * class.c (convert_to_base_statically): New method. * init.c (construct_virtual_base): Use it. * method.c (do_build_assign_ref): Fix typo in comment. * g++.dg/inherit/access5.C: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@69763 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/call.c24
-rw-r--r--gcc/cp/class.c27
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/init.c16
-rw-r--r--gcc/cp/method.c2
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/inherit/access5.C4
8 files changed, 69 insertions, 18 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index c9930bba76c..a4e454bf814 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+2003-07-24 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (convert_to_base_statically): Declare.
+ * call.c (build_special_member_call): Convert INSTANCE to the base
+ type.
+ * class.c (convert_to_base_statically): New method.
+ * init.c (construct_virtual_base): Use it.
+ * method.c (do_build_assign_ref): Fix typo in comment.
+
2003-07-24 Jason Merrill <jason@redhat.com>
* decl.c: Just set truthvalue_* to boolean_*.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 11e8d2e0cab..58888eacf52 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4747,11 +4747,23 @@ build_special_member_call (tree instance, tree name, tree args,
TREE_TYPE (instance) = build_pointer_type (class_type);
instance = build1 (INDIRECT_REF, class_type, instance);
}
- else if (name == complete_dtor_identifier
- || name == base_dtor_identifier
- || name == deleting_dtor_identifier)
- my_friendly_assert (args == NULL_TREE, 20020712);
+ else
+ {
+ if (name == complete_dtor_identifier
+ || name == base_dtor_identifier
+ || name == deleting_dtor_identifier)
+ my_friendly_assert (args == NULL_TREE, 20020712);
+ /* We must perform the conversion here so that we do not
+ subsequently check to see whether BINFO is an accessible
+ base. (It is OK for a constructor to call a constructor in
+ an inaccessible base as long as the constructor being called
+ is accessible.) */
+ if (!same_type_ignoring_top_level_qualifiers_p
+ (TREE_TYPE (instance), BINFO_TYPE (binfo)))
+ instance = convert_to_base_statically (instance, binfo);
+ }
+
my_friendly_assert (instance != NULL_TREE, 20020712);
/* Resolve the name. */
@@ -4787,7 +4799,9 @@ build_special_member_call (tree instance, tree name, tree args,
args = tree_cons (NULL_TREE, sub_vtt, args);
}
- return build_new_method_call (instance, fns, args, binfo, flags);
+ return build_new_method_call (instance, fns, args,
+ TYPE_BINFO (BINFO_TYPE (binfo)),
+ flags);
}
/* Return the NAME, as a C string. The NAME indicates a function that
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 4c46d1c9c66..d2fb90283db 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -391,6 +391,33 @@ convert_to_base (tree object, tree type, bool check_access)
return build_base_path (PLUS_EXPR, object, binfo, /*nonnull=*/1);
}
+/* EXPR is an expression with class type. BASE is a base class (a
+ BINFO) of that class type. Returns EXPR, converted to the BASE
+ type. This function assumes that EXPR is the most derived class;
+ therefore virtual bases can be found at their static offsets. */
+
+tree
+convert_to_base_statically (tree expr, tree base)
+{
+ tree expr_type;
+
+ expr_type = TREE_TYPE (expr);
+ if (!same_type_p (expr_type, BINFO_TYPE (base)))
+ {
+ tree pointer_type;
+
+ pointer_type = build_pointer_type (expr_type);
+ expr = build_unary_op (ADDR_EXPR, expr, /*noconvert=*/1);
+ if (!integer_zerop (BINFO_OFFSET (base)))
+ expr = build (PLUS_EXPR, pointer_type, expr,
+ build_nop (pointer_type, BINFO_OFFSET (base)));
+ expr = build_nop (build_pointer_type (BINFO_TYPE (base)), expr);
+ expr = build1 (INDIRECT_REF, BINFO_TYPE (base), expr);
+ }
+
+ return expr;
+}
+
/* Virtual function things. */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 8e3fcf7701a..8f543b4317e 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3561,6 +3561,7 @@ extern tree build_cxx_call (tree, tree, tree);
/* in class.c */
extern tree build_base_path (enum tree_code, tree, tree, int);
extern tree convert_to_base (tree, tree, bool);
+extern tree convert_to_base_statically (tree, tree);
extern tree build_vtbl_ref (tree, tree);
extern tree build_vfn_ref (tree, tree);
extern tree get_vtable_decl (tree, int);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index fc10a24940b..054ff30cd54 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -863,18 +863,10 @@ construct_virtual_base (tree vbase, tree arguments)
constructing virtual bases, then we must be the most derived
class. Therefore, we don't have to look up the virtual base;
we already know where it is. */
- exp = build (PLUS_EXPR,
- TREE_TYPE (current_class_ptr),
- current_class_ptr,
- fold (build1 (NOP_EXPR, TREE_TYPE (current_class_ptr),
- BINFO_OFFSET (vbase))));
- exp = build1 (NOP_EXPR,
- build_pointer_type (BINFO_TYPE (vbase)),
- exp);
- exp = build1 (INDIRECT_REF, BINFO_TYPE (vbase), exp);
-
- expand_aggr_init_1 (vbase, current_class_ref, exp,
- arguments, LOOKUP_COMPLAIN);
+ exp = convert_to_base_statically (current_class_ref, vbase);
+
+ expand_aggr_init_1 (vbase, current_class_ref, exp, arguments,
+ LOOKUP_COMPLAIN);
finish_compound_stmt (/*has_no_scope=*/1, compound_stmt);
finish_then_clause (inner_if_stmt);
finish_if_stmt ();
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 35319de9346..00428b1348d 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -605,7 +605,7 @@ do_build_assign_ref (tree fndecl)
int cvquals = cp_type_quals (TREE_TYPE (parm));
int i;
- /* Assign to each of thedirect base classes. */
+ /* Assign to each of the direct base classes. */
for (i = 0; i < CLASSTYPE_N_BASECLASSES (current_class_type); ++i)
{
tree binfo;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a362729dc84..0dcc60fc6e5 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2003-07-24 Mark Mitchell <mark@codesourcery.com>
+
+ * g++.dg/inherit/access5.C: New test.
+
2003-07-24 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/11513
diff --git a/gcc/testsuite/g++.dg/inherit/access5.C b/gcc/testsuite/g++.dg/inherit/access5.C
new file mode 100644
index 00000000000..715a4a3b29b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/inherit/access5.C
@@ -0,0 +1,4 @@
+struct S { ~S(); };
+struct T : virtual private S {};
+struct U : private T {};
+U u;