Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td	(revision 97223)
+++ include/clang/Basic/DiagnosticSemaKinds.td	(working copy)
@@ -568,11 +568,36 @@
   "identifier %0 in pseudo-destructor expression does not name a type">;
 
 // C++ initialization
-def err_init_conversion_failed : Error<
-  "cannot initialize %select{a variable|a parameter|return object|an "
-  "exception object|a member subobject|an array element|a new value|a value|a "
-  "base class|a vector element}0 of type %1 with an %select{rvalue|lvalue}2 of "
-  "type %3">;
+def err_init_bad_conv : Error<"cannot initialize %select{the variable |"
+  "%select{the|an unnamed}1 parameter%select{ |}1|the return object|an "
+  "exception object|the data member |an array element|a new value|a temporary "
+  "value|a base class|a vector element}0%select{%2|}1 with an %select{rvalue|"
+  "lvalue}3 of type %4: no known conversion to %5">;
+def err_init_bad_conv_no_overload : Error<"cannot initialize %select{the "
+  "variable |%select{the|an unnamed}1 parameter%select{ |}1|the return object|"
+  "an exception object|the data member |an array element|a new value|a "
+  "temporary value|a base class|a vector element}0%select{%2|}1: "
+  "no overload of the function %4 matches %3">;
+def err_init_bad_conv_incomplete : Error<"cannot initialize %select{the "
+  "variable |%select{the|an unnamed}1 parameter%select{ |}1|the return object|"
+  "an exception object|the data member |an array element|a new value|a "
+  "temporary value|a base class|a vector element}0%select{%2|}1 with an "
+  "%select{rvalue|lvalue}3 %select{pointing to|referring to}4 an incomplete "
+  "type %5: cannot check conversion to a %select{pointer|reference}4 to %6 "
+  "without a complete type">;
+def err_init_bad_conv_addrspace : Error<"cannot initialize %select{the "
+  "variable |%select{the|an unnamed}1 parameter%select{ |}1|the return object|"
+  "an exception object|the data member |an array element|a new value|a "
+  "temporary value|a base class|a vector element}0%select{%2|}1 with an "
+  "%select{rvalue|lvalue}3 of type %4 in address space %5: cannot convert to "
+  "address space %6">;
+def err_init_bad_cvr : Error<"cannot initialize %select{the variable |"
+  "%select{the|an unnamed}1 parameter%select{ |}1|the return object|an "
+  "exception object|the data member |an array element|a new value|a temporary "
+  "value|a base class|a vector element}0%select{%2|}1 with an %select{rvalue|"
+  "lvalue}3 of type %4: conversion to %5 would lose %select{const|volatile|"
+  "const and volatile|restrict|const and restrict|volatile and restrict|const, "
+  "volatile, and restrict}6 qualifier%select{||s||s|s|s}6">;
 
 def err_lvalue_to_rvalue_ref : Error<"rvalue reference cannot bind to lvalue">;
 def err_invalid_initialization : Error<
Index: lib/Sema/SemaInit.cpp
===================================================================
--- lib/Sema/SemaInit.cpp	(revision 97223)
+++ lib/Sema/SemaInit.cpp	(working copy)
@@ -2816,13 +2816,10 @@
                               /*ForceRValue=*/false, 
                               /*FIXME:InOverloadResolution=*/false,
                               /*UserCast=*/Kind.isExplicitCast());
