From: Jason Merrill Date: Fri, 30 Apr 2004 17:25:42 +0000 (-0400) Subject: Refer to base members using COMPONENT_REFs where possible. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=00bfffa4c0730935f8cb16d59a72683b6d4c82bd;p=gcc.git 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 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2eaab1c67ae..0f0a5e2cf7f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2004-04-30 Jason Merrill + + 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 * 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 42310338abe..13d6d03c9a5 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 bbe91707dd7..3c2a311e9ca 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 fb02e41ec56..c3c7c868e25 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))