Hi,
the below is my (very conservative, I think) interpretation of what we
recently summarized we want to do wrt these -Wconversion warnings in the
conditional expressions context. Of course many details could be
different, please let me know... This is booted and tested on x86_64-linux.
Thanks,
Paolo.
/////////////////
/c-family
2012-05-12 Paolo Carlini <paolo.carl...@oracle.com>
PR c/51294
* c-common.c (conversion_warning): In case of COND_EXPR don't warn
when unpromoted integer operands fit the target type.
/testsuite
2012-05-12 Paolo Carlini <paolo.carl...@oracle.com>
PR c/51294
* c-c++-common/Wconversion-pr51294.c: New.
Index: c-family/c-common.c
===================================================================
--- c-family/c-common.c (revision 187424)
+++ c-family/c-common.c (working copy)
@@ -2296,17 +2296,27 @@ conversion_warning (tree type, tree expr)
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. */
+ /* In case of COND_EXPR, if both operands are real constants,
+ integer types, 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);
+ tree op1_type = TREE_TYPE (op1);
+ tree op2_type = TREE_TYPE (op2);
- if ((TREE_CODE (op1) == REAL_CST || TREE_CODE (op1) == INTEGER_CST
+ if ((TREE_CODE (op1) == REAL_CST || INTEGRAL_TYPE_P (op1_type)
|| TREE_CODE (op1) == COND_EXPR)
- && (TREE_CODE (op2) == REAL_CST || TREE_CODE (op2) == INTEGER_CST
+ && (TREE_CODE (op2) == REAL_CST || INTEGRAL_TYPE_P (op2_type)
|| TREE_CODE (op2) == COND_EXPR))
{
+ /* Don't warn about char y = 0xff, x = cond ? y : 0; */
+ if (INTEGRAL_TYPE_P (op1_type)
+ && TREE_CODE (op1) != INTEGER_CST)
+ op1 = get_unwidened (op1, 0);
+ if (INTEGRAL_TYPE_P (op2_type)
+ && TREE_CODE (op2) != INTEGER_CST)
+ op2 = get_unwidened (op2, 0);
+
conversion_warning (type, op1);
conversion_warning (type, op2);
return;
Index: testsuite/c-c++-common/Wconversion-pr51294.c
===================================================================
--- testsuite/c-c++-common/Wconversion-pr51294.c (revision 0)
+++ testsuite/c-c++-common/Wconversion-pr51294.c (revision 0)
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-Wconversion" } */
+
+#ifdef __cplusplus
+#define BOOL bool
+#else
+#define BOOL _Bool
+#endif
+
+void foo (BOOL cond, char c, int i)
+{
+ c = cond ? c : 0;
+ c = cond ? 0 : c;
+ c = cond ? i : 0; /* { dg-warning "conversion" } */
+ c = cond ? 0 : i; /* { dg-warning "conversion" } */
+
+ c = cond ? (cond ? 0 : c) : 0;
+ c = cond ? 0 : (cond ? c : 0);
+ c = cond ? (cond ? 0 : i) : 0; /* { dg-warning "conversion" } */
+ c = cond ? 0 : (cond ? i : 0); /* { dg-warning "conversion" } */
+}