invoke.texi (-Wconversion): Document warnings specific to C++.
authorManuel López-Ibáñez <manu@gcc.gnu.org>
Fri, 16 Mar 2007 23:32:12 +0000 (23:32 +0000)
committerManuel López-Ibáñez <manu@gcc.gnu.org>
Fri, 16 Mar 2007 23:32:12 +0000 (23:32 +0000)
2007-03-16  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>

* doc/invoke.texi (-Wconversion): Document warnings specific to C++.
* c-common.c (convert_and_check): Move warning logic to...
(warnings_for_convert_and_check): ...here. Define.
* c-common.h (warnings_for_convert_and_check): Declare.
cp/
* cvt.c (cp_convert_and_check) : Define.
* cp-tree.h (cp_convert_and_check): Declare.
* call.c (convert_conversion_warnings): Rename to
conversion_null_warnings.  The warning for floating-point to
integer is handled by convert_and_check in convert_like_real.
(convert_like_real): convert_conversion_warnings was renamed as
conversion_null_warnings.
* typeck.c (build_binary_op): Use cp_convert_and_check to warn for
overflow and changes of value during conversion.
testsuite/
* g++.dg/warn/Wconversion-integer.C: New
* g++.dg/warn/Wconversion-real.C: New.
* g++.dg/warn/Wconversion-real-integer.C: New.
* g++.dg/warn/conv2.C: Updated.

From-SVN: r123005

14 files changed:
gcc/ChangeLog
gcc/c-common.c
gcc/c-common.h
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/typeck.c
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/warn/Wconversion-integer.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wconversion-real-integer.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wconversion-real.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/conv2.C

index 5d00c15..008e18c 100644 (file)
@@ -1,3 +1,10 @@
+2007-03-16  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>
+
+       * doc/invoke.texi (-Wconversion): Document warnings specific to C++.
+       * c-common.c (convert_and_check): Move warning logic to...
+       (warnings_for_convert_and_check): ...here. Define.
+       * c-common.h (warnings_for_convert_and_check): Declare.
+       
 2007-03-16  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
 
        * pa.c (attr_length_call): Partially revert change of 2007-03-09.
index 36b87eb..8f71e69 100644 (file)
@@ -1168,7 +1168,7 @@ vector_types_convertible_p (tree t1, tree t2, bool emit_lax_note)
 }
 
 /* Warns if the conversion of EXPR to TYPE may alter a value.
-   This function is called from convert_and_check.  */
+   This is a helper function for warnings_for_convert_and_check.  */
 
 static void
 conversion_warning (tree type, tree expr)
@@ -1276,23 +1276,13 @@ conversion_warning (tree type, tree expr)
     }
 }
 
-/* Convert EXPR to TYPE, warning about conversion problems with constants.
-   Invoke this function on every expression that is converted implicitly,
-   i.e. because of language rules and not because of an explicit cast.  */
+/* Produce warnings after a conversion. RESULT is the result of
+   converting EXPR to TYPE.  This is a helper function for
+   convert_and_check and cp_convert_and_check.  */
 
-tree
-convert_and_check (tree type, tree expr)
+void
+warnings_for_convert_and_check (tree type, tree expr, tree result)
 {
-  tree result;
-
-  if (TREE_TYPE (expr) == type)
-    return expr;
-  
-  result = convert (type, expr);
-
-  if (skip_evaluation || TREE_OVERFLOW_P (expr))
-    return result;
-
   if (TREE_CODE (expr) == INTEGER_CST
       && (TREE_CODE (type) == INTEGER_TYPE
           || TREE_CODE (type) == ENUMERAL_TYPE)
@@ -1332,7 +1322,26 @@ convert_and_check (tree type, tree expr)
              "overflow in implicit constant conversion");
   else if (warn_conversion)
     conversion_warning (type, expr);
+}
+
+
+/* Convert EXPR to TYPE, warning about conversion problems with constants.
+   Invoke this function on every expression that is converted implicitly,
+   i.e. because of language rules and not because of an explicit cast.  */
+
+tree
+convert_and_check (tree type, tree expr)
+{
+  tree result;
+
+  if (TREE_TYPE (expr) == type)
+    return expr;
   
+  result = convert (type, expr);
+
+  if (!skip_evaluation && !TREE_OVERFLOW_P (expr))
+    warnings_for_convert_and_check (type, expr, result);
+
   return result;
 }
 \f
