diff mbox

Move -Wrestrict warning later in the FEs and fix some issues in it (PR c++/79588)

Message ID 20170220203533.GF1849@tucnak
State New
Headers show

Commit Message

Jakub Jelinek Feb. 20, 2017, 8:35 p.m. UTC
Hi!

As mentioned in the PR, -Wrestrict warning is done way too early, where
e.g. default arguments aren't filled up yet (reason for ICE on first
testcase) or where arguments in templates aren't instantiated yet (reason
why we don't diagnose anything on the second testcase).

This patch moves it later where e.g. -Wformat is diagnosed and fixes
some issues I found while looking at the code.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2017-02-20  Jakub Jelinek  <jakub@redhat.com>

	PR c++/79588
c-family/
	* c-common.c (check_function_arguments): Add FNDECL argument.
	Handle -Wrestrict here.
	* c-warn.c (warn_for_restrict): Remove ARGS argument, add ARGARRAY
	and NARGS.  Use auto_vec for ARG_POSITIONS, simplify.
	* c-common.h (check_function_arguments): Add FNDECL argument.
	(warn_for_restrict): Remove ARGS argument, add ARGARRAY and NARGS.
c/
	* c-parser.c (c_parser_postfix_expression_after_primary): Don't
	handle -Wrestrict here.
	* c-typeck.c (build_function_call_vec): Adjust
	check_function_arguments caller.
cp/
	* call.c (build_over_call): Call check_function_arguments even for
	-Wrestrict, adjust check_function_arguments caller.
	* parser.c (cp_parser_postfix_expression): Don't handle -Wrestrict
	here.
	* typeck.c (cp_build_function_call_vec): Adjust
	check_function_arguments caller.
testsuite/
	* g++.dg/warn/Wrestrict-1.C: New test.
	* g++.dg/warn/Wrestrict-2.C: New test.


	Jakub

Comments

Jason Merrill Feb. 21, 2017, 8:41 p.m. UTC | #1
OK if Joseph doesn't object in the next couple of days.

