aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJoshua J Cogliati <jrincayc@yahoo.com>2013-11-20 07:15:40 +0000
committerManuel López-Ibáñez <manu@gcc.gnu.org>2013-11-20 07:15:40 +0000
commit49b0aa187af0ef02227886ef40697e758faed084 (patch)
tree1db592038d3ef44848cd4d54d0f45ab0344081ef /gcc
parent3b891d26733800746d0a95319846bd6134a48195 (diff)
downloadgcc-49b0aa187af0ef02227886ef40697e758faed084.zip
gcc-49b0aa187af0ef02227886ef40697e758faed084.tar.gz
gcc-49b0aa187af0ef02227886ef40697e758faed084.tar.bz2
re PR c/53001 (-Wfloat-conversion should be available to warn about floating point errors)
2013-11-19 Joshua J Cogliati <jrincayc@yahoo.com> PR c/53001 Splitting out a -Wfloat-conversion from -Wconversion for conversions that lower floating point number precision or conversion from floating point numbers to integers. gcc/c-family/ * c-common.c (unsafe_conversion_p): Make this function return an enumeration with more detail. (conversion_warning): Use the new return type of unsafe_conversion_p to separately warn either about conversions that lower floating point number precision or about the other kinds of conversions. * c-common.h (enum conversion_safety): New enumeration. (unsafe_conversion_p): switching return type to conversion_safety enumeration. * c.opt: Adding new warning -Wfloat-conversion and enabling it with -Wconversion. gcc/ * doc/invoke.texi: Adding documentation about -Wfloat-conversion. gcc/testsuite/ * c-c++-common/Wfloat-conversion.c: Copies relevant tests from c-c++-common/Wconversion-real.c, gcc.dg/Wconversion-real-integer.c and gcc.dg/pr35635.c into new testcase for conversions that are warned about by -Wfloat-conversion. From-SVN: r205090
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/c-family/ChangeLog15
-rw-r--r--gcc/c-family/c-common.c47
-rw-r--r--gcc/c-family/c-common.h12
-rw-r--r--gcc/c-family/c.opt4
-rw-r--r--gcc/doc/invoke.texi11
-rw-r--r--gcc/testsuite/ChangeLog9
-rw-r--r--gcc/testsuite/c-c++-common/Wfloat-conversion.c58
8 files changed, 142 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index dd15cd4..3900adf 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2013-11-19 Joshua J Cogliati <jrincayc@yahoo.com>
+
+ PR c/53001
+ * doc/invoke.texi: Adding documentation about
+ -Wfloat-conversion.
+
2013-11-20 Miro Kropacek <miro.kropacek@gmail.com>
* config/m68k/m68k.c (m68k_option_overrides): Fix typo.
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 5bbd5f5..525efad 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,18 @@
+2013-11-19 Joshua J Cogliati <jrincayc@yahoo.com>
+
+ PR c/53001
+ * c-common.c (unsafe_conversion_p): Make this function
+ return an enumeration with more detail.
+ (conversion_warning): Use the new return type of
+ unsafe_conversion_p to separately warn either about conversions
+ that lower floating point number precision or about the other
+ kinds of conversions.
+ * c-common.h (enum conversion_safety): New enumeration.
+ (unsafe_conversion_p): switching return type to
+ conversion_safety enumeration.
+ * c.opt: Adding new warning -Wfloat-conversion and
+ enabling it with -Wconversion.
+
2013-11-19 Basile Starynkevitch <basile@starynkevitch.net>
* c-opts.c: Include plugin.h.
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index b4bd63b..9f89a16 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -2537,7 +2537,7 @@ shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwise)
}
/* Checks if expression EXPR of real/integer type cannot be converted
- to the real/integer type TYPE. Function returns true when:
+ to the real/integer type TYPE. Function returns non-zero when:
* EXPR is a constant which cannot be exactly converted to TYPE
* EXPR is not a constant and size of EXPR's type > than size of TYPE,
for EXPR type and TYPE being both integers or both real.
@@ -2545,12 +2545,12 @@ shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwise)
* EXPR is not a constant of integer type which cannot be
exactly converted to real type.
Function allows conversions between types of different signedness and
- does not return true in that case. Function can produce signedness
- warnings if PRODUCE_WARNS is true. */
-bool
+ can return SAFE_CONVERSION (zero) in that case. Function can produce
+ signedness warnings if PRODUCE_WARNS is true. */
+enum conversion_safety
unsafe_conversion_p (tree type, tree expr, bool produce_warns)
{
- bool give_warning = false;
+ enum conversion_safety give_warning = SAFE_CONVERSION; /* is 0 or false */
tree expr_type = TREE_TYPE (expr);
location_t loc = EXPR_LOC_OR_HERE (expr);
@@ -2562,7 +2562,7 @@ unsafe_conversion_p (tree type, tree expr, bool produce_warns)
&& TREE_CODE (type) == INTEGER_TYPE)
{
if (!real_isinteger (TREE_REAL_CST_PTR (expr), TYPE_MODE (expr_type)))
- give_warning = true;
+ give_warning = UNSAFE_REAL;
}
/* Warn for an integer constant that does not fit into integer type. */
else if (TREE_CODE (expr_type) == INTEGER_TYPE
@@ -2583,7 +2583,7 @@ unsafe_conversion_p (tree type, tree expr, bool produce_warns)
" constant value to negative integer");
}
else
- give_warning = true;
+ give_warning = UNSAFE_OTHER;
}
else if (TREE_CODE (type) == REAL_TYPE)
{
@@ -2592,7 +2592,7 @@ unsafe_conversion_p (tree type, tree expr, bool produce_warns)
{
REAL_VALUE_TYPE a = real_value_from_int_cst (0, expr);
if (!exact_real_truncate (TYPE_MODE (type), &a))
- give_warning = true;
+ give_warning = UNSAFE_REAL;
}
/* Warn for a real constant that does not fit into a smaller
real type. */
@@ -2601,7 +2601,7 @@ unsafe_conversion_p (tree type, tree expr, bool produce_warns)
{
REAL_VALUE_TYPE a = TREE_REAL_CST (expr);
if (!exact_real_truncate (TYPE_MODE (type), &a))
- give_warning = true;
+ give_warning = UNSAFE_REAL;
}
}
}
@@ -2610,7 +2610,7 @@ unsafe_conversion_p (tree type, tree expr, bool produce_warns)
/* Warn for real types converted to integer types. */
if (TREE_CODE (expr_type) == REAL_TYPE
&& TREE_CODE (type) == INTEGER_TYPE)
- give_warning = true;
+ give_warning = UNSAFE_REAL;
else if (TREE_CODE (expr_type) == INTEGER_TYPE
&& TREE_CODE (type) == INTEGER_TYPE)
@@ -2648,7 +2648,7 @@ unsafe_conversion_p (tree type, tree expr, bool produce_warns)
&& int_fits_type_p (op1, c_common_signed_type (type))
&& int_fits_type_p (op1,
c_common_unsigned_type (type))))
- return false;
+ return SAFE_CONVERSION;
/* If constant is unsigned and fits in the target
type, then the result will also fit. */
else if ((TREE_CODE (op0) == INTEGER_CST
@@ -2657,12 +2657,12 @@ unsafe_conversion_p (tree type, tree expr, bool produce_warns)
|| (TREE_CODE (op1) == INTEGER_CST
&& unsigned1
&& int_fits_type_p (op1, type)))
- return false;
+ return SAFE_CONVERSION;
}
}
/* Warn for integer types converted to smaller integer types. */
if (TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
- give_warning = true;
+ give_warning = UNSAFE_OTHER;
/* When they are the same width but different signedness,
then the value may change. */
@@ -2698,14 +2698,14 @@ unsafe_conversion_p (tree type, tree expr, bool produce_warns)
if (!exact_real_truncate (TYPE_MODE (type), &real_low_bound)
|| !exact_real_truncate (TYPE_MODE (type), &real_high_bound))
- give_warning = true;
+ give_warning = UNSAFE_OTHER;
}
/* Warn for real types converted to smaller real types. */
else if (TREE_CODE (expr_type) == REAL_TYPE
&& TREE_CODE (type) == REAL_TYPE
&& TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
- give_warning = true;
+ give_warning = UNSAFE_REAL;
}
return give_warning;
@@ -2719,8 +2719,9 @@ conversion_warning (tree type, tree expr)
{
tree expr_type = TREE_TYPE (expr);
location_t loc = EXPR_LOC_OR_HERE (expr);
+ enum conversion_safety conversion_kind;
- if (!warn_conversion && !warn_sign_conversion)
+ if (!warn_conversion && !warn_sign_conversion && !warn_float_conversion)
return;
switch (TREE_CODE (expr))
@@ -2747,7 +2748,12 @@ conversion_warning (tree type, tree expr)
case REAL_CST:
case INTEGER_CST:
- if (unsafe_conversion_p (type, expr, true))
+ conversion_kind = unsafe_conversion_p (type, expr, true);
+ if (conversion_kind == UNSAFE_REAL)
+ warning_at (loc, OPT_Wfloat_conversion,
+ "conversion to %qT alters %qT constant value",
+ type, expr_type);
+ else if (conversion_kind)
warning_at (loc, OPT_Wconversion,
"conversion to %qT alters %qT constant value",
type, expr_type);
@@ -2766,7 +2772,12 @@ conversion_warning (tree type, tree expr)
}
default: /* 'expr' is not a constant. */
- if (unsafe_conversion_p (type, expr, true))
+ conversion_kind = unsafe_conversion_p (type, expr, true);
+ if (conversion_kind == UNSAFE_REAL)
+ warning_at (loc, OPT_Wfloat_conversion,
+ "conversion to %qT from %qT may alter its value",
+ type, expr_type);
+ else if (conversion_kind)
warning_at (loc, OPT_Wconversion,
"conversion to %qT from %qT may alter its value",
type, expr_type);
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index b931fd6..664e928 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -688,6 +688,16 @@ struct visibility_flags
unsigned inlines_hidden : 1; /* True when -finlineshidden in effect. */
};
+/* These enumerators are possible types of unsafe conversions.
+ SAFE_CONVERSION The conversion is safe
+ UNSAFE_OTHER Another type of conversion with problems
+ UNSAFE_SIGN Conversion between signed and unsigned integers
+ which are all warned about immediately, so this is unused
+ UNSAFE_REAL Conversions that reduce the precision of reals
+ including conversions from reals to integers
+ */
+enum conversion_safety { SAFE_CONVERSION = 0, UNSAFE_OTHER, UNSAFE_SIGN, UNSAFE_REAL };
+
/* Global visibility options. */
extern struct visibility_flags visibility_options;
@@ -741,7 +751,7 @@ extern tree c_common_signed_type (tree);
extern tree c_common_signed_or_unsigned_type (int, tree);
extern void c_common_init_ts (void);
extern tree c_build_bitfield_integer_type (unsigned HOST_WIDE_INT, int);
-extern bool unsafe_conversion_p (tree, tree, bool);
+extern enum conversion_safety unsafe_conversion_p (tree, tree, bool);
extern bool decl_with_nonnull_addr_p (const_tree);
extern tree c_fully_fold (tree, bool, bool *);
extern tree decl_constant_value_for_optimization (tree);
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 0026683..ac67885 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -387,6 +387,10 @@ Werror-implicit-function-declaration
C ObjC RejectNegative Warning Alias(Werror=, implicit-function-declaration)
This switch is deprecated; use -Werror=implicit-function-declaration instead
+Wfloat-conversion
+C ObjC C++ ObjC++ Var(warn_float_conversion) LangEnabledBy(C ObjC C++ ObjC++,Wconversion)
+Warn for implicit type conversions that cause loss of floating point precision
+
Wfloat-equal
C ObjC C++ ObjC++ Var(warn_float_equal) Warning
Warn if testing floating point numbers for equality
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 7074a48..6fc56b9 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -262,7 +262,8 @@ Objective-C and Objective-C++ Dialects}.
-Wpointer-arith -Wno-pointer-to-int-cast @gol
-Wredundant-decls -Wno-return-local-addr @gol
-Wreturn-type -Wsequence-point -Wshadow @gol
--Wsign-compare -Wsign-conversion -Wsizeof-pointer-memaccess @gol
+-Wsign-compare -Wsign-conversion -Wfloat-conversion @gol
+-Wsizeof-pointer-memaccess @gol
-Wstack-protector -Wstack-usage=@var{len} -Wstrict-aliasing @gol
-Wstrict-aliasing=n @gol -Wstrict-overflow -Wstrict-overflow=@var{n} @gol
-Wsuggest-attribute=@r{[}pure@r{|}const@r{|}noreturn@r{|}format@r{]} @gol
@@ -4592,6 +4593,14 @@ value, like assigning a signed integer expression to an unsigned
integer variable. An explicit cast silences the warning. In C, this
option is enabled also by @option{-Wconversion}.
+@item -Wfloat-conversion
+@opindex Wfloat-conversion
+@opindex Wno-float-conversion
+Warn for implicit conversions that reduce the precision of a real value.
+This includes conversions from real to integer, and from higher precision
+real to lower precision real values. This option is also enabled by
+@option{-Wconversion}.
+
@item -Wsizeof-pointer-memaccess
@opindex Wsizeof-pointer-memaccess
@opindex Wno-sizeof-pointer-memaccess
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 178dd39..bb30fd3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,12 @@
+2013-11-19 Joshua J Cogliati <jrincayc@yahoo.com>
+
+ PR c/53001
+ * c-c++-common/Wfloat-conversion.c: Copies relevant
+ tests from c-c++-common/Wconversion-real.c,
+ gcc.dg/Wconversion-real-integer.c and gcc.dg/pr35635.c into
+ new testcase for conversions that are warned about by
+ -Wfloat-conversion.
+
2013-11-19 Martin Jambor <mjambor@suse.cz>
PR rtl-optimization/59099
diff --git a/gcc/testsuite/c-c++-common/Wfloat-conversion.c b/gcc/testsuite/c-c++-common/Wfloat-conversion.c
new file mode 100644
index 0000000..e872755
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wfloat-conversion.c
@@ -0,0 +1,58 @@
+/* Test for diagnostics for Wconversion for floating-point. */
+
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -Wfloat-conversion" { target c } } */
+/* { dg-options "-Wfloat-conversion" { target c++ } } */
+/* { dg-require-effective-target large_double } */
+/* { dg-require-effective-target int32plus } */
+/* { dg-require-effective-target double64plus } */
+#include <limits.h>
+
+float vfloat;
+double vdouble;
+long double vlongdouble;
+int bar;
+
+void fsi (signed int x);
+void fui (unsigned int x);
+void ffloat (float f);
+void fdouble (double d);
+void flongdouble (long double ld);
+
+void h (void)
+{
+ unsigned int ui = 3;
+ int si = 3;
+ unsigned char uc = 3;
+ signed char sc = 3;
+ float f = 0;
+ double d = 0;
+ long double ld = 0;
+
+ ffloat (3.1); /* { dg-warning "conversion to 'float' alters 'double' constant value" } */
+ vfloat = 3.1; /* { dg-warning "conversion to 'float' alters 'double' constant value" } */
+ ffloat (3.1L); /* { dg-warning "conversion to 'float' alters 'long double' constant value" } */
+ vfloat = 3.1L; /* { dg-warning "conversion to 'float' alters 'long double' constant value" } */
+ fdouble (3.1L); /* { dg-warning "conversion to 'double' alters 'long double' constant value" "" { target large_long_double } } */
+ vdouble = 3.1L; /* { dg-warning "conversion to 'double' alters 'long double' constant value" "" { target large_long_double } } */
+ ffloat (vdouble); /* { dg-warning "conversion to 'float' from 'double' may alter its value" } */
+ vfloat = vdouble; /* { dg-warning "conversion to 'float' from 'double' may alter its value" } */
+ ffloat (vlongdouble); /* { dg-warning "conversion to 'float' from 'long double' may alter its value" } */
+ vfloat = vlongdouble; /* { dg-warning "conversion to 'float' from 'long double' may alter its value" } */
+ fdouble (vlongdouble); /* { dg-warning "conversion to 'double' from 'long double' may alter its value" "" { target large_long_double } } */
+ vdouble = vlongdouble; /* { dg-warning "conversion to 'double' from 'long double' may alter its value" "" { target large_long_double } } */
+
+ fsi (3.1f); /* { dg-warning "conversion to 'int' alters 'float' constant value" } */
+ si = 3.1f; /* { dg-warning "conversion to 'int' alters 'float' constant value" } */
+ fsi (3.1); /* { dg-warning "conversion to 'int' alters 'double' constant value" } */
+ si = 3.1; /* { dg-warning "conversion to 'int' alters 'double' constant value" } */
+ fsi (d); /* { dg-warning "conversion to 'int' from 'double' may alter its value" } */
+ si = d; /* { dg-warning "conversion to 'int' from 'double' may alter its value" } */
+ ffloat (INT_MAX); /* { dg-warning "conversion to 'float' alters 'int' constant value" } */
+ vfloat = INT_MAX; /* { dg-warning "conversion to 'float' alters 'int' constant value" } */
+ ffloat (16777217); /* { dg-warning "conversion to 'float' alters 'int' constant value" } */
+ vfloat = 16777217; /* { dg-warning "conversion to 'float' alters 'int' constant value" } */
+
+ sc = bar != 0 ? 2.1 : 10; /* { dg-warning "conversion to 'signed char' alters 'double' constant value" } */
+ uc = bar != 0 ? 2.1 : 10; /* { dg-warning "conversion to 'unsigned char' alters 'double' constant value" } */
+}