This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: fix handling of '#pragma pack(pop [, id])'


Following up to myself: here's a corrected version of Mike's patch
(only style issues) and test cases suitable for inclusion in gcc.dg.
Anyone care to approve?

zw

2000-10-21  Mike Coleman  <mcoleman2@kc.rr.com>

	* c-pragma.c (handle_pragma_pack): Initialize align to -1.
	Improve error messages.  Correct parsing of 
	#pragma pack(pop [,id]).  Do not check the user-supplied
	alignment if we're popping.

	* gcc.dg/pack-test-1.c: New test case.
	* gcc.dg/pack-test-2.c: New test case.
	* gcc.dg/pack-test-1.h: New file.

===================================================================
Index: c-pragma.c
--- c-pragma.c	2000/09/11 04:29:58	1.37
+++ c-pragma.c	2000/10/21 18:54:52
@@ -60,8 +60,8 @@ typedef struct align_stack
 
 static struct align_stack * alignment_stack = NULL;
 
-/* If we have a "global" #pragma pack(<n>) if effect when the first
-   #pragma push(pack,<n>) is encountered, this stores the the value of 
+/* If we have a "global" #pragma pack(<n>) in effect when the first
+   #pragma pack(push,<n>) is encountered, this stores the value of 
    maximum_field_alignment in effect.  When the final pop_alignment() 
    happens, we restore the value to this, not to a value of 0 for
    maximum_field_alignment.  Value is in bits. */
@@ -186,7 +186,7 @@ handle_pragma_pack (dummy)
      cpp_reader *dummy ATTRIBUTE_UNUSED;
 {
   tree x, id = 0;
-  int align;
+  int align = -1;
   enum cpp_ttype token;
   enum { set, push, pop } action;
 
@@ -208,6 +208,12 @@ handle_pragma_pack (dummy)
     }
   else if (token == CPP_NAME)
     {
+#define BAD_ACTION do { if (action == push) \
+	  BAD ("malformed '#pragma pack(push[, id], <n>)' - ignored"); \
+	else \
+	  BAD ("malformed '#pragma pack(pop[, id])' - ignored"); \
+	} while (0)
+
       const char *op = IDENTIFIER_POINTER (x);
       if (!strcmp (op, "push"))
 	action = push;
@@ -216,25 +222,36 @@ handle_pragma_pack (dummy)
       else
 	BAD2 ("unknown action '%s' for '#pragma pack' - ignored", op);
 
-      if (c_lex (&x) != CPP_COMMA)
-	BAD2 ("malformed '#pragma pack(%s[, id], <n>)' - ignored", op);
-
       token = c_lex (&x);
-      if (token == CPP_NAME)
+      if (token != CPP_COMMA && action == push)
+	BAD_ACTION;
+
+      if (token == CPP_COMMA)
 	{
-	  id = x;
-	  if (c_lex (&x) != CPP_COMMA)
-	    BAD2 ("malformed '#pragma pack(%s[, id], <n>)' - ignored", op);
 	  token = c_lex (&x);
+	  if (token == CPP_NAME)
+	    {
+	      id = x;
+	      if (action == push && c_lex (&x) != CPP_COMMA)
+		BAD_ACTION;
+	      token = c_lex (&x);
+	    }
+
+	  if (action == push)
+	    {
+	      if (token == CPP_NUMBER)
+		{
+		  align = TREE_INT_CST_LOW (x);
+		  token = c_lex (&x);
+		}
+	      else
+		BAD_ACTION;
+	    }
 	}
-
-      if (token == CPP_NUMBER)
-	align = TREE_INT_CST_LOW (x);
-      else
-	BAD2 ("malformed '#pragma pack(%s[, id], <n>)' - ignored", op);
 
-      if (c_lex (&x) != CPP_CLOSE_PAREN)
-	BAD ("malformed '#pragma pack' - ignored");
+      if (token != CPP_CLOSE_PAREN)
+	BAD_ACTION;
+#undef BAD_ACTION
     }
   else
     BAD ("malformed '#pragma pack' - ignored");
