aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2004-04-30 13:25:42 -0400
committerJason Merrill <jason@gcc.gnu.org>2004-04-30 13:25:42 -0400
commit00bfffa4c0730935f8cb16d59a72683b6d4c82bd (patch)
tree4ac93946f88f9d873dc4b509f6b118ec816ee667 /gcc
parented9676cf0ca3101a8933826b0dcc9aacae689f23 (diff)
downloadgcc-00bfffa4c0730935f8cb16d59a72683b6d4c82bd.zip
gcc-00bfffa4c0730935f8cb16d59a72683b6d4c82bd.tar.gz
gcc-00bfffa4c0730935f8cb16d59a72683b6d4c82bd.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/class.c87
-rw-r--r--gcc/cp/cp-lang.c4
-rw-r--r--gcc/cp/cp-tree.h7
4 files changed, 99 insertions, 9 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 2eaab1c..0f0a5e2 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 4231033..13d6d03 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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);
}
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index bbe9170..3c2a311 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -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));
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index fb02e41..c3c7c86 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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))