diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2009-09-15 00:10:11 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2009-09-15 00:10:11 +0000 |
commit | 78cf9a26d27349a7b9ae83a0b7d5451571b9b41e (patch) | |
tree | c9722742c44988c01f93e10cbcba07c084c1e8ae | |
parent | d3509faadc1026e4f1f0671e008b91609a498983 (diff) |
Issue a good diagnostics when attempt to select
a type convesion function results in ambiguity.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81812 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 1 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 20 | ||||
-rw-r--r-- | test/SemaCXX/conversion-function.cpp | 6 |
4 files changed, 22 insertions, 7 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 5a5c7da361..cb567eb6f1 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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">; diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 1811f29a3c..d2034ce246 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -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); diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 6c23a844bf..d406dd47c7 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -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 diff --git a/test/SemaCXX/conversion-function.cpp b/test/SemaCXX/conversion-function.cpp index 37ffc1bb53..6182678e31 100644 --- a/test/SemaCXX/conversion-function.cpp +++ b/test/SemaCXX/conversion-function.cpp @@ -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(); } |