--- 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);
+}
