aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMike Coleman <mcoleman2@kc.rr.com>2000-10-28 00:04:11 +0000
committerZack Weinberg <zack@gcc.gnu.org>2000-10-28 00:04:11 +0000
commit63eb1269483a23914c535d12afd5b5e0f4e02391 (patch)
tree72e1c2ef417dd127c4cd13c98dac0385b812a71e /gcc
parentae2eceaad2f95f7228e69ab5513f355e868ab787 (diff)
downloadgcc-63eb1269483a23914c535d12afd5b5e0f4e02391.zip
gcc-63eb1269483a23914c535d12afd5b5e0f4e02391.tar.gz
gcc-63eb1269483a23914c535d12afd5b5e0f4e02391.tar.bz2
c-pragma.c (handle_pragma_pack): Initialize align to -1.
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. From-SVN: r37095
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/c-pragma.c78
-rw-r--r--gcc/testsuite/gcc.dg/pack-test-1.c146
-rw-r--r--gcc/testsuite/gcc.dg/pack-test-1.h12
-rw-r--r--gcc/testsuite/gcc.dg/pack-test-2.c23
5 files changed, 240 insertions, 30 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d23a4e2..ff65937 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+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.
+
2000-10-27 Neil Booth <neilb@earthling.net>
* cpp.texi: Update.
diff --git a/gcc/c-pragma.c b/gcc/c-pragma.c
index 8503f3c..a9f41f9 100644
--- a/gcc/c-pragma.c
+++ b/gcc/c-pragma.c
@@ -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 (token == CPP_NUMBER)
- align = TREE_INT_CST_LOW (x);
- else
- BAD2 ("malformed '#pragma pack(%s[, id], <n>)' - ignored", op);
+ if (action == push)
+ {
+ if (token == CPP_NUMBER)
+ {
+ align = TREE_INT_CST_LOW (x);
+ token = c_lex (&x);
+ }
+ else
+ BAD_ACTION;
+ }
+ }
- 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)
{
diff --git a/gcc/testsuite/gcc.dg/pack-test-1.c b/gcc/testsuite/gcc.dg/pack-test-1.c
new file mode 100644
index 0000000..1ceee99
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pack-test-1.c
@@ -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);
+}
diff --git a/gcc/testsuite/gcc.dg/pack-test-1.h b/gcc/testsuite/gcc.dg/pack-test-1.h
new file mode 100644
index 0000000..f4889fa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pack-test-1.h
@@ -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;
+};
diff --git a/gcc/testsuite/gcc.dg/pack-test-2.c b/gcc/testsuite/gcc.dg/pack-test-2.c
new file mode 100644
index 0000000..65960ed
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pack-test-2.c
@@ -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" */