diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/c-family/c.opt | 4 | ||||
-rw-r--r-- | gcc/c/c-decl.cc | 13 | ||||
-rw-r--r-- | gcc/c/c-tree.h | 1 | ||||
-rw-r--r-- | gcc/c/c-typeck.cc | 2 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 21 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Wenum-int-mismatch-1.c | 43 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Wenum-int-mismatch-2.c | 43 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Wenum-int-mismatch-3.c | 43 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Wenum-int-mismatch-4.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Wenum-int-mismatch-5.c | 5 |
10 files changed, 177 insertions, 3 deletions
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 035b1de..41a20bc6 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 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); diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index c70f0ba..2bcb966 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 bcfe08b..4f3611f 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 e8e6d4e..98a543a 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 0000000..6298018 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wenum-int-mismatch-1.c @@ -0,0 +1,43 @@ +/* PR c/105131 */ +/* { dg-do compile } */ +/* { dg-options "-Wall -fno-short-enums" } */ + +enum E { E1 = -1, E2 = 0, E3 = 1 }; + +int foo(void); /* { dg-message "previous declaration" } */ +enum E foo(void) { return E2; } /* { 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 E2; } /* { 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" } */ + +enum F { F1 = -1, F2, F3 } __attribute__ ((__packed__)); + +enum F fn1(void); /* { dg-message "previous declaration" } */ +signed char fn1(void); /* { dg-warning "conflicting types" } */ + +signed char fn2(void); /* { dg-message "previous declaration" } */ +enum F fn2(void); /* { 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 0000000..e5f7500 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wenum-int-mismatch-2.c @@ -0,0 +1,43 @@ +/* PR c/105131 */ +/* { dg-do compile } */ +/* { dg-options "-Wall -fno-short-enums" } */ + +enum E { E1 = 0, E2, E3 }; + +unsigned int foo(void); /* { dg-message "previous declaration" } */ +enum E foo(void) { return E2; } /* { 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 E2; } /* { 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" } */ + +enum F { F1 = 1u, F2, F3 } __attribute__ ((__packed__)); + +enum F fn1(void); /* { dg-message "previous declaration" } */ +unsigned char fn1(void); /* { dg-warning "conflicting types" } */ + +unsigned char fn2(void); /* { dg-message "previous declaration" } */ +enum F fn2(void); /* { 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 0000000..4ddbeb1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wenum-int-mismatch-3.c @@ -0,0 +1,43 @@ +/* PR c/105131 */ +/* { dg-do compile } */ +/* { dg-options "-Wc++-compat -fno-short-enums" } */ + +enum E { E1 = -1, E2 = 0, E3 = 1 }; + +int foo(void); /* { dg-message "previous declaration" } */ +enum E foo(void) { return E2; } /* { 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 E2; } /* { 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" } */ + +enum F { F1 = -1, F2, F3 } __attribute__ ((__packed__)); + +enum F fn1(void); /* { dg-message "previous declaration" } */ +signed char fn1(void); /* { dg-warning "conflicting types" } */ + +signed char fn2(void); /* { dg-message "previous declaration" } */ +enum F fn2(void); /* { dg-warning "conflicting types" } */ diff --git a/gcc/testsuite/gcc.dg/Wenum-int-mismatch-4.c b/gcc/testsuite/gcc.dg/Wenum-int-mismatch-4.c new file mode 100644 index 0000000..fcaca28 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wenum-int-mismatch-4.c @@ -0,0 +1,5 @@ +/* PR c/105131 */ +/* { dg-do compile } */ +/* { dg-options "-fno-short-enums" } */ + +#include "Wenum-int-mismatch-1.c" diff --git a/gcc/testsuite/gcc.dg/Wenum-int-mismatch-5.c b/gcc/testsuite/gcc.dg/Wenum-int-mismatch-5.c new file mode 100644 index 0000000..db24fd32 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wenum-int-mismatch-5.c @@ -0,0 +1,5 @@ +/* PR c/105131 */ +/* { dg-do compile } */ +/* { dg-options "-fno-short-enums" } */ + +#include "Wenum-int-mismatch-2.c" |