The following implements Jasons suggestion of using a langhook to
return the size of an aggregate without tail padding that might
be re-used when it is inherited from.

Using this langhook we can fix the size of the representative for the 
bitfield properly and thus generate correct code for the testcase.
Previously on x86_64 it was

main:
        movl    c+4(%rip), %eax
        andl    $-258049, %eax
        orb     $16, %ah
        movl    %eax, c+4(%rip)
        movb    $2, c+7(%rip)
        xorl    %eax, %eax
        ret

while after the patch we see

main:
        movzbl  c+5(%rip), %eax
        andb    $-4, c+6(%rip)
        movb    $2, c+7(%rip)
        andl    $15, %eax
        orl     $16, %eax
        movb    %al, c+5(%rip)
        xorl    %eax, %eax
        ret

in particular the store to C::B::d is now properly using a byte store.

Bootstrap and regtest in progress on x86_64-unknown-linux-gnu, ok for 
trunk?

Thanks,
Richard.

2016-12-14  Richard Biener  <rguent...@suse.de>

        PR c++/71694
        * langhooks-def.h (lhd_unit_size_without_reusable_padding): Declare.
        (LANG_HOOKS_UNIT_SIZE_WITHOUT_REUSABLE_PADDING): Define.
        (LANG_HOOKS_FOR_TYPES_INITIALIZER): Adjust.
        * langhooks.h (struct lang_hooks_for_types): Add
        unit_size_without_reusable_padding.
        * langhooks.c (lhd_unit_size_without_reusable_padding): New.
        * stor-layout.c (finish_bitfield_representative): Use
        unit_size_without_reusable_padding langhook to decide on the
        last representatives size.

        cp/
        * cp-objcp-common.h (cp_unit_size_without_reusable_padding): Declare.
        (LANG_HOOKS_UNIT_SIZE_WITHOUT_REUSABLE_PADDING): Define.
        * cp-objcp-common.c (cp_unit_size_without_reusable_padding): New.

        * g++.dg/pr71694.C: New testcase.

Index: gcc/langhooks-def.h
===================================================================
*** gcc/langhooks-def.h (revision 243632)
--- gcc/langhooks-def.h (working copy)
*************** extern tree lhd_make_node (enum tree_cod
*** 161,166 ****
--- 161,168 ----
  
  /* Types hooks.  There are no reasonable defaults for most of them,
     so we create a compile-time error instead.  */
+ extern tree lhd_unit_size_without_reusable_padding (tree);
+ 
  #define LANG_HOOKS_MAKE_TYPE lhd_make_node
  #define LANG_HOOKS_CLASSIFY_RECORD    NULL
  #define LANG_HOOKS_INCOMPLETE_TYPE_ERROR lhd_incomplete_type_error
*************** extern tree lhd_make_node (enum tree_cod
*** 189,194 ****
--- 191,197 ----
  #define LANG_HOOKS_GET_DEBUG_TYPE     NULL
  #define LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO NULL
  #define LANG_HOOKS_TYPE_DWARF_ATTRIBUTE       lhd_type_dwarf_attribute
+ #define LANG_HOOKS_UNIT_SIZE_WITHOUT_REUSABLE_PADDING 
lhd_unit_size_without_reusable_padding
  
  #define LANG_HOOKS_FOR_TYPES_INITIALIZER { \
    LANG_HOOKS_MAKE_TYPE, \
*************** extern tree lhd_make_node (enum tree_cod
*** 212,218 ****
    LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE, \
    LANG_HOOKS_GET_DEBUG_TYPE, \
    LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO, \
!   LANG_HOOKS_TYPE_DWARF_ATTRIBUTE \
  }
  
  /* Declaration hooks.  */
--- 215,222 ----
    LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE, \
    LANG_HOOKS_GET_DEBUG_TYPE, \
    LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO, \
!   LANG_HOOKS_TYPE_DWARF_ATTRIBUTE, \
!   LANG_HOOKS_UNIT_SIZE_WITHOUT_REUSABLE_PADDING \
  }
  
  /* Declaration hooks.  */
Index: gcc/langhooks.h
===================================================================
*** gcc/langhooks.h     (revision 243632)
--- gcc/langhooks.h     (working copy)
*************** struct lang_hooks_for_types
*** 166,171 ****
--- 166,175 ----
    /* Returns -1 if dwarf ATTR shouldn't be added for TYPE, or the attribute
       value otherwise.  */
    int (*type_dwarf_attribute) (const_tree, int);
+ 
+   /* Returns a tree for the unit size of T excluding tail padding that
+      might be used by objects inheriting from T.  */
+   tree (*unit_size_without_reusable_padding) (tree);
  };
  
  /* Language hooks related to decls and the symbol table.  */
Index: gcc/langhooks.c
===================================================================
*** gcc/langhooks.c     (revision 243632)
--- gcc/langhooks.c     (working copy)
*************** lhd_type_dwarf_attribute (const_tree, in
*** 729,734 ****
--- 729,743 ----
    return -1;
  }
  
+ /* Default implementation of LANG_HOOKS_UNIT_SIZE_WITHOUT_REUSABLE_PADDING.
+    Just return TYPE_SIZE_UNIT unadjusted.  */
+ 
+ tree
+ lhd_unit_size_without_reusable_padding (tree t)
+ {
+   return TYPE_SIZE_UNIT (t);
+ }
+ 
  /* Returns true if the current lang_hooks represents the GNU C frontend.  */
  
  bool
