re PR c/7054 (#pragma pack handled incorrectly)
authorJan Beulich <jbeulich@novell.com>
Fri, 3 Sep 2004 17:22:40 +0000 (17:22 +0000)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 3 Sep 2004 17:22:40 +0000 (10:22 -0700)
        PR c/7054
        * defaults.h (TARGET_DEFAULT_PACK_STRUCT): Provide default.
        * tree.h (initial_max_fld_align): Declare
        * stor-layout.c (initial_max_fld_align): Define and initialize.
        (maximum_field_alignment): Initialize to the same value.
        * common.opt: Add -fpack-struct= variant of switch.
        * opts.c: Handle -fpack-struct= variant of switch.
        * c-pragma.c: Change #pragma pack() handling so that it becomes
        compatible to other compilers: accept individual 'push' argument,
        make final pop restore (command line) default, correct interaction
        of push/pop and sole specification of a new alignment (so that the
        sequence #pragma pack(push) - #pragma pack(<n>) becomes identical
        to #pragma pack(push, <n>).
        * doc/extend.texi: New node "Structure-Packing Pragmas" under
        "Pragmas", describing #pragma pack.
        * doc/invoke.texi: Document -fpack-struct=<n> variant of switch.
        * doc/tm.texi: Adjust description for HANDLE_PRAGMA_PACK_PUSH_POP.
        Document new TARGET_DEFAULT_PACK_STRUCT.
testsuite:
        * gcc.dg/pack-test-2.c: Adjust to permit and check #pragma pack(push).
        * gcc.dg/c99-flex-array-4.c: Add -fpack-struct=8 to provide a
        deterministic starting point for the alignment of structure fields.
        * gcc.dg/Wpadded.c: Dito.
        * g++.dg/abi/vbase10.C: Dito.

From-SVN: r87037

15 files changed:
gcc/ChangeLog
gcc/c-pragma.c
gcc/common.opt
gcc/defaults.h
gcc/doc/extend.texi
gcc/doc/invoke.texi
gcc/doc/tm.texi
gcc/opts.c
gcc/stor-layout.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/abi/vbase10.C
gcc/testsuite/gcc.dg/Wpadded.c
gcc/testsuite/gcc.dg/c99-flex-array-4.c
gcc/testsuite/gcc.dg/pack-test-2.c
gcc/tree.h

index 1b36cab3972e3f1d8760dcb868ba6e98908b18fc..71218fc1953225252baccbd6f338306ea159cbae 100644 (file)
@@ -1,3 +1,24 @@
+2004-09-03  Jan Beulich  <jbeulich@novell.com>
+
+       PR c/7054
+       * defaults.h (TARGET_DEFAULT_PACK_STRUCT): Provide default.
+       * tree.h (initial_max_fld_align): Declare
+       * stor-layout.c (initial_max_fld_align): Define and initialize.
+       (maximum_field_alignment): Initialize to the same value.
+       * common.opt: Add -fpack-struct= variant of switch.
+       * opts.c: Handle -fpack-struct= variant of switch.
+       * c-pragma.c: Change #pragma pack() handling so that it becomes
+       compatible to other compilers: accept individual 'push' argument,
+       make final pop restore (command line) default, correct interaction
+       of push/pop and sole specification of a new alignment (so that the
+       sequence #pragma pack(push) - #pragma pack(<n>) becomes identical
+       to #pragma pack(push, <n>).
+       * doc/extend.texi: New node "Structure-Packing Pragmas" under
+       "Pragmas", describing #pragma pack.
+       * doc/invoke.texi: Document -fpack-struct=<n> variant of switch.
+       * doc/tm.texi: Adjust description for HANDLE_PRAGMA_PACK_PUSH_POP.
+       Document new TARGET_DEFAULT_PACK_STRUCT.
+
 2004-09-03  Devang Patel  <dpatel@apple.com>
 
        * dwarf2out.c (gen_field_die). Equate decl number to die.
index 0bf2f1231bc22589fb629cd06f91674fa0cefa68..cb518e0347513fd7441593812ce6a4134eb31161 100644 (file)
@@ -42,7 +42,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 typedef struct align_stack GTY(())
 {
   int                  alignment;
-  unsigned int         num_pushes;
   tree                 id;
   struct align_stack * prev;
 } align_stack;
@@ -59,8 +58,9 @@ static void handle_pragma_pack (cpp_reader *);
    happens, we restore the value to this, not to a value of 0 for
    maximum_field_alignment.  Value is in bits.  */
 static int default_alignment;
-#define SET_GLOBAL_ALIGNMENT(ALIGN) \
-  (default_alignment = maximum_field_alignment = (ALIGN))
+#define SET_GLOBAL_ALIGNMENT(ALIGN) (maximum_field_alignment = *(alignment_stack == NULL \
+       ? &default_alignment \
+       : &alignment_stack->alignment) = (ALIGN))
 
 static void push_alignment (int, tree);
 static void pop_alignment (tree);
@@ -69,31 +69,23 @@ static void pop_alignment (tree);
 static void
 push_alignment (int alignment, tree id)
 {
-  if (alignment_stack == NULL
-      || alignment_stack->alignment != alignment
-      || id != NULL_TREE)
-    {
-      align_stack * entry;
+  align_stack * entry;
 
-      entry = ggc_alloc (sizeof (* entry));
+  entry = ggc_alloc (sizeof (* entry));
 
-      entry->alignment  = alignment;
-      entry->num_pushes = 1;
-      entry->id         = id;
-      entry->prev       = alignment_stack;
-      
-      /* The current value of maximum_field_alignment is not necessarily 
-        0 since there may be a #pragma pack(<n>) in effect; remember it 
-        so that we can restore it after the final #pragma pop().  */
-      if (alignment_stack == NULL)
-       default_alignment = maximum_field_alignment;
-      
-      alignment_stack = entry;
+  entry->alignment  = alignment;
+  entry->id         = id;
+  entry->prev       = alignment_stack;
+       
+  /* The current value of maximum_field_alignment is not necessarily 
+     0 since there may be a #pragma pack(<n>) in effect; remember it 
+     so that we can restore it after the final #pragma pop().  */
+  if (alignment_stack == NULL)
+    default_alignment = maximum_field_alignment;
+  alignment_stack = entry;
 
-      maximum_field_alignment = alignment;
-    }
-  else
-    alignment_stack->num_pushes ++;
+  maximum_field_alignment = alignment;
 }
 
 /* Undo a push of an alignment onto the stack.  */
@@ -103,12 +95,7 @@ pop_alignment (tree id)
   align_stack * entry;
       
   if (alignment_stack == NULL)
-    {
-      warning ("\
-#pragma pack (pop) encountered without matching #pragma pack (push, <n>)"
-              );
-      return;
-    }
+    GCC_BAD("#pragma pack (pop) encountered without matching #pragma pack (push)");
 
   /* If we got an identifier, strip away everything above the target
      entry so that the next step will restore the state just below it.  */
@@ -117,27 +104,20 @@ pop_alignment (tree id)
       for (entry = alignment_stack; entry; entry = entry->prev)
        if (entry->id == id)
          {
-           entry->num_pushes = 1;
            alignment_stack = entry;
            break;
          }
       if (entry == NULL)
        warning ("\
-#pragma pack(pop, %s) encountered without matching #pragma pack(push, %s, <n>)"
+#pragma pack(pop, %s) encountered without matching #pragma pack(push, %s)"
                 , IDENTIFIER_POINTER (id), IDENTIFIER_POINTER (id));
     }
 