index 08ce460..b16a02d 100644 (file)
@@ -671,6 +671,7 @@ struct varray_head_tag;
 extern void constant_expression_warning (tree);
 extern void strict_aliasing_warning (tree, tree, tree);
 extern void empty_if_body_warning (tree, tree);
+extern void warnings_for_convert_and_check (tree, tree, tree);
 extern tree convert_and_check (tree, tree);
 extern void overflow_warning (tree);
 extern void warn_logical_operator (enum tree_code, tree, tree);
index 730c59e..f5d26c0 100644 (file)
@@ -1,3 +1,15 @@
+2007-03-16  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>
+
+       * cvt.c (cp_convert_and_check) : Define.
+       * cp-tree.h (cp_convert_and_check): Declare.
+       * call.c (convert_conversion_warnings): Rename to
+       conversion_null_warnings.  The warning for floating-point to
+       integer is handled by convert_and_check in convert_like_real.
+       (convert_like_real): convert_conversion_warnings was renamed as
+       conversion_null_warnings.
+       * typeck.c (build_binary_op): Use cp_convert_and_check to warn for
+       overflow and changes of value during conversion.
+
 2007-03-15  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>
 
        PR c++/30891
index 9d25298..8218ed4 100644 (file)
@@ -4245,11 +4245,12 @@ build_temp (tree expr, tree type, int flags,
   return expr;
 }
 
-/* Perform warnings about conversion of EXPR to type TOTYPE.
+/* Perform warnings about peculiar, but valid, conversions from/to NULL.
+   EXPR is implicitly converted to type TOTYPE.
    FN and ARGNUM are used for diagnostics.  */
 
 static void
-convert_conversion_warnings (tree totype, tree expr, tree fn, int argnum)
+conversion_null_warnings (tree totype, tree expr, tree fn, int argnum)
 {
   tree t = non_reference (totype);
 
@@ -4263,19 +4264,8 @@ convert_conversion_warnings (tree totype, tree expr, tree fn, int argnum)
        warning (OPT_Wconversion, "converting to non-pointer type %qT from NULL", t);
     }
 
-  /* Warn about assigning a floating-point type to an integer type.  */
-  if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
-      && TREE_CODE (t) == INTEGER_TYPE)
-    {
-      if (fn)
-       warning (OPT_Wconversion, "passing %qT for argument %P to %qD",
-                TREE_TYPE (expr), argnum, fn);
-      else
-       warning (OPT_Wconversion, "converting to %qT from %qT", t, TREE_TYPE (expr));
-    }
-
   /* Issue warnings if "false" is converted to a NULL pointer */
-  if (expr == boolean_false_node && fn && POINTER_TYPE_P (t))
+  else if (expr == boolean_false_node && fn && POINTER_TYPE_P (t))
     warning (OPT_Wconversion,
             "converting %<false%> to pointer type for argument %P of %qD",
             argnum, fn);
@@ -4328,7 +4318,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
     }
 
   if (issue_conversion_warnings)
-    convert_conversion_warnings (totype, expr, fn, argnum);
+    conversion_null_warnings (totype, expr, fn, argnum);
 
   switch (convs->kind)
     {
@@ -4415,7 +4405,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 
   expr = convert_like_real (convs->u.next, expr, fn, argnum,
                            convs->kind == ck_ref_bind ? -1 : 1,
-                           /*issue_conversion_warnings=*/false,
+                           convs->kind == ck_ref_bind ? issue_conversion_warnings : false, 
                            c_cast_p);
   if (expr == error_mark_node)
     return error_mark_node;
index 7d6ebc7..b9b3500 100644 (file)
@@ -4049,6 +4049,7 @@ extern tree convert_from_reference                (tree);
 extern tree force_rvalue                       (tree);
 extern tree ocp_convert                                (tree, tree, int, int);
 extern tree cp_convert                         (tree, tree);
+extern tree cp_convert_and_check                (tree, tree);
 extern tree convert_to_void    (tree, const char */*implicit context*/);
 extern tree convert_force                      (tree, tree, int);
 extern tree build_expr_type_conversion         (int, tree, bool);
index 4e628a5..947f1f2 100644 (file)
@@ -593,6 +593,29 @@ cp_convert (tree type, tree expr)
   return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL);
 }
 
