On 30 August 2016 at 05:34, David Malcolm <dmalc...@redhat.com> wrote: > On Mon, 2016-08-29 at 20:01 -0400, David Malcolm wrote: >> On Mon, 2016-08-29 at 19:55 -0400, David Malcolm wrote: >> [...] >> > Assuming you have the location_t values available, you can create a >> > rich_location for the primary range, and then add secondary ranges >> > like >> > this: >> > >> > rich_location richloc (loc_of_arg1); >> >> Oops, the above should be: >> >> rich_location richloc (line_table, loc_of_arg1); >> >> or: >> >> gcc_rich_location (loc_of_arg1); > and this should be: > > gcc_rich_location richloc (loc_of_arg1); >> which does the same thing (#include "gcc-rich-location.h"). > > Clearly I need to sleep :) Hi David, Thanks for the suggestions. I can now see multiple source ranges for pr35503-2.c (included in patch). Output shows: http://pastebin.com/FNAVDU8A (Posted pastebin link to avoid mangling by the mailer)
However the test for underline fails: FAIL: c-c++-common/pr35503-2.c -Wc++-compat expected multiline pattern lines 12-13 not found: "\s*f \(&alpha, &beta, &alpha, &alpha\);.*\n \^~~~~~ ~~~~~~ ~~~~~~ .*\n" I have attached gcc.log for the test-case. Presumably I have written the test-case incorrectly. Could you please have a look at it ? Thanks, Prathamesh > >> > richloc.add_range (loc_of_arg3, false); /* false here = don't >> > draw >> > a >> > caret, just the underline */ >> > richloc.add_range (loc_of_arg4, false); >> > warning_at_rich_loc (&richloc, OPT_Wrestrict, etc... >> > >> > See line-map.h for more information on rich_location. >> >> [...]
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 3feb910..4239cef 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see #include "gimplify.h" #include "substring-locations.h" #include "spellcheck.h" +#include "gcc-rich-location.h" cpp_reader *parse_in; /* Declared in c-pragma.h. */ @@ -13057,4 +13058,86 @@ diagnose_mismatched_attributes (tree olddecl, tree newdecl) return warned; } +/* 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; + auto_vec<unsigned> arg_positions; + + 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.safe_push (i); + } + } + + if (arg_positions.is_empty ()) + return; + + struct obstack fmt_obstack; + gcc_obstack_init (&fmt_obstack); + char *fmt = (char *) obstack_alloc (&fmt_obstack, 0); + + char num[32]; + sprintf (num, "%u", param_pos + 1); + + obstack_grow (&fmt_obstack, "passing argument ", + strlen ("passing argument ")); + obstack_grow (&fmt_obstack, num, strlen (num)); + obstack_grow (&fmt_obstack, + " to restrict-qualified parameter aliases with argument", + strlen (" to restrict-qualified parameter " + "aliases with argument")); + + /* make argument plural and append space. */ + if (arg_positions.length () > 1) + obstack_1grow (&fmt_obstack, 's'); + obstack_1grow (&fmt_obstack, ' '); + + unsigned pos; + unsigned ranges_added = 1; + + FOR_EACH_VEC_ELT (arg_positions, i, pos) + { + /* FIXME: Fow now, only 3 ranges can be added. Remove this once + the restriction is lifted. */ + if (ranges_added < 3) + { + tree arg = (*args)[pos]; + if (EXPR_HAS_LOCATION (arg)) + { + richloc.add_range (EXPR_LOCATION (arg), false); + ranges_added++; + } + } + + sprintf (num, "%u", pos + 1); + obstack_grow (&fmt_obstack, num, strlen (num)); + + if (i < arg_positions.length () - 1) + obstack_grow (&fmt_obstack, ", ", strlen (", ")); + } + + obstack_1grow (&fmt_obstack, 0); + warning_at_rich_loc (&richloc, OPT_Wrestrict, fmt); + obstack_free (&fmt_obstack, fmt); +} + #include "gt-c-family-c-common.h" diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index bc22baa..cdb762e 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -920,6 +920,7 @@ extern void c_parse_final_cleanups (void); extern void warn_for_omitted_condop (location_t, tree); extern void warn_for_memset (location_t, tree, tree, int); +extern void warn_for_restrict (unsigned, vec<tree, va_gc> *); /* These macros provide convenient access to the various _STMT nodes. */ diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index a5358ed..a029a86 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -1012,6 +1012,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 C++ Var(warn_restrict) Warning LangEnabledBy(C C++,Wall) +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 fe0c95f..d27a4be 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -8369,6 +8369,24 @@ 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)) + warn_for_restrict (param_pos, exprlist); + param_pos++; + } + } + 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 690e928..dce117d 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -6878,6 +6878,25 @@ 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)) + warn_for_restrict (param_pos, args); + } + } + 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 1f04501..3bd9612 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -288,7 +288,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 -Wshift-overflow -Wshift-overflow=@var{n} @gol -Wshift-count-negative -Wshift-count-overflow -Wshift-negative-value @gol @@ -5274,6 +5274,12 @@ compilations. Warn when deleting a pointer to incomplete type, which may cause undefined behavior at runtime. This warning is enabled by default. +@item -Wrestrict @r{(C and C++ only)} +@opindex Wrestrict +@opindex Wno-restrict +Warn when an argument passed to a restrict-qualified parameter +aliases with another argument + @item -Wuseless-cast @r{(C++ and Objective-C++ only)} @opindex Wuseless-cast @opindex Wno-useless-cast 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..b47fdda --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr35503-1.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-Wrestrict" } */ + +int foo (const 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..b09872a --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr35503-2.c @@ -0,0 +1,15 @@ +/* { 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" "" { target *-*-* } 8 } */ + +/* { 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" } */ +}
Test Run By bilbo on Tue Aug 30 16:52:28 2016 Native configuration is x86_64-pc-linux-gnu === gcc tests === Schedule of variations: unix Running target unix Using /usr/share/dejagnu/baseboards/unix.exp as board description file for target. Using /usr/share/dejagnu/config/unix.exp as generic interface file for target. Using /home/bilbo/gnu-toolchain/gcc/pr35503/gcc/gcc/testsuite/config/default.exp as tool-and-target-specific interface file. Running /home/bilbo/gnu-toolchain/gcc/pr35503/gcc/gcc/testsuite/gcc.dg/dg.exp ... LD_LIBRARY_PATH=:/home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc:/home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc/32: LD_RUN_PATH=:/home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc:/home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc/32 SHLIB_PATH=:/home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc:/home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc/32 LD_LIBRARY_PATH_32=:/home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc:/home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc/32: LD_LIBRARY_PATH_64=:/home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc:/home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc/32: DYLD_LIBRARY_PATH=:/home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc:/home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc/32 Executing on host: /home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc/xgcc -B/home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc/ -fno-diagnostics-show-caret -fdiagnostics-color=never -flto -c -o lto13374.o lto13374.c (timeout = 300) spawn -ignore SIGHUP /home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc/xgcc -B/home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc/ -fno-diagnostics-show-caret -fdiagnostics-color=never -flto -c -o lto13374.o lto13374.c Executing on host: /home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc/xgcc -B/home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc/ linker_plugin13374.c -fno-diagnostics-show-caret -fdiagnostics-color=never -flto -fuse-linker-plugin -lm -o linker_plugin13374.exe (timeout = 300) spawn -ignore SIGHUP /home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc/xgcc -B/home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc/ linker_plugin13374.c -fno-diagnostics-show-caret -fdiagnostics-color=never -flto -fuse-linker-plugin -lm -o linker_plugin13374.exe Executing on host: /home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc/xgcc -B/home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc/ /home/bilbo/gnu-toolchain/gcc/pr35503/gcc/gcc/testsuite/c-c++-common/pr35503-2.c -fno-diagnostics-show-caret -fdiagnostics-color=never -Wc++-compat -fdiagnostics-show-caret -Wrestrict -S -o pr35503-2.s (timeout = 300) spawn -ignore SIGHUP /home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc/xgcc -B/home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc/ /home/bilbo/gnu-toolchain/gcc/pr35503/gcc/gcc/testsuite/c-c++-common/pr35503-2.c -fno-diagnostics-show-caret -fdiagnostics-color=never -Wc++-compat -fdiagnostics-show-caret -Wrestrict -S -o pr35503-2.s /home/bilbo/gnu-toolchain/gcc/pr35503/gcc/gcc/testsuite/c-c++-common/pr35503-2.c: In function 'foo': /home/bilbo/gnu-toolchain/gcc/pr35503/gcc/gcc/testsuite/c-c++-common/pr35503-2.c:8:6: warning: passing argument 1 to restrict-qualified parameter aliases with arguments 3, 4 [-Wrestrict] f (&alpha, &beta, &alpha, &alpha); ^~~~~~ ~~~~~~ ~~~~~~ output is: /home/bilbo/gnu-toolchain/gcc/pr35503/gcc/gcc/testsuite/c-c++-common/pr35503-2.c: In function 'foo': /home/bilbo/gnu-toolchain/gcc/pr35503/gcc/gcc/testsuite/c-c++-common/pr35503-2.c:8:6: warning: passing argument 1 to restrict-qualified parameter aliases with arguments 3, 4 [-Wrestrict] f (&alpha, &beta, &alpha, &alpha); ^~~~~~ ~~~~~~ ~~~~~~ PASS: c-c++-common/pr35503-2.c -Wc++-compat (test for warnings, line 8) FAIL: c-c++-common/pr35503-2.c -Wc++-compat expected multiline pattern lines 12-13 not found: "\s*f \(&alpha, &beta, &alpha, &alpha\);.*\n \^~~~~~ ~~~~~~ ~~~~~~ .*\n" FAIL: c-c++-common/pr35503-2.c -Wc++-compat (test for excess errors) Excess errors: f (&alpha, &beta, &alpha, &alpha); ^~~~~~ ~~~~~~ ~~~~~~ testcase /home/bilbo/gnu-toolchain/gcc/pr35503/gcc/gcc/testsuite/gcc.dg/dg.exp completed in 0 seconds === gcc Summary === # of expected passes 1 # of unexpected failures 2 Executing on host: /home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc/xgcc -v (timeout = 300) spawn -ignore SIGHUP /home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc/xgcc -v Using built-in specs. COLLECT_GCC=/home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc/xgcc Target: x86_64-pc-linux-gnu Configured with: ../gcc/configure --enable-languages=c,c++,fortran --disable-bootstrap Thread model: posix gcc version 7.0.0 20160824 (experimental) (GCC) /home/bilbo/gnu-toolchain/gcc/pr35503/stage1-build/gcc/xgcc version 7.0.0 20160824 (experimental) (GCC) runtest completed at Tue Aug 30 16:52:28 2016