From 975672f3573329b6ef9f687b706c566944a5887f Mon Sep 17 00:00:00 2001 From: Prathamesh Kulkarni Date: Sun, 13 Nov 2016 19:38:36 +0000 Subject: [PATCH] re PR tree-optimization/35503 (Warning about restricted pointers?) 2016-11-13 Prathamesh Kulkarni PR c/35503 * doc/invoke.texi: Document Wrestrict. * pretty-print.c (pp_format): Add case for "Z" specifier. (test_pp_format): Test "Z" specifier. c-family/ * c-common.h (warn_for_restrict): Declare. * c-warn.c: Include gcc-rich-location.h. (warn_for_restrict): New function. * c-format.c (gcc_tdiag_char_table): Add entry for "Z" specifier. (gcc_cdiag_char_table): Likewise. (gcc_cxxdiag_char_table): Likewise. * c.opt (Wrestrict): New option. c/ * c-parser.c (c_parser_postfix_expression_after_primary): Call warn_for_restrict. cp/ * parser.c (cp_parser_postfix_pexpression): Call warn_for_restrict. testsuite/ * c-c++-common/pr35503-1.c: New test. * c-c++-common/pr35503-2.c: Likewise. * c-c++-common/pr35503-3.c: Likewise. * gcc.dg/format/gcc_diag-1.c: Add tests for "Z" specifier. From-SVN: r242366 --- gcc/ChangeLog | 20 +++++++++ gcc/c-family/c-common.h | 1 + gcc/c-family/c-format.c | 3 ++ gcc/c-family/c-warn.c | 56 ++++++++++++++++++++++++ gcc/c-family/c.opt | 5 +++ gcc/c/c-parser.c | 22 ++++++++++ gcc/cp/parser.c | 23 ++++++++++ gcc/doc/invoke.texi | 8 +++- gcc/pretty-print.c | 26 +++++++++++ gcc/testsuite/ChangeLog | 8 ++++ gcc/testsuite/c-c++-common/pr35503-1.c | 10 +++++ gcc/testsuite/c-c++-common/pr35503-2.c | 14 ++++++ gcc/testsuite/c-c++-common/pr35503-3.c | 9 ++++ gcc/testsuite/gcc.dg/format/gcc_diag-1.c | 9 +++- 14 files changed, 212 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/pr35503-1.c create mode 100644 gcc/testsuite/c-c++-common/pr35503-2.c create mode 100644 gcc/testsuite/c-c++-common/pr35503-3.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0be66610f34..b9de75bd9e2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +2016-11-13 Prathamesh Kulkarni + + PR c/35503 + * doc/invoke.texi: Document Wrestrict. + * pretty-print.c (pp_format): Add case for "Z" specifier. + (test_pp_format): Test "Z" specifier. +c-family/ + * c-common.h (warn_for_restrict): Declare. + * c-warn.c: Include gcc-rich-location.h. + (warn_for_restrict): New function. + * c-format.c (gcc_tdiag_char_table): Add entry for "Z" specifier. + (gcc_cdiag_char_table): Likewise. + (gcc_cxxdiag_char_table): Likewise. + * c.opt (Wrestrict): New option. +c/ + * c-parser.c (c_parser_postfix_expression_after_primary): Call + warn_for_restrict. +cp/ + * parser.c (cp_parser_postfix_pexpression): Call warn_for_restrict. + 2016-11-13 Eric Botcazou * ipa-icf.c (sem_function::merge): Do not create a wrapper also if the diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 547bab2ac4e..4f27f81b5b3 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1492,6 +1492,7 @@ extern void warnings_for_convert_and_check (location_t, tree, tree, tree); extern void c_do_switch_warnings (splay_tree, location_t, tree, tree, bool, bool); extern void warn_for_omitted_condop (location_t, tree); +extern void warn_for_restrict (unsigned, vec *); /* Places where an lvalue, or modifiable lvalue, may be required. Used to select diagnostic messages in lvalue_error and diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c index bf39ee06e79..8a4bf6f0d29 100644 --- a/gcc/c-family/c-format.c +++ b/gcc/c-family/c-format.c @@ -713,6 +713,7 @@ static const format_char_info gcc_tdiag_char_table[] = { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "cR", NULL }, { "<>'R",0, STD_C89, NOARGUMENTS, "", "", NULL }, { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL }, + { "Z", 1, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", &gcc_tdiag_char_table[0] }, { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } }; @@ -736,6 +737,7 @@ static const format_char_info gcc_cdiag_char_table[] = { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "cR", NULL }, { "<>'R",0, STD_C89, NOARGUMENTS, "", "", NULL }, { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL }, + { "Z", 1, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", &gcc_tdiag_char_table[0] }, { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } }; @@ -762,6 +764,7 @@ static const format_char_info gcc_cxxdiag_char_table[] = { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "cR", NULL }, { "<>'R",0, STD_C89, NOARGUMENTS, "", "", NULL }, { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL }, + { "Z", 1, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", &gcc_tdiag_char_table[0] }, { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } }; diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c index 18ee24787a9..7197fe3d750 100644 --- a/gcc/c-family/c-warn.c +++ b/gcc/c-family/c-warn.c @@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic.h" #include "intl.h" #include "asan.h" +#include "gcc-rich-location.h" /* Print a warning if a constant expression had overflow in folding. Invoke this function on every expression that the language @@ -2161,3 +2162,58 @@ maybe_warn_bool_compare (location_t loc, enum tree_code code, tree op0, "with boolean expression is always false", cst); } } + +/* Warn if an argument at position param_pos is passed to a + restrict-qualified param, and it aliases with another argument. */ + +void +warn_for_restrict (unsigned param_pos, vec *args) +{ + tree arg = (*args)[param_pos]; + if (TREE_VISITED (arg) || operand_equal_p (arg, null_pointer_node, 0)) + return; + + location_t loc = EXPR_LOC_OR_LOC (arg, input_location); + gcc_rich_location richloc (loc); + + unsigned i; + tree current_arg; + int *arg_positions = XNEWVEC (int, args->length ()); + unsigned arg_positions_len = 0; + + FOR_EACH_VEC_ELT (*args, i, current_arg) + { + if (i == param_pos) + continue; + + tree current_arg = (*args)[i]; + if (operand_equal_p (arg, current_arg, 0)) + { + TREE_VISITED (current_arg) = 1; + arg_positions[arg_positions_len++] = (i + 1); + } + } + + if (arg_positions_len == 0) + { + free (arg_positions); + return; + } + + for (unsigned i = 0; i < arg_positions_len; i++) + { + unsigned pos = arg_positions[i]; + tree arg = (*args)[pos - 1]; + if (EXPR_HAS_LOCATION (arg)) + richloc.add_range (EXPR_LOCATION (arg), false); + } + + warning_at_rich_loc_n (&richloc, OPT_Wrestrict, arg_positions_len, + "passing argument %i to restrict-qualified parameter" + " aliases with argument %Z", + "passing argument %i to restrict-qualified parameter" + " aliases with arguments %Z", + param_pos + 1, arg_positions, arg_positions_len); + + free (arg_positions); +} diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 213353b9abd..cf946e7b86e 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -1085,6 +1085,11 @@ Wduplicate-decl-specifier C ObjC Var(warn_duplicate_decl_specifier) Warning LangEnabledBy(C ObjC,Wall) Warn when a declaration has duplicate const, volatile, restrict or _Atomic specifier. +Wrestrict +C ObjC C++ ObjC++ Var(warn_restrict) Warning LangEnabledBy(C ObjC C++ ObjC++) +Warn when an argument passed to a restrict-qualified parameter aliases with +another argument. + ansi C ObjC C++ ObjC++ A synonym for -std=c89 (for C) or -std=c++98 (for C++). diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 6bc42da08d6..52a5eddff7b 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -8451,6 +8451,28 @@ c_parser_postfix_expression_after_primary (c_parser *parser, warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask); } + if (TREE_CODE (expr.value) == FUNCTION_DECL && warn_restrict) + { + unsigned i; + tree arg; + FOR_EACH_VEC_SAFE_ELT (exprlist, i, arg) + TREE_VISITED (arg) = 0; + + unsigned param_pos = 0; + function_args_iterator iter; + tree t; + FOREACH_FUNCTION_ARGS (TREE_TYPE (expr.value), t, iter) + { + if (POINTER_TYPE_P (t) && TYPE_RESTRICT (t) + && !TYPE_READONLY (TREE_TYPE (t))) + warn_for_restrict (param_pos, exprlist); + param_pos++; + } + + FOR_EACH_VEC_SAFE_ELT (exprlist, i, arg) + TREE_VISITED (arg) = 0; + } + start = expr.get_start (); finish = parser->tokens_buf[0].get_finish (); expr.value diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index b3b69b3b8be..1efe4eaf7d7 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -6925,6 +6925,29 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, warn_for_memset (input_location, arg0, arg2, literal_mask); } + if (TREE_CODE (postfix_expression) == FUNCTION_DECL + && warn_restrict) + { + unsigned i; + tree arg; + FOR_EACH_VEC_SAFE_ELT (args, i, arg) + TREE_VISITED (arg) = 0; + + unsigned param_pos = 0; + for (tree decl = DECL_ARGUMENTS (postfix_expression); + decl != NULL_TREE; + decl = DECL_CHAIN (decl), param_pos++) + { + tree type = TREE_TYPE (decl); + if (POINTER_TYPE_P (type) && TYPE_RESTRICT (type) + && !TYPE_READONLY (TREE_TYPE (type))) + warn_for_restrict (param_pos, args); + } + + FOR_EACH_VEC_SAFE_ELT (args, i, arg) + TREE_VISITED (arg) = 0; + } + if (TREE_CODE (postfix_expression) == COMPONENT_REF) { tree instance = TREE_OPERAND (postfix_expression, 0); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 04a6fac356b..eb89804a8b7 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -292,7 +292,7 @@ Objective-C and Objective-C++ Dialects}. -Wparentheses -Wno-pedantic-ms-format @gol -Wplacement-new -Wplacement-new=@var{n} @gol -Wpointer-arith -Wno-pointer-to-int-cast @gol --Wno-pragmas -Wredundant-decls -Wno-return-local-addr @gol +-Wno-pragmas -Wredundant-decls -Wrestrict -Wno-return-local-addr @gol -Wreturn-type -Wsequence-point -Wshadow -Wno-shadow-ivar @gol -Wshadow=global, -Wshadow=local, -Wshadow=compatible-local @gol -Wshift-overflow -Wshift-overflow=@var{n} @gol @@ -6187,6 +6187,12 @@ reduce the padding and so make the structure smaller. Warn if anything is declared more than once in the same scope, even in cases where multiple declaration is valid and changes nothing. +@item -Wrestrict +@opindex Wrestrict +@opindex Wno-restrict +Warn when an argument passed to a restrict-qualified parameter +aliases with another argument. + @item -Wnested-externs @r{(C and Objective-C only)} @opindex Wnested-externs @opindex Wno-nested-externs diff --git a/gcc/pretty-print.c b/gcc/pretty-print.c index a39815ea511..e58619dcda7 100644 --- a/gcc/pretty-print.c +++ b/gcc/pretty-print.c @@ -294,6 +294,8 @@ pp_indent (pretty_printer *pp) integer. %Ns: likewise, but length specified as constant in the format string. Flag 'q': quote formatted text (must come immediately after '%'). + %Z: Requires two arguments - array of int, and len. Prints elements + of the array. Arguments can be used sequentially, or through %N$ resp. *N$ notation Nth argument after the format string. If %N$ / *N$ @@ -610,6 +612,23 @@ pp_format (pretty_printer *pp, text_info *text) (pp, *text->args_ptr, precision, unsigned, "u"); break; + case 'Z': + { + int *v = va_arg (*text->args_ptr, int *); + unsigned len = va_arg (*text->args_ptr, unsigned); + + for (unsigned i = 0; i < len; ++i) + { + pp_scalar (pp, "%i", v[i]); + if (i < len - 1) + { + pp_comma (pp); + pp_space (pp); + } + } + break; + } + case 'x': if (wide) pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX, @@ -1424,6 +1443,13 @@ test_pp_format () "`\33[01m\33[Kfoo\33[m\33[K' 12345678", "%qs %x", "foo", 0x12345678); + /* Verify %Z. */ + int v[] = { 1, 2, 3 }; + ASSERT_PP_FORMAT_3 ("1, 2, 3 12345678", "%Z %x", v, 3, 0x12345678); + + int v2[] = { 0 }; + ASSERT_PP_FORMAT_3 ("0 12345678", "%Z %x", v2, 1, 0x12345678); + /* Verify that combinations work, along with unformatted text. */ assert_pp_format (SELFTEST_LOCATION, "the quick brown fox jumps over the lazy dog", diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 58d86392b41..a83c6e7a84b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2016-11-13 Prathamesh Kulkarni + + PR c/35503 + * c-c++-common/pr35503-1.c: New test. + * c-c++-common/pr35503-2.c: Likewise. + * c-c++-common/pr35503-3.c: Likewise. + * gcc.dg/format/gcc_diag-1.c: Add tests for "Z" specifier. + 2016-11-13 Uros Bizjak PR rtl-optimization/78232 diff --git a/gcc/testsuite/c-c++-common/pr35503-1.c b/gcc/testsuite/c-c++-common/pr35503-1.c new file mode 100644 index 00000000000..25e3721df93 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr35503-1.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-Wrestrict" } */ + +int foo (char *__restrict buf, const char *__restrict fmt, ...); + +void f(void) +{ + char buf[100] = "hello"; + foo (buf, "%s-%s", buf, "world"); /* { dg-warning "passing argument 1 to restrict-qualified parameter aliases with argument 3" } */ +} diff --git a/gcc/testsuite/c-c++-common/pr35503-2.c b/gcc/testsuite/c-c++-common/pr35503-2.c new file mode 100644 index 00000000000..bfcd9448e03 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr35503-2.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-fdiagnostics-show-caret -Wrestrict" } */ + +void f(int *__restrict x, int *y, int *__restrict z, int *w); + +void foo(int alpha, int beta) +{ + f (&alpha, &beta, &alpha, &alpha); /* { dg-warning "passing argument 1 to restrict-qualified parameter aliases with arguments 3, 4" } */ + +/* { dg-begin-multiline-output "" } + f (&alpha, &beta, &alpha, &alpha); + ^~~~~~ ~~~~~~ ~~~~~~ + { dg-end-multiline-output "" } */ +} diff --git a/gcc/testsuite/c-c++-common/pr35503-3.c b/gcc/testsuite/c-c++-common/pr35503-3.c new file mode 100644 index 00000000000..8cbacabba62 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr35503-3.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-Wrestrict" } */ + +void f(int *x, int *__restrict y); + +void foo(int a) +{ + f (&a, &a); /* { dg-warning "passing argument 2 to restrict-qualified parameter aliases with argument 1" } */ +} diff --git a/gcc/testsuite/gcc.dg/format/gcc_diag-1.c b/gcc/testsuite/gcc.dg/format/gcc_diag-1.c index 953c944b4e8..f4922cd4966 100644 --- a/gcc/testsuite/gcc.dg/format/gcc_diag-1.c +++ b/gcc/testsuite/gcc.dg/format/gcc_diag-1.c @@ -32,7 +32,7 @@ foo (int i, int i1, int i2, unsigned int u, double d, char *s, void *p, ullong ull, unsigned int *un, const int *cn, signed char *ss, unsigned char *us, const signed char *css, unsigned int u1, unsigned int u2, location_t *loc, tree t1, union tree_node *t2, - tree *t3, tree t4[]) + tree *t3, tree t4[], int *v, unsigned v_len) { /* Acceptable C90 specifiers, flags and modifiers. */ diag ("%%"); @@ -90,6 +90,10 @@ foo (int i, int i1, int i2, unsigned int u, double d, char *s, void *p, cdiag ("%v%qv%#v", i, i, i); cxxdiag ("%v%qv%#v", i, i, i); + tdiag ("%Z", v, v_len); + cdiag ("%Z", v, v_len); + cxxdiag ("%Z", v, v_len); + /* Bad stuff with extensions. */ diag ("%m", i); /* { dg-warning "format" "extra arg" } */ tdiag ("%m", i); /* { dg-warning "format" "extra arg" } */ @@ -133,6 +137,9 @@ foo (int i, int i1, int i2, unsigned int u, double d, char *s, void *p, cdiag ("%v", t1); /* { dg-warning "format" "wrong arg" } */ cxxdiag ("%v", t1); /* { dg-warning "format" "wrong arg" } */ + tdiag ("%Z"); /* { dg-warning "format" "missing arg" } */ + tdiag ("%Z", t1); /* { dg-warning "format" "wrong arg" } */ + /* Standard specifiers not accepted in the diagnostic framework. */ diag ("%X\n", u); /* { dg-warning "format" "HEX" } */ diag ("%f\n", d); /* { dg-warning "format" "float" } */ -- 2.30.2