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>
|
2000-10-27 Neil Booth <neilb@earthling.net>
|
||||||
|
|
||||||
* cpp.texi: Update.
|
* cpp.texi: Update.
|
||||||
|
@ -60,8 +60,8 @@ typedef struct align_stack
|
|||||||
|
|
||||||
static struct align_stack * alignment_stack = NULL;
|
static struct align_stack * alignment_stack = NULL;
|
||||||
|
|
||||||
/* If we have a "global" #pragma pack(<n>) if effect when the first
|
/* If we have a "global" #pragma pack(<n>) in effect when the first
|
||||||
#pragma push(pack,<n>) is encountered, this stores the the value of
|
#pragma pack(push,<n>) is encountered, this stores the value of
|
||||||
maximum_field_alignment in effect. When the final pop_alignment()
|
maximum_field_alignment in effect. When the final pop_alignment()
|
||||||
happens, we restore the value to this, not to a value of 0 for
|
happens, we restore the value to this, not to a value of 0 for
|
||||||
maximum_field_alignment. Value is in bits. */
|
maximum_field_alignment. Value is in bits. */
|
||||||
@ -186,7 +186,7 @@ handle_pragma_pack (dummy)
|
|||||||
cpp_reader *dummy ATTRIBUTE_UNUSED;
|
cpp_reader *dummy ATTRIBUTE_UNUSED;
|
||||||
{
|
{
|
||||||
tree x, id = 0;
|
tree x, id = 0;
|
||||||
int align;
|
int align = -1;
|
||||||
enum cpp_ttype token;
|
enum cpp_ttype token;
|
||||||
enum { set, push, pop } action;
|
enum { set, push, pop } action;
|
||||||
|
|
||||||
@ -208,6 +208,12 @@ handle_pragma_pack (dummy)
|
|||||||
}
|
}
|
||||||
else if (token == CPP_NAME)
|
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);
|
const char *op = IDENTIFIER_POINTER (x);
|
||||||
if (!strcmp (op, "push"))
|
if (!strcmp (op, "push"))
|
||||||
action = push;
|
action = push;
|
||||||
@ -216,25 +222,36 @@ handle_pragma_pack (dummy)
|
|||||||
else
|
else
|
||||||
BAD2 ("unknown action '%s' for '#pragma pack' - ignored", op);
|
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);
|
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);
|
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)
|
if (token != CPP_CLOSE_PAREN)
|
||||||
align = TREE_INT_CST_LOW (x);
|
BAD_ACTION;
|
||||||
else
|
#undef BAD_ACTION
|
||||||
BAD2 ("malformed '#pragma pack(%s[, id], <n>)' - ignored", op);
|
|
||||||
|
|
||||||
if (c_lex (&x) != CPP_CLOSE_PAREN)
|
|
||||||
BAD ("malformed '#pragma pack' - ignored");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
BAD ("malformed '#pragma pack' - ignored");
|
BAD ("malformed '#pragma pack' - ignored");
|
||||||
@ -242,19 +259,20 @@ handle_pragma_pack (dummy)
|
|||||||
if (c_lex (&x) != CPP_EOF)
|
if (c_lex (&x) != CPP_EOF)
|
||||||
warning ("junk at end of '#pragma pack'");
|
warning ("junk at end of '#pragma pack'");
|
||||||
|
|
||||||
switch (align)
|
if (action != pop)
|
||||||
{
|
switch (align)
|
||||||
case 0:
|
{
|
||||||
case 1:
|
case 0:
|
||||||
case 2:
|
case 1:
|
||||||
case 4:
|
case 2:
|
||||||
case 8:
|
case 4:
|
||||||
case 16:
|
case 8:
|
||||||
align *= BITS_PER_UNIT;
|
case 16:
|
||||||
break;
|
align *= BITS_PER_UNIT;
|
||||||
default:
|
break;
|
||||||
BAD2 ("alignment must be a small power of two, not %d", align);
|
default:
|
||||||
}
|
BAD2 ("alignment must be a small power of two, not %d", align);
|
||||||
|
}
|
||||||
|
|
||||||
switch (action)
|
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…
x
Reference in New Issue
Block a user