@@ -242,19 +259,20 @@ handle_pragma_pack (dummy)
   if (c_lex (&x) != CPP_EOF)
     warning ("junk at end of '#pragma pack'");
 
-  switch (align)
-    {
-    case 0:
-    case 1:
-    case 2:
-    case 4:
-    case 8:
-    case 16:
-      align *= BITS_PER_UNIT;
-      break;
-    default:
-      BAD2 ("alignment must be a small power of two, not %d", align);
-    }
+  if (action != pop)
+    switch (align)
+      {
+      case 0:
+      case 1:
+      case 2:
+      case 4:
+      case 8:
+      case 16:
+	align *= BITS_PER_UNIT;
+	break;
+      default:
+	BAD2 ("alignment must be a small power of two, not %d", align);
+      }
 
   switch (action)
     {
===================================================================
Index: testsuite/gcc.dg/pack-test-1.c
--- testsuite/gcc.dg/pack-test-1.c	Tue May  5 13:32:27 1998
+++ testsuite/gcc.dg/pack-test-1.c	Sat Oct 21 11:54:59 2000
@@ -0,0 +1,146 @@
+/* Test semantics of #pragma pack.
+   Contributed by Mike Coleman <mcoleman2@kc.rr.com> */
+
+/* { dg-do compile { target *-*-linux* *-*-cygwin* } } */
+
+/* We only test the alignment of char, short, and int, because these
+   are the only ones that are pretty certain to be the same across
+   platforms (and maybe not even those).  Mainly we're just testing
+   whether pushing and popping seem to be working correctly, and
+   verifying the (alignment == 1) case, which is really the only
+   reason anyone would use this pragma anyway.
+*/
+
+#include <stddef.h>
+
+/* gap in bytes between fields a and b in struct s */
+#define gap(s, a, b) (offsetof(struct s, a) - offsetof(struct s, b))
+/* generalized compile-time test expression */
+#define test(n, expr) int test_##n [(expr) ? 1 : -1]
+/* test a gap */
+#define testgap(n, a, b, val) test(n, gap(SNAME, a, b) == val)
+
+#define SNAME s0
+#include "pack-test-1.h"
+
+/* Save original alignment values.  Can't use const ints because they
+   won't be expanded and we'll get bogus errors about variable length
+   arrays.  (Possible bug in C front end?)  Use s0, not SNAME, so these
+   won't change later.  */
+#define al1 gap(s0, f1, f0)
+#define al2 gap(s0, f2, f1)
+#define al3 gap(s0, f3, f2)
+#define al4 gap(s0, f4, f3)
+#define al5 gap(s0, f5, f4)
+#define al6 gap(s0, f6, f5)
+#define al7 gap(s0, f7, f6)
+
+#undef SNAME
+#define SNAME s1
+#pragma pack(push, p1, 1)
+#include "pack-test-1.h"
+
+void SNAME() {
+  testgap(0, f1, f0, sizeof(char));
+  testgap(1, f3, f2, sizeof(short));
+  testgap(2, f5, f4, sizeof(int));
+}
+
+#undef SNAME
+#define SNAME s2
+#pragma pack(push, p2, 2)
+#include "pack-test-1.h"
+
+void SNAME() {
+  testgap(0, f1, f0, sizeof(short));
+  testgap(1, f3, f2, sizeof(short));
+  testgap(2, f5, f4, sizeof(int));
+}
+
+#undef SNAME
+#define SNAME s3
+#pragma pack(push, p3, 4)
+#include "pack-test-1.h"
+
+void SNAME() {
+  testgap(0, f1, f0, sizeof(int));
+  testgap(1, f3, f2, sizeof(int));
+  testgap(2, f5, f4, sizeof(int));
+}
+
+#undef SNAME
+#define SNAME s4
+#pragma pack(pop)
+#include "pack-test-1.h"
+
+void SNAME() {
+  testgap(0, f1, f0, sizeof(short));
+  testgap(1, f3, f2, sizeof(short));
+  testgap(2, f5, f4, sizeof(int));
+}
+
+#undef SNAME
+#define SNAME s5
+#pragma pack(pop, p2)
+#include "pack-test-1.h"
+
+void SNAME() {
+  testgap(0, f1, f0, sizeof(char));
+  testgap(1, f3, f2, sizeof(short));
+  testgap(2, f5, f4, sizeof(int));
+}
+
+#undef SNAME
+#define SNAME s6
+#pragma pack(pop, p1)
+#include "pack-test-1.h"
+
+void SNAME() {
+  testgap(0, f1, f0, al1);
+  testgap(1, f3, f2, al3);
+  testgap(2, f5, f4, al5);
+}
+
+#undef SNAME
+#define SNAME s7
+#pragma pack(1)
+#include "pack-test-1.h"
+
+void SNAME() {
+  testgap(0, f1, f0, sizeof(char));
+  testgap(1, f3, f2, sizeof(short));
+  testgap(2, f5, f4, sizeof(int));
+}
+
+#undef SNAME
+#define SNAME s8
+#pragma pack(push, p2, 2)
+#include "pack-test-1.h"
+
+void SNAME() {
+  testgap(0, f1, f0, sizeof(short));
+  testgap(1, f3, f2, sizeof(short));
+  testgap(2, f5, f4, sizeof(int));
+}
+
+#undef SNAME
+#define SNAME s9
+#pragma pack(pop)
+#include "pack-test-1.h"
+
+void SNAME() {
+  testgap(0, f1, f0, sizeof(char));
+  testgap(1, f3, f2, sizeof(short));
+  testgap(2, f5, f4, sizeof(int));
+}
+
+#undef SNAME
+#define SNAME s10
+#pragma pack()
+#include "pack-test-1.h"
+
+void SNAME() {
+  testgap(0, f1, f0, al1);
+  testgap(1, f3, f2, al3);
+  testgap(2, f5, f4, al5);
+}
===================================================================
Index: testsuite/gcc.dg/pack-test-1.h
--- testsuite/gcc.dg/pack-test-1.h	Tue May  5 13:32:27 1998
+++ testsuite/gcc.dg/pack-test-1.h	Sat Oct 21 11:54:59 2000
@@ -0,0 +1,12 @@
+/* Helper file, included repeatedly by pack-test-1.c.  */
+
+struct SNAME {
+  char f0;
+  double f1;
+  short f2;
+  double f3;
+  int f4;
+  double f5;
+  double f6;
+  double f7;
+};
===================================================================
Index: testsuite/gcc.dg/pack-test-2.c
--- testsuite/gcc.dg/pack-test-2.c	Tue May  5 13:32:27 1998
+++ testsuite/gcc.dg/pack-test-2.c	Sat Oct 21 11:54:59 2000
@@ -0,0 +1,23 @@
+/* Tests for syntax checking of #pragma pack.
+   Contributed by Mike Coleman <mcoleman2@kc.rr.com> */
+
+/* { dg-do compile { target *-*-linux* *-*-cygwin* } } */
+
+#pragma pack(push)              /* { dg-error "malformed" } */
+#pragma pack(pop)               /* { dg-error "without matching" } */
+
+#pragma pack(push, foo, 1)
+#pragma pack(pop, foo, 1)       /* { dg-error "malformed" } (/
+#pragma pack(pop)               /* reset */
+
+#pragma pack(push, foo, 1)
+#pragma pack(pop, bar)          /* { dg-error "without matching" } */
+#pragma pack(pop)               /* reset */
+
+#pragma pack(push, foo, 1)
+#pragma pack(pop)
+#pragma pack(pop, foo)          /* { dg-error "without matching" } */
+
+#pragma pack(push, foo, 3)      /* { dg-error "small power of two" } */
+
+extern int blah;	/* prevent "ISO C forbids an empty source file" */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]