Index: gcc/stor-layout.c
===================================================================
*** gcc/stor-layout.c   (revision 243632)
--- gcc/stor-layout.c   (working copy)
*************** finish_bitfield_representative (tree rep
*** 1864,1876 ****
      }
    else
      {
!       /* ???  If you consider that tail-padding of this struct might be
!          re-used when deriving from it we cannot really do the following
!        and thus need to set maxsize to bitsize?  Also we cannot
!        generally rely on maxsize to fold to an integer constant, so
!        use bitsize as fallback for this case.  */
!       tree maxsize = size_diffop (TYPE_SIZE_UNIT (DECL_CONTEXT (field)),
!                                 DECL_FIELD_OFFSET (repr));
        if (tree_fits_uhwi_p (maxsize))
        maxbitsize = (tree_to_uhwi (maxsize) * BITS_PER_UNIT
                      - tree_to_uhwi (DECL_FIELD_BIT_OFFSET (repr)));
--- 1864,1877 ----
      }
    else
      {
!       /* Note that if the C++ FE sets up tail-padding to be re-used it
!          creates a as-base variant of the type with TYPE_SIZE adjusted
!        accordingly.  So it is safe to include tail-padding here.  */
!       tree aggsize = lang_hooks.types.unit_size_without_reusable_padding
!                                                       (DECL_CONTEXT (field));
!       tree maxsize = size_diffop (aggsize, DECL_FIELD_OFFSET (repr));
!       /* We cannot generally rely on maxsize to fold to an integer constant,
!        so use bitsize as fallback for this case.  */
        if (tree_fits_uhwi_p (maxsize))
        maxbitsize = (tree_to_uhwi (maxsize) * BITS_PER_UNIT
                      - tree_to_uhwi (DECL_FIELD_BIT_OFFSET (repr)));
Index: gcc/cp/cp-objcp-common.c
===================================================================
*** gcc/cp/cp-objcp-common.c    (revision 243632)
--- gcc/cp/cp-objcp-common.c    (working copy)
*************** cp_type_dwarf_attribute (const_tree type
*** 252,257 ****
--- 252,267 ----
    return -1;
  }
  
+ /* Return the unit size of TYPE without reusable tail padding.  */
+ 
+ tree
+ cp_unit_size_without_reusable_padding (tree type)
+ {
+   if (CLASS_TYPE_P (type))
+     return CLASSTYPE_SIZE_UNIT (type);
+   return TYPE_SIZE_UNIT (type);
+ }
+ 
  /* Stubs to keep c-opts.c happy.  */
  void
  push_file_scope (void)
Index: gcc/cp/cp-objcp-common.h
===================================================================
*** gcc/cp/cp-objcp-common.h    (revision 243632)
--- gcc/cp/cp-objcp-common.h    (working copy)
*************** extern tree objcp_tsubst_copy_and_build
*** 30,35 ****
--- 30,36 ----
  extern int cp_decl_dwarf_attribute (const_tree, int);
  extern int cp_type_dwarf_attribute (const_tree, int);
  extern void cp_common_init_ts (void);
+ extern tree cp_unit_size_without_reusable_padding (tree);
  
  /* Lang hooks that are shared between C++ and ObjC++ are defined here.  Hooks
     specific to C++ or ObjC++ go in cp/cp-lang.c and objcp/objcp-lang.c,
*************** extern void cp_common_init_ts (void);
*** 137,142 ****
--- 138,146 ----
  #define LANG_HOOKS_DECL_DWARF_ATTRIBUTE cp_decl_dwarf_attribute
  #undef LANG_HOOKS_TYPE_DWARF_ATTRIBUTE
  #define LANG_HOOKS_TYPE_DWARF_ATTRIBUTE cp_type_dwarf_attribute
+ #undef LANG_HOOKS_UNIT_SIZE_WITHOUT_REUSABLE_PADDING
+ #define LANG_HOOKS_UNIT_SIZE_WITHOUT_REUSABLE_PADDING 
cp_unit_size_without_reusable_padding
+ 
  #undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
  #define LANG_HOOKS_OMP_PREDETERMINED_SHARING cxx_omp_predetermined_sharing
  #undef LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR
Index: gcc/testsuite/g++.dg/pr71694.C
===================================================================
*** gcc/testsuite/g++.dg/pr71694.C      (revision 0)
--- gcc/testsuite/g++.dg/pr71694.C      (working copy)
***************
*** 0 ****
--- 1,27 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2" } */
+ 
+ struct B {
+     B() {}
+     int x;
+     int a : 6;
+     int b : 6;
+     int c : 6;
+ };
+ 
+ struct C : B {
+     char d;
+ };
+ 
+ C c;
+ 
+ int main()
+ {
+   /* We have to make sure to not cause a store data race between
+      c.c and c.d residing in the tail padding of B.  */
+   c.c = 1;
+   c.d = 2;
+ }
+ 
+ /* In particular on x86 c.d should not be loaded/stored via movl.  */
+ /* { dg-final { scan-assembler-not "movl" { target { x86_64-*-* i?86-*-* } } 
} } */

Reply via email to