diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 035b1de0d84..41a20bc625e 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -638,6 +638,10 @@ Wenum-conversion
 C ObjC C++ ObjC++ Var(warn_enum_conversion) Init(0) Warning LangEnabledBy(C ObjC,Wextra)
 Warn about implicit conversion of enum types.
 
+Wenum-int-mismatch
+C ObjC Var(warn_enum_int_mismatch) Warning LangEnabledBy(C ObjC,Wall || Wc++-compat)
+Warn about enum/integer type mismatches.
+
 Werror
 C ObjC C++ ObjC++
 ; Documented in common.opt
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 83655548fc4..5266a61b859 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -1993,9 +1993,12 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
 
   bool pedwarned = false;
   bool warned = false;
+  bool enum_and_int_p = false;
   auto_diagnostic_group d;
 
-  if (!comptypes (oldtype, newtype))
+  int comptypes_result = comptypes_check_enum_int (oldtype, newtype,
+						   &enum_and_int_p);
+  if (!comptypes_result)
     {
       if (TREE_CODE (olddecl) == FUNCTION_DECL
 	  && fndecl_built_in_p (olddecl, BUILT_IN_NORMAL)
@@ -2137,6 +2140,13 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
 	  return false;
 	}
     }
+  /* Warn about enum/integer type mismatches.  They are compatible types
+     (C2X 6.7.2.2/5), but may pose portability problems.  */
+  else if (enum_and_int_p && TREE_CODE (newdecl) != TYPE_DECL)
+    warned = warning_at (DECL_SOURCE_LOCATION (newdecl),
+			 OPT_Wenum_int_mismatch,
+			 "conflicting types for %q+D due to enum/integer "
+			 "mismatch; have %qT", newdecl, newtype);
 
   /* Redeclaration of a type is a constraint violation (6.7.2.3p1),
      but silently ignore the redeclaration if either is in a system
@@ -2146,7 +2156,6 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
   if (TREE_CODE (newdecl) == TYPE_DECL)
     {
       bool types_different = false;
-      int comptypes_result;
 
       comptypes_result
 	= comptypes_check_different_types (oldtype, newtype, &types_different);
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index c70f0ba5ab6..2bcb9662620 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -685,6 +685,7 @@ extern tree require_complete_type (location_t, tree);
 extern bool same_translation_unit_p (const_tree, const_tree);
 extern int comptypes (tree, tree);
 extern int comptypes_check_different_types (tree, tree, bool *);
+extern int comptypes_check_enum_int (tree, tree, bool *);
 extern bool c_vla_type_p (const_tree);
 extern bool c_mark_addressable (tree, bool = false);
 extern void c_incomplete_type_error (location_t, const_tree, const_tree);
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index bcfe08b82bc..4f3611f1b89 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -1055,7 +1055,7 @@ comptypes (tree type1, tree type2)
 /* Like comptypes, but if it returns non-zero because enum and int are
    compatible, it sets *ENUM_AND_INT_P to true.  */
 
-static int
+int
 comptypes_check_enum_int (tree type1, tree type2, bool *enum_and_int_p)
 {
   const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index e8e6d4e039b..98a543ae06f 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -349,6 +349,7 @@ Objective-C and Objective-C++ Dialects}.
 -Wno-div-by-zero  -Wdouble-promotion @gol
 -Wduplicated-branches  -Wduplicated-cond @gol
 -Wempty-body  -Wno-endif-labels  -Wenum-compare  -Wenum-conversion @gol
+-Wenum-int-mismatch @gol
 -Werror  -Werror=*  -Wexpansion-to-defined  -Wfatal-errors @gol
 -Wfloat-conversion  -Wfloat-equal  -Wformat  -Wformat=2 @gol
 -Wno-format-contains-nul  -Wno-format-extra-args  @gol
@@ -5759,6 +5760,7 @@ Options} and @ref{Objective-C and Objective-C++ Dialect Options}.
 -Wdangling-pointer=2  @gol
 -Wduplicate-decl-specifier @r{(C and Objective-C only)} @gol
 -Wenum-compare @r{(in C/ObjC; this is on by default in C++)} @gol
+-Wenum-int-mismatch @r{(C and Objective-C only)} @gol
 -Wformat   @gol
 -Wformat-overflow  @gol
 -Wformat-truncation  @gol
@@ -8735,6 +8737,25 @@ Warn when a value of enumerated type is implicitly converted to a
 different enumerated type.  This warning is enabled by @option{-Wextra}
 in C@.
 
+@item -Wenum-int-mismatch @r{(C and Objective-C only)}
+@opindex Wenum-int-mismatch
+@opindex Wno-enum-int-mismatch
+Warn about mismatches between an enumerated type and an integer type in
+declarations.  For example:
+
+@smallexample
+enum E @{ l = -1, z = 0, g = 1 @};
+int foo(void);
+enum E foo(void);
+@end smallexample
+
+In C, an enumerated type is compatible with @code{char}, a signed
+integer type, or an unsigned integer type.  However, since the choice
+of the underlying type of an enumerated type is implementation-defined,
+such mismatches may cause portability issues.  In C++, such mismatches
+are an error.  In C, this warning is enabled by @option{-Wall} and
+@option{-Wc++-compat}.
+
 @item -Wjump-misses-init @r{(C, Objective-C only)}
 @opindex Wjump-misses-init
 @opindex Wno-jump-misses-init
