re PR c++/71694 (store-data race with bitfields and tail-padding in C++)
authorRichard Biener <rguenther@suse.de>
Fri, 16 Dec 2016 09:40:03 +0000 (09:40 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 16 Dec 2016 09:40:03 +0000 (09:40 +0000)
2016-12-16  Richard Biener  <rguenther@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.

From-SVN: r243738

gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/cp-objcp-common.c
gcc/cp/cp-objcp-common.h
gcc/langhooks-def.h
gcc/langhooks.c
gcc/langhooks.h
gcc/stor-layout.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/pr71694.C [new file with mode: 0644]

index ca4f4f4f5ed033ae488de5a7ffa2c13b9b3d3f72..cf4e49a24869d51df9b30056bc00257e55f69f48 100644 (file)
@@ -1,3 +1,16 @@
+2016-12-16  Richard Biener  <rguenther@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.
+
 2016-12-16  Richard Biener  <rguenther@suse.de>
 
        PR middle-end/71632
index 5c6713234a8e1c08cdfad418d8087001fa7a585e..757bcef99d50c794a26a7d10c67f1c13efcdc2d5 100644 (file)
@@ -1,3 +1,10 @@
+2016-12-16  Richard Biener  <rguenther@suse.de>
+
+       PR c++/71694
+       * 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.
+
 2016-12-15  Jakub Jelinek  <jakub@redhat.com>
 
        P0490R0 GB 20: decomposition declaration should commit to tuple
index 633831ce4b3a822b3c0d32e7a9d221f350164746..b78d24d139402a5dae14064608f05e8507027887 100644 (file)
@@ -252,6 +252,16 @@ cp_type_dwarf_attribute (const_tree type, int attr)
   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 65ac95c2ee1f56ab90925217abfb624cf6393df7..f0e45c58f2100c23c8a444a6345001b12b1c25ea 100644 (file)
@@ -30,6 +30,7 @@ extern tree objcp_tsubst_copy_and_build (tree, tree, tsubst_flags_t,
 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,
@@ -137,6 +138,9 @@ extern void cp_common_init_ts (void);
 #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 e4c0ffb799d4859d4d4de49fb018999b37bcdc75..b25c5a787c731af6994695e310c36b048f4d9359 100644 (file)
@@ -161,6 +161,8 @@ extern tree lhd_make_node (enum tree_code);
 
 /* 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
@@ -189,6 +191,7 @@ extern tree lhd_make_node (enum tree_code);
 #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, \
@@ -212,7 +215,8 @@ extern tree lhd_make_node (enum tree_code);
   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_TYPE_DWARF_ATTRIBUTE, \
+  LANG_HOOKS_UNIT_SIZE_WITHOUT_REUSABLE_PADDING \
 }
 
 /* Declaration hooks.  */
index 1ce19628b2a04d459121fad529a59ad3f63103f4..260d33c3ffe958a5960ea1a005895f17c3f826da 100644 (file)
@@ -729,6 +729,15 @@ lhd_type_dwarf_attribute (const_tree, int)
   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 4e925ad69021d0c26a0907c5403fc2bc64e84dea..19e3fa1e99773cb76ec323e8f49b75ad0bd019db 100644 (file)
@@ -166,6 +166,10 @@ struct lang_hooks_for_types
   /* 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 5a4bcf1d6640354451de3fb72e11089f9c703821..0aa3861d941e5579dbac832ef421b1a36a053cb3 100644 (file)
@@ -1864,13 +1864,14 @@ finish_bitfield_representative (tree repr, tree field)
     }
   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));
+      /* 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 8de3e189c4b65683fea74fda0c7facf4ab899868..8aa1ad9fd5bee896819522eb02d41bb2d0b580d2 100644 (file)
@@ -1,3 +1,8 @@
+2016-12-16  Richard Biener  <rguenther@suse.de>
+
+       PR c++/71694
+       * g++.dg/pr71694.C: New testcase.
+
 2016-12-16  Richard Biener  <rguenther@suse.de>
 
        PR middle-end/71632
diff --git a/gcc/testsuite/g++.dg/pr71694.C b/gcc/testsuite/g++.dg/pr71694.C
new file mode 100644 (file)
index 0000000..e79f62a
--- /dev/null
@@ -0,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-*-* } } } } */