diff -ur gcc/gcc/c-decl.c gcc-tmp/gcc/c-decl.c
--- gcc/gcc/c-decl.c	Mon Oct  2 06:19:23 2000
+++ gcc-tmp/gcc/c-decl.c	Sat Oct  7 00:51:46 2000
@@ -101,6 +101,10 @@
 
 static int enum_overflow;
 
+/* Enum type being defined now */
+
+static tree enum_being_defined;
+
 /* Parsing a function declarator leaves a list of parameter names
    or a chain or parameter decls here.  */
 
@@ -421,6 +425,10 @@
 
 int warn_strict_prototypes;
 
+/* Nonzero means warn for implicit conversions to/from enums.  */
+
+int warn_strict_enums;
+
 /* Nonzero means warn for any global function def
    without separate previous prototype decl.  */
 
@@ -711,6 +719,8 @@
     warn_strict_prototypes = 1;
   else if (!strcmp (p, "-Wno-strict-prototypes"))
     warn_strict_prototypes = 0;
+  else if (!strcmp (p, "-Wstrict-enums"))
+    warn_strict_enums = 1;
   else if (!strcmp (p, "-Wmissing-prototypes"))
     warn_missing_prototypes = 1;
   else if (!strcmp (p, "-Wno-missing-prototypes"))
@@ -5599,6 +5609,7 @@
     }
 
   C_TYPE_BEING_DEFINED (enumtype) = 1;
+  enum_being_defined = enumtype;
 
   if (TYPE_VALUES (enumtype) != 0)
     {
@@ -5610,7 +5621,7 @@
       TYPE_VALUES (enumtype) = 0;
     }
 
-  enum_next_value = integer_zero_node;
+  enum_next_value = copy_node (integer_zero_node);
   enum_overflow = 0;
 
   if (flag_short_enums)
@@ -5757,12 +5768,16 @@
      tree name, value;
 {
   register tree decl, type;
+  int old_warn_strict_enums = warn_strict_enums;
 
   /* Validate and default VALUE.  */
 
-  /* Remove no-op casts from the value.  */
+  /* Remove no-op casts from the value; need unique for INT_CST_ENUM  */
   if (value)
-    STRIP_TYPE_NOPS (value);
+    {
+      STRIP_TYPE_NOPS (value);
+      value = copy_node (value);
+    }
 
   if (value != 0)
     {
@@ -5795,8 +5810,10 @@
       value = convert (integer_type_node, value);
     }
 
-  /* Set basis for default for next value.  */
+  /* Set basis for default for next value: suppress strict enum warn */
+  warn_strict_enums = 0;
   enum_next_value = build_binary_op (PLUS_EXPR, value, integer_one_node, 0);
+  warn_strict_enums = old_warn_strict_enums;
   enum_overflow = tree_int_cst_lt (enum_next_value, value);
 
   /* Now create a declaration for the enum value name.  */
@@ -5810,6 +5827,7 @@
 
   decl = build_decl (CONST_DECL, name, type);
   DECL_INITIAL (decl) = convert (type, value);
+  TREE_INT_CST_ENUM (DECL_INITIAL (decl))= enum_being_defined;
   pushdecl (decl);
 
   return tree_cons (decl, value, NULL_TREE);
diff -ur gcc/gcc/c-tree.h gcc-tmp/gcc/c-tree.h
--- gcc/gcc/c-tree.h	Sun Sep 17 18:38:11 2000
+++ gcc-tmp/gcc/c-tree.h	Sat Oct  7 00:49:39 2000
@@ -318,6 +318,10 @@
 
 extern int warn_strict_prototypes;
 
+/* Nonzero means warn for implicit conversions to/from enums.  */
+
+extern int warn_strict_enums;
+
 /* Nonzero means warn about multiple (redundant) decls for the same single
    variable or function.  */
 
diff -ur gcc/gcc/c-typeck.c gcc-tmp/gcc/c-typeck.c
--- gcc/gcc/c-typeck.c	Wed Sep 20 01:26:38 2000
+++ gcc-tmp/gcc/c-typeck.c	Sat Oct  7 00:49:39 2000
@@ -554,6 +554,75 @@
   return val;
 }
 
