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:
Mike Coleman 2000-10-28 00:04:11 +00:00 committed by Zack Weinberg
parent ae2eceaad2
commit 63eb126948
5 changed files with 240 additions and 30 deletions

View File

@ -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.

View File

@ -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)
{

View 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);
}

View 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;
};

View 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" */