diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 20 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 22 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 23 | ||||
-rw-r--r-- | test/SemaCXX/deleted-function.cpp | 2 | ||||
-rw-r--r-- | test/SemaCXX/direct-initializer.cpp | 14 |
6 files changed, 56 insertions, 27 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 109bb4d08b..6a8ad5c617 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1643,6 +1643,8 @@ def warn_value_always_false : Warning<"%0 is always false in this context">; // FIXME: %2 is an english string here. def err_typecheck_convert_incompatible : Error< "incompatible type %2 %1, expected %0">; +def err_typecheck_convert_ambiguous : Error< + "ambiguity in initializing value of type %0 with initializer of type %1">; def err_cannot_initialize_decl_noname : Error< "cannot initialize a value of type %0 with an %select{rvalue|lvalue}1 " "of type %2">; diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 2713f7a955..84e73a6fec 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -734,6 +734,15 @@ public: 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 @@ public: 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 @@ public: 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/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 328609a192..6574524d14 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -70,11 +70,23 @@ static bool CheckSingleInitializer(Expr *&Init, QualType DeclType, 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/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index d406dd47c7..cda7c82968 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -417,7 +417,7 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType, 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 @@ static void GetFunctionAndTemplate(AnyFunctionDecl Orig, T *&Function, /// /// \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 @@ bool Sema::IsUserDefinedConversion(Expr *From, QualType ToType, 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 @@ bool Sema::IsUserDefinedConversion(Expr *From, QualType ToType, // 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 @@ bool Sema::PerformContextuallyConvertToBool(Expr *&From) { 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(); diff --git a/test/SemaCXX/deleted-function.cpp b/test/SemaCXX/deleted-function.cpp index 8064ed349b..637b2b1b2d 100644 --- a/test/SemaCXX/deleted-function.cpp +++ b/test/SemaCXX/deleted-function.cpp @@ -18,7 +18,7 @@ void ov(double) = delete; // expected-note {{candidate function has been explici struct WithDel { WithDel() = delete; // expected-note {{candidate function has been explicitly deleted}} void fn() = delete; // expected-note {{function has been explicitly marked deleted here}} - operator int() = delete; + operator int() = delete; void operator +(int) = delete; int i = delete; // expected-error {{only functions can have deleted definitions}} diff --git a/test/SemaCXX/direct-initializer.cpp b/test/SemaCXX/direct-initializer.cpp index 149b65c8d7..e95ba22769 100644 --- a/test/SemaCXX/direct-initializer.cpp +++ b/test/SemaCXX/direct-initializer.cpp @@ -34,3 +34,17 @@ void g() { Z z; // expected-error{{no matching constructor for initialization of 'z'}} } + +struct Base { + operator int*() const; // expected-note {{candidate function}} +}; + +struct Derived : Base { + operator int*(); // expected-note {{candidate function}} +}; + +void foo(const Derived cd, Derived d) { + int *pi = cd; + int *ppi = d; // expected-error {{ambiguity in initializing value of type 'int *' with initializer of type 'struct Derived'}} + +} |