re PR tree-optimization/35503 (Warning about restricted pointers?)
authorPrathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
Sun, 13 Nov 2016 19:38:36 +0000 (19:38 +0000)
committerPrathamesh Kulkarni <prathamesh3492@gcc.gnu.org>
Sun, 13 Nov 2016 19:38:36 +0000 (19:38 +0000)
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

14 files changed:
gcc/ChangeLog
gcc/c-family/c-common.h
gcc/c-family/c-format.c
gcc/c-family/c-warn.c
gcc/c-family/c.opt
gcc/c/c-parser.c
gcc/cp/parser.c
gcc/doc/invoke.texi
gcc/pretty-print.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/pr35503-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/pr35503-2.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/pr35503-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/format/gcc_diag-1.c

index 0be66610f34f2e6b1c19d134937be38f0d0cfa49..b9de75bd9e20795a779e73b6591d41f878903cc0 100644 (file)
@@ -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
index 547bab2ac4e457c23aac6e0c6aaa1ec1a61819b1..4f27f81b5b3a6adfa31220bfd22fbbd92d62f73b 100644 (file)
@@ -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
index bf39ee06e79f2bd98c961ff885ffd8d13c7615ac..8a4bf6f0d29a6f9d3619024a1963a4135da7c93b 100644 (file)
@@ -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 }
 };
 
index 18ee24787a964d352c79a668efcecb2e1d27d3fa..7197fe3d75024ffb0aa3466e2e8a7e0e44bba40e 100644 (file)
@@ -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);
+}
index 213353b9abdf766b59dce9ee6432e04d4f094499..cf946e7b86ea28255104af51a85f2bf3a6709402 100644 (file)
@@ -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++).
index 6bc42da08d64206b849db834ed1f3d6153c5d976..52a5eddff7b46acdc1061629bb8ba7541873c683 100644 (file)
@@ -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
index b3b69b3b8bede2bf021b23e94df2a8822b7721b7..1efe4eaf7d72afe75564f2654cc0b22c96ab3efc 100644 (file)
@@ -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);
index 04a6fac356b9ad16e522f28229f9889790eb80ef..eb89804a8b7be6a5ef0468a7556151d901e8b8b8 100644 (file)
@@ -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
index a39815ea511e1fbd65bd7abd5d4dd95af8e6664b..e58619dcda70a3220d19ab171e8a1aa261d128b2 100644 (file)
@@ -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",
index 58d86392b41dc0b67150de7a88a3f26dbbf3d89e..a83c6e7a84b74492402bc9f1b80b801a540b4e64 100644 (file)
@@ -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 (file)
index 0000000..25e3721
--- /dev/null
@@ -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 (file)
index 0000000..bfcd944
--- /dev/null
@@ -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 (file)
index 0000000..8cbacab
--- /dev/null
@@ -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" } */
+}
index 953c944b4e884c0a88ed6d0f485fda1bd2a4335e..f4922cd4966a62fc8d7c088bd4864ce0d0b2f789 100644 (file)
@@ -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" } */