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;