From: Nathan Sidwell Date: Tue, 22 Jul 2003 09:26:01 +0000 (+0000) Subject: c-common.c (handle_packed_attribute): Don't pack a struct via a typedef. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c6e4cc53e53de0f671b715bfb83f37dbf73aaf2f;p=gcc.git c-common.c (handle_packed_attribute): Don't pack a struct via a typedef. * c-common.c (handle_packed_attribute): Don't pack a struct via a typedef. Propagate packedness from a main variant. testsuite: * gcc.dg/pack-test-3.c: New test. From-SVN: r69668 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0db16641e58..85eab61d0cf 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2003-07-16 Nathan Sidwell + + * c-common.c (handle_packed_attribute): Don't pack a struct via a + typedef. Propagate packedness from a main variant. + 2003-07-22 Nathanael Nerode * Makefile.in (install-common): Add dependency on installdirs. diff --git a/gcc/c-common.c b/gcc/c-common.c index c33e6326527..b5d6651ade4 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -4534,25 +4534,33 @@ static tree handle_packed_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED, int flags, bool *no_add_attrs) { - tree *type = NULL; - if (DECL_P (*node)) - { - if (TREE_CODE (*node) == TYPE_DECL) - type = &TREE_TYPE (*node); - } - else - type = node; - - if (type) + if (TYPE_P (*node)) { if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) - *type = build_type_copy (*type); - TYPE_PACKED (*type) = 1; + *node = build_type_copy (*node); + TYPE_PACKED (*node) = 1; + if (TYPE_MAIN_VARIANT (*node) == *node) + { + /* If it is the main variant, then pack the other variants + too. This happens in, + + struct Foo { + struct Foo const *ptr; // creates a variant w/o packed flag + } __ attribute__((packed)); // packs it now. + */ + tree probe; + + for (probe = *node; probe; probe = TYPE_NEXT_VARIANT (probe)) + TYPE_PACKED (probe) = 1; + } + } else if (TREE_CODE (*node) == FIELD_DECL) DECL_PACKED (*node) = 1; /* We can't set DECL_PACKED for a VAR_DECL, because the bit is - used for DECL_REGISTER. It wouldn't mean anything anyway. */ + used for DECL_REGISTER. It wouldn't mean anything anyway. + We can't set DECL_PACKED on the type of a TYPE_DECL, because + that changes what the typedef is typing. */ else { warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ec601810919..25fd05966c1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2003-07-22 Nathan Sidwell + + * gcc.dg/pack-test-3.c: New test. + 2003-07-21 Janis Johnson * lib/compat.exp: Handle dg-options per source file. diff --git a/gcc/testsuite/gcc.dg/pack-test-3.c b/gcc/testsuite/gcc.dg/pack-test-3.c new file mode 100644 index 00000000000..8b0390378b3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pack-test-3.c @@ -0,0 +1,44 @@ +/* { dg-do compile } */ + +/* Copyright (C) 2003 Free Software Foundation, Inc. + Contributed by Nathan Sidwell 15 Jul 2003 */ + +/* you should not be able to pack a typedef to a struct, only the + underlying struct can be packed. */ + +/* ok */ +struct u1 +{ + char field1; + short field2; + int field3; +}; + +/* ok */ +typedef struct p1 { + char field1; + short field2; + int field3; +} __attribute__ ((packed)) p1_t1; + +/* ok */ +typedef struct __attribute__ ((packed)) p2 { + char field1; + short field2; + int field3; +} p2_t1; + +int ary1[sizeof (struct p1) == sizeof (p1_t1) ? 1 : -1]; +int ary2[sizeof (struct p2) == sizeof (p2_t1) ? 1 : -1]; +int ary3[sizeof (struct p1) == sizeof (struct p2) ? 1 : -1]; + +/* not ok */ +typedef struct u1 __attribute__ ((packed)) u1_t1; /* { dg-warning "attribute ignored" "" }*/ +typedef struct u1 u1_t2 __attribute__ ((packed)); /* { dg-warning "attribute ignored" "" }*/ + +typedef struct p3 { + char field1; + short field2; + int field3; +} p3_t1 __attribute__ ((packed)); /* { dg-warning "attribute ignored" "" }*/ +