diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7d63a5bd6c1f8d3f5d06a077499235fe79c84f27..25938ff74b2c437d5b0d226c3706c527713784d4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2005-09-24  Richard Henderson  <rth@redhat.com>
+
+	* c-common.c (handle_mode_attribute): When not modifying in place,
+	create subtypes for enumerations.
+	(sync_resolve_return): Use TYPE_MAIN_VARIANT.
+	* gimplify.c (create_tmp_from_val): Likewise.
+
 2005-09-24  Alexandre Oliva  <aoliva@redhat.com>
 
 	* config/i386/i386.md (*tls_global_dynamic_64,
diff --git a/gcc/c-common.c b/gcc/c-common.c
index edd744893cbaf0430c028d7e223e5f9404d4bdbd..fe4bd8c48647e76e93957038f6058895a6011f60 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -4520,21 +4520,24 @@ handle_mode_attribute (tree *node, tree name, tree args,
 	      return NULL_TREE;
 	    }
 
-	  if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
-	    type = build_variant_type_copy (type);
-
-	  /* We cannot use layout_type here, because that will attempt
-	     to re-layout all variants, corrupting our original.  */
-	  TYPE_PRECISION (type) = TYPE_PRECISION (typefm);
-	  TYPE_MIN_VALUE (type) = TYPE_MIN_VALUE (typefm);
-	  TYPE_MAX_VALUE (type) = TYPE_MAX_VALUE (typefm);
-	  TYPE_SIZE (type) = TYPE_SIZE (typefm);
-	  TYPE_SIZE_UNIT (type) = TYPE_SIZE_UNIT (typefm);
-	  TYPE_MODE (type) = TYPE_MODE (typefm);
-	  if (!TYPE_USER_ALIGN (type))
-	    TYPE_ALIGN (type) = TYPE_ALIGN (typefm);
-
-	  typefm = type;
+	  if (flags & ATTR_FLAG_TYPE_IN_PLACE)
+	    {
+	      TYPE_PRECISION (type) = TYPE_PRECISION (typefm);
+	      typefm = type;
+	    }
+	  else
+	    {
+	      /* We cannot build a type variant, as there's code that assumes
+		 that TYPE_MAIN_VARIANT has the same mode.  This includes the
+		 debug generators.  Instead, create a subrange type.  This
+		 results in all of the enumeral values being emitted only once
+		 in the original, and the subtype gets them by reference.  */
+	      if (TYPE_UNSIGNED (type))
+		typefm = make_unsigned_type (TYPE_PRECISION (typefm));
+	      else
+		typefm = make_signed_type (TYPE_PRECISION (typefm));
+	      TREE_TYPE (typefm) = type;
+	    }
 	}
       else if (VECTOR_MODE_P (mode)
 	       ? TREE_CODE (type) != TREE_CODE (TREE_TYPE (typefm))
@@ -6119,6 +6122,7 @@ static tree
 sync_resolve_return (tree params, tree result)
 {
   tree ptype = TREE_TYPE (TREE_TYPE (TREE_VALUE (params)));
+  ptype = TYPE_MAIN_VARIANT (ptype);
   return convert (ptype, result);
 }
 
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index cba1704e8a0a9199fabd6197a78d7a7d0e50c995..42b8740d08330b910adfb545be5853152b82636d 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -404,7 +404,7 @@ get_name (tree t)
 static inline tree
 create_tmp_from_val (tree val)
 {
-  return create_tmp_var (TREE_TYPE (val), get_name (val));
+  return create_tmp_var (TYPE_MAIN_VARIANT (TREE_TYPE (val)), get_name (val));
 }
 
 /* Create a temporary to hold the value of VAL.  If IS_FORMAL, try to reuse