From 80c6d1f4463b5a848451513d788d38bb366dbefb Mon Sep 17 00:00:00 2001 From: Martin Jambor Date: Mon, 17 Sep 2018 15:12:12 +0200 Subject: [PATCH] Add -Wabsolute-value 2018-09-17 Martin Jambor gcc/ * doc/invoke.texi (Warning Options): Likewise. gcc/c-family/ * c.opt (Wabsolute-value): New. gcc/c/ * c-parser.c: (warn_for_abs): New function. (c_parser_postfix_expression_after_primary): Call it. testsuite/ * gcc.dg/warn-abs-1.c: New test. * gcc.dg/dfp/warn-abs-2.c: Likewise. From-SVN: r264368 --- gcc/ChangeLog | 5 + gcc/c-family/ChangeLog | 5 + gcc/c-family/c.opt | 4 + gcc/c/ChangeLog | 6 + gcc/c/c-parser.c | 156 +++++++++++++++++++++++++- gcc/doc/invoke.texi | 8 ++ gcc/testsuite/ChangeLog | 6 + gcc/testsuite/gcc.dg/dfp/warn-abs-2.c | 28 +++++ gcc/testsuite/gcc.dg/warn-abs-1.c | 67 +++++++++++ 9 files changed, 279 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/dfp/warn-abs-2.c create mode 100644 gcc/testsuite/gcc.dg/warn-abs-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 738f0c3fbb5..f653d66f288 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2018-09-17 Martin Jambor + + PR c/63886 + * doc/invoke.texi (Warning Options): Likewise. + 2018-09-17 Richard Biener PR tree-optimization/87301 diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 75064a2b684..b299ad2bc22 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,8 @@ +2018-09-17 Martin Jambor + + PR c/63886 + * c.opt (Wabsolute-value): New. + 2018-09-06 Bernd Edlinger * c-common.c (complete_flexible_array_elts): New helper function. diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 31a2b972919..092ec940d86 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -271,6 +271,10 @@ Warn if a subobject has an abi_tag attribute that the complete object type does Wpsabi C ObjC C++ ObjC++ LTO Var(warn_psabi) Init(1) Warning Undocumented LangEnabledBy(C ObjC C++ ObjC++,Wabi) +Wabsolute-value +C ObjC Var(warn_absolute_value) Warning EnabledBy(Wextra) +Warn on suspicious calls of standard functions computing absolute values. + Waddress C ObjC C++ ObjC++ Var(warn_address) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) Warn about suspicious uses of memory addresses. diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index c28fb1c0ebc..3133ca6b6b0 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,9 @@ +2018-09-17 Martin Jambor + + PR c/63886 + * c-parser.c: (warn_for_abs): New function. + (c_parser_postfix_expression_after_primary): Call it. + 2018-09-13 Bernd Edlinger * c-typeck.c (digest_init): Shorten overlength strings. diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 69ed5ae9d2f..1766a256633 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -9101,6 +9101,144 @@ sizeof_ptr_memacc_comptypes (tree type1, tree type2) return comptypes (type1, type2) == 1; } +/* Warn for patterns where abs-like function appears to be used incorrectly, + gracely ignore any non-abs-like function. The warning location should be + LOC. FNDECL is the declaration of called function, it must be a + BUILT_IN_NORMAL function. ARG is the first and only argument of the + call. */ + +static void +warn_for_abs (location_t loc, tree fndecl, tree arg) +{ + tree atype = TREE_TYPE (arg); + + /* Casts from pointers (and thus arrays and fndecls) will generate + -Wint-conversion warnings. Most other wrong types hopefully lead to type + mismatch errors. TODO: Think about what to do with FIXED_POINT_TYPE_P + types and possibly other exotic types. */ + if (!INTEGRAL_TYPE_P (atype) + && !SCALAR_FLOAT_TYPE_P (atype) + && TREE_CODE (atype) != COMPLEX_TYPE) + return; + + enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); + + switch (fcode) + { + case BUILT_IN_ABS: + case BUILT_IN_LABS: + case BUILT_IN_LLABS: + case BUILT_IN_IMAXABS: + if (!INTEGRAL_TYPE_P (atype)) + { + if (SCALAR_FLOAT_TYPE_P (atype)) + warning_at (loc, OPT_Wabsolute_value, + "using integer absolute value function %qD when " + "argument is of floating point type %qT", + fndecl, atype); + else if (TREE_CODE (atype) == COMPLEX_TYPE) + warning_at (loc, OPT_Wabsolute_value, + "using integer absolute value function %qD when " + "argument is of complex type %qT", fndecl, atype); + else + gcc_unreachable (); + return; + } + if (TYPE_UNSIGNED (atype)) + warning_at (loc, OPT_Wabsolute_value, + "taking the absolute value of unsigned type %qT " + "has no effect", atype); + break; + + CASE_FLT_FN (BUILT_IN_FABS): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS): + if (!SCALAR_FLOAT_TYPE_P (atype) + || DECIMAL_FLOAT_MODE_P (TYPE_MODE (atype))) + { + if (INTEGRAL_TYPE_P (atype)) + warning_at (loc, OPT_Wabsolute_value, + "using floating point absolute value function %qD " + "when argument is of integer type %qT", fndecl, atype); + else if (DECIMAL_FLOAT_TYPE_P (atype)) + warning_at (loc, OPT_Wabsolute_value, + "using floating point absolute value function %qD " + "when argument is of decimal floating point type %qT", + fndecl, atype); + else if (TREE_CODE (atype) == COMPLEX_TYPE) + warning_at (loc, OPT_Wabsolute_value, + "using floating point absolute value function %qD when " + "argument is of complex type %qT", fndecl, atype); + else + gcc_unreachable (); + return; + } + break; + + CASE_FLT_FN (BUILT_IN_CABS): + if (TREE_CODE (atype) != COMPLEX_TYPE) + { + if (INTEGRAL_TYPE_P (atype)) + warning_at (loc, OPT_Wabsolute_value, + "using complex absolute value function %qD when " + "argument is of integer type %qT", fndecl, atype); + else if (SCALAR_FLOAT_TYPE_P (atype)) + warning_at (loc, OPT_Wabsolute_value, + "using complex absolute value function %qD when " + "argument is of floating point type %qT", + fndecl, atype); + else + gcc_unreachable (); + + return; + } + break; + + case BUILT_IN_FABSD32: + case BUILT_IN_FABSD64: + case BUILT_IN_FABSD128: + if (!DECIMAL_FLOAT_TYPE_P (atype)) + { + if (INTEGRAL_TYPE_P (atype)) + warning_at (loc, OPT_Wabsolute_value, + "using decimal floating point absolute value " + "function %qD when argument is of integer type %qT", + fndecl, atype); + else if (SCALAR_FLOAT_TYPE_P (atype)) + warning_at (loc, OPT_Wabsolute_value, + "using decimal floating point absolute value " + "function %qD when argument is of floating point " + "type %qT", fndecl, atype); + else if (TREE_CODE (atype) == COMPLEX_TYPE) + warning_at (loc, OPT_Wabsolute_value, + "using decimal floating point absolute value " + "function %qD when argument is of complex type %qT", + fndecl, atype); + else + gcc_unreachable (); + return; + } + break; + + default: + return; + } + + tree ftype = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl))); + if (TREE_CODE (atype) == COMPLEX_TYPE) + { + gcc_assert (TREE_CODE (ftype) == COMPLEX_TYPE); + atype = TREE_TYPE (atype); + ftype = TREE_TYPE (ftype); + } + + if (TYPE_PRECISION (ftype) < TYPE_PRECISION (atype)) + warning_at (loc, OPT_Wabsolute_value, + "absolute value function %qD given an argument of type %qT " + "but has parameter of type %qT which may cause truncation " + "of value", fndecl, atype, ftype); +} + + /* Parse a postfix expression after the initial primary or compound literal; that is, parse a series of postfix operators. @@ -9165,13 +9303,19 @@ c_parser_postfix_expression_after_primary (c_parser *parser, expr.value, exprlist, sizeof_arg, sizeof_ptr_memacc_comptypes); - if (TREE_CODE (expr.value) == FUNCTION_DECL - && fndecl_built_in_p (expr.value, BUILT_IN_MEMSET) - && vec_safe_length (exprlist) == 3) + if (TREE_CODE (expr.value) == FUNCTION_DECL) { - tree arg0 = (*exprlist)[0]; - tree arg2 = (*exprlist)[2]; - warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask); + if (fndecl_built_in_p (expr.value, BUILT_IN_MEMSET) + && vec_safe_length (exprlist) == 3) + { + tree arg0 = (*exprlist)[0]; + tree arg2 = (*exprlist)[2]; + warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask); + } + if (warn_absolute_value + && fndecl_built_in_p (expr.value, BUILT_IN_NORMAL) + && vec_safe_length (exprlist) == 1) + warn_for_abs (expr_loc, expr.value, (*exprlist)[0]); } start = expr.get_start (); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index ec127113356..94304c314cf 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -6281,6 +6281,14 @@ example, warn if an unsigned variable is compared against zero with @code{<} or @code{>=}. This warning is also enabled by @option{-Wextra}. +@item -Wabsolute-value @r{(C and Objective-C only)} +@opindex Wabsolute-value +@opindex Wno-absolute-value +Warn when a wrong absolute value function seems to be used or when it +does not have any effect because its argument is an unsigned type. +This warning be suppressed with an explicit type cast and it is also +enabled by @option{-Wextra}. + @include cppwarnopts.texi @item -Wbad-function-cast @r{(C and Objective-C only)} diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2e7c8787511..4fd1ff928ab 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2018-09-17 Martin Jambor + + PR c/63886 + * gcc.dg/warn-abs-1.c: New test. + * gcc.dg/dfp/warn-abs-2.c: Likewise. + 2018-09-17 Bernd Edlinger * gcc.target/x86_64/abi/ms-sysv/ms-sysv.exp: Don't pass diff --git a/gcc/testsuite/gcc.dg/dfp/warn-abs-2.c b/gcc/testsuite/gcc.dg/dfp/warn-abs-2.c new file mode 100644 index 00000000000..c1a1994997f --- /dev/null +++ b/gcc/testsuite/gcc.dg/dfp/warn-abs-2.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-Wabsolute-value" } */ + +#include +#include +#include + +void tst_decimal (_Decimal32 *p32, _Decimal64 *p64, _Decimal128 *p128) +{ + *p32 = abs(*p32); /* { dg-warning "using integer absolute value function" } */ + *p64 = fabs(*p64); /* { dg-warning "using floating point absolute value function" } */ + *p128 = cabsl(*p128); /* { dg-warning "using complex absolute value function" } */ +} + +void tst_notdecimal (int *pi, double *pd, long double *pld, complex double *pc) +{ + *pi = __builtin_fabsd32 (*pi); /* { dg-warning "using decimal floating point absolute value function" } */ + *pd = __builtin_fabsd64 (*pd); /* { dg-warning "using decimal floating point absolute value function" } */ + *pld = __builtin_fabsd64 (*pld); /* { dg-warning "using decimal floating point absolute value function" } */ + *pc = __builtin_fabsd128 (*pc); /* { dg-warning "using decimal floating point absolute value function" } */ +} + +void +test_size (_Decimal64 *p64, _Decimal128 *p128) +{ + *p64 = __builtin_fabsd32 (*p64); /* { dg-warning "may cause truncation of value" } */ + *p128 = __builtin_fabsd64 (*p128); /* { dg-warning "may cause truncation of value" } */ +} diff --git a/gcc/testsuite/gcc.dg/warn-abs-1.c b/gcc/testsuite/gcc.dg/warn-abs-1.c new file mode 100644 index 00000000000..6aa937c3a2e --- /dev/null +++ b/gcc/testsuite/gcc.dg/warn-abs-1.c @@ -0,0 +1,67 @@ +/* { dg-do compile } */ +/* { dg-options "-Wabsolute-value" } */ + +#include +#include +#include +#include + +void +tst_unsigned (unsigned *pu, unsigned long *pl, unsigned long long *pll, + uintmax_t *pm) +{ + *pu = abs (*pu); /* { dg-warning "taking the absolute value of unsigned type" } */ + *pl = labs (*pl); /* { dg-warning "taking the absolute value of unsigned type" } */ + *pll = llabs (*pll); /* { dg-warning "taking the absolute value of unsigned type" } */ + *pm = imaxabs (*pm); /* { dg-warning "taking the absolute value of unsigned type" } */ +} + +void +test_int_size (long long *pll) +{ + *pll = abs (*pll); /* { dg-warning "may cause truncation of value" } */ + *pll = abs ((int) *pll); +} + +void +tst_notint (float *pf, double *pd, _Complex double *pc) +{ + *pf = abs (*pf); /* { dg-warning "using integer absolute value function" } */ + *pd = labs (*pd); /* { dg-warning "using integer absolute value function" } */ + *pc = abs (*pc); /* { dg-warning "using integer absolute value function" } */ +} + +void +tst_notfloat (int *pi, long *pl, complex double *pc) +{ + *pi = fabsf (*pi); /* { dg-warning "using floating point absolute value function" } */ + *pl = fabs (*pl); /* { dg-warning "using floating point absolute value function" } */ + *pc = fabs (*pc); /* { dg-warning "using floating point absolute value function" } */ +} + +void +tst_float_size (double *pd, long double *pld, _Float128 *pf128) +{ + *pd = fabsf (*pd); /* { dg-warning "may cause truncation of value" } */ + *pld = fabs (*pld); /* { dg-warning "may cause truncation of value" } */ + *pld = fabs ((double) *pld); + *pf128 = fabsl (*pf128); /* { dg-warning "may cause truncation of value" } */ +} + +void tst_notcomplex (int *pi, long *pl, long double *pld) +{ + *pi = cabs (*pi); /* { dg-warning "using complex absolute value function" } */ + *pl = cabs (*pl); /* { dg-warning "using complex absolute value function" } */ + *pld = cabsl (*pld);/* { dg-warning "using complex absolute value function" } */ +} + +void tst_cplx_size (complex double *pcd, complex long double *pcld) +{ + *pcd = cabsf (*pcd); /* { dg-warning "may cause truncation of value" } */ + *pcld = cabs (*pcld); /* { dg-warning "may cause truncation of value" } */ + *pcld = cabs ((complex double) *pcld); +} + + + + -- 2.30.2