diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index ef445e0..3bc42f5 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -436,6 +436,8 @@ struct conversion_info {
   tree from;
   /* The type of the parameter.  */
   tree to_type;
+  /* The location of the argument.  */
+  location_t loc;
 };
   
 struct rejection_reason {
@@ -627,24 +629,28 @@ arity_rejection (tree first_arg, int expected, int actual)
 }
 
 static struct rejection_reason *
-arg_conversion_rejection (tree first_arg, int n_arg, tree from, tree to)
+arg_conversion_rejection (tree first_arg, int n_arg, tree from, tree to,
+			  location_t loc)
 {
   struct rejection_reason *r = alloc_rejection (rr_arg_conversion);
   int adjust = first_arg != NULL_TREE;
   r->u.conversion.n_arg = n_arg - adjust;
   r->u.conversion.from = from;
   r->u.conversion.to_type = to;
+  r->u.conversion.loc = loc;
   return r;
 }
 
 static struct rejection_reason *
-bad_arg_conversion_rejection (tree first_arg, int n_arg, tree from, tree to)
+bad_arg_conversion_rejection (tree first_arg, int n_arg, tree from, tree to,
+			      location_t loc)
 {
   struct rejection_reason *r = alloc_rejection (rr_bad_arg_conversion);
   int adjust = first_arg != NULL_TREE;
   r->u.bad_conversion.n_arg = n_arg - adjust;
   r->u.bad_conversion.from = from;
   r->u.bad_conversion.to_type = to;
+  r->u.bad_conversion.loc = loc;
   return r;
 }
 
@@ -655,6 +661,7 @@ explicit_conversion_rejection (tree from, tree to)
   r->u.conversion.n_arg = 0;
   r->u.conversion.from = from;
   r->u.conversion.to_type = to;
+  r->u.conversion.loc = UNKNOWN_LOCATION;
   return r;
 }
 
@@ -665,6 +672,7 @@ template_conversion_rejection (tree from, tree to)
   r->u.conversion.n_arg = 0;
   r->u.conversion.from = from;
   r->u.conversion.to_type = to;
+  r->u.conversion.loc = UNKNOWN_LOCATION;
   return r;
 }
 
@@ -2254,14 +2262,17 @@ add_function_candidate (struct z_candidate **candidates,
       if (! t)
 	{
 	  viable = 0;
-	  reason = arg_conversion_rejection (first_arg, i, argtype, to_type);
+	  reason = arg_conversion_rejection (first_arg, i, argtype, to_type,
+					     EXPR_LOCATION (arg));
 	  break;
 	}
 
       if (t->bad_p)
 	{
 	  viable = -1;
-	  reason = bad_arg_conversion_rejection (first_arg, i, arg, to_type);
+	  reason = bad_arg_conversion_rejection (first_arg, i, arg, to_type,
+						 EXPR_LOCATION (arg));
+
 	}
     }
 
@@ -2350,7 +2361,8 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
       if (t->bad_p)
 	{
 	  viable = -1;
-	  reason = bad_arg_conversion_rejection (NULL_TREE, i, arg, convert_type);
+	  reason = bad_arg_conversion_rejection (NULL_TREE, i, arg, convert_type,
+						 EXPR_LOCATION (arg));
 	}
 
       if (i == 0)
@@ -2411,13 +2423,14 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname,
 	  /* We need something for printing the candidate.  */
 	  t = build_identity_conv (types[i], NULL_TREE);
 	  reason = arg_conversion_rejection (NULL_TREE, i, argtypes[i],
-					     types[i]);
+					     types[i], EXPR_LOCATION (args[i]));
 	}
       else if (t->bad_p)
 	{
 	  viable = 0;
 	  reason = bad_arg_conversion_rejection (NULL_TREE, i, args[i],
-						 types[i]);
+						 types[i],
+						 EXPR_LOCATION (args[i]));
 	}
       convs[i] = t;
     }
@@ -2436,7 +2449,8 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname,
 	{
 	  viable = 0;
 	  reason = arg_conversion_rejection (NULL_TREE, 0, argtypes[2],
-					     boolean_type_node);
+					     boolean_type_node,
+					     EXPR_LOCATION (args[2]));
 	}
     }
 
