aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c-family/c.opt4
-rw-r--r--gcc/c/c-decl.cc13
-rw-r--r--gcc/c/c-tree.h1
-rw-r--r--gcc/c/c-typeck.cc2
-rw-r--r--gcc/doc/invoke.texi21
-rw-r--r--gcc/testsuite/gcc.dg/Wenum-int-mismatch-1.c43
-rw-r--r--gcc/testsuite/gcc.dg/Wenum-int-mismatch-2.c43
-rw-r--r--gcc/testsuite/gcc.dg/Wenum-int-mismatch-3.c43
-rw-r--r--gcc/testsuite/gcc.dg/Wenum-int-mismatch-4.c5
-rw-r--r--gcc/testsuite/gcc.dg/Wenum-int-mismatch-5.c5
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"