This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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))

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]