diff options
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 23 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 15 | ||||
-rw-r--r-- | test/SemaCXX/overload-call.cpp | 20 |
3 files changed, 44 insertions, 14 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 0708d4176a..b959202b88 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -4526,20 +4526,23 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, OverloadCandidateSet::iterator Best; switch (BestViableFunction(CandidateSet, DeclLoc, Best)) { case OR_Success: + // C++ [over.ics.ref]p1: + // + // [...] If the parameter binds directly to the result of + // applying a conversion function to the argument + // expression, the implicit conversion sequence is a + // user-defined conversion sequence (13.3.3.1.2), with the + // second standard conversion sequence either an identity + // conversion or, if the conversion function returns an + // entity of a type that is a derived class of the parameter + // type, a derived-to-base Conversion. + if (!Best->FinalConversion.DirectBinding) + break; + // This is a direct binding. BindsDirectly = true; if (ICS) { - // C++ [over.ics.ref]p1: - // - // [...] If the parameter binds directly to the result of - // applying a conversion function to the argument - // expression, the implicit conversion sequence is a - // user-defined conversion sequence (13.3.3.1.2), with the - // second standard conversion sequence either an identity - // conversion or, if the conversion function returns an - // entity of a type that is a derived class of the parameter - // type, a derived-to-base Conversion. ICS->setUserDefined(); ICS->UserDefined.Before = Best->Conversions[0].Standard; ICS->UserDefined.After = Best->FinalConversion; diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 98db60854f..3540cd02e6 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -2273,10 +2273,17 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, Sema::ReferenceCompareResult NewRefRelationship = S.CompareReferenceRelationship(DeclLoc, T1, T2.getNonReferenceType(), NewDerivedToBase); - assert(NewRefRelationship != Sema::Ref_Incompatible && - "Overload resolution picked a bad conversion function"); - (void)NewRefRelationship; - if (NewDerivedToBase) + if (NewRefRelationship == Sema::Ref_Incompatible) { + // If the type we've converted to is not reference-related to the + // type we're looking for, then there is another conversion step + // we need to perform to produce a temporary of the right type + // that we'll be binding to. + ImplicitConversionSequence ICS; + ICS.setStandard(); + ICS.Standard = Best->FinalConversion; + T2 = ICS.Standard.getToType(2); + Sequence.AddConversionSequenceStep(ICS, T2); + } else if (NewDerivedToBase) Sequence.AddDerivedToBaseCastStep( S.Context.getQualifiedType(T1, T2.getNonReferenceType().getQualifiers()), diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp index 77e0908ef4..c286028c29 100644 --- a/test/SemaCXX/overload-call.cpp +++ b/test/SemaCXX/overload-call.cpp @@ -386,3 +386,23 @@ namespace DerivedToBase { float &fr = f0(C()); } } + +namespace PR6483 { + struct X0 { + operator const unsigned int & () const; + }; + + struct X1 { + operator unsigned int & () const; + }; + + void f0(const bool &); + void f1(bool &); // expected-note 2{{not viable}} + + void g(X0 x0, X1 x1) { + f0(x0); + f1(x0); // expected-error{{no matching function for call}} + f0(x1); + f1(x1); // expected-error{{no matching function for call}} + } +} |