From 22ed7e5f2c90a20b426d6a4886f469cf4910b816 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Thu, 24 Jul 2003 23:33:26 +0000 Subject: [PATCH] cp-tree.h (convert_to_base_statically): Declare. * 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. From-SVN: r69763 --- gcc/cp/ChangeLog | 9 +++++++++ gcc/cp/call.c | 24 ++++++++++++++++++----- gcc/cp/class.c | 27 ++++++++++++++++++++++++++ gcc/cp/cp-tree.h | 1 + gcc/cp/init.c | 14 +++---------- gcc/cp/method.c | 2 +- gcc/testsuite/ChangeLog | 4 ++++ gcc/testsuite/g++.dg/inherit/access5.C | 4 ++++ 8 files changed, 68 insertions(+), 17 deletions(-) create mode 100644 gcc/testsuite/g++.dg/inherit/access5.C 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 + + * 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 * 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); + exp = convert_to_base_statically (current_class_ref, vbase); - expand_aggr_init_1 (vbase, current_class_ref, exp, - arguments, LOOKUP_COMPLAIN); + 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 + + * g++.dg/inherit/access5.C: New test. + 2003-07-24 Kriang Lerdsuwanakij 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;