On 29 August 2016 at 19:59, Marek Polacek <pola...@redhat.com> wrote:
> On Mon, Aug 29, 2016 at 04:25:25PM +0200, Tobias Burnus wrote:
>> Prathamesh Kulkarni wrote:
>> > Attachment: pr35503-3.txt
>>
>> I tried the patch - and it found a bug in our code; nice!
>>
>>
>> (a) Regarding the [-Werror] output:
>>
>>    error: passing argument 24 to restrict qualified parameter aliases with 
>> argument 29 [-Werror]
>>
>> Shouldn't that output "[-Werror=restrict]" instead of a bare "[-Werror]? 
>> Namely, instead of
>>
>> +     warning_at (loc, 0,
>> +                 "passing argument %u to restrict qualified parameter 
>> aliases with "
>> +                 "argument %u", param_pos + 1, i + 1);
>>
>> I think one gets this with
>>         warning_at (loc, OPT_Wrestrict, ...
>
> Yes, this needs to be fixed in the patch.
Hi,
Thanks for all the suggestions, I have tried to incorporate them in
the attached version.
To avoid duplicating the warnings for multiple aliased arguments,
I am using TREE_VISITED to mark all the aliased arguments of the current
arg, which makes diagnostic emitted only once per same set of aliases.
Is using TREE_VISITED ok as in the patch ?

eg:
void f(int *__restrict x, int *y, int *__restrict z, int *w);

void foo(int a, int b)
{
  f (&a, &b, &a, &a);
}

Output:
test-2.c: In function ‘foo’:
test-2.c:5:6: warning: passing argument 1 to restrict-qualified
parameter aliases with arguments 3, 4 [-Wrestrict]
   f (&a, &b, &a, &a);
       ^~

Using EXPR_LOCATION (arg), helps underline the argument for both C and C++
as in the example above. However in case of variadic functions, it
appears C++FE doesn't set EXPR_LOCATION,
so I am falling back to using input_location if EXPR_LOCATION is unknown.
However it gives the location correctly for non-variadic functions.
For setting locations correctly I will try the approach suggested by Jason in
https://gcc.gnu.org/ml/gcc-patches/2016-08/msg01987.html

I was wondering how to underline all the aliased arguments ?
I would like to see the output for above eg as:

test-2.c: In function ‘foo’:
test-2.c:5:6: warning: passing argument 1 to restrict-qualified
parameter aliases with arguments 3, 4 [-Wrestrict]
   f (&a, &b, &a, &a);
       ^~        ~~   ~~

I would be grateful for suggestions for the same.
Bootstrap+test in progress on x86_64-unknown-linux-gnu.

Thanks,
Prathamesh
>
>         Marek
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 3feb910..abb92b3 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -13057,4 +13057,76 @@ 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))
+    return;
+
+  location_t loc = (EXPR_LOCATION (arg) != UNKNOWN_LOCATION)
+                  ? EXPR_LOCATION (arg)
+                  : input_location;
+
+  if (operand_equal_p (arg, null_pointer_node, 0))
+    return;
+
+  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;
+  FOR_EACH_VEC_ELT (arg_positions, i, pos)
+    {
+      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 (loc, 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..7eaca04 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_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..5d0182f 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_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..c7828b8
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr35503-2.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-Wrestrict" } */
+
+void f(int *__restrict x, int *__restrict y);
+
+void foo(int a)
+{
+  f (&a, &a); /* { dg-warning "passing argument 1 to restrict-qualified 
parameter aliases with argument 2" } */
+}
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" } */
+}

Reply via email to