+
+/* Warn for cross-enum conversions */
+static void
+warn_maybe_enum (enumtype, rhs_enumtype, errtype, fundecl, funname, parmnum)
+     tree enumtype, rhs_enumtype;
+     const char *errtype;
+     tree fundecl, funname;
+     int parmnum;
+{
+  if (enumtype)
+    {
+      if (!rhs_enumtype)
+	warn_for_assignment ("%s implicitly converts to enum",
+			     errtype, funname, parmnum);
+      else if (enumtype && TYPE_NAME (enumtype) != TYPE_NAME (rhs_enumtype))
+	warn_for_assignment ("%s implicitly converts to different enum",
+			     errtype, funname, parmnum);
+    }
+  else if (rhs_enumtype)
+    warn_for_assignment ("%s implicitly converts from enum",
+			 errtype, funname, parmnum);
+}
+
+/* Return the enum type of this node, or NULL_TREE */
+static tree
+find_enum_type (node)
+     tree node;
+{
+  enum tree_code code;
+
+  if (node == NULL_TREE)
+	  return NULL_TREE;
+
+  code = TREE_CODE (node);
+
+  if (code == ENUMERAL_TYPE)
+    return node;
+
+  if (code == INTEGER_CST)
+    return TREE_INT_CST_ENUM (node);
+
+  if (TREE_CODE_CLASS (code) == 'd')
+    return find_enum_type (TREE_TYPE (node));
+
+  if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
+      && TREE_CODE (TREE_TYPE (node)) == INTEGER_TYPE)
+    {
+      /* expensive, but user asked for it with -Wstrict-enums */
+      int i;
+      for (i = 0; i < tree_code_length[(int) code]; i++)
+	{
+	  tree type = find_enum_type (TREE_OPERAND (node, i));
+	  if (type)
+	    return type;
+	}
+    }
+  return NULL_TREE;
+}
+
+static void
+warn_op_maybe_enum (node1, node2, code)
+     tree node1, node2;
+     enum tree_code code;
+{
+  warn_maybe_enum (find_enum_type (node1), find_enum_type (node2),
+		   tree_code_name[(int) code],
+		   NULL_TREE, NULL_TREE, 0);
+}
+
 /* Subroutines of `comptypes'.  */
 
 /* Return 1 if two function types F1 and F2 are compatible.
@@ -1954,6 +2023,9 @@
   if (code0 == ERROR_MARK || code1 == ERROR_MARK)
     return error_mark_node;
 
+  if (warn_strict_enums)
+    warn_op_maybe_enum(op0, op1, code);
+
   switch (code)
     {
     case PLUS_EXPR:
@@ -4024,6 +4096,10 @@
 
   if (coder == ERROR_MARK)
     return error_mark_node;
+
+  if (warn_strict_enums)
+    warn_maybe_enum (find_enum_type (type), find_enum_type (rhs),
+		     errtype, fundecl, funname, parmnum);
 
   if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
     {
diff -ur gcc/gcc/fold-const.c gcc-tmp/gcc/fold-const.c
--- gcc/gcc/fold-const.c	Fri Aug 25 06:31:31 2000
+++ gcc-tmp/gcc/fold-const.c	Sat Oct  7 00:49:39 2000
@@ -1610,6 +1610,11 @@
     {
       t = build_int_2 (low, hi);
       TREE_TYPE (t) = TREE_TYPE (arg1);
+      /* Preserve enum info where possible */
+      if (TREE_INT_CST_ENUM (arg1))
+	TREE_INT_CST_ENUM (t) = TREE_INT_CST_ENUM (arg1);
+      else
+	TREE_INT_CST_ENUM (t) = TREE_INT_CST_ENUM (arg2);
     }
 
   TREE_OVERFLOW (t)
diff -ur gcc/gcc/invoke.texi gcc-tmp/gcc/invoke.texi
--- gcc/gcc/invoke.texi	Sat Sep 30 19:04:00 2000
+++ gcc-tmp/gcc/invoke.texi	Sat Oct  7 00:52:16 2000
@@ -142,7 +142,7 @@
 -Wreturn-type -Wshadow  -Wsign-compare -Wswitch -Wsystem-headers
 -Wtrigraphs -Wundef  -Wuninitialized  -Wunknown-pragmas -Wunreachable-code 
 -Wunused -Wunused-function -Wunused-label -Wunused-parameter
--Wunused-variable -Wunused-value -Wwrite-strings
+-Wunused-variable -Wunused-value -Wwrite-strings -Wstrict-enums
 @end smallexample
 
 @item C-only Warning Options
@@ -2029,6 +2029,12 @@
 the warning messages, use @samp{-Wno-long-long}.  Flags
 @samp{-Wlong-long} and @samp{-Wno-long-long} are taken into account
 only when @samp{-pedantic} flag is used.
+
+@item -Wstrict-enums
+Use a stronger form of typechecking for @code{enum} types: warn when
+they are implicitly converted to @code{int}, or from @code{int} (except
+in the definition of an @code{enum} value), or to/from a different type
+of enumeration.
 
 @item -Wdisabled-optimization
 Warn if a requested optimization pass is disabled.  This warning does
diff -ur gcc/gcc/toplev.c gcc-tmp/gcc/toplev.c
--- gcc/gcc/toplev.c	Tue Sep 26 09:54:04 2000
+++ gcc-tmp/gcc/toplev.c	Sat Oct  7 00:49:39 2000
@@ -1259,6 +1259,7 @@
   { "-Wunknown-pragmas", "Warn about unrecognized pragmas" },
   { "-Wno-unknown-pragmas", "" },
   { "-Wstrict-prototypes", "Warn about non-prototyped function decls" },
+  { "-Wstrict-enums", "Warn about implicit casts to/from enum types" },
   { "-Wno-strict-prototypes", "" },
   { "-Wtraditional", "Warn about constructs whose meaning change in ISO C"},
   { "-Wno-traditional", "" },
diff -ur gcc/gcc/tree.h gcc-tmp/gcc/tree.h
--- gcc/gcc/tree.h	Wed Sep 20 05:19:43 2000
+++ gcc-tmp/gcc/tree.h	Sat Oct  7 00:54:35 2000
@@ -661,6 +661,7 @@
 #define TREE_INT_CST(NODE) (INTEGER_CST_CHECK (NODE)->int_cst.int_cst)
 #define TREE_INT_CST_LOW(NODE) (TREE_INT_CST (NODE).low)
 #define TREE_INT_CST_HIGH(NODE) (TREE_INT_CST (NODE).high)
+#define TREE_INT_CST_ENUM(NODE) ((NODE)->int_cst.enumtype)
 
 #define INT_CST_LT(A, B)  \
 (TREE_INT_CST_HIGH (A) < TREE_INT_CST_HIGH (B)			\
@@ -679,6 +680,7 @@
   struct tree_common common;
   struct rtx_def *rtl;	/* acts as link to register transfer language
 			   (rtl) info */
+  tree enumtype;  /* ENUMERAL_TYPE if it was originally an enum */
   /* A sub-struct is necessary here because the function `const_hash'
      wants to scan both words as a unit and taking the address of the
      sub-struct yields the properly inclusive bounded pointer.  */