-  if (-- alignment_stack->num_pushes == 0)
-    {
-      entry = alignment_stack->prev;
+  entry = alignment_stack->prev;
 
-      if (entry == NULL)
-       maximum_field_alignment = default_alignment;
-      else
-       maximum_field_alignment = entry->alignment;
+  maximum_field_alignment = entry ? entry->alignment : default_alignment;
 
-      alignment_stack = entry;
-    }
+  alignment_stack = entry;
 }
 #else  /* not HANDLE_PRAGMA_PACK_PUSH_POP */
 #define SET_GLOBAL_ALIGNMENT(ALIGN) (maximum_field_alignment = (ALIGN))
@@ -150,7 +130,9 @@ pop_alignment (tree id)
 /* #pragma pack ()
    #pragma pack (N)
    
+   #pragma pack (push)
    #pragma pack (push, N)
+   #pragma pack (push, ID)
    #pragma pack (push, ID, N)
    #pragma pack (pop)
    #pragma pack (pop, ID) */
@@ -169,7 +151,7 @@ handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy))
   if (token == CPP_CLOSE_PAREN)
     {
       action = set;
-      align = 0;
+      align = initial_max_fld_align;
     }
   else if (token == CPP_NUMBER)
     {
@@ -180,8 +162,8 @@ handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy))
     }
   else if (token == CPP_NAME)
     {
-#define GCC_BAD_ACTION do { if (action == push) \
-         GCC_BAD ("malformed '#pragma pack(push[, id], <n>)' - ignored"); \
+#define GCC_BAD_ACTION do { if (action != pop) \
+         GCC_BAD ("malformed '#pragma pack(push[, id][, <n>])' - ignored"); \
        else \
          GCC_BAD ("malformed '#pragma pack(pop[, id])' - ignored"); \
        } while (0)