+/* C++ equivalent of convert_and_check but using cp_convert as the
+   conversion function.
+
+   Convert EXPR to TYPE, warning about conversion problems with constants.
+   Invoke this function on every expression that is converted implicitly,
+   i.e. because of language rules and not because of an explicit cast.  */
+
+tree
+cp_convert_and_check (tree type, tree expr)
+{
+  tree result;
+
+  if (TREE_TYPE (expr) == type)
+    return expr;
+  
+  result = cp_convert (type, expr);
+
+  if (!skip_evaluation && !TREE_OVERFLOW_P (expr))
+    warnings_for_convert_and_check (type, expr, result);
+
+  return result;
+}
+
 /* Conversion...
 
    FLAGS indicates how we should behave.  */
index ac6eb2b..6478b37 100644 (file)
@@ -3837,9 +3837,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
   if (! converted)
     {
       if (TREE_TYPE (op0) != result_type)
-       op0 = cp_convert (result_type, op0);
+       op0 = cp_convert_and_check (result_type, op0);
       if (TREE_TYPE (op1) != result_type)
-       op1 = cp_convert (result_type, op1);
+       op1 = cp_convert_and_check (result_type, op1);
 
       if (op0 == error_mark_node || op1 == error_mark_node)
        return error_mark_node;
index fa9ed7f..b3fe752 100644 (file)
@@ -3396,6 +3396,12 @@ like @code{unsigned ui = -1}; and conversions to smaller types, like
 ((int) x)} and @code{ui = (unsigned) -1}, or if the value is not
 changed by the conversion like in @code{abs (2.0)}.
 
+For C++, also warn for conversions between @code{NULL} and non-pointer
+types; confusing overload resolution for user-defined conversions; and
+conversions that will never use a type conversion operator:
+conversions to @code{void}, the same type, a base class or a reference
+to them.
+
 @item -Wempty-body
 @opindex Wempty-body
 An empty body occurs in an @samp{if}, @samp{else} or @samp{do while}
index f761dcc..560fab9 100644 (file)
@@ -1,3 +1,10 @@
+2007-03-16  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>
+
+       * g++.dg/warn/Wconversion-integer.C: New
+       * g++.dg/warn/Wconversion-real.C: New.
+       * g++.dg/warn/Wconversion-real-integer.C: New.
+       * g++.dg/warn/conv2.C: Updated.
+       
 2007-03-16  Richard Sandiford  <richard@codesourcery.com>
 
        * gcc.dg/intmax_t-1.c: Restrict XFAIL to VxWorks kernels;
