[Bug target/52991] [6/7/8 Regression] attribute packed broken on mingw32?

dev at benjarobin dot fr gcc-bugzilla@gcc.gnu.org
Fri Dec 29 22:04:00 GMT 2017


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991

--- Comment #26 from Benjamin Robin <dev at benjarobin dot fr> ---
I try to work on this bug, by curiosity... And I did found 3 bug in the current
layout of structure when ms_bitfield_layout_p = 1:

**************************
 1) Basic packing (the failing test):
--------------------------
PACK(struct test_sp1 {
    int a;
    short b;
    int c;
    char d;
});

assert_cc(sizeof(struct test_sp1) == 11);
assert_cc(offsetof(struct test_sp1, a) == 0);
assert_cc(offsetof(struct test_sp1, b) == 4);
assert_cc(offsetof(struct test_sp1, c) == 6);
assert_cc(offsetof(struct test_sp1, d) == 10);
--------------------------
Associated Patch :
--------------------------
@@ -1460,7 +1475,8 @@ place_field (record_layout_info rli, tree field)
            }

          /* Now align (conventionally) for the new type.  */
-         type_align = TYPE_ALIGN (TREE_TYPE (field));
+         if (!DECL_PACKED(field))
+           type_align = TYPE_ALIGN (TREE_TYPE (field));

          if (maximum_field_alignment != 0)
            type_align = MIN (type_align, maximum_field_alignment);
--------------------------

**************************
 2) Struct packing that contains a field with an aligned attribute 
(the failing test):
--------------------------
PACK(struct test_sp3 {
    int a;
    ALIGN(short b, 8);
    int c;
    char d;
});

assert_cc(sizeof(struct test_sp3) == 16);
assert_cc(offsetof(struct test_sp3, a) == 0);
assert_cc(offsetof(struct test_sp3, b) == 8);
assert_cc(offsetof(struct test_sp3, c) == 10);
assert_cc(offsetof(struct test_sp3, d) == 14);
--------------------------
Associated Patch :
--------------------------
@@ -1018,8 +1018,13 @@ update_alignment_for_field (record_layout_info rli, tree
field,
          if (maximum_field_alignment != 0)
            type_align = MIN (type_align, maximum_field_alignment);
          rli->record_align = MAX (rli->record_align, type_align);
-         rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
-       }
+        }
+      else
+        {
+          rli->record_align = MAX (rli->record_align, desired_align);
+        }
+
+      rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
     }
   else if (is_bitfield && PCC_BITFIELD_TYPE_MATTERS)
     {
--------------------------

**************************
 3) Struct with a bit-field followed by a char (the failing test):
--------------------------
struct test_s4 {
    int a;
    short b;
    int c:15;
    char d;
};

#ifdef _WIN32
assert_cc(sizeof(struct test_s4) == 16);
assert_cc(offsetof(struct test_s4, a) == 0);
assert_cc(offsetof(struct test_s4, b) == 4);
assert_cc(offsetof(struct test_s4, d) == 12);
#else
assert_cc(sizeof(struct test_s4) == 12);
assert_cc(offsetof(struct test_s4, a) == 0);
assert_cc(offsetof(struct test_s4, b) == 4);
assert_cc(offsetof(struct test_s4, d) == 8);
#endif
--------------------------
Associated Patch :
--------------------------
@@ -1218,9 +1223,21 @@ place_field (record_layout_info rli, tree field)
       /* No, we need to skip space before this field.
         Bump the cumulative size to multiple of field alignment.  */

-      if (!targetm.ms_bitfield_layout_p (rli->t)
-          && DECL_SOURCE_LOCATION (field) != BUILTINS_LOCATION)
-       warning (OPT_Wpadded, "padding struct to align %q+D", field);
+      if (targetm.ms_bitfield_layout_p (rli->t))
+        {
+          if (rli->prev_field != NULL &&
+              !integer_zerop (DECL_SIZE (rli->prev_field)) )
+            {
+              rli->bitpos = size_binop (PLUS_EXPR, rli->bitpos,
+                                 bitsize_int (rli->remaining_in_alignment));
+            }
+            rli->prev_field = NULL;
+        }
+      else
+        {
+          if (DECL_SOURCE_LOCATION (field) != BUILTINS_LOCATION)
+            warning (OPT_Wpadded, "padding struct to align %q+D", field);
+        }

       /* If the alignment is still within offset_align, just align
         the bit position.  */
--------------------------

************************

 *) Macro used in the code above
--------------------------
#ifdef _WIN32
# ifdef _MSC_VER
#  define PACK(typeDec) __pragma( pack(push, 1) ) typeDec __pragma( pack(pop) )
# else
#  define PACK(typeDec) typeDec __attribute__((__packed__,ms_struct))
# endif
#else
# define PACK(typeDec) typeDec __attribute__((__packed__))
#endif

#ifdef _MSC_VER
# define ALIGN(typeDec, n) __declspec(align(n)) typeDec
#else
# define ALIGN(typeDec, n) typeDec __attribute__((aligned(n)))
#endif
--------------------------


More information about the Gcc-bugs mailing list