@@ -3927,7 +3941,8 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags,
 	    {
 	      cand->viable = 0;
 	      cand->reason = arg_conversion_rejection (NULL_TREE, -2,
-						       rettype, totype);
+						       rettype, totype,
+						       EXPR_LOCATION (expr));
 	    }
 	  else if (DECL_NONCONVERTING_P (cand->fn)
 		   && ics->rank > cr_exact)
@@ -3947,7 +3962,8 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags,
 	      cand->viable = -1;
 	      cand->reason
 		= bad_arg_conversion_rejection (NULL_TREE, -2,
-						rettype, totype);
+						rettype, totype,
+						EXPR_LOCATION (expr));
 	    }
 	  else if (primary_template_specialization_p (cand->fn)
 		   && ics->rank > cr_exact)
@@ -9157,6 +9173,61 @@ name_as_c_string (tree name, tree type, bool *free_p)
   return CONST_CAST (char *, pretty_name);
 }
 
+/* Subroutine of get_location_for_unmatched_call.
+   Return the location of the pertinent argument in INFO, if
+   available.
+   Otherwise, return DEFAULT_LOCATION.  */
+
+static location_t
+get_location_for_arg_conversion (conversion_info *info,
+				 location_t default_location)
+{
+  if (info->loc == UNKNOWN_LOCATION)
+    return default_location;
+  return info->loc;
+}
+
+/* Get the best location to use when reporting a function call
+   for which there are no valid candidates.
+
+   If there is just one candidate, and it is invalid due to the
+   argument type, use the location of the pertinent argument.
+
+   Otherwise, use DEFAULT_LOCATION.  */
+
+static location_t
+get_location_for_unmatched_call (z_candidate *candidates,
+				 location_t default_location)
+{
+  if (!candidates)
+    return default_location;
+
+  /* Must be exactly one candidate.  */
+  if (candidates->next)
+    return default_location;
+
+  /* Must be an rr_arg_conversion or rr_bad_arg_conversion.  */
+  z_candidate *candidate = candidates;
+  rejection_reason *r = candidate->reason;
+
+  if (r == NULL)
+    return default_location;
+
+  switch (r->code)
+    {
+    default:
+      return default_location;
+
+    case rr_arg_conversion:
+      return get_location_for_arg_conversion (&r->u.conversion,
+					      default_location);
+
+    case rr_bad_arg_conversion:
+      return get_location_for_arg_conversion (&r->u.bad_conversion,
+					      default_location);
+    }
+}
+
 /* Build a call to "INSTANCE.FN (ARGS)".  If FN_P is non-NULL, it will
    be set, upon return, to the function called.  ARGS may be NULL.
    This may change ARGS.  */
