diff options
author | Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org> | 2016-11-13 19:38:36 +0000 |
---|---|---|
committer | Prathamesh Kulkarni <prathamesh3492@gcc.gnu.org> | 2016-11-13 19:38:36 +0000 |
commit | 975672f3573329b6ef9f687b706c566944a5887f (patch) | |
tree | 9aad4b4532ab8376d649d4e85993c1dd06279056 /gcc | |
parent | 8d5a1b4f64ed7e4c3712ec1a27c59441e89e5ea9 (diff) | |
download | gcc-975672f3573329b6ef9f687b706c566944a5887f.zip gcc-975672f3573329b6ef9f687b706c566944a5887f.tar.gz gcc-975672f3573329b6ef9f687b706c566944a5887f.tar.bz2 |
re PR tree-optimization/35503 (Warning about restricted pointers?)
2016-11-13 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 20 | ||||
-rw-r--r-- | gcc/c-family/c-common.h | 1 | ||||
-rw-r--r-- | gcc/c-family/c-format.c | 3 | ||||
-rw-r--r-- | gcc/c-family/c-warn.c | 56 | ||||
-rw-r--r-- | gcc/c-family/c.opt | 5 | ||||
-rw-r--r-- | gcc/c/c-parser.c | 22 | ||||
-rw-r--r-- | gcc/cp/parser.c | 23 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 8 | ||||
-rw-r--r-- | gcc/pretty-print.c | 26 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/pr35503-1.c | 10 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/pr35503-2.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/pr35503-3.c | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/format/gcc_diag-1.c | 9 |
14 files changed, 212 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0be6661..b9de75b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +2016-11-13 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org> + + 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 <ebotcazou@adacore.com> * 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 547bab2..4f27f81 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<tree, va_gc> *); /* 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 bf39ee0..8a4bf6f 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 18ee247..7197fe3 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<tree, va_gc> *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 213353b..cf946e7 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 6bc42da..52a5edd 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 b3b69b3..1efe4ea 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 04a6fac..eb89804 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 a39815e..e58619d 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 58d8639..a83c6e7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2016-11-13 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org> + + 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 <ubizjak@gmail.com> 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 0000000..25e3721 --- /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 0000000..bfcd944 --- /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 0000000..8cbacab --- /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 953c944..f4922cd 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" } */ |