From b13e752fd50ce3c0084d0e4392280d8290bf1c3d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Manuel=20L=C3=B3pez-Ib=C3=A1=C3=B1ez?= Date: Sat, 9 Aug 2008 00:30:41 +0000 Subject: [PATCH] re PR c++/12242 (g++ should warn about out-of-range int->enum conversions) 2008-08-09 Manuel Lopez-Ibanez 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 --- gcc/cp/ChangeLog | 5 ++++ gcc/cp/cvt.c | 36 ++++++++++++++++------- gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/g++.dg/warn/pr12242.C | 57 +++++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/g++.dg/warn/pr12242.C 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 + PR c++/12242 + * cvt.c (ocp_convert): Warn for out-of-range conversions to enum. + +2008-08-09 Manuel Lopez-Ibanez + 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 + PR c++/12242 + * g++.dg/warn/pr12242.C: New. + +2008-08-09 Manuel Lopez-Ibanez + 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 (10); // { dg-warning "warning:\[^\n\]*unspecified" } + X b = static_cast (0); + X c = static_cast (1); + X d = static_cast (2); // { dg-warning "warning:\[^\n\]*unspecified" } + X f = static_cast ((int)A); + X g = static_cast (B); + X h = static_cast (C); + X e = static_cast (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" } + ); +} + -- 2.7.4