On Mon, Feb 20, 2017 at 12:35 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!
>
> As mentioned in the PR, -Wrestrict warning is done way too early, where
> e.g. default arguments aren't filled up yet (reason for ICE on first
> testcase) or where arguments in templates aren't instantiated yet (reason
> why we don't diagnose anything on the second testcase).
>
> This patch moves it later where e.g. -Wformat is diagnosed and fixes
> some issues I found while looking at the code.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2017-02-20  Jakub Jelinek  <jakub@redhat.com>
>
>         PR c++/79588
> c-family/
>         * c-common.c (check_function_arguments): Add FNDECL argument.
>         Handle -Wrestrict here.
>         * c-warn.c (warn_for_restrict): Remove ARGS argument, add ARGARRAY
>         and NARGS.  Use auto_vec for ARG_POSITIONS, simplify.
>         * c-common.h (check_function_arguments): Add FNDECL argument.
>         (warn_for_restrict): Remove ARGS argument, add ARGARRAY and NARGS.
> c/
>         * c-parser.c (c_parser_postfix_expression_after_primary): Don't
>         handle -Wrestrict here.
>         * c-typeck.c (build_function_call_vec): Adjust
>         check_function_arguments caller.
> cp/
>         * call.c (build_over_call): Call check_function_arguments even for
>         -Wrestrict, adjust check_function_arguments caller.
>         * parser.c (cp_parser_postfix_expression): Don't handle -Wrestrict
>         here.
>         * typeck.c (cp_build_function_call_vec): Adjust
>         check_function_arguments caller.
> testsuite/
>         * g++.dg/warn/Wrestrict-1.C: New test.
>         * g++.dg/warn/Wrestrict-2.C: New test.
>
> --- gcc/c-family/c-common.c.jj  2017-01-24 23:29:05.000000000 +0100
> +++ gcc/c-family/c-common.c     2017-02-20 13:17:06.601211847 +0100
> @@ -5605,8 +5605,8 @@ attribute_fallthrough_p (tree attr)
>     There are NARGS arguments in the array ARGARRAY.  LOC should be used for
>     diagnostics.  Return true if -Wnonnull warning has been diagnosed.  */
>  bool
> -check_function_arguments (location_t loc, const_tree fntype, int nargs,
> -                         tree *argarray)
> +check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype,
> +                         int nargs, tree *argarray)
>  {
>    bool warned_p = false;
>
> @@ -5624,6 +5624,44 @@ check_function_arguments (location_t loc
>
>    if (warn_format)
>      check_function_sentinel (fntype, nargs, argarray);
> +
> +  if (warn_restrict)
> +    {
> +      int i;
> +      tree parms;
> +
> +      if (fndecl
> +         && TREE_CODE (fndecl) == FUNCTION_DECL
> +         && DECL_ARGUMENTS (fndecl))
> +       parms = DECL_ARGUMENTS (fndecl);
> +      else
> +       parms = TYPE_ARG_TYPES (fntype);
> +
> +      for (i = 0; i < nargs; i++)
> +        TREE_VISITED (argarray[i]) = 0;
> +
> +      for (i = 0; i < nargs && parms && parms != void_list_node; i++)
> +       {
> +         tree type;
> +         if (TREE_CODE (parms) == PARM_DECL)
> +           {
> +             type = TREE_TYPE (parms);
> +             parms = DECL_CHAIN (parms);
> +           }
> +         else
> +           {
> +             type = TREE_VALUE (parms);
> +             parms = TREE_CHAIN (parms);
> +           }
> +         if (POINTER_TYPE_P (type)
> +             && TYPE_RESTRICT (type)
> +             && !TYPE_READONLY (TREE_TYPE (type)))
> +           warn_for_restrict (i, argarray, nargs);
> +       }
> +
> +      for (i = 0; i < nargs; i++)
> +        TREE_VISITED (argarray[i]) = 0;
> +    }
>    return warned_p;
>  }
>
> --- gcc/c-family/c-warn.c.jj    2017-02-15 18:06:19.000000000 +0100
> +++ gcc/c-family/c-warn.c       2017-02-20 12:36:29.008455672 +0100
> @@ -2170,55 +2170,49 @@ maybe_warn_bool_compare (location_t loc,
>     restrict-qualified param, and it aliases with another argument.  */
>
>  void
> -warn_for_restrict (unsigned param_pos, vec<tree, va_gc> *args)
> +warn_for_restrict (unsigned param_pos, tree *argarray, unsigned nargs)
>  {
> -  tree arg = (*args)[param_pos];
> -  if (TREE_VISITED (arg) || operand_equal_p (arg, null_pointer_node, 0))
> +  tree arg = argarray[param_pos];
> +  if (TREE_VISITED (arg) || integer_zerop (arg))
>      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;
> +  auto_vec<int, 16> arg_positions;
>
> -  FOR_EACH_VEC_ELT (*args, i, current_arg)
> +  for (i = 0; i < nargs; i++)
>      {
>        if (i == param_pos)
>         continue;
>
> -      tree current_arg = (*args)[i];
> +      tree current_arg = argarray[i];
>        if (operand_equal_p (arg, current_arg, 0))
>         {
>           TREE_VISITED (current_arg) = 1;
> -         arg_positions[arg_positions_len++] = (i + 1);
> +         arg_positions.safe_push (i + 1);
>         }
>      }
>
> -  if (arg_positions_len == 0)
> -    {
> -      free (arg_positions);
> -      return;
> -    }
> +  if (arg_positions.is_empty ())
> +    return;
>
> -  for (unsigned i = 0; i < arg_positions_len; i++)
> +  int pos;
> +  FOR_EACH_VEC_ELT (arg_positions, i, pos)
>      {
> -      unsigned pos = arg_positions[i];
> -      tree arg = (*args)[pos - 1];
> +      arg = argarray[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,
> +  warning_at_rich_loc_n (&richloc, OPT_Wrestrict, arg_positions.length (),
>                          "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);
> +                        param_pos + 1, arg_positions.address (),
> +                        arg_positions.length ());
>  }
>
>  /* Callback function to determine whether an expression TP or one of its
> --- gcc/c-family/c-common.h.jj  2017-01-24 23:29:05.000000000 +0100
> +++ gcc/c-family/c-common.h     2017-02-20 13:00:55.540080276 +0100
> @@ -807,7 +807,8 @@ extern const char *fname_as_string (int)
>  extern tree fname_decl (location_t, unsigned, tree);
>
>  extern int check_user_alignment (const_tree, bool);
> -extern bool check_function_arguments (location_t loc, const_tree, int, tree *);
> +extern bool check_function_arguments (location_t loc, const_tree, const_tree,
> +                                     int, tree *);
>  extern void check_function_arguments_recurse (void (*)
>                                               (void *, tree,
>                                                unsigned HOST_WIDE_INT),
> @@ -1501,7 +1502,7 @@ extern void warnings_for_convert_and_che
>  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> *);
> +extern void warn_for_restrict (unsigned, tree *, unsigned);
>
>  /* Places where an lvalue, or modifiable lvalue, may be required.
>     Used to select diagnostic messages in lvalue_error and
> --- gcc/c/c-parser.c.jj 2017-02-16 13:01:31.000000000 +0100
> +++ gcc/c/c-parser.c    2017-02-20 12:22:55.610210942 +0100
> @@ -8418,28 +8418,6 @@ c_parser_postfix_expression_after_primar
>               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
> --- gcc/c/c-typeck.c.jj 2017-01-21 02:25:57.000000000 +0100
> +++ gcc/c/c-typeck.c    2017-02-20 13:01:36.829532979 +0100
> @@ -3110,7 +3110,8 @@ build_function_call_vec (location_t loc,
>      return error_mark_node;
>
>    /* Check that the arguments to the function are valid.  */
> -  bool warned_p = check_function_arguments (loc, fntype, nargs, argarray);
> +  bool warned_p = check_function_arguments (loc, fundecl, fntype,
> +                                           nargs, argarray);
>
>    if (name != NULL_TREE
>        && !strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10))
> --- gcc/cp/call.c.jj    2017-02-17 18:29:21.000000000 +0100
> +++ gcc/cp/call.c       2017-02-20 13:03:21.874140599 +0100
> @@ -7900,14 +7900,17 @@ build_over_call (struct z_candidate *can
>       the check_function_arguments function might warn about something.  */
>
>    bool warned_p = false;
> -  if (warn_nonnull || warn_format || warn_suggest_attribute_format)
> +  if (warn_nonnull
> +      || warn_format
> +      || warn_suggest_attribute_format
> +      || warn_restrict)
>      {
>        tree *fargs = (!nargs ? argarray
>                             : (tree *) alloca (nargs * sizeof (tree)));
>        for (j = 0; j < nargs; j++)
>         fargs[j] = maybe_constant_value (argarray[j]);
>
> -      warned_p = check_function_arguments (input_location, TREE_TYPE (fn),
> +      warned_p = check_function_arguments (input_location, fn, TREE_TYPE (fn),
>                                            nargs, fargs);
>      }
>
> --- gcc/cp/parser.c.jj  2017-02-18 14:12:36.000000000 +0100
> +++ gcc/cp/parser.c     2017-02-20 12:21:32.257313679 +0100
> @@ -6933,29 +6933,6 @@ cp_parser_postfix_expression (cp_parser
>                 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);
> --- gcc/cp/typeck.c.jj  2017-02-13 20:30:33.000000000 +0100
> +++ gcc/cp/typeck.c     2017-02-20 13:04:10.994489395 +0100
> @@ -3661,7 +3661,7 @@ cp_build_function_call_vec (tree functio
>
>    /* Check for errors in format strings and inappropriately
>       null parameters.  */
> -  bool warned_p = check_function_arguments (input_location, fntype,
> +  bool warned_p = check_function_arguments (input_location, fndecl, fntype,
>                                             nargs, argarray);
>
>    ret = build_cxx_call (function, nargs, argarray, complain);
> --- gcc/testsuite/g++.dg/warn/Wrestrict-1.C.jj  2017-02-18 18:07:19.535116220 +0100
> +++ gcc/testsuite/g++.dg/warn/Wrestrict-1.C     2017-02-18 18:05:52.000000000 +0100
> @@ -0,0 +1,12 @@
> +// PR c++/79588
> +// { dg-do compile }
> +// { dg-options "-Wrestrict" }
> +
> +void foo (char *__restrict, char *__restrict = __null);
> +
> +void
> +bar (char *p)
> +{
> +  foo (p, p);  // { dg-warning "to restrict-qualified parameter aliases with" }
> +  foo (p);
> +}
> --- gcc/testsuite/g++.dg/warn/Wrestrict-2.C.jj  2017-02-20 13:07:34.635789299 +0100
> +++ gcc/testsuite/g++.dg/warn/Wrestrict-2.C     2017-02-20 12:55:12.000000000 +0100
> @@ -0,0 +1,30 @@
> +// PR c++/79588
> +// { dg-do compile }
> +// { dg-options "-Wrestrict" }
> +
> +void foo (char *__restrict, char *__restrict = __null);
> +
> +template <int N>
> +void
> +bar (char **p)
> +{
> +  foo (p[0], p[0]);    // { dg-warning "to restrict-qualified parameter aliases with" }
> +  foo (p[0], p[N]);    // { dg-warning "to restrict-qualified parameter aliases with" }
> +  foo (p[0]);
> +}
> +
> +template <int N>
> +void
> +bar2 (char **p)
> +{
> +  foo (p[0], p[0]);    // { dg-warning "to restrict-qualified parameter aliases with" }
> +  foo (p[0], p[N]);    // { dg-bogus "to restrict-qualified parameter aliases with" }
> +  foo (p[0]);
> +}
> +
> +void
> +baz (char **p)
> +{
> +  bar<0> (p);
> +  bar2<1> (p);
> +}
>
>         Jakub
Jeff Law Feb. 23, 2017, 10:09 p.m. UTC | #2
On 02/20/2017 01:35 PM, Jakub Jelinek wrote:
> Hi!
>
> As mentioned in the PR, -Wrestrict warning is done way too early, where
> e.g. default arguments aren't filled up yet (reason for ICE on first
> testcase) or where arguments in templates aren't instantiated yet (reason
> why we don't diagnose anything on the second testcase).
>
> This patch moves it later where e.g. -Wformat is diagnosed and fixes
> some issues I found while looking at the code.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2017-02-20  Jakub Jelinek  <jakub@redhat.com>
>
> 	PR c++/79588
> c-family/
> 	* c-common.c (check_function_arguments): Add FNDECL argument.
> 	Handle -Wrestrict here.
> 	* c-warn.c (warn_for_restrict): Remove ARGS argument, add ARGARRAY
> 	and NARGS.  Use auto_vec for ARG_POSITIONS, simplify.
> 	* c-common.h (check_function_arguments): Add FNDECL argument.
> 	(warn_for_restrict): Remove ARGS argument, add ARGARRAY and NARGS.
> c/
> 	* c-parser.c (c_parser_postfix_expression_after_primary): Don't
> 	handle -Wrestrict here.
> 	* c-typeck.c (build_function_call_vec): Adjust
> 	check_function_arguments caller.
> cp/
> 	* call.c (build_over_call): Call check_function_arguments even for
> 	-Wrestrict, adjust check_function_arguments caller.
> 	* parser.c (cp_parser_postfix_expression): Don't handle -Wrestrict
> 	here.
> 	* typeck.c (cp_build_function_call_vec): Adjust
> 	check_function_arguments caller.
> testsuite/
> 	* g++.dg/warn/Wrestrict-1.C: New test.
> 	* g++.dg/warn/Wrestrict-2.C: New test.
Please  refactor the restrict warning bits into their own function, then 
calling that from check_function_arguments.  That's the style already 
used there.

OK with that change.

jeff
diff mbox

Patch

--- gcc/c-family/c-common.c.jj	2017-01-24 23:29:05.000000000 +0100
+++ gcc/c-family/c-common.c	2017-02-20 13:17:06.601211847 +0100
@@ -5605,8 +5605,8 @@  attribute_fallthrough_p (tree attr)
    There are NARGS arguments in the array ARGARRAY.  LOC should be used for
    diagnostics.  Return true if -Wnonnull warning has been diagnosed.  */
 bool
-check_function_arguments (location_t loc, const_tree fntype, int nargs,
-			  tree *argarray)
+check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype,
+			  int nargs, tree *argarray)
 {
   bool warned_p = false;
 
@@ -5624,6 +5624,44 @@  check_function_arguments (location_t loc
 
   if (warn_format)
     check_function_sentinel (fntype, nargs, argarray);
+
+  if (warn_restrict)
+    {
+      int i;
+      tree parms;
+
+      if (fndecl
+	  && TREE_CODE (fndecl) == FUNCTION_DECL
+	  && DECL_ARGUMENTS (fndecl))
+	parms = DECL_ARGUMENTS (fndecl);
+      else
+	parms = TYPE_ARG_TYPES (fntype);
+
+      for (i = 0; i < nargs; i++)
+        TREE_VISITED (argarray[i]) = 0;
+
+      for (i = 0; i < nargs && parms && parms != void_list_node; i++)
+	{
+	  tree type;
+	  if (TREE_CODE (parms) == PARM_DECL)
+	    {
+	      type = TREE_TYPE (parms);
+	      parms = DECL_CHAIN (parms);
+	    }
+	  else
+	    {
+	      type = TREE_VALUE (parms);
+	      parms = TREE_CHAIN (parms);
+	    }
+	  if (POINTER_TYPE_P (type)
+	      && TYPE_RESTRICT (type)
+	      && !TYPE_READONLY (TREE_TYPE (type)))
+	    warn_for_restrict (i, argarray, nargs);
+	}
+
+      for (i = 0; i < nargs; i++)
+        TREE_VISITED (argarray[i]) = 0;
+    }
   return warned_p;
 }
 
--- gcc/c-family/c-warn.c.jj	2017-02-15 18:06:19.000000000 +0100
+++ gcc/c-family/c-warn.c	2017-02-20 12:36:29.008455672 +0100
@@ -2170,55 +2170,49 @@  maybe_warn_bool_compare (location_t loc,
    restrict-qualified param, and it aliases with another argument.  */
 
 void
-warn_for_restrict (unsigned param_pos, vec<tree, va_gc> *args)
+warn_for_restrict (unsigned param_pos, tree *argarray, unsigned nargs)
 {
-  tree arg = (*args)[param_pos];
-  if (TREE_VISITED (arg) || operand_equal_p (arg, null_pointer_node, 0))
+  tree arg = argarray[param_pos];
+  if (TREE_VISITED (arg) || integer_zerop (arg))
     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;
+  auto_vec<int, 16> arg_positions;
 
-  FOR_EACH_VEC_ELT (*args, i, current_arg) 
+  for (i = 0; i < nargs; i++)
     {
       if (i == param_pos)
 	continue;
 
-      tree current_arg = (*args)[i];
+      tree current_arg = argarray[i];
       if (operand_equal_p (arg, current_arg, 0))
 	{
 	  TREE_VISITED (current_arg) = 1; 
-	  arg_positions[arg_positions_len++] = (i + 1);
+	  arg_positions.safe_push (i + 1);
 	}
     }
 
-  if (arg_positions_len == 0)
-    {
-      free (arg_positions);
-      return;
-    }
+  if (arg_positions.is_empty ())
+    return;
 
-  for (unsigned i = 0; i < arg_positions_len; i++)
+  int pos;
+  FOR_EACH_VEC_ELT (arg_positions, i, pos)
     {
-      unsigned pos = arg_positions[i];
-      tree arg = (*args)[pos - 1];
+      arg = argarray[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,
+  warning_at_rich_loc_n (&richloc, OPT_Wrestrict, arg_positions.length (),
 			 "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);
+			 param_pos + 1, arg_positions.address (),
+			 arg_positions.length ());
 }
 
 /* Callback function to determine whether an expression TP or one of its
--- gcc/c-family/c-common.h.jj	2017-01-24 23:29:05.000000000 +0100
+++ gcc/c-family/c-common.h	2017-02-20 13:00:55.540080276 +0100
@@ -807,7 +807,8 @@  extern const char *fname_as_string (int)
 extern tree fname_decl (location_t, unsigned, tree);
 
 extern int check_user_alignment (const_tree, bool);
-extern bool check_function_arguments (location_t loc, const_tree, int, tree *);
+extern bool check_function_arguments (location_t loc, const_tree, const_tree,
+				      int, tree *);
 extern void check_function_arguments_recurse (void (*)
 					      (void *, tree,
 					       unsigned HOST_WIDE_INT),
@@ -1501,7 +1502,7 @@  extern void warnings_for_convert_and_che
 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> *);
+extern void warn_for_restrict (unsigned, tree *, unsigned);
 
 /* Places where an lvalue, or modifiable lvalue, may be required.
    Used to select diagnostic messages in lvalue_error and
--- gcc/c/c-parser.c.jj	2017-02-16 13:01:31.000000000 +0100
+++ gcc/c/c-parser.c	2017-02-20 12:22:55.610210942 +0100
@@ -8418,28 +8418,6 @@  c_parser_postfix_expression_after_primar
 	      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
--- gcc/c/c-typeck.c.jj	2017-01-21 02:25:57.000000000 +0100
+++ gcc/c/c-typeck.c	2017-02-20 13:01:36.829532979 +0100
@@ -3110,7 +3110,8 @@  build_function_call_vec (location_t loc,
     return error_mark_node;
 
   /* Check that the arguments to the function are valid.  */
-  bool warned_p = check_function_arguments (loc, fntype, nargs, argarray);
+  bool warned_p = check_function_arguments (loc, fundecl, fntype,
+					    nargs, argarray);
 
   if (name != NULL_TREE
       && !strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10))
--- gcc/cp/call.c.jj	2017-02-17 18:29:21.000000000 +0100
+++ gcc/cp/call.c	2017-02-20 13:03:21.874140599 +0100
@@ -7900,14 +7900,17 @@  build_over_call (struct z_candidate *can
      the check_function_arguments function might warn about something.  */
 
   bool warned_p = false;
-  if (warn_nonnull || warn_format || warn_suggest_attribute_format)
+  if (warn_nonnull
+      || warn_format
+      || warn_suggest_attribute_format
+      || warn_restrict)
     {
       tree *fargs = (!nargs ? argarray
 			    : (tree *) alloca (nargs * sizeof (tree)));
       for (j = 0; j < nargs; j++)
 	fargs[j] = maybe_constant_value (argarray[j]);
 
-      warned_p = check_function_arguments (input_location, TREE_TYPE (fn),
+      warned_p = check_function_arguments (input_location, fn, TREE_TYPE (fn),
 					   nargs, fargs);
     }
 
--- gcc/cp/parser.c.jj	2017-02-18 14:12:36.000000000 +0100
+++ gcc/cp/parser.c	2017-02-20 12:21:32.257313679 +0100
@@ -6933,29 +6933,6 @@  cp_parser_postfix_expression (cp_parser
 		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);
--- gcc/cp/typeck.c.jj	2017-02-13 20:30:33.000000000 +0100
+++ gcc/cp/typeck.c	2017-02-20 13:04:10.994489395 +0100
@@ -3661,7 +3661,7 @@  cp_build_function_call_vec (tree functio
 
   /* Check for errors in format strings and inappropriately
      null parameters.  */
-  bool warned_p = check_function_arguments (input_location, fntype,
+  bool warned_p = check_function_arguments (input_location, fndecl, fntype,
 					    nargs, argarray);
 
   ret = build_cxx_call (function, nargs, argarray, complain);
--- gcc/testsuite/g++.dg/warn/Wrestrict-1.C.jj	2017-02-18 18:07:19.535116220 +0100
+++ gcc/testsuite/g++.dg/warn/Wrestrict-1.C	2017-02-18 18:05:52.000000000 +0100
@@ -0,0 +1,12 @@ 
+// PR c++/79588
+// { dg-do compile }
+// { dg-options "-Wrestrict" }
+
+void foo (char *__restrict, char *__restrict = __null);
+
+void
+bar (char *p)
+{
+  foo (p, p);	// { dg-warning "to restrict-qualified parameter aliases with" }
+  foo (p);
+}
--- gcc/testsuite/g++.dg/warn/Wrestrict-2.C.jj	2017-02-20 13:07:34.635789299 +0100
+++ gcc/testsuite/g++.dg/warn/Wrestrict-2.C	2017-02-20 12:55:12.000000000 +0100
@@ -0,0 +1,30 @@ 
+// PR c++/79588
+// { dg-do compile }
+// { dg-options "-Wrestrict" }
+
+void foo (char *__restrict, char *__restrict = __null);
+
+template <int N>
+void
+bar (char **p)
+{
+  foo (p[0], p[0]);	// { dg-warning "to restrict-qualified parameter aliases with" }
+  foo (p[0], p[N]);	// { dg-warning "to restrict-qualified parameter aliases with" }
+  foo (p[0]);
+}
+
+template <int N>
+void
+bar2 (char **p)
+{
+  foo (p[0], p[0]);	// { dg-warning "to restrict-qualified parameter aliases with" }
+  foo (p[0], p[N]);	// { dg-bogus "to restrict-qualified parameter aliases with" }
+  foo (p[0]);
+}
+
+void
+baz (char **p)
+{
+  bar<0> (p);
+  bar2<1> (p);
+}