@@ -9375,13 +9446,16 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
     {
       if (complain & tf_error)
 	{
+	  location_t loc = get_location_for_unmatched_call (candidates,
+							    input_location);
 	  auto_diagnostic_group d;
 	  if (!COMPLETE_OR_OPEN_TYPE_P (basetype))
 	    cxx_incomplete_type_error (instance, basetype);
 	  else if (optype)
-	    error ("no matching function for call to %<%T::operator %T(%A)%#V%>",
-		   basetype, optype, build_tree_list_vec (user_args),
-		   TREE_TYPE (instance));
+	    error_at (loc,
+		      "no matching function for call to %<%T::operator %T(%A)%#V%>",
+		      basetype, optype, build_tree_list_vec (user_args),
+		      TREE_TYPE (instance));
 	  else
 	    {
 	      tree arglist = build_tree_list_vec (user_args);
@@ -9396,9 +9470,10 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
 		errname = lookup_template_function (errname, explicit_targs);
 	      if (skip_first_for_error)
 		arglist = TREE_CHAIN (arglist);
-	      error ("no matching function for call to %<%T::%s%E(%A)%#V%>",
-		     basetype, &"~"[!twiddle], errname, arglist,
-		     TREE_TYPE (instance));
+	      error_at (loc,
+			"no matching function for call to %<%T::%s%E(%A)%#V%>",
+			basetype, &"~"[!twiddle], errname, arglist,
+			TREE_TYPE (instance));
 	    }
 	  print_z_candidates (location_of (name), candidates);
 	}
diff --git a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C
index 4957f61..8fb167a 100644
--- a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C
+++ b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C
@@ -74,7 +74,7 @@ int test_4 (int first, const char *second, float third)
   return s4::member_1 (first, second, third); // { dg-error "no matching function for call to 's4::member_1\\(int&, const char\\*&, float&\\)'" }
   /* { dg-begin-multiline-output "" }
    return s4::member_1 (first, second, third);
-                                            ^
+                               ^~~~~~
      { dg-end-multiline-output "" } */
   // { dg-message "candidate: 'static int s4::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s4_member_1 }
   /* { dg-begin-multiline-output "" }
@@ -98,7 +98,7 @@ int test_5 (int first, const char *second, float third)
   return inst.member_1 (first, second, third); // { dg-error "no matching function for call to 's5::member_1\\(int&, const char\\*&, float&\\)'" }
   /* { dg-begin-multiline-output "" }
    return inst.member_1 (first, second, third);
-                                             ^
+                                ^~~~~~
      { dg-end-multiline-output "" } */
   // { dg-message "candidate: 'int s5::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s5_member_1 }
   /* { dg-begin-multiline-output "" }
@@ -121,7 +121,7 @@ int test_6 (int first, const char *second, float third, s6 *ptr)
   return ptr->member_1 (first, second, third); // { dg-error "no matching function for call to 's6::member_1\\(int&, const char\\*&, float&\\)'" }
   /* { dg-begin-multiline-output "" }
    return ptr->member_1 (first, second, third);
-                                             ^
+                                ^~~~~~
      { dg-end-multiline-output "" } */
   // { dg-message "candidate: 'int s6::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s6_member_1 }
   /* { dg-begin-multiline-output "" }
@@ -171,7 +171,7 @@ int test_8 (int first, const char *second, float third)
   return s8 <const char **>::member_1 (first, second, third); // { dg-error "no matching function for call to 's8<const char\\*\\*>::member_1\\(int&, const char\\*&, float&\\)'" }
   /* { dg-begin-multiline-output "" }
    return s8 <const char **>::member_1 (first, second, third);
-                                                            ^
+                                               ^~~~~~
      { dg-end-multiline-output "" } */
   // { dg-message "candidate: 'static int s8<T>::member_1\\(int, T, float\\)" "" { target *-*-* } s8_member_1 }
   /* { dg-begin-multiline-output "" }
@@ -196,7 +196,7 @@ int test_9 (int first, const char *second, float third)
   return inst.member_1 (first, second, third); // { dg-error "no matching function for call to 's9<const char\\*\\*>::member_1\\(int&, const char\\*&, float&\\)'" }
   /* { dg-begin-multiline-output "" }
    return inst.member_1 (first, second, third);
-                                             ^
+                                ^~~~~~
      { dg-end-multiline-output "" } */
   // { dg-message "candidate: 'int s9<T>::member_1\\(int, T, float\\)" "" { target *-*-* } s9_member_1 }
   /* { dg-begin-multiline-output "" }
@@ -209,3 +209,30 @@ int test_9 (int first, const char *second, float third)
                                     ~~^~~
      { dg-end-multiline-output "" } */
 }
+
+/* Overloaded operator (with one candidate).  */
+
+struct s10 {};
+
+extern int operator- (const s10&, int); // { dg-line s10_operator }
+
+int test_10 ()
+{
+  s10 v10_a, v10_b;
+
+  return v10_a - v10_b; // { dg-error "no match for" }
+  /* { dg-begin-multiline-output "" }
+   return v10_a - v10_b;
+          ~~~~~~^~~~~~~
+     { dg-end-multiline-output "" } */
+  // { dg-message "candidate" "" { target *-*-* } s10_operator }
+  /* { dg-begin-multiline-output "" }
+ extern int operator- (const s10&, int);
+            ^~~~~~~~
+     { dg-end-multiline-output "" } */
+  // { dg-message "no known conversion for argument 2 from" "" { target *-*-* } s10_operator }
+  /* { dg-begin-multiline-output "" }
+ extern int operator- (const s10&, int);
+                                   ^~~
+     { dg-end-multiline-output "" } */
+}
