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
This commit is contained in:
parent
ae2eceaad2
commit
63eb126948
@ -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.
|
||||
|
@ -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)
|
||||
{
|
||||
|
146
gcc/testsuite/gcc.dg/pack-test-1.c
Normal file
146
gcc/testsuite/gcc.dg/pack-test-1.c
Normal file
@ -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);
|
||||
}
|
12
gcc/testsuite/gcc.dg/pack-test-1.h
Normal file
12
gcc/testsuite/gcc.dg/pack-test-1.h
Normal file
@ -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;
|
||||
};
|
23
gcc/testsuite/gcc.dg/pack-test-2.c
Normal file
23
gcc/testsuite/gcc.dg/pack-test-2.c
Normal file
@ -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" */
|
Loading…
Reference in New Issue
Block a user