https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105131

--- Comment #2 from Marek Polacek <mpolacek at gcc dot gnu.org> ---
Maybe something like the attached patch would work (but needs a new option,
maybe -Wenum-int-mismatch, possibly enabled by -Wall?).  With it, the following
test

enum E { l = -1, z = 0, g = 1 };
int foo(void);
enum E foo(void) { return z; }

void bar(int);
void bar(enum E);

extern enum E arr[10];
extern int arr[10];

is diagnosed like this:

105131.c:3:8: warning: conflicting types for ‘foo’ due to enum/integer
mismatch; have ‘enum E(void)’
    3 | enum E foo(void) { return z; }
      |        ^~~
105131.c:2:5: note: previous declaration of ‘foo’ with type ‘int(void)’
    2 | int foo(void);
      |     ^~~
105131.c:6:6: warning: conflicting types for ‘bar’ due to enum/integer
mismatch; have ‘void(enum E)’
    6 | void bar(enum E);
      |      ^~~
105131.c:5:6: note: previous declaration of ‘bar’ with type ‘void(int)’
    5 | void bar(int);
      |      ^~~
105131.c:9:12: warning: conflicting types for ‘arr’ due to enum/integer
mismatch; have ‘int[10]’
    9 | extern int arr[10];
      |            ^~~
105131.c:8:15: note: previous declaration of ‘arr’ with type ‘enum E[10]’
    8 | extern enum E arr[10];
      |               ^~~



diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index c701f07befe..60a0bb3ea36 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -1995,9 +1995,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)
@@ -2139,6 +2142,14 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
          return false;
        }
     }
+  else if (enum_and_int_p && TREE_CODE (newdecl) != TYPE_DECL)
+    {
+      location_t newloc = DECL_SOURCE_LOCATION (newdecl);
+      auto_diagnostic_group d;
+      warned = warning_at (newloc, 0, "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
@@ -2148,7 +2159,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 6c4af5e4cde..b6a45fd9836 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;

Reply via email to