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.

From-SVN: r81349
This commit is contained in:
Jason Merrill 2004-04-30 13:25:42 -04:00 committed by Jason Merrill
parent ed9676cf0c
commit 00bfffa4c0
4 changed files with 99 additions and 9 deletions

View File

@ -1,3 +1,13 @@
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.
2004-04-30 Kazu Hirata <kazu@cs.umass.edu>
* class.c, cp-tree.h, decl.c, decl2.c, pt.c, rtti.c: Fix

View File

@ -129,6 +129,7 @@ static void add_implicitly_declared_members (tree, int, int, int);
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);
@ -253,6 +254,7 @@ build_base_path (enum tree_code code,
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;
@ -260,6 +262,8 @@ build_base_path (enum tree_code code,
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;
}
@ -267,13 +271,17 @@ build_base_path (enum tree_code code,
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'",
@ -285,16 +293,36 @@ build_base_path (enum tree_code code,
/* 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 (fixed_type_p <= 0 && TREE_SIDE_EFFECTS (expr))
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 (want_pointer && !nonnull)
if (null_test)
null_test = fold (build2 (NE_EXPR, boolean_type_node,
expr, integer_zero_node));
offset = BINFO_OFFSET (binfo);
/* 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
@ -365,6 +393,7 @@ build_base_path (enum tree_code code,
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,
@ -373,6 +402,47 @@ build_base_path (enum tree_code code,
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. */
@ -4885,6 +4955,11 @@ layout_class_type (tree t, tree *virtuals_p)
/* 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);
}

View File

@ -292,9 +292,7 @@ ok_to_generate_alias_set_for_type (tree t)
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)
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));

View File

@ -1302,6 +1302,13 @@ struct lang_type GTY(())
#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))