diff options
author | Marek Polacek <polacek@redhat.com> | 2022-04-01 16:55:58 -0400 |
---|---|---|
committer | Marek Polacek <polacek@redhat.com> | 2022-05-18 17:43:56 -0400 |
commit | 7da9a089608b0ca09683332ce014fb6184842724 (patch) | |
tree | a66671c0a6edc1a4191f4ec0d97d6a5c55ff6191 /gcc/c/c-decl.cc | |
parent | 1875214cd1ca3e8bd0121f703537eb98edd84027 (diff) | |
download | gcc-7da9a089608b0ca09683332ce014fb6184842724.zip gcc-7da9a089608b0ca09683332ce014fb6184842724.tar.gz gcc-7da9a089608b0ca09683332ce014fb6184842724.tar.bz2 |
c: Implement new -Wenum-int-mismatch warning [PR105131]
In C, an enumerated type is compatible with char, a signed integer type,
or an unsigned integer type (6.7.2.2/5). Therefore this code compiles:
enum E { l = -1, z = 0, g = 1 };
int foo(void);
enum E foo(void) { return z; }
if the underlying type of 'enum E' is 'int' (if not, we emit an error).
This is different for typedefs, where C11 permits typedefs to be
redeclared to the same type, but not to compatible types. In C++, the
code above is invalid.
It seems desirable to emit a warning in the C case, because it is
probably a mistake and definitely a portability error, given that the
choice of the underlying type is implementation-defined.
To that end, this patch implements a new -Wenum-int-mismatch warning.
Conveniently, we already have comptypes_check_enum_int to detect such
mismatches. This warning is enabled by either -Wall or -Wc++-compat.
PR c/105131
gcc/c-family/ChangeLog:
* c.opt (Wenum-int-mismatch): New.
gcc/c/ChangeLog:
* c-decl.cc (diagnose_mismatched_decls): Warn about enum/integer type
mismatches.
* c-tree.h (comptypes_check_enum_int): Declare.
* c-typeck.cc (comptypes): No longer static.
gcc/ChangeLog:
* doc/invoke.texi: Document -Wenum-int-mismatch.
gcc/testsuite/ChangeLog:
* gcc.dg/Wenum-int-mismatch-1.c: New test.
* gcc.dg/Wenum-int-mismatch-2.c: New test.
* gcc.dg/Wenum-int-mismatch-3.c: New test.
* gcc.dg/Wenum-int-mismatch-4.c: New test.
* gcc.dg/Wenum-int-mismatch-5.c: New test.
Diffstat (limited to 'gcc/c/c-decl.cc')
-rw-r--r-- | gcc/c/c-decl.cc | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 8365554..5266a61 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); |