diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0b0ef57d94e4d9d8644f7d869212adcbf7b49386..a62e378d102c9f01ea9ac70dc916809e7704397d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+2006-09-23  Jakub Jelinek  <jakub@redhat.com>
+
+	PR c/28706
+	PR c/28712
+	* tree.c (merge_attributes, attribute_list_contained): If both
+	TREE_VALUEs are TREE_LISTs, use simple_cst_list_equal instead of
+	simple_cst_equal.
+	* c-typeck.c (comptypes_internal): Don't consider aggregates
+	in different TUs as compatible if there one set of attributes is
+	not a subset of the other type's attributes.
+	(composite_type): Try harder not to create a new aggregate type.
+
 2006-09-22  Geoffrey Keating  <geoffk@apple.com>
 
 	* config/i386/driver-i386.c: Always define host_detect_local_cpu.
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 42e01d2af5298e9abebdc8fd3af9419dbd462fa1..00537ac3f4c6ad08a726caf31c0ec1dcbb3df070 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -375,6 +375,19 @@ composite_type (tree t1, tree t2)
 	return build_type_attribute_variant (t1, attributes);
       }
 
+    case ENUMERAL_TYPE:
+    case RECORD_TYPE:
+    case UNION_TYPE:
+      if (attributes != NULL)
+	{
+	  /* Try harder not to create a new aggregate type.  */
+	  if (attribute_list_equal (TYPE_ATTRIBUTES (t1), attributes))
+	    return t1;
+	  if (attribute_list_equal (TYPE_ATTRIBUTES (t2), attributes))
+	    return t2;
+	}
+      return build_type_attribute_variant (t1, attributes);
+
     case FUNCTION_TYPE:
       /* Function types: prefer the one that specified arg types.
 	 If both do, merge the arg types.  Also merge the return types.  */
@@ -891,6 +904,13 @@ comptypes_internal (tree type1, tree type2)
     case UNION_TYPE:
       if (val != 1 && !same_translation_unit_p (t1, t2))
 	{
+	  tree a1 = TYPE_ATTRIBUTES (t1);
+	  tree a2 = TYPE_ATTRIBUTES (t2);
+
+	  if (! attribute_list_contained (a1, a2)
+	      && ! attribute_list_contained (a2, a1))
+	    break;
+
 	  if (attrval != 2)
 	    return tagged_types_tu_compatible_p (t1, t2);
 	  val = tagged_types_tu_compatible_p (t1, t2);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 55a77b43d4f8b9cd9eeefa2a83c3cdbc6daead4b..e6c4a117b31d59a607f1656c6d5df4ea0e3def7e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2006-09-23  Jakub Jelinek  <jakub@redhat.com>
+
+	PR c/28706
+	* gcc.dg/pr28706.c: New test.
+
+	PR c/28712
+	* gcc.dg/pr28712.c: New test.
+
 2006-09-22  Mike Stump  <mrs@apple.com>
 
 	* obj-c++.dg/encode-3.mm: Fix for 64-bit support.
diff --git a/gcc/testsuite/gcc.dg/pr28706.c b/gcc/testsuite/gcc.dg/pr28706.c
new file mode 100644
index 0000000000000000000000000000000000000000..4c185af41237efe14b1045ce53f21270ec7c4d7b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr28706.c
@@ -0,0 +1,12 @@
+/* PR c/28706 */
+/* { dg-do compile } */
+/* { dg-options "--combine" } */
+/* { dg-additional-sources "pr28706.c" } */
+
+struct A
+{
+  int i;
+} __attribute__((aligned (sizeof (long int))));
+
+extern void foo (struct A *);
+extern void foo (struct A *);
diff --git a/gcc/testsuite/gcc.dg/pr28712.c b/gcc/testsuite/gcc.dg/pr28712.c
new file mode 100644
index 0000000000000000000000000000000000000000..0bbb45314cf1e611a0b1a5651d2db2c1a57ef7b0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr28712.c
@@ -0,0 +1,16 @@
+/* PR c/28712 */
+/* { dg-do compile } */
+/* { dg-options "--combine" } */
+/* { dg-additional-sources "pr28712.c pr28712.c" } */
+
+struct A;
+
+extern struct A *a;
+
+struct A { } __attribute__((packed));
+
+struct B __attribute__((aligned (sizeof (int))));
+
+extern struct B *b;
+
+struct B { int i; } __attribute__((packed));
diff --git a/gcc/tree.c b/gcc/tree.c
index a58c3274c4bf0db876d3feadd315ea282c62f975..cfbfe1462b651cda82a10f56b800e8bf5c8273cb 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -3554,7 +3554,17 @@ merge_attributes (tree a1, tree a2)
 		   a = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
 					 TREE_CHAIN (a)))
 		{
-		  if (simple_cst_equal (TREE_VALUE (a), TREE_VALUE (a2)) == 1)
+		  if (TREE_VALUE (a) != NULL
+		      && TREE_CODE (TREE_VALUE (a)) == TREE_LIST
+		      && TREE_VALUE (a2) != NULL
+		      && TREE_CODE (TREE_VALUE (a2)) == TREE_LIST)
+		    {
+		      if (simple_cst_list_equal (TREE_VALUE (a),
+						 TREE_VALUE (a2)) == 1)
+			break;
+		    }
+		  else if (simple_cst_equal (TREE_VALUE (a),
+					     TREE_VALUE (a2)) == 1)
 		    break;
 		}
 	      if (a == NULL_TREE)
@@ -4374,15 +4384,21 @@ attribute_list_contained (tree l1, tree l2)
 	   attr = lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (t2)),
 				    TREE_CHAIN (attr)))
 	{
-	  if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) == 1)
+	  if (TREE_VALUE (t2) != NULL
+	      && TREE_CODE (TREE_VALUE (t2)) == TREE_LIST
+	      && TREE_VALUE (attr) != NULL
+	      && TREE_CODE (TREE_VALUE (attr)) == TREE_LIST)
+	    {
+	      if (simple_cst_list_equal (TREE_VALUE (t2),
+					 TREE_VALUE (attr)) == 1)
+		break;
+	    }
+	  else if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) == 1)
 	    break;
 	}
 
       if (attr == 0)
 	return 0;
-
-      if (simple_cst_equal (TREE_VALUE (t2), TREE_VALUE (attr)) != 1)
-	return 0;
     }
 
   return 1;