aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/c-common.c34
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/pack-test-3.c44
4 files changed, 74 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0db1664..85eab61 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2003-07-16 Nathan Sidwell <nathan@codesourcery.com>
+
+ * 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 <neroden@gcc.gnu.org>
* Makefile.in (install-common): Add dependency on installdirs.
diff --git a/gcc/c-common.c b/gcc/c-common.c
index c33e632..b5d6651 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 ec60181..25fd059 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2003-07-22 Nathan Sidwell <nathan@codesourcery.com>
+
+ * gcc.dg/pack-test-3.c: New test.
+
2003-07-21 Janis Johnson <janis187@us.ibm.com>
* 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 0000000..8b03903
--- /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 <nathan@codesourcery.com> */
+
+/* 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" "" }*/
+