diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8fd88428567..bd8821cf7a7 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +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 diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 3ee3ba7956b..8e26927c373 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 2603ac27521..31b271e94d0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2008-08-09 Manuel Lopez-Ibanez + + PR c++/12242 + * g++.dg/warn/pr12242.C: New. + 2008-08-09 Manuel Lopez-Ibanez PR 36901 diff --git a/gcc/testsuite/g++.dg/warn/pr12242.C b/gcc/testsuite/g++.dg/warn/pr12242.C new file mode 100644 index 00000000000..db4cc103c3a --- /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" } + ); +} +