aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/c-common.c41
-rw-r--r--gcc/c-common.h1
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/call.c22
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/cvt.c23
-rw-r--r--gcc/cp/typeck.c4
-rw-r--r--gcc/doc/invoke.texi6
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/g++.dg/warn/Wconversion-integer.C95
-rw-r--r--gcc/testsuite/g++.dg/warn/Wconversion-real-integer.C73
-rw-r--r--gcc/testsuite/g++.dg/warn/Wconversion-real.C85
-rw-r--r--gcc/testsuite/g++.dg/warn/conv2.C3
14 files changed, 345 insertions, 35 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5d00c15..008e18c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 36b87eb..8f71e691 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -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;
}
diff --git a/gcc/c-common.h b/gcc/c-common.h
index 08ce460..b16a02d 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -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);
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 730c59e..f5d26c0 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 9d25298..8218ed4 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7d6ebc7..b9b3500 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 4e628a5..947f1f2 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -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. */
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index ac6eb2b..6478b37 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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;
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index fa9ed7f..b3fe752 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -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}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index f761dcc..560fab9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..93f05cd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wconversion-integer.C
@@ -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
index 0000000..64d5199
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wconversion-real-integer.C
@@ -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
index 0000000..f769bac
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wconversion-real.C
@@ -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;
+}
+
+
diff --git a/gcc/testsuite/g++.dg/warn/conv2.C b/gcc/testsuite/g++.dg/warn/conv2.C
index 4dfeb86..45f5183 100644
--- a/gcc/testsuite/g++.dg/warn/conv2.C
+++ b/gcc/testsuite/g++.dg/warn/conv2.C
@@ -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" }