diff --git a/gcc/testsuite/g++.dg/warn/Wconversion-integer.C b/gcc/testsuite/g++.dg/warn/Wconversion-integer.C
new file mode 100644 (file)
index 0000000..93f05cd
--- /dev/null
@@ -0,0 +1,95 @@
+/* Test for diagnostics for implicit conversions between integer types
+   C++ equivalent of gcc/testsuite/gcc.dg/Wconversion-integer.c  */
+
+// { dg-do compile } 
+// { dg-options "-fsigned-char -Wconversion" } 
+
+#include <limits.h>
+
+void fsc (signed char sc);
+void fuc (unsigned char uc);
+unsigned fui (unsigned int  ui);
+void fsi (signed int ui);
+
+void h (int x)
+{
+  unsigned int ui = 3;
+  int   si = 3;
+  unsigned char uc = 3;
+  signed char   sc = 3;
+
+  fuc (-1); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  uc = -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  fuc ('\xa0'); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  uc = '\xa0'; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  uc = x ? 1U : -1; /* { dg-warning "conversion" } */
+  /* { dg-warning "negative integer implicitly converted to unsigned type" "" { target *-*-* } 25 } */
+  uc = x ? SCHAR_MIN : 1U; /* { dg-warning "conversion" } */
+  /* { dg-warning "negative integer implicitly converted to unsigned type" "" { target *-*-* } 27 } */
+
+  uc = x ? 1 : -1; /* { dg-warning "conversion" } */
+
+  uc = x ? SCHAR_MIN : 1; /* { dg-warning "conversion" } */
+
+  fuc ('A');
+  uc = 'A';
+  uc = (unsigned char) -1;
+
+  fui (-1); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  ui = -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  ui = x ? 1U : -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  ui = x ? INT_MIN : 1U; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  ui = ui ? SCHAR_MIN : 1U; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  ui = 1U * -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  ui = ui + INT_MIN; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  ui = x ? 1 : -1; /* { dg-warning "conversion" } */
+  ui = ui ? SCHAR_MIN : 1; /* { dg-warning "conversion" } */
+
+  ui = -1 * (1 * -1);
+  ui = (unsigned) -1;
+
+  fsc (uc); /* { dg-warning "conversion" } */
+  sc = uc;  /* { dg-warning "conversion" } */
+  fuc (sc); /* { dg-warning "conversion" } */
+  uc = sc;  /* { dg-warning "conversion" } */
+  fsi (ui); /* { dg-warning "conversion" } */
+  si = ui;  /* { dg-warning "conversion" } */
+  fui (si); /* { dg-warning "conversion" } */ 
+  ui = si;  /* { dg-warning "conversion" } */ 
+  fui (sc); /* { dg-warning "conversion" } */
+  ui = sc;  /* { dg-warning "conversion" } */
+
+  fui ('\xa0');/* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  ui = '\xa0'; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+
+  fsi (si);
+  fui (ui);
+  fsi (uc);
+  si = uc;
+  fui (uc);
+  ui = uc;
+  fui ('A');
+  ui = 'A';
+  fsi ('A');
+  si = 'A';
+  
+
+  fsi (UINT_MAX - 1);  /* { dg-warning "conversion" } */
+  si = UINT_MAX - 1;   /* { dg-warning "conversion" } */
+  fsi (UINT_MAX - 1U); /* { dg-warning "conversion" } */
+  si = UINT_MAX - 1U;  /* { dg-warning "conversion" } */
+  fsi (UINT_MAX/3U);
+  si = UINT_MAX/3U;
+  fsi (UINT_MAX/3);
+  si = UINT_MAX/3;
+  fui (UINT_MAX - 1);
+  ui = UINT_MAX - 1;
+
+  fsi (0x80000000); /* { dg-warning "conversion" } */
+  si = 0x80000000;  /* { dg-warning "conversion" } */
+}
+
+
+unsigned fui (unsigned a) { return a + -1; } /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+
+
diff --git a/gcc/testsuite/g++.dg/warn/Wconversion-real-integer.C b/gcc/testsuite/g++.dg/warn/Wconversion-real-integer.C
new file mode 100644 (file)
index 0000000..64d5199
--- /dev/null
@@ -0,0 +1,73 @@
+/* Test for diagnostics for Wconversion between floating-point and
+   integers. C++ equivalent of
+   gcc/testsuite/gcc.dg/Wconversion-real-integer.c */
+
+/* { dg-do compile }
+/* { dg-options "-Wconversion" } */
+
+#include <limits.h>
+
+void fsi (signed int x);
+void fui (unsigned int x);
+void ffloat (float x);
+void fdouble (double x);
+
+float  vfloat;
+double vdouble;
+
+void h (void)
+{
+  unsigned int ui = 3;
+  int   si = 3;
+  unsigned char uc = 3;
+  signed char sc = 3;
+  float  f = 3;
+  double d = 3;
+
+  fsi (3.1f); /* { dg-warning "conversion" } */
+  si = 3.1f; /* { dg-warning "conversion" } */
+  fsi (3.1);  /* { dg-warning "conversion" } */
+  si = 3.1;  /* { dg-warning "conversion" } */
+  fsi (d);    /* { dg-warning "conversion" } */
+  si = d;    /* { dg-warning "conversion" } */
+  fui (-1.0); /* { dg-warning "overflow" } */
+  ui = -1.0;   /* { dg-warning "overflow" } */
+  ffloat (INT_MAX);  /* { dg-warning "conversion" } */
+  vfloat = INT_MAX;  /* { dg-warning "conversion" } */
+  ffloat (16777217); /* { dg-warning "conversion" } */
+  vfloat = 16777217; /* { dg-warning "conversion" } */
+  ffloat (si); /* { dg-warning "conversion" } */
+  vfloat = si; /* { dg-warning "conversion" } */
+  ffloat (ui); /* { dg-warning "conversion" } */
+  vfloat = ui; /* { dg-warning "conversion" } */
+
+  fsi (3);
+  si = 3;
+  fsi (3.0f);
+  si = 3.0f;
+  fsi (3.0);
+  si = 3.0;
+  fsi (16777217.0f);
+  si = 16777217.0f;
+  fsi ((int) 3.1);
+  si = (int) 3.1;
+  ffloat (3U);
+  vfloat = 3U;
+  ffloat (3);
+  vfloat = 3;
+  ffloat (INT_MIN);
+  vfloat = INT_MIN;
+  ffloat (uc);
+  vfloat = uc;
+  ffloat (sc);
+  vfloat = sc;
+
+  fdouble (UINT_MAX);
+  vdouble = UINT_MAX;
+  fdouble (ui);
+  vdouble = ui;
+  fdouble (si);
+  vdouble = si;
+}
+
+
diff --git a/gcc/testsuite/g++.dg/warn/Wconversion-real.C b/gcc/testsuite/g++.dg/warn/Wconversion-real.C
new file mode 100644 (file)
index 0000000..f769bac
--- /dev/null
@@ -0,0 +1,85 @@
+/* Test for diagnostics for Wconversion for floating-point.  
+   C++ equivalent of gcc/testsuite/gcc.dg/Wconversion-real.c */
+
+/* { dg-do compile }
+/* { dg-options "-Wconversion" } */
+
+float  vfloat;
+double vdouble;
+long double vlongdouble;
+
+void ffloat (float f);
+void fdouble (double d);
+void flongdouble (long double ld);
+
+void h (void)
+{
+  float f = 0;
+  double d = 0;
+  long double ld = 0;
+
+  ffloat (3.1); /* { dg-warning "conversion" } */
+  vfloat = 3.1; /* { dg-warning "conversion" } */
+  ffloat (3.1L); /* { dg-warning "conversion" } */
+  vfloat = 3.1L;  /* { dg-warning "conversion" } */
+  fdouble (3.1L); /* { dg-warning "conversion" "" { target large_long_double } } */
+  vdouble = 3.1L; /* { dg-warning "conversion" "" { target large_long_double } } */
+  ffloat (vdouble); /* { dg-warning "conversion" } */
+  vfloat = vdouble; /* { dg-warning "conversion" } */
+  ffloat (vlongdouble); /* { dg-warning "conversion" } */
+  vfloat = vlongdouble; /* { dg-warning "conversion" } */
+  fdouble (vlongdouble); /* { dg-warning "conversion" "" { target large_long_double } } */
+  vdouble = vlongdouble; /* { dg-warning "conversion" "" { target large_long_double } } */
+
+
+  ffloat ((float) 3.1); 
+  vfloat = (float) 3.1;
+  ffloat ((float) 3.1L);
+  vfloat = (float) 3.1L; 
+  fdouble ((double) 3.1L); 
+  vdouble = (double) 3.1L; 
+  ffloat ((float) vdouble); 
+  vfloat = (float) vdouble; 
+  ffloat ((float) vlongdouble); 
+  vfloat = (float) vlongdouble;
+  fdouble ((double) vlongdouble);
+  vdouble = (double) vlongdouble;
+
+
+  ffloat (3.0);
+  vfloat = 3.0;
+  ffloat (3.1f);
+  vfloat = 3.1f;
+  ffloat (0.25L);
+  vfloat = 0.25L;
+
+
+  fdouble (3.0);
+  vdouble = 3.0;
+  fdouble (3.1f);
+  vdouble = 3.1f;
+  fdouble (0.25L);
+  vdouble = 0.25L;
+
+  flongdouble (3.0);
+  vlongdouble = 3.0;
+  flongdouble (3.1f);
+  vlongdouble = 3.1f;
+  flongdouble (0.25L);
+  vlongdouble = 0.25L;
+
+  ffloat (f);
+  vfloat = f;
+  fdouble (f);
+  vdouble = f;
+  fdouble (d);
+  vdouble = d;
+  flongdouble (f);
+  vlongdouble = f;
+  flongdouble (d);
+  vlongdouble = d;
+  flongdouble (ld);
+  vlongdouble = ld;
+}
+
+
index 4dfeb86..45f5183 100644 (file)
@@ -1,4 +1,5 @@
 // PR c++/13932
 // { dg-options "-Wconversion" }
 
-int i = 1.; // { dg-warning "converting" }
+int i = 1.;
+int j = 1.1; // { dg-warning "conversion" }