diff --git a/gcc/testsuite/gcc.dg/Wenum-int-mismatch-1.c b/gcc/testsuite/gcc.dg/Wenum-int-mismatch-1.c
new file mode 100644
index 00000000000..f71a308bc19
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wenum-int-mismatch-1.c
@@ -0,0 +1,35 @@
+/* PR c/105131 */
+/* { dg-do compile } */
+/* { dg-options "-Wall" } */
+
+enum E { l = -1, z = 0, g = 1 };
+
+int foo(void); /* { dg-message "previous declaration" } */
+enum E foo(void) { return z; } /* { dg-warning "conflicting types" } */
+
+void bar(int); /* { dg-message "previous declaration" } */
+void bar(enum E); /* { dg-warning "conflicting types" } */
+
+extern int arr[10]; /* { dg-message "previous declaration" } */
+extern enum E arr[10]; /* { dg-warning "conflicting types" } */
+
+extern int i; /* { dg-message "previous declaration" } */
+extern enum E i; /* { dg-warning "conflicting types" } */
+
+extern int *p; /* { dg-message "previous declaration" } */
+extern enum E *p; /* { dg-warning "conflicting types" } */
+
+enum E foo2(void) { return z; } /* { dg-message "previous definition" } */
+int foo2(void); /* { dg-warning "conflicting types" } */
+
+void bar2(enum E); /* { dg-message "previous declaration" } */
+void bar2(int); /* { dg-warning "conflicting types" } */
+
+extern enum E arr2[10]; /* { dg-message "previous declaration" } */
+extern int arr2[10]; /* { dg-warning "conflicting types" } */
+
+extern enum E i2; /* { dg-message "previous declaration" } */
+extern int i2; /* { dg-warning "conflicting types" } */
+
+extern enum E *p2; /* { dg-message "previous declaration" } */
+extern int *p2; /* { dg-warning "conflicting types" } */
diff --git a/gcc/testsuite/gcc.dg/Wenum-int-mismatch-2.c b/gcc/testsuite/gcc.dg/Wenum-int-mismatch-2.c
new file mode 100644
index 00000000000..7296b703672
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wenum-int-mismatch-2.c
@@ -0,0 +1,35 @@
+/* PR c/105131 */
+/* { dg-do compile } */
+/* { dg-options "-Wall" } */
+
+enum E { l = 0, z, g };
+
+unsigned int foo(void); /* { dg-message "previous declaration" } */
+enum E foo(void) { return z; } /* { dg-warning "conflicting types" } */
+
+void bar(unsigned int); /* { dg-message "previous declaration" } */
+void bar(enum E); /* { dg-warning "conflicting types" } */
+
+extern enum E arr[10]; /* { dg-message "previous declaration" } */
+extern unsigned int arr[10]; /* { dg-warning "conflicting types" } */
+
+extern unsigned int i; /* { dg-message "previous declaration" } */
+extern enum E i; /* { dg-warning "conflicting types" } */
+
+extern unsigned int *p; /* { dg-message "previous declaration" } */
+extern enum E *p; /* { dg-warning "conflicting types" } */
+
+enum E foo2(void) { return z; } /* { dg-message "previous definition" } */
+unsigned int foo2(void); /* { dg-warning "conflicting types" } */
+
+void bar2(enum E); /* { dg-message "previous declaration" } */
+void bar2(unsigned int); /* { dg-warning "conflicting types" } */
+
+extern unsigned int arr2[10]; /* { dg-message "previous declaration" } */
+extern enum E arr2[10]; /* { dg-warning "conflicting types" } */
+
+extern enum E i2; /* { dg-message "previous declaration" } */
+extern unsigned int i2; /* { dg-warning "conflicting types" } */
+
+extern enum E *p2; /* { dg-message "previous declaration" } */
+extern unsigned int *p2; /* { dg-warning "conflicting types" } */
diff --git a/gcc/testsuite/gcc.dg/Wenum-int-mismatch-3.c b/gcc/testsuite/gcc.dg/Wenum-int-mismatch-3.c
new file mode 100644
index 00000000000..8773f01869c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wenum-int-mismatch-3.c
@@ -0,0 +1,35 @@
+/* PR c/105131 */
+/* { dg-do compile } */
+/* { dg-options "-Wc++-compat" } */
+
+enum E { l = -1, z = 0, g = 1 };
+
+int foo(void); /* { dg-message "previous declaration" } */
+enum E foo(void) { return z; } /* { dg-warning "conflicting types" } */
+
+void bar(int); /* { dg-message "previous declaration" } */
+void bar(enum E); /* { dg-warning "conflicting types" } */
+
+extern int arr[10]; /* { dg-message "previous declaration" } */
+extern enum E arr[10]; /* { dg-warning "conflicting types" } */
+
+extern int i; /* { dg-message "previous declaration" } */
+extern enum E i; /* { dg-warning "conflicting types" } */
+
+extern int *p; /* { dg-message "previous declaration" } */
+extern enum E *p; /* { dg-warning "conflicting types" } */
+
+enum E foo2(void) { return z; } /* { dg-message "previous definition" } */
+int foo2(void); /* { dg-warning "conflicting types" } */
+
+void bar2(enum E); /* { dg-message "previous declaration" } */
+void bar2(int); /* { dg-warning "conflicting types" } */
+
+extern enum E arr2[10]; /* { dg-message "previous declaration" } */
+extern int arr2[10]; /* { dg-warning "conflicting types" } */
+
+extern enum E i2; /* { dg-message "previous declaration" } */
+extern int i2; /* { dg-warning "conflicting types" } */
+
+extern enum E *p2; /* { dg-message "previous declaration" } */
+extern int *p2; /* { dg-warning "conflicting types" } */
