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;