Issue good diagnostics when initialization failes due to
ambiguity in type conversion function selection.

llvm-svn: 81898
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 2713f7a..84e73a6 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -734,6 +734,15 @@
     return NULL;
   }
 
+  /// OverloadingResult - Capture the result of performing overload
+  /// resolution.
+  enum OverloadingResult {
+    OR_Success,             ///< Overload resolution succeeded.
+    OR_No_Viable_Function,  ///< No viable function found.
+    OR_Ambiguous,           ///< Ambiguous candidates found.
+    OR_Deleted              ///< Overload resoltuion refers to a deleted function.
+  };
+
 
   /// Subroutines of ActOnDeclarator().
   TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T);
@@ -770,7 +779,7 @@
   bool CheckMemberPointerConversion(Expr *From, QualType ToType,
                                     CastExpr::CastKind &Kind);
   bool IsQualificationConversion(QualType FromType, QualType ToType);
-  bool IsUserDefinedConversion(Expr *From, QualType ToType,
+  OverloadingResult IsUserDefinedConversion(Expr *From, QualType ToType,
                                UserDefinedConversionSequence& User,
                                OverloadCandidateSet& Conversions,
                                bool AllowConversionFunctions,
@@ -808,15 +817,6 @@
 
   bool PerformObjectMemberConversion(Expr *&From, NamedDecl *Member);
 
-  /// OverloadingResult - Capture the result of performing overload
-  /// resolution.
-  enum OverloadingResult {
-    OR_Success,             ///< Overload resolution succeeded.
-    OR_No_Viable_Function,  ///< No viable function found.
-    OR_Ambiguous,           ///< Ambiguous candidates found.
-    OR_Deleted              ///< Overload resoltuion refers to a deleted function.
-  };
-
   // Members have to be NamespaceDecl* or TranslationUnitDecl*.
   // TODO: make this is a typesafe union.
   typedef llvm::SmallPtrSet<DeclContext   *, 16> AssociatedNamespaceSet;
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 328609a..6574524 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -70,11 +70,23 @@
 
   if (S.getLangOptions().CPlusPlus) {
     // FIXME: I dislike this error message. A lot.
-    if (S.PerformImplicitConversion(Init, DeclType, "initializing", DirectInit))
-      return S.Diag(Init->getSourceRange().getBegin(),
-                    diag::err_typecheck_convert_incompatible)
-        << DeclType << Init->getType() << "initializing"
-        << Init->getSourceRange();
+    if (S.PerformImplicitConversion(Init, DeclType, 
+                                    "initializing", DirectInit)) {
+      ImplicitConversionSequence ICS;
+      OverloadCandidateSet CandidateSet;
+      if (S.IsUserDefinedConversion(Init, DeclType, ICS.UserDefined,
+                              CandidateSet,
+                              true, false, false) != S.OR_Ambiguous)
+        return S.Diag(Init->getSourceRange().getBegin(),
+                      diag::err_typecheck_convert_incompatible)
+                      << DeclType << Init->getType() << "initializing"
+                      << Init->getSourceRange();
+      S.Diag(Init->getSourceRange().getBegin(),
+             diag::err_typecheck_convert_ambiguous)
+            << DeclType << Init->getType() << Init->getSourceRange();
+      S.PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
+      return true;
+    }
     return false;
   }
 
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index d406dd4..cda7c82 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -417,7 +417,7 @@
            IsUserDefinedConversion(From, ToType, ICS.UserDefined,
                                    Conversions,
                                    !SuppressUserConversions, AllowExplicit,
-                                   ForceRValue)) {
+                                   ForceRValue) == OR_Success) {
     ICS.ConversionKind = ImplicitConversionSequence::UserDefinedConversion;
     // C++ [over.ics.user]p4:
     //   A conversion of an expression of class type to the same class
@@ -1355,7 +1355,8 @@
 ///
 /// \param ForceRValue  true if the expression should be treated as an rvalue
 /// for overload resolution.
-bool Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
+Sema::OverloadingResult Sema::IsUserDefinedConversion(
+                                   Expr *From, QualType ToType,
                                    UserDefinedConversionSequence& User,
                                    OverloadCandidateSet& CandidateSet,
                                    bool AllowConversionFunctions,
@@ -1458,7 +1459,7 @@
         User.After.FromTypePtr
           = ThisType->getAs<PointerType>()->getPointeeType().getAsOpaquePtr();
         User.After.ToTypePtr = ToType.getAsOpaquePtr();
-        return true;
+        return OR_Success;
       } else if (CXXConversionDecl *Conversion
                    = dyn_cast<CXXConversionDecl>(Best->Function)) {
         // C++ [over.ics.user]p1:
@@ -1480,24 +1481,25 @@
         //   user-defined conversion sequence (see 13.3.3 and
         //   13.3.3.1).
         User.After = Best->FinalConversion;
-        return true;
+        return OR_Success;
       } else {
         assert(false && "Not a constructor or conversion function?");
-        return false;
+        return OR_No_Viable_Function;
       }
 
     case OR_No_Viable_Function:
+      return OR_No_Viable_Function;
     case OR_Deleted:
       // No conversion here! We're done.
-      return false;
+      return OR_Deleted;
 
     case OR_Ambiguous:
       // FIXME: See C++ [over.best.ics]p10 for the handling of
       // ambiguous conversion sequences.
-      return false;
+      return OR_Ambiguous;
     }
 
-  return false;
+  return OR_No_Viable_Function;
 }
 
 /// CompareImplicitConversionSequences - Compare two implicit
@@ -2100,10 +2102,9 @@
     return false;
 
     OverloadCandidateSet CandidateSet;
-    IsUserDefinedConversion(From, Context.BoolTy, ICS.UserDefined,
+    if (IsUserDefinedConversion(From, Context.BoolTy, ICS.UserDefined,
                             CandidateSet,
-                            true, true, false);
-    if (CandidateSet.begin() == CandidateSet.end())
+                            true, true, false) != OR_Ambiguous)
       return  Diag(From->getSourceRange().getBegin(),
                    diag::err_typecheck_bool_condition)
                     << From->getType() << From->getSourceRange();