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();