@@ -194,31 +176,21 @@ handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy))
       else
        GCC_BAD2 ("unknown action '%s' for '#pragma pack' - ignored", op);
 
-      token = c_lex (&x);
-      if (token != CPP_COMMA && action == push)
-       GCC_BAD_ACTION;
-
-      if (token == CPP_COMMA)
+      while ((token = c_lex (&x)) == CPP_COMMA)
        {
          token = c_lex (&x);
-         if (token == CPP_NAME)
+         if (token == CPP_NAME && id == 0)
            {
              id = x;
-             if (action == push && c_lex (&x) != CPP_COMMA)
-               GCC_BAD_ACTION;
-             token = c_lex (&x);
            }
-
-         if (action == push)
+         else if (token == CPP_NUMBER && action == push && align == -1)
            {
-             if (token == CPP_NUMBER)
-               {
-                 align = TREE_INT_CST_LOW (x);
-                 token = c_lex (&x);
-               }
-             else
-               GCC_BAD_ACTION;
+             align = TREE_INT_CST_LOW (x);
+             if (align == -1)
+               action = set;
            }
+         else
+           GCC_BAD_ACTION;
        }
 
       if (token != CPP_CLOSE_PAREN)
@@ -231,6 +203,9 @@ handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy))
   if (c_lex (&x) != CPP_EOF)
     warning ("junk at end of '#pragma pack'");
 
+  if (flag_pack_struct)
+    GCC_BAD ("#pragma pack has no effect with -fpack-struct - ignored");
+
   if (action != pop)
     switch (align)
       {
@@ -242,6 +217,12 @@ handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy))
       case 16:
        align *= BITS_PER_UNIT;
        break;
+      case -1:
+       if (action == push)
+         {
+           align = maximum_field_alignment;
+           break;
+         }
       default:
        GCC_BAD2 ("alignment must be a small power of two, not %d", align);
       }
index c3baf31f484e1dfd1f254a2731db38cdd9550a16..a74921df92a1da224f019a7d8bffd68bed222a4b 100644 (file)
@@ -575,6 +575,10 @@ fpack-struct
 Common Report Var(flag_pack_struct)
 Pack structure members together without holes
 
+fpack-struct=
+Common RejectNegative Joined UInteger
+-fpack-struct=<number> Set initial maximum structure member alignment
+
 fpcc-struct-return
 Common Report Var(flag_pcc_struct_return,1) VarExists
 Return small aggregates in memory, not registers
