diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 23e458d3252..52c9f4265a4 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -8459,12 +8459,21 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum,
 		if (pedwarn (loc, 0, "converting to %qT from initializer list "
 			     "would use explicit constructor %qD",
 			     totype, convfn))
-		  inform (loc, "in C++11 and above a default constructor "
-			  "can be explicit");
+		  {
+		    inform (DECL_SOURCE_LOCATION (convfn), "%qD declared here",
+			    convfn);
+		    inform (loc, "in C++11 and above a default constructor "
+			    "can be explicit");
+		  }
 	      }
 	    else
-	      error ("converting to %qT from initializer list would use "
-		     "explicit constructor %qD", totype, convfn);
+	      {
+		auto_diagnostic_group d;
+		error ("converting to %qT from initializer list would use "
+		       "explicit constructor %qD", totype, convfn);
+		inform (DECL_SOURCE_LOCATION (convfn), "%qD declared here",
+			convfn);
+	      }
 	  }
 
 	/* If we're initializing from {}, it's value-initialization.  */
@@ -14323,4 +14332,28 @@ is_list_ctor (tree decl)
   return true;
 }
 
+/* We know that can_convert_arg_bad already said "no" when trying to convert
+   FROM to TO with ARG and FLAGS.  Try to figure out if it was because
+   an explicit conversion function was skipped when looking for a way to
+   perform the conversion.  At this point we've already printed an error.  */
+
+void
+maybe_show_nonconverting_candidate (tree to, tree from, tree arg, int flags)
+{
+  if (!(flags & LOOKUP_ONLYCONVERTING))
+    return;
+
+  conversion_obstack_sentinel cos;
+  conversion *c = implicit_conversion (to, from, arg, /*c_cast_p=*/false,
+				       flags & ~LOOKUP_ONLYCONVERTING, tf_none);
+  if (c && !c->bad_p && c->user_conv_p)
+    /* Ay, the conversion would have worked in copy-init context.  */
+    for (; c; c = next_conversion (c))
+      if (c->kind == ck_user
+	  && DECL_P (c->cand->fn)
+	  && DECL_NONCONVERTING_P (c->cand->fn))
+	inform (DECL_SOURCE_LOCATION (c->cand->fn), "explicit conversion "
+		"function was not considered");
+}
+
 #include "gt-cp-call.h"
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 608d6310e53..6b225ca182f 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6727,6 +6727,7 @@ extern bool cp_handle_deprecated_or_unavailable (tree, tsubst_flags_t = tf_warni
 extern void cp_warn_deprecated_use_scopes	(tree);
 extern tree get_function_version_dispatcher	(tree);
 extern bool any_template_arguments_need_structural_equality_p (tree);
+extern void maybe_show_nonconverting_candidate	(tree, tree, tree, int);
 
 /* in class.cc */
 extern tree build_vfield_ref			(tree, tree);
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index d5c0c85ed51..459739d5866 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -10262,6 +10262,8 @@ convert_for_assignment (tree type, tree rhs,
 		{
 		  range_label_for_type_mismatch label (rhstype, type);
 		  gcc_rich_location richloc (rhs_loc, has_loc ? &label : NULL);
+		  auto_diagnostic_group d;
+
 		  switch (errtype)
 		    {
 		    case ICR_DEFAULT_ARGUMENT:
@@ -10296,6 +10298,10 @@ convert_for_assignment (tree type, tree rhs,
 		      gcc_unreachable();
 		  }
 		}
+
+	      /* See if we can be more helpful.  */
+	      maybe_show_nonconverting_candidate (type, rhstype, rhs, flags);
+
 	      if (TYPE_PTR_P (rhstype)
 		  && TYPE_PTR_P (type)
 		  && CLASS_TYPE_P (TREE_TYPE (rhstype))
diff --git a/gcc/testsuite/g++.dg/diagnostic/explicit.C b/gcc/testsuite/g++.dg/diagnostic/explicit.C
new file mode 100644
index 00000000000..122accb86c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/explicit.C
@@ -0,0 +1,33 @@
+// { dg-do compile { target c++11 } }
+
+struct A {
+  long int l;
+};
+
+struct S {
+  explicit S(int) { }
+  explicit operator bool() const { return true; } // { dg-message "explicit conversion function was not considered" }
+  explicit operator int() const { return 42; } // { dg-message "explicit conversion function was not considered" }
+  explicit operator char() const { return 42; } // { dg-message "explicit conversion function was not considered" }
+  explicit operator double() const { return 42.; } // { dg-message "explicit conversion function was not considered" }
+  explicit operator float() const { return 42.; } // { dg-message "explicit conversion function was not considered" }
+  explicit operator long() const { return 42.; } // { dg-message "explicit conversion function was not considered" }
+};
+
+double
+f (char)
+{
+  return S{2}; // { dg-error "cannot convert .S. to .double. in return" }
+}
+
+void
+g ()
+{
+  S s = {1}; // { dg-error "would use explicit constructor" }
+  bool b = S{1}; // { dg-error "cannot convert .S. to .bool. in initialization" }
+  int i;
+  i = S{2}; // { dg-error "cannot convert .S. to .int. in assignment" }
+  f (S{3}); // { dg-error "cannot convert .S. to .char." }
+  A a{ S{4} }; // { dg-error "cannot convert .S. to .long int. in initialization" }
+  float arr[1] = { S{5} }; // { dg-error "cannot convert .S. to .float. in initialization" }
+}
