Issue a good diagnostics when attempt to select

a type convesion function results in ambiguity.

llvm-svn: 81812
This commit is contained in:
Fariborz Jahanian 2009-09-15 00:10:11 +00:00
parent f8122966a9
commit 19c7328881
4 changed files with 22 additions and 7 deletions

View File

@ -1619,6 +1619,8 @@ def err_type_defined_in_condition : Error<
"types may not be defined in conditions">;
def err_typecheck_bool_condition : Error<
"value of type %0 is not contextually convertible to 'bool'">;
def err_typecheck_ambiguous_bool_condition : Error<
"conversion from %0 to 'bool' is ambiguous">;
def err_expected_class_or_namespace : Error<"expected a class or namespace">;
def err_invalid_declarator_scope : Error<
"definition or redeclaration of %0 not in a namespace enclosing %1">;

View File

@ -772,6 +772,7 @@ public:
bool IsQualificationConversion(QualType FromType, QualType ToType);
bool IsUserDefinedConversion(Expr *From, QualType ToType,
UserDefinedConversionSequence& User,
OverloadCandidateSet& Conversions,
bool AllowConversionFunctions,
bool AllowExplicit, bool ForceRValue);

View File

@ -410,10 +410,12 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType,
bool AllowExplicit, bool ForceRValue,
bool InOverloadResolution) {
ImplicitConversionSequence ICS;
OverloadCandidateSet Conversions;
if (IsStandardConversion(From, ToType, InOverloadResolution, ICS.Standard))
ICS.ConversionKind = ImplicitConversionSequence::StandardConversion;
else if (getLangOptions().CPlusPlus &&
IsUserDefinedConversion(From, ToType, ICS.UserDefined,
Conversions,
!SuppressUserConversions, AllowExplicit,
ForceRValue)) {
ICS.ConversionKind = ImplicitConversionSequence::UserDefinedConversion;
@ -1355,9 +1357,9 @@ static void GetFunctionAndTemplate(AnyFunctionDecl Orig, T *&Function,
/// for overload resolution.
bool Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
UserDefinedConversionSequence& User,
OverloadCandidateSet& CandidateSet,
bool AllowConversionFunctions,
bool AllowExplicit, bool ForceRValue) {
OverloadCandidateSet CandidateSet;
if (const RecordType *ToRecordType = ToType->getAs<RecordType>()) {
if (CXXRecordDecl *ToRecordDecl
= dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) {
@ -2097,9 +2099,19 @@ bool Sema::PerformContextuallyConvertToBool(Expr *&From) {
if (!PerformImplicitConversion(From, Context.BoolTy, ICS, "converting"))
return false;
return Diag(From->getSourceRange().getBegin(),
diag::err_typecheck_bool_condition)
<< From->getType() << From->getSourceRange();
OverloadCandidateSet CandidateSet;
IsUserDefinedConversion(From, Context.BoolTy, ICS.UserDefined,
CandidateSet,
true, true, false);
if (CandidateSet.begin() == CandidateSet.end())
return Diag(From->getSourceRange().getBegin(),
diag::err_typecheck_bool_condition)
<< From->getType() << From->getSourceRange();
Diag(From->getSourceRange().getBegin(),
diag::err_typecheck_ambiguous_bool_condition)
<< From->getType() << From->getSourceRange();
PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
return true;
}
/// AddOverloadCandidate - Adds the given function to the set of

View File

@ -79,16 +79,16 @@ void f(const C& c) {
// Test. Conversion in base class is visible in derived class.
class XB {
public:
operator int();
operator int(); // expected-note {{candidate function}}
};
class Yb : public XB {
public:
operator char();
operator char(); // expected-note {{candidate function}}
};
void f(Yb& a) {
if (a) { } // expected-error {{value of type 'class Yb' is not contextually convertible to 'bool'}}
if (a) { } // expected-error {{conversion from 'class Yb' to 'bool' is ambiguous}}
int i = a; // OK. calls XB::operator int();
char ch = a; // OK. calls Yb::operator char();
}