diff -ur gcc-2.95.2/gcc/c-decl.c working-2.95.2/gcc/c-decl.c
--- gcc-2.95.2/gcc/c-decl.c	Tue Apr 13 00:05:29 1999
+++ working-2.95.2/gcc/c-decl.c	Fri Oct  6 14:42:22 2000
@@ -239,6 +239,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.  */
 
@@ -531,6 +535,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.  */
 
@@ -788,6 +796,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"))
@@ -6183,6 +6193,7 @@
     }
 
   C_TYPE_BEING_DEFINED (enumtype) = 1;
+  enum_being_defined = enumtype;
 
   if (TYPE_VALUES (enumtype) != 0)
     {
@@ -6194,7 +6205,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)
@@ -6328,12 +6339,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)
     {
@@ -6366,8 +6381,10 @@
       value = integer_zero_node;
     }
 
-  /* 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.  */
@@ -6381,6 +6398,7 @@
 
   decl = build_decl (CONST_DECL, name, type);
   DECL_INITIAL (decl) = value;
+  TREE_INT_CST_ENUM (value) = enum_being_defined;
   TREE_TYPE (value) = type;
   pushdecl (decl);
 
diff -ur gcc-2.95.2/gcc/c-tree.h working-2.95.2/gcc/c-tree.h
--- gcc-2.95.2/gcc/c-tree.h	Fri Feb 19 07:38:43 1999
+++ working-2.95.2/gcc/c-tree.h	Fri Oct  6 14:33:41 2000
@@ -460,6 +460,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-2.95.2/gcc/c-typeck.c working-2.95.2/gcc/c-typeck.c
--- gcc-2.95.2/gcc/c-typeck.c	Thu Sep 16 14:17:51 1999
+++ working-2.95.2/gcc/c-typeck.c	Fri Oct  6 18:31:54 2000
@@ -545,6 +545,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.
@@ -2007,6 +2101,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:
@@ -4059,6 +4156,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-2.95.2/gcc/fold-const.c working-2.95.2/gcc/fold-const.c
--- gcc-2.95.2/gcc/fold-const.c	Tue Oct 19 18:40:05 1999
+++ working-2.95.2/gcc/fold-const.c	Fri Oct  6 03:30:31 2000
@@ -1458,6 +1458,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-2.95.2/gcc/invoke.texi working-2.95.2/gcc/invoke.texi
--- gcc-2.95.2/gcc/invoke.texi	Thu Oct 21 17:01:37 1999
+++ working-2.95.2/gcc/invoke.texi	Fri Oct  6 18:58:58 2000
@@ -132,7 +132,7 @@
 -Wreturn-type -Wshadow  -Wsign-compare  -Wstrict-prototypes  
 -Wswitch  -Wtraditional  
 -Wtrigraphs -Wundef  -Wuninitialized  -Wunused  -Wwrite-strings
--Wunknown-pragmas
+-Wunknown-pragmas -Wstrict-enums
 @end smallexample
 
 @item Debugging Options
@@ -1769,6 +1769,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 -Werror
 Make all warnings into errors.
diff -ur gcc-2.95.2/gcc/toplev.c working-2.95.2/gcc/toplev.c
--- gcc-2.95.2/gcc/toplev.c	Thu Oct 21 17:01:37 1999
+++ working-2.95.2/gcc/toplev.c	Fri Oct  6 01:06:41 2000
@@ -1090,6 +1090,7 @@
   { "-Wunknown-pragmas", "Warn about unrecognised 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 ANSI C"},
   { "-Wno-traditional", "" },
--- gcc-2.95.2/gcc/tree.h	Mon May  3 03:43:32 1999
+++ working-2.95.2/gcc/tree.h	Fri Oct  6 19:05:36 2000
@@ -555,6 +559,7 @@
    In an unsigned constant shorter than 2 words, the extra bits are 0.  */
 #define TREE_INT_CST_LOW(NODE) (INTEGER_CST_CHECK (NODE)->int_cst.int_cst_low)
 #define TREE_INT_CST_HIGH(NODE) (INTEGER_CST_CHECK (NODE)->int_cst.int_cst_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)			\
@@ -575,6 +580,7 @@
   char common[sizeof (struct tree_common)];
   struct rtx_def *rtl;	/* acts as link to register transfer language
 			   (rtl) info */
+  tree enumtype;  /* ENUMERAL_TYPE if it was originally an enum */
   HOST_WIDE_INT int_cst_low;
   HOST_WIDE_INT int_cst_high;
 };