-  
-  if (ICS.isBad()) {
+
+  Sequence.AddConversionSequenceStep(ICS, Entity.getType());
+  if (ICS.isBad())
     Sequence.SetFailed(InitializationSequence::FK_ConversionFailed);
-    return;
-  }
-  
-  Sequence.AddConversionSequenceStep(ICS, Entity.getType());
 }
 
 InitializationSequence::InitializationSequence(Sema &S,
@@ -3516,6 +3513,102 @@
 //===----------------------------------------------------------------------===//
 // Diagnose initialization failures
 //===----------------------------------------------------------------------===//
+
+// FIXME: Much of the logic here was shameless stolen from
+// DiagnoseBadConversion in SemaOverload, but the behavior and situations end
+// up being somewhat different. It would be good to factor and share the
+// smaller pieces.
+static void DiagnoseBadInitConversion(Sema &S, const InitializedEntity &Entity,
+                                      const InitializationKind &Kind,
+                                      const ImplicitConversionSequence &Conv) {
+  assert(Conv.isBad());
+
+  Expr *FromExpr = Conv.Bad.FromExpr;
+  assert(FromExpr && "The ICS doesn't contain the bad from expression.");
+  QualType FromTy = Conv.Bad.getFromType();
+  QualType ToTy = Conv.Bad.getToType();
+
+  DeclarationName Name = Entity.getName();
+  bool isFromLvalue = FromExpr->isLvalue(S.Context) == Expr::LV_Valid;
+
+  // Handle overloaded expressions specially as they don't have a fixed type.
+  if (FromTy == S.Context.OverloadTy) {
+    // Dig out the actual function name.
+    Expr *E = FromExpr->IgnoreParens();
+    if (isa<UnaryOperator>(E))
+      E = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens();
+    DeclarationName FromName = cast<OverloadExpr>(E)->getName();
+    S.Diag(Kind.getLocation(), diag::err_init_bad_conv_no_overload)
+      << (int)Entity.getKind() << !Name << Name << ToTy << FromName
+      << E->getSourceRange();
+    return;
+  }
+
+  // Do some hand-waving analysis to see if the non-viability is due
+  // to a qualifier mismatch.
+  CanQualType CFromTy = S.Context.getCanonicalType(FromTy);
+  CanQualType CToTy = S.Context.getCanonicalType(ToTy);
+  if (CanQual<ReferenceType> RT = CToTy->getAs<ReferenceType>())
+    CToTy = RT->getPointeeType();
+  else {
+    // TODO: detect and diagnose the full richness of const mismatches.
+    if (CanQual<PointerType> FromPT = CFromTy->getAs<PointerType>())
+      if (CanQual<PointerType> ToPT = CToTy->getAs<PointerType>())
+        CFromTy = FromPT->getPointeeType(), CToTy = ToPT->getPointeeType();
+  }
+
+  if (CToTy.getUnqualifiedType() == CFromTy.getUnqualifiedType() &&
+      !CToTy.isAtLeastAsQualifiedAs(CFromTy)) {
+    // It is dumb that we have to do this here.
+    while (isa<ArrayType>(CFromTy))
+      CFromTy = CFromTy->getAs<ArrayType>()->getElementType();
+    while (isa<ArrayType>(CToTy))
+      CToTy = CFromTy->getAs<ArrayType>()->getElementType();
+
+    Qualifiers FromQs = CFromTy.getQualifiers();
+    Qualifiers ToQs = CToTy.getQualifiers();
+
+    if (FromQs.getAddressSpace() != ToQs.getAddressSpace()) {
+      S.Diag(Kind.getLocation(), diag::err_init_bad_conv_addrspace)
+        << (int)Entity.getKind() << !Name << Name << isFromLvalue
+        << FromTy << FromExpr->getSourceRange() << FromQs.getAddressSpace()
+        << ToQs.getAddressSpace();
+      return;
+    }
+
+    unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers();
+    assert(CVR && "unexpected qualifiers mismatch");
+
+    S.Diag(Kind.getLocation(), diag::err_init_bad_cvr)
+      << (int)Entity.getKind() << !Name << Name << isFromLvalue
+      << FromTy << FromExpr->getSourceRange() << ToTy << (CVR - 1);
+    return;
+  }
+
+  // Diagnose references or pointers to incomplete types differently,
+  // since it's far from impossible that the incompleteness triggered
+  // the failure.
+  QualType TempFromTy = FromTy.getNonReferenceType();
+  if (const PointerType *PTy = TempFromTy->getAs<PointerType>())
+    TempFromTy = PTy->getPointeeType();
+  QualType TempToTy = ToTy.getNonReferenceType();
+  if (const PointerType *PTy = TempToTy->getAs<PointerType>())
+    TempToTy = PTy->getPointeeType();
+  if (TempFromTy->isIncompleteType()) {
+    S.Diag(Kind.getLocation(), diag::err_init_bad_conv_incomplete)
+      << (int)Entity.getKind() << !Name << Name << isFromLvalue
+      << TempFromTy->isPointerType() << TempFromTy
+      << FromExpr->getSourceRange() << TempToTy;
+    return;
+
+  }
+
+  // TODO: specialize more based on the kind of mismatch
+  S.Diag(Kind.getLocation(), diag::err_init_bad_conv)
+    << (int)Entity.getKind() << !Name << Name << isFromLvalue
+    << FromTy << FromExpr->getSourceRange() << ToTy;
+}
+
 bool InitializationSequence::Diagnose(Sema &S, 
                                       const InitializedEntity &Entity,
                                       const InitializationKind &Kind,
@@ -3627,14 +3720,20 @@
       << Args[0]->getSourceRange();
     break;
       
-  case FK_ConversionFailed:
-    S.Diag(Kind.getLocation(), diag::err_init_conversion_failed)
-      << (int)Entity.getKind()
-      << DestType
-      << (Args[0]->isLvalue(S.Context) == Expr::LV_Valid)
-      << Args[0]->getType()
-      << Args[0]->getSourceRange();
+  case FK_ConversionFailed: {
+    const ImplicitConversionSequence *ICS = 0;
+    for (llvm::SmallVectorImpl<Step>::iterator Step = Steps.begin(),
+                                            StepEnd = Steps.end();
+         Step != StepEnd; ++Step) {
+      if (Step->Kind == SK_ConversionSequence) {
+        ICS = Step->ICS;
+        break;
+      }
+    }
+    assert(ICS && "Unable to find failed conversion sequence.");
+    DiagnoseBadInitConversion(S, Entity, Kind, *ICS);
     break;
+  }
 
   case FK_TooManyInitsForScalar: {
     SourceRange R;
