From: Mike Coleman Date: Sat, 28 Oct 2000 00:04:11 +0000 (+0000) Subject: c-pragma.c (handle_pragma_pack): Initialize align to -1. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=63eb1269483a23914c535d12afd5b5e0f4e02391;p=gcc.git c-pragma.c (handle_pragma_pack): Initialize align to -1. 2000-10-21 Mike Coleman * 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d23a4e2cf26..ff659375336 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2000-10-21 Mike Coleman + + * 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 * cpp.texi: Update. diff --git a/gcc/c-pragma.c b/gcc/c-pragma.c index 8503f3cacca..a9f41f91aa6 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() if effect when the first - #pragma push(pack,) is encountered, this stores the the value of +/* If we have a "global" #pragma pack() in effect when the first + #pragma pack(push,) 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], )' - 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], )' - 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], )' - 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], )' - 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 00000000000..1ceee99a7f9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pack-test-1.c @@ -0,0 +1,146 @@ +/* Test semantics of #pragma pack. + Contributed by Mike Coleman */ + +/* { 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 + +/* 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 00000000000..f4889fabef6 --- /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 00000000000..65960ed9d36 --- /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 */ + +/* { 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" */