aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorManuel López-Ibáñez <manu@gcc.gnu.org>2008-08-09 00:30:41 +0000
committerManuel López-Ibáñez <manu@gcc.gnu.org>2008-08-09 00:30:41 +0000
commitb13e752fd50ce3c0084d0e4392280d8290bf1c3d (patch)
tree1a4421253e39d8a04c7c0e7d3bf749563fa6341d /gcc
parent97679e5f65218a9f6cef39b194f7845bba8bf90b (diff)
downloadgcc-b13e752fd50ce3c0084d0e4392280d8290bf1c3d.zip
gcc-b13e752fd50ce3c0084d0e4392280d8290bf1c3d.tar.gz
gcc-b13e752fd50ce3c0084d0e4392280d8290bf1c3d.tar.bz2
re PR c++/12242 (g++ should warn about out-of-range int->enum conversions)
2008-08-09 Manuel Lopez-Ibanez <manu@gcc.gnu.org> PR c++/12242 cp/ * cvt.c (ocp_convert): Warn for out-of-range conversions to enum. testsuite/ * g++.dg/warn/pr12242.C: New. From-SVN: r138898
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/cvt.c36
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/warn/pr12242.C57
4 files changed, 93 insertions, 10 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8fd8842..bd8821c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,10 @@
2008-08-09 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
+ PR c++/12242
+ * cvt.c (ocp_convert): Warn for out-of-range conversions to enum.
+
+2008-08-09 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
+
PR 36901
* cp-tree.h (struct diagnostic_context, struct diagnostic_info):
Delete forward declarations. Check that toplev.h has not been
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 3ee3ba7..8e26927 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -638,19 +638,35 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
if (INTEGRAL_CODE_P (code))
{
tree intype = TREE_TYPE (e);
- /* enum = enum, enum = int, enum = float, (enum)pointer are all
- errors. */
- if (TREE_CODE (type) == ENUMERAL_TYPE
- && (((INTEGRAL_OR_ENUMERATION_TYPE_P (intype)
+
+ if (TREE_CODE (type) == ENUMERAL_TYPE)
+ {
+ /* enum = enum, enum = int, enum = float, (enum)pointer are all
+ errors. */
+ if (((INTEGRAL_OR_ENUMERATION_TYPE_P (intype)
|| TREE_CODE (intype) == REAL_TYPE)
&& ! (convtype & CONV_STATIC))
- || TREE_CODE (intype) == POINTER_TYPE))
- {
- if (flags & LOOKUP_COMPLAIN)
- permerror ("conversion from %q#T to %q#T", intype, type);
+ || TREE_CODE (intype) == POINTER_TYPE)
+ {
+ if (flags & LOOKUP_COMPLAIN)
+ permerror ("conversion from %q#T to %q#T", intype, type);
- if (!flag_permissive)
- return error_mark_node;
+ if (!flag_permissive)
+ return error_mark_node;
+ }
+
+ /* [expr.static.cast]
+
+ 8. A value of integral or enumeration type can be explicitly
+ converted to an enumeration type. The value is unchanged if
+ the original value is within the range of the enumeration
+ values. Otherwise, the resulting enumeration value is
+ unspecified. */
+ if (TREE_CODE (expr) == INTEGER_CST && !int_fits_type_p (expr, type))
+ warning (OPT_Wconversion,
+ "the result of the conversion is unspecified because "
+ "%qE is outside the range of type %qT",
+ expr, type);
}
if (MAYBE_CLASS_TYPE_P (intype))
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2603ac2..31b271e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
2008-08-09 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
+ PR c++/12242
+ * g++.dg/warn/pr12242.C: New.
+
+2008-08-09 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
+
PR 36901
* gcc.dg/pr36901-1.c: New.
* gcc.dg/pr36901-3.c: New.
diff --git a/gcc/testsuite/g++.dg/warn/pr12242.C b/gcc/testsuite/g++.dg/warn/pr12242.C
new file mode 100644
index 0000000..db4cc10
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/pr12242.C
@@ -0,0 +1,57 @@
+// PR 12242: should warn about out-of-range int->enum conversions
+// { dg-do compile }
+// { dg-options "-Wconversion -fpermissive" }
+enum X { A };
+enum Y { B, C, D };
+
+void example ()
+{
+ int i = 5;
+ X x;
+ Y y;
+
+ x = 10; // { dg-warning "warning: invalid conversion from .int. to .X." }
+ // { dg-warning "warning:\[^\n\]*unspecified" "" { target *-*-* } 13 }
+ x = 1; // { dg-warning "warning: invalid conversion from .int. to .X." }
+ x = C; // { dg-error "error: cannot convert .Y. to .X. in assignment" }
+ x = D; // { dg-error "error: cannot convert .Y. to .X. in assignment" }
+ y = A; // { dg-error "error: cannot convert .X. to .Y. in assignment" }
+ x = y; // { dg-error "error: cannot convert .Y. to .X. in assignment" }
+ x = i; // { dg-warning "warning: invalid conversion from .int. to .X." }
+}
+
+void foo ()
+{
+ X a = static_cast<X> (10); // { dg-warning "warning:\[^\n\]*unspecified" }
+ X b = static_cast<X> (0);
+ X c = static_cast<X> (1);
+ X d = static_cast<X> (2); // { dg-warning "warning:\[^\n\]*unspecified" }
+ X f = static_cast<X> ((int)A);
+ X g = static_cast<X> (B);
+ X h = static_cast<X> (C);
+ X e = static_cast<X> (D); // { dg-warning "warning\[^\n\]*unspecified" }
+}
+
+enum QEvent { x = 42 };
+
+int bar()
+{
+ QEvent x = ( QEvent ) 42000; // { dg-warning "warning\[^\n\]*unspecified" }
+ return ( int ) x;
+}
+
+enum W {a,b,c};
+enum Z {d,e,f,g};
+void bazz (int, int, int, int);
+
+void baz() {
+ int three = 3;
+ int four = 4;
+ bazz (
+ W(three),
+ W(3),
+ Z(four),
+ Z(4) // { dg-warning "warning\[^\n\]*unspecified" }
+ );
+}
+