mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-22 19:41:06 +08:00
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:
parent
ed9676cf0c
commit
00bfffa4c0
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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))
|
||||
|
Loading…
x
Reference in New Issue
Block a user