diff options
author | Manuel López-Ibáñez <manu@gcc.gnu.org> | 2008-08-13 10:01:52 +0000 |
---|---|---|
committer | Manuel López-Ibáñez <manu@gcc.gnu.org> | 2008-08-13 10:01:52 +0000 |
commit | 374035cb20b323d0e95559499fc0089aa4cedff9 (patch) | |
tree | c369a65444f35bfe20b1e10fe92aa6089f0b2b5e /gcc/c-common.c | |
parent | 25c6036a5bc49ba73bc3f5d2573cf2506b513a1f (diff) | |
download | gcc-374035cb20b323d0e95559499fc0089aa4cedff9.zip gcc-374035cb20b323d0e95559499fc0089aa4cedff9.tar.gz gcc-374035cb20b323d0e95559499fc0089aa4cedff9.tar.bz2 |
re PR c/35635 (-Wconversion problematic with bitfields)
2008-08-13 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
PR 35635
* c-common.c (conversion_warning): Use a switch. Ignore boolean
expressions except for conversions to signed:1 bitfields. Handle
COND_EXPR with constant operands.
testsuite/
* gcc.dg/pr35635.c: New.
* gcc.dg/Wconversion-integer.c: Update.
* gcc.dg/Wconversion-integer-no-sign.c: Update.
* gcc.dg/Wsign-conversion.c: Update.
* g++.dg/warn/pr35635.C: New.
* g++.dg/warn/Wconversion-integer.C: Update.
* g++.dg/warn/Wsign-conversion.C: Update.
From-SVN: r139049
Diffstat (limited to 'gcc/c-common.c')
-rw-r--r-- | gcc/c-common.c | 105 |
1 files changed, 76 insertions, 29 deletions
diff --git a/gcc/c-common.c b/gcc/c-common.c index 59da62f..9302182 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -1559,39 +1559,63 @@ conversion_warning (tree type, tree expr) { bool give_warning = false; - unsigned int formal_prec = TYPE_PRECISION (type); + tree expr_type = TREE_TYPE (expr); if (!warn_conversion && !warn_sign_conversion) return; - if (TREE_CODE (expr) == REAL_CST || TREE_CODE (expr) == INTEGER_CST) + switch (TREE_CODE (expr)) { + case EQ_EXPR: + case NE_EXPR: + case LE_EXPR: + case GE_EXPR: + case LT_EXPR: + case GT_EXPR: + case TRUTH_ANDIF_EXPR: + case TRUTH_ORIF_EXPR: + case TRUTH_AND_EXPR: + case TRUTH_OR_EXPR: + case TRUTH_XOR_EXPR: + case TRUTH_NOT_EXPR: + /* Conversion from boolean to a signed:1 bit-field (which only + can hold the values 0 and -1) doesn't lose information - but + it does change the value. */ + if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type)) + warning (OPT_Wconversion, + "conversion to %qT from boolean expression", type); + return; + + case REAL_CST: + case INTEGER_CST: + /* Warn for real constant that is not an exact integer converted to integer type. */ - if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE + if (TREE_CODE (expr_type) == REAL_TYPE && TREE_CODE (type) == INTEGER_TYPE) { - if (!real_isinteger (TREE_REAL_CST_PTR (expr), TYPE_MODE (TREE_TYPE (expr)))) + if (!real_isinteger (TREE_REAL_CST_PTR (expr), TYPE_MODE (expr_type))) give_warning = true; } /* Warn for an integer constant that does not fit into integer type. */ - else if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE + else if (TREE_CODE (expr_type) == INTEGER_TYPE && TREE_CODE (type) == INTEGER_TYPE && !int_fits_type_p (expr, type)) { - if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (TREE_TYPE (expr))) + if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (expr_type) + && tree_int_cst_sgn (expr) < 0) warning (OPT_Wsign_conversion, "negative integer implicitly converted to unsigned type"); - else if (!TYPE_UNSIGNED (type) && TYPE_UNSIGNED (TREE_TYPE (expr))) - warning (OPT_Wsign_conversion, - "conversion of unsigned constant value to negative integer"); + else if (!TYPE_UNSIGNED (type) && TYPE_UNSIGNED (expr_type)) + warning (OPT_Wsign_conversion, "conversion of unsigned constant " + "value to negative integer"); else give_warning = true; } else if (TREE_CODE (type) == REAL_TYPE) { /* Warn for an integer constant that does not fit into real type. */ - if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE) + if (TREE_CODE (expr_type) == INTEGER_TYPE) { REAL_VALUE_TYPE a = real_value_from_int_cst (0, expr); if (!exact_real_truncate (TYPE_MODE (type), &a)) @@ -1599,8 +1623,8 @@ conversion_warning (tree type, tree expr) } /* Warn for a real constant that does not fit into a smaller real type. */ - else if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE - && formal_prec < TYPE_PRECISION (TREE_TYPE (expr))) + else if (TREE_CODE (expr_type) == REAL_TYPE + && TYPE_PRECISION (type) < TYPE_PRECISION (expr_type)) { REAL_VALUE_TYPE a = TREE_REAL_CST (expr); if (!exact_real_truncate (TYPE_MODE (type), &a)) @@ -1611,11 +1635,31 @@ conversion_warning (tree type, tree expr) if (give_warning) warning (OPT_Wconversion, "conversion to %qT alters %qT constant value", - type, TREE_TYPE (expr)); - } - else /* 'expr' is not a constant. */ - { - tree expr_type = TREE_TYPE (expr); + type, expr_type); + + return; + + case COND_EXPR: + { + /* In case of COND_EXPR, if both operands are constants or + COND_EXPR, then we do not care about the type of COND_EXPR, + only about the conversion of each operand. */ + tree op1 = TREE_OPERAND (expr, 1); + tree op2 = TREE_OPERAND (expr, 2); + + if ((TREE_CODE (op1) == REAL_CST || TREE_CODE (op1) == INTEGER_CST + || TREE_CODE (op1) == COND_EXPR) + && (TREE_CODE (op2) == REAL_CST || TREE_CODE (op2) == INTEGER_CST + || TREE_CODE (op2) == COND_EXPR)) + { + conversion_warning (type, op1); + conversion_warning (type, op2); + return; + } + /* Fall through. */ + } + + default: /* 'expr' is not a constant. */ /* Warn for real types converted to integer types. */ if (TREE_CODE (expr_type) == REAL_TYPE @@ -1631,11 +1675,11 @@ conversion_warning (tree type, tree expr) /* Don't warn for short y; short x = ((int)y & 0xff); */ if (TREE_CODE (expr) == BIT_AND_EXPR - || TREE_CODE (expr) == BIT_IOR_EXPR + || TREE_CODE (expr) == BIT_IOR_EXPR || TREE_CODE (expr) == BIT_XOR_EXPR) { - /* It both args were extended from a shortest type, use - that type if that is safe. */ + /* If both args were extended from a shortest type, + use that type if that is safe. */ expr_type = shorten_binary_op (expr_type, TREE_OPERAND (expr, 0), TREE_OPERAND (expr, 1), @@ -1652,25 +1696,26 @@ conversion_warning (tree type, tree expr) && int_fits_type_p (op0, c_common_signed_type (type)) && int_fits_type_p (op0, c_common_unsigned_type (type))) || (TREE_CODE (op1) == INTEGER_CST - && int_fits_type_p (op1, c_common_signed_type (type)) - && int_fits_type_p (op1, c_common_unsigned_type (type)))) + && int_fits_type_p (op1, c_common_signed_type (type)) + && int_fits_type_p (op1, + c_common_unsigned_type (type)))) return; } } /* Warn for integer types converted to smaller integer types. */ - if (formal_prec < TYPE_PRECISION (expr_type)) + if (TYPE_PRECISION (type) < TYPE_PRECISION (expr_type)) give_warning = true; /* When they are the same width but different signedness, then the value may change. */ - else if ((formal_prec == TYPE_PRECISION (expr_type) + else if ((TYPE_PRECISION (type) == TYPE_PRECISION (expr_type) && TYPE_UNSIGNED (expr_type) != TYPE_UNSIGNED (type)) /* Even when converted to a bigger type, if the type is unsigned but expr is signed, then negative values will be changed. */ || (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (expr_type))) - warning (OPT_Wsign_conversion, - "conversion to %qT from %qT may change the sign of the result", + warning (OPT_Wsign_conversion, "conversion to %qT from %qT " + "may change the sign of the result", type, expr_type); } @@ -1682,8 +1727,10 @@ conversion_warning (tree type, tree expr) { tree type_low_bound = TYPE_MIN_VALUE (expr_type); tree type_high_bound = TYPE_MAX_VALUE (expr_type); - REAL_VALUE_TYPE real_low_bound = real_value_from_int_cst (0, type_low_bound); - REAL_VALUE_TYPE real_high_bound = real_value_from_int_cst (0, type_high_bound); + REAL_VALUE_TYPE real_low_bound + = real_value_from_int_cst (0, type_low_bound); + REAL_VALUE_TYPE real_high_bound + = real_value_from_int_cst (0, type_high_bound); if (!exact_real_truncate (TYPE_MODE (type), &real_low_bound) || !exact_real_truncate (TYPE_MODE (type), &real_high_bound)) @@ -1693,7 +1740,7 @@ conversion_warning (tree type, tree expr) /* Warn for real types converted to smaller real types. */ else if (TREE_CODE (expr_type) == REAL_TYPE && TREE_CODE (type) == REAL_TYPE - && formal_prec < TYPE_PRECISION (expr_type)) + && TYPE_PRECISION (type) < TYPE_PRECISION (expr_type)) give_warning = true; |