index d16adf4ad4a8ed891ce8d7d357ae266a1004be71..dd5c21fe2c1993becb4880f08982d294b7997e09 100644 (file)
@@ -476,6 +476,10 @@ do { fputs (integer_asm_op (POINTER_SIZE / BITS_PER_UNIT, TRUE), FILE); \
 #define PREFERRED_STACK_BOUNDARY STACK_BOUNDARY
 #endif
 
+#ifndef TARGET_DEFAULT_PACK_STRUCT
+#define TARGET_DEFAULT_PACK_STRUCT 0
+#endif
+
 /* By default, the C++ compiler will use function addresses in the
    vtable entries.  Setting this nonzero tells the compiler to use
    function descriptors instead.  The value of this macro says how
index 5023f2776d672c4a8561794afc3876961df33747..fe25cd1b0662b7b58bd8bc7724263ba6c2310db6 100644 (file)
@@ -7672,6 +7672,7 @@ for further explanation.
 * Darwin Pragmas::
 * Solaris Pragmas::
 * Symbol-Renaming Pragmas::
+* Structure-Packing Pragmas::
 @end menu
 
 @node ARM Pragmas
@@ -7848,6 +7849,30 @@ labels, but if @code{#pragma extern_prefix} triggers first we have no
 way of knowing that that happened.)
 @end enumerate
 
+@node Structure-Packing Pragmas
+@subsection Structure-Packing Pragmas
+
+For compatibility with Win32, GCC supports as set of @code{#pragma}
+directives which change the maximum alignment of members of structures,
+unions, and classes subsequently defined.  The @var{n} value below always
+is required to be a small power of two and specifies the new alignment
+in bytes.
+
+@enumerate
+@item @code{#pragma pack(@var{n})} simply sets the new alignment.
+@item @code{#pragma pack()} sets the alignment to the one that was in
+effect when compilation started (see also command line option
+@option{-fpack-struct[=<n>]} @pxref{Code Gen Options}).
+@item @code{#pragma pack(push[,@var{n}])} pushes the current alignment
+setting on an internal stack and then optionally sets the new alignment.
+@item @code{#pragma pack(pop)} restores the alignment setting to the one
+saved at the top of the internal stack (and removes that stack entry).
+Note that @code{#pragma pack([@var{n}])} does not influence this internal
+stack; thus it is possible to have @code{#pragma pack(push)} followed by
+multiple @code{#pragma pack(@var{n})} instances and finalized by a single
+@code{#pragma pack(pop)}.
+@end enumerate
+
 @node Unnamed Fields
 @section Unnamed struct/union fields within structs/unions.
 @cindex struct
index 6772ba0917e33b28944faf05f33787e56185e3df..5c0030e141310048ff4f556be0aa0a8f3c595870 100644 (file)
@@ -699,7 +699,7 @@ See S/390 and zSeries Options.
 -fpcc-struct-return  -fpic  -fPIC -fpie -fPIE @gol
 -freg-struct-return  -fshared-data  -fshort-enums @gol
 -fshort-double  -fshort-wchar @gol
--fverbose-asm  -fpack-struct  -fstack-check @gol
+-fverbose-asm  -fpack-struct[=@var{n}]  -fstack-check @gol
 -fstack-limit-register=@var{reg}  -fstack-limit-symbol=@var{sym} @gol
 -fargument-alias  -fargument-noalias @gol
 -fargument-noalias-global  -fleading-underscore @gol
@@ -11789,9 +11789,13 @@ a register in which function values may be returned.
 This flag does not have a negative form, because it specifies a
 three-way choice.
 
-@item -fpack-struct
+@item -fpack-struct[=@var{n}]
 @opindex fpack-struct
-Pack all structure members together without holes.
+Without a value specified, pack all structure members together without
+holes. When a value is specified (which must be a small power of two), pack
+structure members according to this value, representing the maximum
+alignment (that is, objects with default alignment requirements larger than
+this will be output potentially unaligned at the next fitting location.
 
 @strong{Warning:} the @option{-fpack-struct} switch causes GCC to generate
 code that is not binary compatible with code generated without that switch.
index bba444c0fbe9f675ba2be2fd9e10991392881ac2..26724858e9911411aae50921f44465d2e9bb93eb 100644 (file)
@@ -9017,16 +9017,23 @@ of specifically named weak labels, optionally with a value.
 @findex pragma
 @defmac HANDLE_PRAGMA_PACK_PUSH_POP
 Define this macro (to a value of 1) if you want to support the Win32
-style pragmas @samp{#pragma pack(push,@var{n})} and @samp{#pragma
-pack(pop)}.  The @samp{pack(push,@var{n})} pragma specifies the maximum alignment
-(in bytes) of fields within a structure, in much the same way as the
-@samp{__aligned__} and @samp{__packed__} @code{__attribute__}s do.  A
+style pragmas @samp{#pragma pack(push[,@var{n}])} and @samp{#pragma
+pack(pop)}.  The @samp{pack(push,[@var{n}])} pragma specifies the maximum
+alignment (in bytes) of fields within a structure, in much the same way as
+the @samp{__aligned__} and @samp{__packed__} @code{__attribute__}s do.  A
 pack value of zero resets the behavior to the default.  Successive
 invocations of this pragma cause the previous values to be stacked, so
 that invocations of @samp{#pragma pack(pop)} will return to the previous
 value.
 @end defmac
 
+@defmac TARGET_DEFAULT_PACK_STRUCT
+If your target requires a structure packing default other than 0 (meaning
+the machine default), define this macro the the necessary value (in bytes).
+This must be a value that would also valid to be used with
+@samp{#pragma pack()} (that is, a small power of two).
+@end defmac
+
 @defmac DOLLARS_IN_IDENTIFIERS
 Define this macro to control use of the character @samp{$} in
 identifier names for the C family of languages.  0 means @samp{$} is
index 3c4982735126c31cfb4e8f5bdb3a633ae48fee2d..e0271287c5edfe4b22702b1827aad793c8cc0651 100644 (file)
@@ -810,6 +810,16 @@ common_handle_option (size_t scode, const char *arg, int value)
       pp_set_line_maximum_length (global_dc->printer, value);
       break;
 
+    case OPT_fpack_struct_:
+      if (value <= 0 || (value & (value - 1)) || value > 16)
+       error("structure alignment must be a small power of two, not %d", value);
+      else
+       {
+         initial_max_fld_align = value;
+         maximum_field_alignment = value * BITS_PER_UNIT;
+       }
+      break;
+
     case OPT_fpeel_loops:
       flag_peel_loops_set = true;
       break;
index 395a5f948cba0ab8ca9e74570bc20b455a18b466..75ff523c6a10b2558dae2280b0313273115e1a16 100644 (file)
@@ -43,7 +43,9 @@ tree sizetype_tab[(int) TYPE_KIND_LAST];
 
 /* If nonzero, this is an upper limit on alignment of structure fields.
    The value is measured in bits.  */
-unsigned int maximum_field_alignment;
+unsigned int maximum_field_alignment = TARGET_DEFAULT_PACK_STRUCT * BITS_PER_UNIT;
+/* ... and its original value in bytes, specified via -fpack-struct=<value>. */
+unsigned int initial_max_fld_align = TARGET_DEFAULT_PACK_STRUCT;
 
 /* If nonzero, the alignment of a bitstring or (power-)set value, in bits.
    May be overridden by front-ends.  */
index 6e8ef6c719e338af8bce9474a649f086c8260790..c4a03852763041a9324de375940f789901eacd1c 100644 (file)
@@ -1,3 +1,11 @@
+2004-09-03  Jan Beulich  <jbeulich@novell.com>
+
+       * gcc.dg/pack-test-2.c: Adjust to permit and check #pragma pack(push).
+       * gcc.dg/c99-flex-array-4.c: Add -fpack-struct=8 to provide a
+       deterministic starting point for the alignment of structure fields.
+       * gcc.dg/Wpadded.c: Dito.
+       * g++.dg/abi/vbase10.C: Dito.
+
 2004-09-03  Devang Patel  <dpatel@apple.com>
 
        * g++.dg/debug/pr15736.cc: New test.
index a0d113ade79bae3f9007f4ff82292a245642d7e8..b6e7f88fcaa2990a36d62310da1c72617f421dd4 100644 (file)
@@ -1,5 +1,7 @@
 // { dg-do compile }
-// { dg-options "-Wabi -fabi-version=1" }
+// -fpack-struct is necessary because the code below assumes the initial
+// packing is larger than 1, which cannot ge guaranteed for all targets.
+// { dg-options "-Wabi -fabi-version=1 -fpack-struct=8" }
 // On ARM processors, the alignment of B will be 4 even though it
 // contains only a single "char".  That would avoids the situation
 // that the warning below is designed to catch.  We therefore
index 74376e52828c9eb75ef0578a644d3f5a83de9d2f..e55fd113f7576d67822331ec9f057bb5f22701d1 100644 (file)
@@ -1,7 +1,9 @@
 /* Source: EMC.  */
 
 /* { dg-do compile } */
-/* { dg-options "-Wpadded" } */
+/* -fpack-struct is necessary because the warning expected requires the initial
+   packing to be larger than 1, which cannot ge guaranteed for all targets. */
+/* { dg-options "-Wpadded -fpack-struct=8" } */
 
 struct foo {
   char bar;
index ab20cf07cc468dd72ab9a22067938456a59cdaba..c4a0564b59961142146c5d44a299f30b114142f3 100644 (file)
@@ -5,7 +5,9 @@
    from Tony Finch <dot@dotat.at>, adapted to a testcase by Joseph Myers
    <jsm28@cam.ac.uk>.  See also WG14 reflector messages 9571-3.  */
 /* { dg-do compile } */
-/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
+/* -fpack-struct is necessary because the code below assumes the initial
+   packing is larger than 1, which cannot ge guaranteed for all targets. */
+/* { dg-options "-std=iso9899:1999 -fpack-struct=8 -pedantic-errors" } */
 
 #include <stddef.h>
 
index f15ac842bb4095a8730c4e4d8fd6c4b6f4dcd2c2..974d982c5055320abb20823d1afb5645bdbf7506 100644 (file)
@@ -3,9 +3,11 @@
 
 /* { dg-do compile { target *-*-linux* *-*-cygwin* powerpc*-*-eabi* } } */
 
-#pragma pack(push)              /* { dg-error "malformed" } */
 #pragma pack(pop)               /* { dg-error "without matching" } */
 
+#pragma pack(push)
+#pragma pack(pop)               /* reset */
+
 #pragma pack(push, foo, 1)
 #pragma pack(pop, foo, 1)       /* { dg-error "malformed" } (/
 #pragma pack(pop)               /* reset */
index 9c0fc85f50f5b1f3ae708da04d6a4beb78c13470..0f619b0c62df305c04bd2a0ccaa3d1e14d5bdb22 100644 (file)
@@ -3102,8 +3102,10 @@ extern void put_pending_sizes (tree);
    + (BITS_PER_UNIT > 8) + (BITS_PER_UNIT > 16) + (BITS_PER_UNIT > 32) \
    + (BITS_PER_UNIT > 64) + (BITS_PER_UNIT > 128) + (BITS_PER_UNIT > 256))
 
-/* If nonzero, an upper limit on alignment of structure fields, in bits.  */
+/* If nonzero, an upper limit on alignment of structure fields, in bits,  */
 extern unsigned int maximum_field_alignment;
+/* and its original value in bytes, specified via -fpack-struct=<value>. */
+extern unsigned int initial_max_fld_align;
 
 /* If nonzero, the alignment of a bitstring or (power-)set value, in bits.  */
 extern unsigned int set_alignment;