This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH to refer to base members using COMPONENT_REF
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 30 Apr 2004 13:24:51 -0400
- Subject: C++ PATCH to refer to base members using COMPONENT_REF
Previously, given
struct A { int i; };
struct B: public A { };
int main()
{
B b;
b.i = 42;
}
b.i would be represented as ((A*)&b)->i. This patch changes the
representation to b.<A base field>.i, which is more friendly to alias
analysis.
Tested athlon-pc-linux-gnu, applied to trunk.
2004-04-30 Jason Merrill <jason@redhat.com>
Refer to base members using COMPONENT_REFs where possible.
* class.c (build_simple_base_path): New fn.
(build_base_path): Use it for non-virtual base references.
(layout_class_type): Change base fields to their real type
after layout is done.
* cp-tree.h (IS_FAKE_BASE_TYPE): New macro.
* cp-lang.c (cxx_get_alias_set): Use it.
*** cp/class.c.~1~ 2004-04-20 15:24:54.000000000 -0400
--- cp/class.c 2004-04-30 13:18:25.000000000 -0400
*************** static void add_implicitly_declared_memb
*** 129,134 ****
--- 129,135 ----
static tree fixed_type_or_null (tree, int *, int *);
static tree resolve_address_of_overloaded_function (tree, tree, tsubst_flags_t,
bool, tree);
+ static tree build_simple_base_path (tree expr, tree binfo);
static tree build_vtbl_ref_1 (tree, tree);
static tree build_vtbl_initializer (tree, tree, tree, tree, int *);
static int count_fields (tree);
*************** build_base_path (enum tree_code code,
*** 253,258 ****
--- 254,260 ----
tree ptr_target_type;
int fixed_type_p;
int want_pointer = TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE;
+ bool has_empty = false;
if (expr == error_mark_node || binfo == error_mark_node || !binfo)
return error_mark_node;
*************** build_base_path (enum tree_code code,
*** 260,265 ****
--- 262,269 ----
for (probe = binfo; probe; probe = BINFO_INHERITANCE_CHAIN (probe))
{
d_binfo = probe;
+ if (is_empty_class (BINFO_TYPE (probe)))
+ has_empty = true;
if (!v_binfo && TREE_VIA_VIRTUAL (probe))
v_binfo = probe;
}
*************** build_base_path (enum tree_code code,
*** 267,279 ****
probe = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
if (want_pointer)
probe = TYPE_MAIN_VARIANT (TREE_TYPE (probe));
!
my_friendly_assert (code == MINUS_EXPR
? same_type_p (BINFO_TYPE (binfo), probe)
: code == PLUS_EXPR
? same_type_p (BINFO_TYPE (d_binfo), probe)
: false, 20010723);
if (code == MINUS_EXPR && v_binfo)
{
error ("cannot convert from base `%T' to derived type `%T' via virtual base `%T'",
--- 271,287 ----
probe = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
if (want_pointer)
probe = TYPE_MAIN_VARIANT (TREE_TYPE (probe));
!
my_friendly_assert (code == MINUS_EXPR
? same_type_p (BINFO_TYPE (binfo), probe)
: code == PLUS_EXPR
? same_type_p (BINFO_TYPE (d_binfo), probe)
: false, 20010723);
+ if (binfo == d_binfo)
+ /* Nothing to do. */
+ return expr;
+
if (code == MINUS_EXPR && v_binfo)
{
error ("cannot convert from base `%T' to derived type `%T' via virtual base `%T'",
*************** build_base_path (enum tree_code code,
*** 285,300 ****
/* This must happen before the call to save_expr. */
expr = build_unary_op (ADDR_EXPR, expr, 0);
fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull);
! if (fixed_type_p <= 0 && TREE_SIDE_EFFECTS (expr))
expr = save_expr (expr);
! if (want_pointer && !nonnull)
null_test = fold (build2 (NE_EXPR, boolean_type_node,
expr, integer_zero_node));
!
! offset = BINFO_OFFSET (binfo);
!
if (v_binfo && fixed_type_p <= 0)
{
/* Going via virtual base V_BINFO. We need the static offset
--- 293,328 ----
/* This must happen before the call to save_expr. */
expr = build_unary_op (ADDR_EXPR, expr, 0);
+ offset = BINFO_OFFSET (binfo);
fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull);
!
! if (want_pointer && !nonnull
! && (!integer_zerop (offset) || (v_binfo && fixed_type_p <= 0)))
! null_test = error_mark_node;
!
! if (TREE_SIDE_EFFECTS (expr)
! && (null_test || (v_binfo && fixed_type_p <= 0)))
expr = save_expr (expr);
! if (null_test)
null_test = fold (build2 (NE_EXPR, boolean_type_node,
expr, integer_zero_node));
!
! /* If this is a simple base reference, express it as a COMPONENT_REF. */
! if (code == PLUS_EXPR
! && (v_binfo == NULL_TREE || fixed_type_p > 0)
! /* We don't build base fields for empty bases, and they aren't very
! interesting to the optimizers anyway. */
! && !has_empty)
! {
! expr = build_indirect_ref (expr, NULL);
! expr = build_simple_base_path (expr, binfo);
! if (want_pointer)
! expr = build_unary_op (ADDR_EXPR, expr, 0);
! target_type = TREE_TYPE (expr);
! goto out;
! }
!
if (v_binfo && fixed_type_p <= 0)
{
/* Going via virtual base V_BINFO. We need the static offset
*************** build_base_path (enum tree_code code,
*** 365,370 ****
--- 393,399 ----
if (!want_pointer)
expr = build_indirect_ref (expr, NULL);
+ out:
if (null_test)
expr = fold (build3 (COND_EXPR, target_type, null_test, expr,
fold (build1 (NOP_EXPR, target_type,
*************** build_base_path (enum tree_code code,
*** 373,378 ****
--- 402,448 ----
return expr;
}
+ /* Subroutine of build_base_path; EXPR and BINFO are as in that function.
+ Perform a derived-to-base conversion by recursively building up a
+ sequence of COMPONENT_REFs to the appropriate base fields. */
+
+ static tree
+ build_simple_base_path (tree expr, tree binfo)
+ {
+ tree type = BINFO_TYPE (binfo);
+ tree d_binfo;
+ tree field;
+
+ /* For primary virtual bases, we can't just follow
+ BINFO_INHERITANCE_CHAIN. */
+ d_binfo = BINFO_PRIMARY_BASE_OF (binfo);
+ if (d_binfo == NULL_TREE)
+ d_binfo = BINFO_INHERITANCE_CHAIN (binfo);
+
+ if (d_binfo == NULL_TREE)
+ {
+ if (TYPE_MAIN_VARIANT (TREE_TYPE (expr)) != type)
+ abort ();
+ return expr;
+ }
+
+ /* Recurse. */
+ expr = build_simple_base_path (expr, d_binfo);
+
+ for (field = TYPE_FIELDS (BINFO_TYPE (d_binfo));
+ field; field = TREE_CHAIN (field))
+ /* Is this the base field created by build_base_field? */
+ if (TREE_CODE (field) == FIELD_DECL
+ && TREE_TYPE (field) == type
+ && DECL_ARTIFICIAL (field)
+ && DECL_IGNORED_P (field))
+ return build_class_member_access_expr (expr, field,
+ NULL_TREE, false);
+
+ /* Didn't find the base field?!? */
+ abort ();
+ }
+
/* Convert OBJECT to the base TYPE. If CHECK_ACCESS is true, an error
message is emitted if TYPE is inaccessible. OBJECT is assumed to
be non-NULL. */
*************** layout_class_type (tree t, tree *virtual
*** 4885,4890 ****
--- 4955,4965 ----
/* Warn about bases that can't be talked about due to ambiguity. */
warn_about_ambiguous_bases (t);
+ /* Now that we're done with layout, give the base fields the real types. */
+ for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
+ if (DECL_ARTIFICIAL (field) && IS_FAKE_BASE_TYPE (TREE_TYPE (field)))
+ TREE_TYPE (field) = TYPE_CONTEXT (TREE_TYPE (field));
+
/* Clean up. */
splay_tree_delete (empty_base_offsets);
}
*** cp/cp-lang.c.~1~ 2004-04-15 16:58:37.000000000 -0400
--- cp/cp-lang.c 2004-04-30 13:16:21.000000000 -0400
*************** ok_to_generate_alias_set_for_type (tree
*** 292,300 ****
static HOST_WIDE_INT
cxx_get_alias_set (tree t)
{
! if (TREE_CODE (t) == RECORD_TYPE
! && TYPE_CONTEXT (t) && CLASS_TYPE_P (TYPE_CONTEXT (t))
! && CLASSTYPE_AS_BASE (TYPE_CONTEXT (t)) == t)
/* The base variant of a type must be in the same alias set as the
complete type. */
return get_alias_set (TYPE_CONTEXT (t));
--- 292,298 ----
static HOST_WIDE_INT
cxx_get_alias_set (tree t)
{
! if (IS_FAKE_BASE_TYPE (t))
/* The base variant of a type must be in the same alias set as the
complete type. */
return get_alias_set (TYPE_CONTEXT (t));
*** cp/cp-tree.h.~1~ 2004-04-15 16:58:37.000000000 -0400
--- cp/cp-tree.h 2004-04-30 13:16:21.000000000 -0400
*************** struct lang_type GTY(())
*** 1302,1307 ****
--- 1302,1314 ----
#define CLASSTYPE_AS_BASE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->as_base)
+ /* True iff NODE is the CLASSTYPE_AS_BASE version of some type. */
+
+ #define IS_FAKE_BASE_TYPE(NODE) \
+ (TREE_CODE (NODE) == RECORD_TYPE \
+ && TYPE_CONTEXT (NODE) && CLASS_TYPE_P (TYPE_CONTEXT (NODE)) \
+ && CLASSTYPE_AS_BASE (TYPE_CONTEXT (NODE)) == (NODE))
+
/* These are the size and alignment of the type without its virtual
base classes, for when we use this type as a base itself. */
#define CLASSTYPE_SIZE(NODE) TYPE_SIZE (CLASSTYPE_AS_BASE (NODE))