pragma pack(<n>) fix

Mumit Khan khan@xraylith.wisc.EDU
Fri Jun 11 21:33:00 GMT 1999


The following fixes the packing pragma code on x86-win32 for all the test
cases that I can come up with. Currently, it's horribly broken. Nick
Clifton and I had come up with a hack that Jason Merrill subsequently,
and justfiably so, removed (Mon Apr 26 21:17:41 1999) and that caused all
the bugs to show up right away. Currently, the system headers are being
compiled correctly for any of the x86-win32 ports except for Interix.

I'm attaching a set of 3 test cases, along with side-by-side comparison
with MSVC's output. Note how the pragma pack fails in almost cases except
for where #pragma pack(1) is specified. The testcases test all 5 possible
cases, <n>=1,2,4,8,16, for 3 different structures.

The main confusion arises from MS docs, which says the following:
  
  Whe use #pragma pack(<n>), where <n> is 1, 2, 4, 8, or 16, each structure
  member is after the first is stored on the smaller member type or <n>-
  byte boundaries.

After much experimentation trying to figure out what this means, I believe
the "smaller member type ..." means that the members are aligned to the
*smaller* of natural alignment and specified packing <n>.

Many thanks to GrahamS <grahams@rcp.co.uk> for suggesting the fix!

The patch in push_alignment just corrects an omission in Jason's last 
patch on 1999-04-26.

Fri Jun 11 22:09:13 1999  Mumit Khan  <khan@xraylith.wisc.edu>

	* c-pragma.c (push_alignment): Don't ignore alignments greater than
	4 bytes.
	(insert_pack_attributes): Take into account member natural 
	alignment.

Index: c-pragma.c
===================================================================
RCS file: /homes/khan/src/CVSROOT/gcc-2.95/gcc/c-pragma.c,v
retrieving revision 1.1.1.1
diff -u -3 -p -r1.1.1.1 c-pragma.c
--- c-pragma.c	1999/06/10 02:09:53	1.1.1.1
+++ c-pragma.c	1999/06/12 01:39:19
@@ -141,7 +141,7 @@ pop_alignment (id)
     {
       entry = alignment_stack->prev;
 
-      if (entry == NULL || entry->alignment > 4)
+      if (entry == NULL)
 	maximum_field_alignment = 0;
       else
 	maximum_field_alignment = entry->alignment * 8;
@@ -163,6 +163,7 @@ insert_pack_attributes (node, attributes
      tree * prefix;
 {
   tree a;
+  int field_alignment;
 
   /* If we are not packing, then there is nothing to do.  */
   if (maximum_field_alignment == 0
@@ -173,12 +174,16 @@ insert_pack_attributes (node, attributes
   if (TREE_CODE_CLASS (TREE_CODE (node)) != 'd'
       || TREE_CODE (node) != FIELD_DECL)
     return;
+  
+  field_alignment = TYPE_ALIGN (TREE_TYPE (node));
+  if (field_alignment <= 0 || field_alignment > maximum_field_alignment)
+    field_alignment = maximum_field_alignment;
 
   /* Add a 'packed' attribute.  */
   * attributes = tree_cons (get_identifier ("packed"), NULL, * attributes);
   
   /* If the alignment is > 8 then add an alignment attribute as well.  */
-  if (maximum_field_alignment > 8)
+  if (field_alignment > 8)
     {
       /* If the aligned attribute is already present then do not override it.  */
       for (a = * attributes; a; a = TREE_CHAIN (a))
@@ -201,7 +206,7 @@ insert_pack_attributes (node, attributes
 	  * attributes = tree_cons
 	      (get_identifier ("aligned"),
 	       tree_cons (NULL,
-			  build_int_2 (maximum_field_alignment / 8, 0),
+			  build_int_2 (field_alignment / 8, 0),
 			  NULL),
 	       * attributes);
 	}

Regards,
Mumit



More information about the Gcc-patches mailing list